Подсчёт токенов: где расход на запросы выходит из-под контроля
Любой запрос к языковой модели оплачивается не за смысл ответа, а за объём контекста: подсчёт токенов идёт по входной инструкции, истории диалога и сгенерированному ответу. Пока сценарий один, а переписка короткая, расход на запросы предсказуем и укладывается в ожидания. Как только появляется длинный контекст диалога, прикреплённые документы и цепочки вызовов, счётчик на стороне сервиса перестаёт совпадать с тем, что команда планировала.
Первая механика утечки — накопление истории. Каждый следующий ход в диалоге отправляет заново всю предыдущую переписку вместе с системной инструкцией, поэтому десятая реплика стоит кратно дороже первой, хотя пользователь написал одну строку. Без подсчёта токенов по каждому шагу это становится заметно только по итогам периода.
Вторая — повторные вызовы модели. Повторы по таймауту, веерные параллельные обращения, перезапрос на каждое действие в интерфейсе: один и тот же фрагмент контекста оплачивается несколько раз. Сюда же неизменные системные блоки, которые передаются на каждом шаге и не кэшируются.
Третья — отсутствие учёта по пользователям и сценариям. Когда расход на запросы лежит одной общей суммой, нельзя ответить, какая функция или какой аккаунт забирает основную долю. Разбивка по сценариям, клиентам и типу операции превращает счёт в управляемую величину.
Разбираем, как это закрывается: где ставить счётчики, как урезать контекст без потери качества и как выставлять лимиты до того, как расход уйдёт вверх.
Что даёт подсчёт токенов: контроль, лимиты, отчётность
Каждое обращение к языковой модели считается в токенах: входные — промпт вместе с историей диалога, выходные — ответ. У OpenAI и других поставщиков моделей тарификация построена ровно на этом, поэтому расход без учёта — производная от того, кто и как часто спрашивал. Мы снимаем счётчик на каждом вызове и привязываем его к пользователю, сервису и сессии — дальше это не сырой лог, а метрика.
Учёт расхода в разбивке по пользователям показывает, где уходит основной объём: один отдел даёт тяжёлые длинные промпты, а частые короткие запросы справочника — почти ничего. Отдельно видно долю попаданий в кэш: повторяющийся контекст не оплачивается дважды, и это самый быстрый рычаг снижения расхода. Аномалии — запрос с историей в десятки тысяч токенов, циклические повторы, забытый отладочный скрипт — находятся в первые дни, а не в конце периода.
Лимиты на запросы ставятся раздельно по числу вызовов и по объёму токенов в минуту — на пользователя, команду и сервис. Мягкий порог уводит обращение в очередь или сокращает ответ, жёсткий возвращает отказ; выбор зависит от сценария. Пиковые нагрузки сглаживают очередью, пакетной обработкой и кэшем — расход перестаёт расти ступеньками.
Отчётность — это суточный срез по сервисам и пользователям: объём токенов, динамика, источник всплеска. По нему видно, что менять: формулировку промпта, длину передаваемого контекста или саму модель.
Режимы учёта: прокси-слой, обёртка вызовов, журналы провайдера
Считать расход можно в трёх точках: на сетевом посреднике, внутри кода приложения или по журналам самого поставщика модели. Точки различаются тем, что каждая из них видит: посредник — только тело запроса и ответа, обёртка — ещё и контекст вызова, а журналы содержат уже посчитанные значения.
| Режим | Когда подходит | Ограничения |
|---|---|---|
| Прокси-слой | Нужен единый контроль над всеми сервисами сразу, включая чужие приложения, без правок кода | Терминирует соединение и требует доверия к узлу; не знает логических границ операции — одна задача дробится на несколько вызовов |
| Обёртка вызовов | Учёт нужен по операциям и пользователям, с лимитами и оценкой расхода до отправки | Работает только там, где её подключили; прямые обращения в обход обёртки выпадают из учёта |
| Журналы провайдера | Сверка и контроль: цифры приходят от поставщика, расхождений со списанием нет | Задержка от минут до часов; нет разбивки по внутренним операциям; часть вызовов может быть не размечена |
Кеширование ответов добавляет развилку. Попадание в кеш токенов не тратит, но списывать ли его с лимита пользователя — вопрос политики: при списании по факту обращения кеш незаметно съедает бюджет, при полном отказе от списания появляется стимул дробить одинаковые запросы.
Практичнее совмещать режимы: обёртка даёт оперативный лимит и оценку до отправки, прокси закрывает сервисы без правок кода, журналы служат источником истины для сверки. Расхождение между ними — сигнал, что часть трафика идёт мимо учёта.
Внедрение учёта расхода: от аудита вызовов до регламента
Порядок работ одинаков и для нового сервиса, и для уже работающего: сначала измеряем, потом ограничиваем. Начинаем с аудита вызовов — он показывает, где расход формируется на самом деле, а не там, где его ожидают. Дальше схема учёта, лимиты, проверка на нагрузке и передача вместе с регламентом.
- Аудит вызовов. Инвентаризация потоков: кто инициирует запрос, сколько контекста уходит в модель, какие обращения дублируются, где полный ответ генерируется ради одной строки. Результат — карта с долей каждого сценария в общем объёме.
- Схема учёта. Выбираем точку замера: приложение до отправки или прокси-слой. Фиксируем, что относим к запросу — контекст, историю диалога, ответ модели, обращения к инструментам.
- Подсчёт токенов. Один токенизатор под целевую модель, иначе отчёт расходится со счётом поставщика. Входящие и исходящие считаем раздельно, с разрезом по сценариям.
- Настройка лимитов. Три уровня: суточный на сценарий, на сессию пользователя и аварийный стоп на весь сервис. При исчерпании — предсказуемая деградация вместо тихого превышения.
- Проверка на нагрузке. Профиль реальных обращений: как счётчики ведут себя при параллельных запросах и обрывах соединения, попадают ли потоковые ответы в учёт. Расхождение с данными поставщика в единицы процентов — норма, больше означает ошибку в точке замера.
- Регламент и передача. Отдаём панель мониторинга, правила пересмотра лимитов, порядок разбора расхождений и владельца каждого сценария. Дальше правки промптов идут по тому же контуру: изменение → замер → лимит.
Комплект передачи: схемы учёта, политики лимитов, регламенты
Внедрение заканчивается не работающим счётчиком, а моментом, когда команда заказчика сама меняет лимиты, разбирает превышения и подключает новый сервис без нас. Поэтому передаём не отчёт о проделанной работе, а рабочий комплект: конфигурации, схемы и регламенты, которые лежат в том же хранилище кода и обновляются вместе с сервисом.
- Схема потоков данных: в какой точке считается расход в токенах, куда стекаются агрегаты, как они попадают в отчётность, где точки отказа и кто отвечает за каждый участок.
- Политики лимитов: пороги на подразделение, сервис и отдельного пользователя плюс поведение при исчерпании — предупреждение, отказ или переход на более экономную модель.
- Регламент эскалации: при каком отклонении от обычного профиля расхода поднимается тревога, кто и в какой срок реагирует, кто вправе временно поднять порог.
- Передаточная документация: порядок развёртывания, обновление справочника ставок, подключение новой модели и проверка, что учёт не разошёлся с потреблением.
- Сверочные сценарии: набор запросов с заранее известным расходом, который прогоняется после каждого изменения и ловит расхождение до того, как оно дойдёт до отчётности.
- Отчётность и выгрузки: расход по командам и сценариям, доля повторных запросов, закрытых без обращения к модели, динамика за произвольный период.
Комплект остаётся рабочим без нас: правки политик проходят обычное ревью, а новый инженер входит в контур по документации, а не по рассказам коллег.
Кейс: расход на языковые модели перестал расти при росте нагрузки
Что было
Ассистент первого уровня вёл диалоги в чате и почте: история переписки, выдержки из базы знаний и системные инструкции уходили в модель одним блоком. Обращения выросли втрое за сезон, и расход на модель повторил этот график почти линейно. Всплески добавляли своё: при исчерпании лимита провайдера запрос падал с ошибкой и уходил на повтор, а повтор тарифицировался как новый.
Что изменили
Учёт токенов вынесли на шлюз перед моделью — вход и выход считали отдельно, с разбивкой по сценарию, пользователю и классу модели; метрики снимали через Langfuse. По ним стало видно, что 60% объёма съедают три сценария из двенадцати, а больше половины переданной истории диалога модель не использует.
Дальше — лимиты вместо отказов: усечение истории до последних сообщений с сохранением краткого резюме, маршрутизация коротких запросов на модель младшего класса, кэш повторяющихся промптов в пределах окна диалога. На каждый сценарий поставили порог: предупреждение на 80% и плавная деградация вместо ошибки при исчерпании.
Что стало
| Метрика | До | После |
|---|---|---|
| Обращений в месяц | базовый уровень | втрое больше |
| Токенов на запрос | полный контекст | втрое меньше |
| Доля повторов после ошибки | 18% | 4% |
| Отказы из-за лимита провайдера | регулярные всплески | нулевые |
Расход перестал следовать за нагрузкой: обращений втрое больше, объём токенов вырос лишь на пятую часть и на этом уровне держится. Появился и второй эффект — по разбивке видно заранее, во сколько раз новый сценарий увеличит нагрузку, ещё до выката в продакшен.
Что делать, если лимиты уже превышены, а расход продолжает расти?
Превышение лимитов почти никогда не связано с ростом тарифов — растёт потребление токенов в одном конкретном контуре: раздутый контекст, цикл в агенте, повторы после сбоев или фоновая задача без потолка. Поэтому порядок действий обратный интуиции: сначала остановить рост, потом искать причину. Диагностика на живом трафике, который продолжает расходовать квоту, ничего не покажет.
Первый шаг — срезать низкоприоритетный трафик: пакетную обработку, переиндексацию, фоновые обогащения. Это снимает заметную долю расхода за минуты и не затрагивает пользовательские сценарии. Дальше расход раскладывается по осям: ключ доступа, модель, метод, арендатор, час суток. Журналы запросов провайдера — OpenAI и аналоги отдают такую разбивку — сопоставляем с базовой линией прошлой недели и находим точку, где график пошёл вверх.
Аварийные пороги ставятся заранее: 70–80% дневной квоты — уведомление ответственному, 100% — автоматическое переключение низкоприоритетных сценариев на более экономную модель либо отказ в обслуживании. После стабилизации пороги пересматриваются по фактическому профилю нагрузки, иначе защита начнёт срабатывать на нормальном пике.
Частые технические сомнения по учёту расхода и лимитам
Сомнения по учёту обычно касаются не самой формулы, а поведения счётчика в реальном трафике: сходится ли он с выставленным счётом, что происходит на потоковом ответе, сколько стоит сам контроль. Разбираем вопросы, с которыми инженерные команды приходят чаще всего.
Насколько точен подсчёт токенов и где он расходится с провайдером?
Считаем тем же токенизатором, что и целевая модель, поэтому расхождение возникает только на служебных обёртках и системных сообщениях. В отчёте храним оба значения — своё и подтверждённое ответом провайдера — и показываем разницу отдельной колонкой. Если расхождение выходит за заданный порог, это сигнал, что модель обновили и разметку нужно перепроверить.
Как считаются токены при потоковой выдаче, когда ответ приходит фрагментами?
Счётчик инкрементально накапливает фрагменты по мере поступления и фиксирует итог в момент завершения потока — промежуточные значения не пишем в историю, иначе получим десятки ложных записей на один вызов. Для оборванных соединений сохраняем оценку по промпту и уже пришедшему тексту с отдельным признаком, чтобы такие записи не смешивались с полными.
Насколько подсчёт замедляет ответ — растёт ли задержка?
Контрольный слой стоит на пути запроса и добавляет к общему времени ответа единицы процентов, а не фиксированную величину. При потоковой выдаче первый фрагмент уходит клиенту до того, как посчитан весь ответ, поэтому пользователь разницы не замечает. Если слой становится узким местом, его выносим из основного пути и считаем асинхронно, по завершении вызова.
Что именно хранится в истории вызовов и как она не разрастается?
Пишем компактные записи: идентификатор запроса, модель, счётчики, признак потока, метка времени и результат проверки лимита. Тексты промптов и ответов сохраняем опционально, с настраиваемым сроком хранения и очисткой по расписанию — тогда история остаётся пригодной для разбора инцидентов, но объём не растёт бесконечно.
Обсудим задачу: как поставить учёт расхода под контроль
Чтобы оценка внедрения была не «на глаз», а по факту, нужны исходные данные о том, как сейчас расходуются запросы к моделям. Ниже — короткий перечень: если часть пунктов отсутствует, это тоже ответ, он показывает объём подготовительной работы в плане работ.
- перечень сервисов и сценариев, которые обращаются к моделям, с примерной частотой вызовов;
- обезличенные образцы запросов и ответов — по ним видно, где контекст разрастается без пользы для результата;
- текущие правила лимитов и то, как сейчас обрабатываются превышения;
- выгрузка журналов обращений за типичный период: спокойная неделя и пик нагрузки;
- схема маршрутизации: какие модели и в каких режимах задействованы, где есть запас для переключения;
- требования к отчётности — в каком разрезе расход нужно видеть: по продукту, команде или клиенту;
- ограничения по инфраструктуре и доступам, если учёт нужно встроить в существующий контур.
С этим набором мы возвращаемся с оценкой внедрения и планом работ: последовательность шагов, точки контроля, что и когда появится в отчётах. Опишите задачу в удобном виде — обсудим, что в вашем случае даст эффект сразу, а что можно не делать.







