Что делает токенизатор и почему это важно
LLM не работает с текстом напрямую. Перед подачей в модель строка разбивается на токены — целочисленные идентификаторы, каждый из которых соответствует фрагменту текста: символу, части слова или целому слову. От того, как именно происходит это разбиение, зависят три практические вещи:
- Расход контекстного окна. Лимит модели задаётся в токенах, а не в символах. Один и тот же абзац может занять 80 токенов в одной модели и 140 в другой.
- Стоимость инференса. API-провайдеры тарифицируют запросы по числу токенов на входе и выходе.
- Качество генерации. Если токенизатор плохо представляет язык (например, разбивает кириллицу посимвольно), модель тратит ёмкость на «склейку» фрагментов вместо семантики.
Конвейер токенизации: три этапа
Прежде чем текст превратится в последовательность ID, он проходит три стадии:
1. Нормализация
Общая очистка входной строки. Конкретные операции зависят от модели:
- Удаление лишних пробельных символов.
- Приведение к нижнему регистру (например,
bert-base-uncased).
- Удаление диакритических знаков (ударений, умляутов).
- Unicode-нормализация (NFC, NFKC).
Нормализация определяет, будет ли токенизация обратимой.
bert-base-uncased приводит всё к нижнему регистру и убирает ударения — восстановить исходную строку из токенов невозможно.2. Претокенизация
Разбиение текста на мелкие фрагменты, которые станут границами для дальнейшего дробления на подтокены. Правила различаются:
| Токенизатор | Разбиение | Обработка пробелов | Двойные пробелы |
|---|---|---|---|
| BERT | по пробелам и пунктуации | удаляет | игнорирует |
| GPT-2 | по пробелам и пунктуации | заменяет на Ġ | сохраняет |
| T5 (SentencePiece) | только по пробелам | заменяет на ▁ | игнорирует |
Пример для строки
"Hello, how are you?":- BERT:
['Hello', ',', 'how', 'are', 'you', '?']— пунктуация отделена, пробелы выброшены.
- GPT-2:
['Hello', ',', 'Ġhow', 'Ġare', 'Ġ', 'Ġyou', '?']— пробелы закодированы префиксомĠ, двойной пробел сохранён как отдельный токен.
- T5:
['▁Hello,', '▁how', '▁are', '▁you?']— пунктуация остаётся внутри фрагмента, пробелы закодированы▁.
3. Алгоритм подтокенизации
На этом этапе фрагменты из претокенизации дробятся дальше — на подтокены, которые присутствуют в словаре модели. Три основных алгоритма:
- BPE (Byte-Pair Encoding) — GPT-2, LLaMA, Mistral и большинство decoder-only моделей.
- WordPiece — BERT и модели на его архитектуре.
- Unigram — T5, ALBERT.
Как работает BPE
BPE — итеративный алгоритм слияния пар. Обучение происходит на корпусе текстов:
- Инициализация. Словарь начинается с отдельных символов (или байтов, в зависимости от реализации). Каждый символ — базовый токен.
- Подсчёт пар. Алгоритм считает, какие пары соседних токенов встречаются в корпусе чаще всего.
- Слияние. Самая частая пара объединяется в новый токен и добавляется в словарь.
- Повторение. Шаги 2–3 повторяются, пока словарь не достигнет заданного размера.
В результате словарь содержит как отдельные символы, так и часто встречающиеся последовательности: целые слова (
the, function), распространённые аффиксы (ing, tion), характерные биграммы.При инференсе токенизатор применяет выученные слияния в том же порядке, в котором они были созданы при обучении. Слово, которое встречалось в корпусе целиком, останется одним токеном. Редкое или неизвестное слово будет разбито на знакомые подтокены.
Ключевое свойство BPE: алгоритм детерминирован и жаден — для данного входа результат всегда одинаков, но он не гарантирует глобально оптимальное разбиение с точки зрения вероятности.
SentencePiece: не алгоритм, а фреймворк
SentencePiece часто путают с конкретным алгоритмом токенизации. На деле это фреймворк предобработки, который можно комбинировать с BPE, Unigram или другими методами. Его отличительные черты:
- Текст рассматривается как последовательность символов Unicode. Нет отдельного шага претокенизации по пробелам или пунктуации. Это критично для языков без пробельного разделения слов: китайского, японского, тайского.
- Пробелы заменяются специальным символом
▁(U+2581, lower one eighth block). Это позволяет отличить начало слова от продолжения.
- Обратимая токенизация. Декодирование — простая конкатенация токенов с заменой
▁на пробел. Никакой информации не теряется.
- Пробел добавляется в начало предложения по умолчанию, поэтому первый токен обычно начинается с
▁.
Когда SentencePiece комбинируется с Unigram, претокенизация не требуется вовсе: алгоритм сам определяет оптимальное разбиение на основе языковой модели, обученной на корпусе.
Почему один текст даёт разное число токенов
Разница в количестве токенов для одной и той же строки между моделями объясняется несколькими факторами:
Размер и состав словаря
Словарь BPE обучается на конкретном корпусе. Если в корпусе доминировал английский, частые английские слова станут едиными токенами, а кириллица будет разбита на мелкие фрагменты. Модель с мультиязычным корпусом (например, mBERT, XLM-R) имеет более сбалансированное покрытие.
Правила претокенизации
Как показано выше, GPT-2 сохраняет двойные пробелы как отдельные токены, а T5 их игнорирует. Пунктуация в BERT отделяется от слов, а в T5 остаётся внутри фрагмента. Это напрямую влияет на число итоговых токенов.
Нормализация
Модель с lowercasing и удалением диакритики может дать меньше токенов для текста с ударениями, но потеряет информацию. Модель без нормализации сохранит каждый вариант написания как отдельную последовательность.
Базовые единицы
Некоторые реализации BPE работают на уровне байтов (byte-level BPE, как в GPT-2). Это гарантирует, что любой Unicode-символ может быть представлен, но для не-ASCII текстов увеличивает число токенов: один символ UTF-8 может занимать 2–4 байта, каждый из которых — отдельный базовый токен до слияния.
Практические следствия
Контекстное окно и стоимость
Если модель A токенизирует русский текст в 1.8 раза плотнее, чем модель B, то при одинаковом лимите контекста модель A обработает почти вдвое больше текста. При тарификации по токенам разница напрямую конвертируется в деньги.
Качество генерации на не-английских языках
Когда токенизатор разбивает слово на 5–7 подтокенов, модели сложнее уловить его семантику за один шаг внимания. Это одна из причин, почему модели с англоцентричным словарем хуже генерируют на русском, китайском или арабском — не из-за архитектуры, а из-за представления входа.
Structured output и парсинг
Токенизация влияет на генерацию JSON и других структурированных форматов. Если ключ или значение разбиты на несколько токенов, модели сложнее гарантировать синтаксическую корректность. Подробнее об этом — в материале Structured Output: как получать от LLM валидный JSON и не парсить ответ регулярками.
Как проверить число токенов для конкретной модели
Самый надёжный способ — использовать токенизатор целевой модели напрямую:
Python:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3-8B")
text = "Пример текста для проверки токенизации."
tokens = tokenizer.encode(text)
print(f"Токенов: {len(tokens)}")
print(f"ID: {tokens}")
Для визуализации разбиения на подтокены:
Python:
print(tokenizer.tokenize(text))
Это покажет, на какие фрагменты разбивается каждое слово. Если кириллическое слово распадается на 4–6 кусков — словарь модели плохо покрывает русский язык.
Сравнение нескольких моделей
Python:
from transformers import AutoTokenizer
models = ["gpt2", "t5-small", "bert-base-uncased"]
text = "Hello, how are you?"
for name in models:
tok = AutoTokenizer.from_pretrained(name)
ids = tok.encode(text)
print(f"{name:25s} → {len(ids)} токенов")
Для одного и того же текста результаты будут различаться из-за разных словарей и правил претокенизации.
Типичные ошибки при оценке токенов
- Оценка по символам или словам. Деление числа символов на 4 — грубая эвристика для английского текста в GPT-подобных моделях. Для русского, китайского или кода она даёт ошибку в 1.5–3 раза.
- Использование токенизатора одной модели для оценки другой. Словари несовместимы.
tiktoken(OpenAI) не подходит для LLaMA, и наоборот.
- Игнорирование специальных токенов.
[CLS],[SEP],<s>,</s>и системные промпты тоже занимают токены. При расчёте доступного контекста их нужно учитывать.
- Предположение, что токенизация обратима. Для BERT-подобных токенизаторов с нормализацией это не так: исходный регистр и диакритику восстановить невозможно.
Что учитывать при выборе модели под задачу
| Критерий | На что смотреть |
|---|---|
| Основной язык контента | Покрытие языка в словаре: проверить tokenize() на типичных строках |
| Лимит контекста | Реальная ёмкость в токенах с учётом системного промпта и специальных токенов |
| Стоимость API | Тариф за 1K токенов × средний объём запроса |
| Structured output | Чем плотнее токенизация целевого формата, тем надёжнее генерация Structured Output: как получать от LLM валидный JSON и не парсить ответ регулярками |
| Мультиязычность | Предпочтение моделям с мультиязычным корпусом обучения |
Токенизатор — не вспомогательная деталь, а часть архитектуры, которая определяет, как модель «видит» текст. Понимание его механики позволяет точнее оценивать стоимость, выбирать модель под язык задачи и диагностировать проблемы с качеством генерации.
