localaiforum
Войти
Руководство › Основы

Токены и токенизаторы

Модели никогда не видят ни слов, ни букв. Они видят ID токенов — целые числа, индексирующие фиксированный словарь кусочков-подслов, построенный с помощью кодирования пар байтов (BPE) или близкого варианта. Токенизация — пограничный переход для всего: вашего промпта, ответа, окна контекста, счётчика токенов в секунду, счетов за API. Как только вы начинаете думать токенами, половина фольклора о поведении LLM рассыпается.

Как строится словарь

BPE стартует с сырых байтов и снова и снова сливает самую частую соседнюю пару, пока словарь не упрётся в бюджет. Результат: частые слова становятся одиночными токенами, редкие — 2–5 кусками, и нет ничего непредставимого — байтовый фолбэк покрывает любую строку, включая опечатки и эмодзи. Словари варьируются от ~30k записей (старые модели) до ~250k (современные мультиязычные):

Токенизатор Размер словаря Примечание
GPT-2 ~50k Перекос в английский/веб
Llama 2 ~32k Корейский режется болезненно
Llama 3 ~128k Большой мультиязычный апгрейд
Qwen 2 / 2.5 / 3 ~151k Сильные CJK-слияния
Gemma ~256k Самый большой из распространённых словарей

Токенизатор, обученный в основном на английском, агрессивно сливает английские фрагменты; корейские пары слогов получают куда меньше полезных слияний. Словарь определяет ваш «корейский налог» задолго до того, как дело дойдёт до того, насколько хороша сама модель в корейском.

Разбор на примере: английский

"Tokenization turns text into pieces."

→ ["Token", "ization", " turns", " text", " into", " pieces", "."]
→ 37 символов → 7 токенов ≈ 5.3 символа/токен

Обратите внимание на детали: частое слово "Token" — один кусок; суффикс получает собственный; пробел в начале принадлежит следующему токену (" turns", а не "turns"). Поэтому "hello", " hello" и "Hello" — разные токены: промпты, различающиеся пробелом или заглавной, токенизируются по-разному.

Разбор на примере: корейский

То же предложение, худшая экономика. Хангыль пишется слоговыми блоками, а корейские слияния редки в англо-тяжёлых словарях (разбиения ниже правдоподобны, не точны):

"안녕하세요, 만나서 반가워요."        # 17 символов

сильный мультиязычный словарь (~150k записей):
["안녕", "하세요", ",", " 만나", "서", " 반", "가", "워", "요", "."]
→ ~10 токенов ≈ 1.7 символа/токен

слабый словарь (~32k записей, разбиение до джамо):
["안", "녕", "하", "세", "요", ",", " 만", "나", "서", ...]
→ 15+ токенов ≈ 1.1 символа/токен

Английский в среднем ~4 символа/токен. Корейский обычно попадает в 1–1.5. Тот же смысл — в 3–4 раза больше токенов. Поэтому:

  • CJK-промпты пожирают окна контекста пугающе быстро — окно на 8k токенов вмещает примерно в 3–4 раза больше английского, чем корейского.
  • Генерация «ощущается» медленнее на корейском при том же tok/s: больше токенов на предложение, меньше текста на токен.
  • Корейский дороже на API с оплатой за токены, и цепочки рассуждений на корейском сжигают бюджет так же.

Почему модели проваливают подсчёт букв

Спросите «сколько r в strawberry» — и даже большие модели мажут. Причина: модель никогда не видит букв. "strawberry" приходит примерно как ["straw", "berry"] — два целых числа. Внутри целого числа нет счёта букв — как номер страницы не сообщает правописание страницы. Модель может воспроизвести зазубренные написания или рассуждать шаг за шагом, и оба пути ненадёжны. Если нужно сделать: заставьте модель сначала разобрать слово по одной букве в строке, а потом посчитайте строки.

Словарь поставляется вместе с моделью

  • Файлы токенизатора (словарь, слияния) — часть релиза; GGUF встраивает их, репозитории safetensors несут их рядом с весами.
  • Движки (llama.cpp, LM Studio, vLLM, ...) загружают правильный токенизатор автоматически. Вам никогда не нужно его выбирать.
  • Количество токенов относительно модели: один и тот же текст может быть 1,000 токенов в словаре одного семейства и 1,150 в словаре другого. Никогда не хардкодьте токен-бюджеты между моделями.
  • Качество словаря и качество модели — отдельные оси: модель со словарём 32k может справляться с корейским (она понимает свои токены); она просто тратит больше токенов на предложение.

Всё оценено в токенах

Что вам важно В чём измеряется
Окно контекста (4k → 128k+) токены на входе + токены на выходе вместе
Скорость генерации токенов в секунду
Память KV-кэша растёт на каждый токен в контексте (KV-кэш)
Цены API за миллион токенов
Лимиты длины вывода максимальные выходные токены
Бюджеты рассуждения/thinking токены, которые модель может потратить до ответа
Эмбеддинг документов для RAG чанкуется и считается за миллионы токенов

Специальные токены и чат-шаблон

Помимо кусочков текста, словарь резервирует управляющие ID: начало последовательности, конец последовательности и маркеры ролей. Когда ваш чат-UI отправляет сообщение, он отправляет не сырой текст — он заполняет чат-шаблон, который перемежает специальные токены вроде <|im_start|>user ... <|im_end|> вокруг ваших слов. Эта обёртка — причина, по которой счётчик токенов движка всегда чуть выше, чем текст вашего сообщения, и почему смешение шаблонов разных семейств путает модели.

Правила оценки: английский — символы ÷ 4. Корейский — символы ÷ 1.0–1.5, рассчитывайте на худшее. Симулятор использует приближение ~4 символа/токен и откалиброван на английском; для корейского мысленно завышайте.

Считаем токены сами

pip install tiktoken
python -c "import tiktoken as t; e = t.get_encoding('o200k_base'); print(len(e.encode('hello world')))"
  • tiktoken (https://github.com/openai/tiktoken) покрывает кодировки семейства OpenAI; другие семейства отличаются, но для английского попадают примерно в ±15%.
  • Страницы моделей на Hugging Face содержат просмотрщик токенизатора; песочницы токенизаторов позволяют вставить текст и посмотреть разбиение вживую.
  • Локальные движки печатают счётчик токенов промпта в логах — сверьте один раз со своими реальными промптами, дальше оценивайте по пропорции.

Связанные разделы: внутри трансформера · префилл и декодирование · KV-кэш