Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Токенизация LLM: как считать токены и цену

Токенизация LLM: почему символы не равны токенам и как считать расход

Токенизация: BPE и SentencePiece, оценка длины текста, подсчёт токенов для русского и кода, лимиты и стоимость, практические проверки в коде.

Прямой ответ

Токенизация — разбиение текста на единицы (токены), которыми оперирует модель: части слов, целые слова или отдельные символы. Почти все современные модели используют субсловные алгоритмы — BPE (byte-pair encoding) или SentencePiece. Ключевой практический факт: токен ≠ символ и ≠ слово.

Ориентиры, которые стоит запомнить:

  • для английского текста один токен ≈ 4 символа ≈ 0.75 слова;
  • для русского текста расход выше: кириллица часто кодируется меньшим числом байт на токен, поэтому одно слово может занимать 2–3 токена;
  • код расходует больше обычного текста из-за обилия пунктуации и отступов;
  • редкие слова, опечатки и спецсимволы разбиваются на много мелких токенов.

Следствия для практики:

  1. Оценка «на глаз» по символам приводит к ошибкам на 30–60 %. Для лимитов контекста и расчёта стоимости нужен точный подсчёт токенизатором.
  2. Токенизатор привязан к модели. Счётчик от одной модели даёт неверный результат для другой: словари различаются.
  3. Служебные токены тоже считаются. Разделители ролей и шаблон чата добавляют десятки токенов на каждый запрос.

Как считать точно:

from transformers import AutoTokenizer

tok = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")

def count_tokens(text: str) -> int:
    return len(tok.encode(text))

for s in ["Hello world", "Привет, мир", "def f(x): return x * 2"]:
    print(repr(s), count_tokens(s), tok.tokenize(s))

Быстрая оценка без токенизатора (для прикидки, не для лимитов): len(text) / 3.5 для русского, len(text) / 4 для английского.

Практика: где токенизация влияет на решения

1. Планирование контекстного окна. Точный подсчёт позволяет уложить в лимит историю и данные, а не обрезать их «на удачу». Управление бюджетом — в статье про контекстное окно.

2. Расчёт стоимости. Для платных API цена считается по токенам входа и выхода. Для локального запуска стоимость выражается во времени и памяти, но зависимость та же: больше токенов — дольше генерация.

3. Оценка пропускной способности. Планирование нагрузки для LLM-сервиса невозможно без среднего числа токенов на запрос. Как переводить это в ресурсы — в статье про capacity planning.

4. Оптимизация промпта. Токенизация объясняет, почему сжатие формулировок экономит заметно больше, чем кажется: короткие частотные слова кодируются одним токеном, а длинные редкие — несколькими.

Проверка расходов в приложении:

def report(messages, tok):
    total = 0
    for m in messages:
        n = len(tok.apply_chat_template([m], tokenize=True))
        total += n
        print(f"{m['role']:<9} {n:>5} токенов")
    print("итого:", total)

Рекомендации:

  1. Логируйте токены, а не символы. Метрика prompt_tokens и completion_tokens на запрос даёт картину расходов и помогает находить аномальные сценарии.
  2. Учитывайте шаблон чата. apply_chat_template показывает реальный расход вместе со служебными токенами; ручная склейка строк его недооценивает.
  3. Проверяйте поведение на кириллице и коде. Если продукт работает с русским текстом и исходниками, тестируйте именно их: оценки «по английскому образцу» занижают расход.
  4. Не токенизируйте «в лоб» большие документы. Для длинных текстов сначала делите на фрагменты, а затем считайте; иначе пиковое потребление памяти на кодирование станет неприятным сюрпризом.

Практический сценарий: запросы обрываются на 80 % лимита

Контекст: сервис суммаризации документов; при документе «на 6000 символов» ответ обрывается, хотя окно модели 8192 токена.

  1. Диагностика. Считаем токены реальным токенизатором: документ на 6000 кириллических символов занимает 4100 токенов, системный промпт — 700, шаблон чата и история — 900. Итого 5700, плюс запрошенный max_tokens=3000 — это 8700, то есть больше окна.
  2. Ошибка в коде. Оценка длины шла по символам (len(text) / 4), поэтому приложение считало вход равным 1500 токенам и не обрезало документ.
  3. Исправление. Переходим на точный подсчёт токенизатором; вводим явный бюджет: система + данные + история ≤ 5500, резерв под ответ 1500, запас 500. Документы длиннее бюджета делятся на части с последующим объединением выжимок.
  4. Проверка. На наборе из 40 документов обрывы исчезают; метрика доли запросов у границы лимита падает с 35 % до 2 %.
  5. Профилактика. Добавляем юнит-тест на подсчёт токенов для кириллического текста и кода, чтобы возврат к оценке по символам был заметен сразу.

Вывод: точный подсчёт токенов — это не микрооптимизация, а условие корректности: от него зависят обрезка данных, стоимость и отсутствие обрывов ответа.

FAQ

Можно ли уменьшить расход токенов на русском тексте? Частично: выбирать модели с большим словарём и хорошей поддержкой кириллицы, избегать редких аббревиатур и опечаток, не передавать текст в верхнем регистре целиком (регистр влияет на разбиение). Существенно сократить расход помогает сжатие самих формулировок.

Почему код расходует больше токенов, чем проза? В коде много редких последовательностей: скобки, отступы, имена переменных, специальные символы. Они разбиваются на мелкие токены, поэтому страница кода часто «весит» больше страницы текста.

Нужно ли считать токены для локальной модели без оплаты API? Да: токены определяют время генерации, объём KV-кэша и допустимый параллелизм. На локальном железе это прямой компромисс с памятью, особенно при квантованных моделях — см. квантование.

Как токенизация связана с качеством ответов? Косвенно, но заметно: модели хуже работают с языками, которые представлены в словаре слабо, потому что текст распадается на короткие фрагменты без цельного смысла. При выборе модели под русский язык стоит проверять не только бенчмарки, но и то, как токенизатор разбивает типичные для вас тексты.

Источники: Transformers docs (tokenizer summary), SentencePiece, BPE paper — ссылки в шапке.