developer-tools
ctok считает токены Claude офлайн, без обращения к API
Claude News
developer-toolsНеофициальный пакет ctok восстанавливает подсчёт токенов Claude офлайн, без обращения к API, доступа к сети и зависимостей во время выполнения: строка «hello, world» стоит 10 токенов в семействе v3 и 15 в v4.7. Код опубликован на Github, с Anthropic проект не связан, а исследование в его основе описано в работе «On the biology of Claude's tokenizer».
Коротко
- Библиотека нормализует текст по NFC с семейным свёртыванием кавычек, переписывает его в поток с маркерами слов, регистра и байтов, затем ищет покрытие минимальной стоимости по измеренному словарю и байтовому запасу UTF-8.
- В сохранённых наборах измерений нет ни одного занижения: 0 из 1 664 940 текстов v3 и 0 из 1 722 961 текста v4.7; такие проверки сравнивают вывод библиотеки с записанными ответами эндпоинта count_tokens.
- Границы токенов Claude не публикуются, поэтому tokenize() возвращает одно допустимое покрытие минимальной стоимости; это не заявление о фактической сегментации Anthropic, и реконструкция нацелена на сами числа.
Офлайновый счётчик закрывает практическую дыру: до сих пор точное число токенов для Claude получалось запросом к эндпоинту count_tokens, что стоит времени и сетевого обхода на каждом шаге конвейера. Судя по разнице счётчиков между семействами, стоимость одной и той же строки заметно зависит от поколения модели, и оценка бюджета контекста по чужим токенизаторам, вероятно, даёт систематическую ошибку.
Семейство v5 использует словарь v4.7 с другой рамкой сообщения
Семейство выбирается строкой версии: v3 применяется по умолчанию и покрывает модели от Claude 3 до Opus 4.6, v4.7 отвечает за Opus с 4.7 по 4.9, а версии от «5.0» относятся к Opus 5 и Sonnet 5. На «5.0» строка «hello, world» снова стоит 10 токенов, поскольку v5 работает со словарём v4.7 при другой рамке сообщения.
Версия передаётся строкой, а её компоненты сравниваются как целые числа, поэтому «4.10» оказывается после «4.9». Python читает литерал 4.10 как 4.1, и передача не строки вызывает TypeError. Команда ctok «hello, world» печатает размеченный поток вместе с его покрытием.
Внутренняя разметка видна в выводе: ⟨bow⟩ и ⟨eow⟩ отмечают границы слова, ⟨shift⟩ и ⟨caps⟩ обозначают переписывание регистра, ⟨0xNN⟩ соответствует байтовому запасному токену, а ⟨pad⟩ входит в рамку одиночного сообщения. Готовое покрытие дополняется измеренной рамкой сообщения, и token_count(text) равен len(tokenize(text)).
Точное совпадение на 350 000 строк Goldfish и 22 языках MultiPL-E
Точное совпадение зафиксировано и для v3, и для v4.7 на всех перечисленных корпусах. При подборе элементов участвовали 350 000 строк Goldfish на 350 языках, 1 741 документ Rosetta Code и 501 язык UDHR, входящий в выборку с 12 августа 2026 года; отложенными остались 22 языка программирования MultiPL-E и отдельные 250 документов Rosetta Code.
Семейство v5 в таблицу не включено: его отклонение от записанных ответов совпадает с отклонением v4.7 на каждом документе публичных проверок, а правила рамки сообщения покрыты отдельными тестами через API. Публичные проверки запускаются двумя командами: uv run pytest и uv run python tests/gates.py, входящими в репозиторий.
Словари содержат 48 645 элементов v3 и 15 240 элементов v4.7
Два файла словаря содержат 48 645 элементов v3 и 15 240 элементов v4.7, и каждая запись снабжена фиксированным свидетельством членства либо относится к структурным маркерным атомам, которые проверяет набор тестов. Вызов len(pieces("4.7")) возвращает 15240, а witness("⟨bow⟩the⟨eow⟩", "4.7") отдаёт поля probe, raw и kind со значениями 'the', 12 и 'raw'.
Свидетельство означает, что один размеченный элемент стоит один токен в калиброванном зонде. Файл tests/test_witness.py проверяет каждое опубликованное свидетельство и требует, чтобы любая запись либо имела свидетельство, либо была отнесена к специальным. Пакет ставится командой pip install ctok и распространяется по лицензии MIT.
Чего свидетельства не доказывают Свидетельства не подтверждают переписывание в кодировщике и не разрешают выбор между покрытиями равной стоимости, поэтому совпадение по числам не означает совпадения по разбиению строки. Отсутствие занижений в сохранённых наборах измерений авторы прямо не распространяют на произвольный ввод. Сроки поддержки будущих семейств моделей в описании проекта не названы.
Комментарии
Пока никто не написал. Будьте первым.
Присоединяйтесь к разговору
Войдите через Google, чтобы оставить комментарий. Имя и аватар подставятся из вашего профиля Google, а комментарий появится после модерации.
Из Google мы используем только имя и аватар. Почту не сохраняем.
