Любой план контекстного окна начинается с допущения, сколько символов помещается в токен. Наше оказалось неверным для русского — публично, в замороженном корпусе — и измеренная поправка полезнее исходных чисел, поэтому мы опубликовали её как данные, а не тихо пересобрали корпус.
Что мы предполагали и что намерили
Long-context корпус резался на номинальные ступени 2k/8k/16k/32k токенов по
оценке символов на токен: около 4 для английской прозы и 2.2 для русской.
Английское допущение выдержало; русское — нет. Поштучные измеренные
значения, снятые с собственного prompt-eval учёта рантайма и опубликованные
в tokens-measured.json
| Элемент корпуса (номинал) | Оценка токенов | Измерено | Отношение |
|---|---|---|---|
| en-32k (Диккенс) | 32034 | 30005 | 0.94 |
| ru-2k (Достоевский) | 2054 | 1372 | 0.67 |
| ru-8k | 8061 | 5295 | 0.66 |
| ru-16k | 16059 | 10415 | 0.65 |
| ru-32k | 32044 | 21062 | 0.66 |
Английский лёг в пределах ~6% от номинала. Русский — примерно на две трети: этот токенизатор (Qwen3.6, вшит в GGUF) тратит на литературный русский примерно 3.3 символа на токен, а не 2.2, как предполагал сборщик корпуса
.Что это значит на практике
- Один и тот же бюджет документа покупает разную глубину в разных языках. План «32k контекста», заполненный русской прозой при нашей предполагаемой плотности, реально занял около 21k токенов — окно оказалось на треть пустее своей этикетки. В обратную сторону: чтобы по-настоящему заполнить 32k токенов, русского текста нужно примерно в полтора раза больше, чем предсказывала оценка.
- Chars-per-token зависит от токенизатора и языка. Отношение, измеренное на английском, не переносится на кириллицу; измеренное на одном токенизаторе — не переносится на другой. Если ваш RAG-чанкинг, бюджет контекста или ценовая математика используют одну константу chars/token на все языки — она неверна минимум в одном из них.
- Меряйте, а не оценивайте: рантайм сам говорит. Каждый ответ
llama.cpp-сервера несёт учёт токенов промпта; один проход по своему
корпусу заменяет фольклорную константу на факт. Весь
tokens-measured.json— ровно это.
Как это всплыло (и что сделало с нашими же этикетками)
Ошибка разметки поймана при ревизии нашей long-context работы: поле
approx_tokens корпуса разошлось с собственным учётом сервера в наших же
опубликованных логах. Сам файл корпуса заморожен хэшем и не менялся;
измеренные значения теперь лежат рядом с ним, поправка зафиксирована в
errata, а опубликованные клеймы по глубинам — только
английские и потому не задеты. Затронутые русские ступени везде подписаны
измеренными значениями.
Более глубокий разбор — почему кириллица токенизируется дорого, на нескольких токенизаторах, с экономикой — в нашем лонгриде на Habr.
Ограничения
- Здесь измерен один токенизатор (Qwen3.6 GGUF); статья на Habr рассматривает другие, и отношения различаются по семействам. Цифра 3.3 символа на токен — литературная проза; русский с кодом или техническими терминами токенизируется иначе.
- Это счётчики токенов промпта, не заявления о качестве. Что глубина делает с поиском и честностью — работа long-context ворклоада, см. полезную глубину контекста.