Перейти к содержимому
08 нояб. 2024 г.·7 мин чтения

Скачок токенов: как найти причину до счёта после релиза

После релиза скачок токенов легко пропустить. Разберём, как проверить длину промпта, частоту вызовов, ретраи и странные сценарии до счёта.

Скачок токенов: как найти причину до счёта после релиза

Когда рост токенов уже становится проблемой

Рост сам по себе не означает поломку. Если после релиза пришло больше пользователей и токенов стало больше примерно на те же 10-20%, это похоже на обычную нагрузку. Проблема начинается, когда расход растет быстрее, чем полезное действие. Запросов столько же, а токенов на один сценарий стало в полтора-два раза больше.

Такой скачок часто замечают слишком поздно. Счет живет отдельно от продакшена: провайдеры и шлюзы сначала собирают usage, потом сводят его по часам или дням, а финансы видят сумму еще позже. Когда команда смотрит на деньги, ошибка уже могла проработать сутки.

Первые сигналы видны раньше. Обычно меняется одна из трех вещей: растет длина промпта, увеличивается частота вызовов LLM или после релиза появляется странное поведение. Бот внезапно делает два запроса вместо одного, фоновая задача проходит по старым диалогам, ретраи резко растут из-за новой ошибки.

Быстрый тест простой: смотрите не на общие токены, а на токены на одно полезное действие. Для чата это токены на диалог или сообщение. Для классификации - токены на документ. Если бизнес-метрика почти не изменилась, а расход ушел вверх, это уже не рост, а дефект или плохая настройка.

Сразу идти в код не обязательно. Сначала проверьте базовые цифры: сколько стало запросов в минуту, сколько токенов уходит на один вызов, какие модели стали вызываться чаще, есть ли всплеск ошибок и повторных запросов, не пропал ли cache и не вырос ли системный промпт.

Если у вас есть единый шлюз с логами и статистикой по ключам, такие сдвиги обычно видно в первые часы. Если отдельного слоя нет, берите логи приложения и usage у провайдера.

Обычный рост редко выглядит как резкая ступенька. Поломка выглядит именно так: в 11:40 вышел релиз, в 11:45 токены на запрос выросли на 70%, а к вечеру счетчик уже далеко от нормы. В такой ситуации ждать биллинга нельзя. Отклонение нужно ловить в день релиза.

Как понять, что выросло на самом деле

Когда после релиза виден скачок, не смотрите сразу на общий расход. Сначала разделите проблему на две части: запросов стало больше или каждый запрос стал тяжелее. Для счета это почти одно и то же. Для поиска причины - совсем разные истории.

Полезная формула простая: общий объем токенов = число запросов x средние токены на запрос. Иногда обе цифры растут понемногу и вместе дают очень неприятный итог. Если вызовов стало на 30% больше, а средняя длина запроса выросла на 25%, общий расход уже выглядит как авария.

Сравните по дням или по часам четыре показателя:

  • входные токены на один запрос
  • выходные токены на один ответ
  • число запросов на пользователя, экран или задачу
  • число запросов на одно действие в продукте

Если выросли входные токены, первым делом проверьте длину промпта. После релиза часто незаметно распухает system prompt: добавили новые правила, большой JSON со схемой, длинные инструкции для tool calling, больше сообщений из истории чата или лишние куски базы знаний. Особенно неприятный случай - когда приложение начинает отправлять всю переписку целиком там, где раньше хватало последних 3-5 сообщений.

Если вход почти не изменился, смотрите на длину ответа. Модель могла начать отвечать длиннее из-за нового шаблона, другой модели, убранного ограничения по max_tokens или более общих инструкций. Задача, где раньше хватало пары строк, вдруг получает объяснение на 400-600 токенов.

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

Хороший разрез данных - по ключу, модели и маршруту. Так быстрее видно, где сломалась логика: в одном эндпоинте вырос размер контекста, а в другом просто удвоилась частота запросов.

Для контроля расходов полезно держать простую таблицу по сценариям: запросов на действие, входных токенов на запрос и выходных токенов на ответ. Обычно одна колонка сразу показывает, что именно пошло не так.

Что чаще всего ломается сразу после релиза

После релиза токены почти никогда не растут без причины. Обычно ломается мелкая настройка, которую не заметили в тестах.

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

Не меньше проблем создают повторы после таймаута. Клиент не дождался ответа, решил, что запрос пропал, и отправил его снова. Но первый вызов уже ушел в модель и тоже попал в счет. Пользователь видит один ответ, а система оплачивает два или три.

После релиза это часто происходит из-за новой политики повторов в SDK, мобильном приложении или бэкенде. Если никто не сверил число таймаутов с числом повторных вызовов, скачок токенов легко спутать с ростом нагрузки.

Еще один частый источник расходов - мусор в промпте. В него внезапно начинают попадать логи, сырой JSON, полный текст истории диалога или слишком длинный контекст из поиска. Один такой хвост добавляет сотни или тысячи входных токенов, хотя полезной информации там мало.

Стоит проверить и запасную модель. Если основная модель недоступна, сервис может уйти на резервный вариант, который отвечает заметно длиннее или работает без жесткого лимита на длину ответа. Само переключение полезно, но его правила нужно задавать очень точно.

Быстрая проверка обычно выглядит так:

  • сравнить среднюю длину входа и выхода до релиза и после него
  • найти повторные запросы с одинаковым идентификатором или телом
  • открыть несколько реальных промптов и проверить, не попали ли туда логи, JSON или лишняя история
  • убедиться, что модель не изменилась и лимит на длину ответа не исчез

Если вырос только один график, причина часто простая. Если одновременно увеличились длина промпта, частота вызовов и доля резервной модели, искать нужно уже не в одном месте, а во всей цепочке релиза.

Как проверить причину по шагам

Начните не со счета, а с формы трафика. Рост расходов почти всегда раскладывается на три причины: запрос стал длиннее, вызовов стало больше, или код начал делать лишнюю работу после релиза.

Самый быстрый путь - сравнить до и после релиза средние input и output tokens по одному и тому же сценарию. Если вырос input, ищите новый системный промпт, лишний контекст, историю чата или дубли документов. Если вырос output, проверьте лимиты ответа, формат вывода и не просит ли приложение более длинное объяснение.

Дальше разрежьте трафик на понятные куски:

  1. Сравните 24 часа до релиза и 24 часа после него по средним токенам на запрос.
  2. Разбейте данные по эндпоинтам, моделям и API-ключам.
  3. Привяжите всплеск по времени к деплою, фиче-флагу или смене маршрута на другую модель.
  4. Возьмите 20-50 живых запросов и посмотрите, что реально попало в промпт.
  5. Проверьте ретраи, таймауты и параллельные вызовы одного и того же действия.

На третьем шаге часто находится причина, которую никто не ждал. Например, один флаг включил RAG только для части пользователей, и в промпт начали попадать не 3 коротких фрагмента, а 12 длинных. На графике это выглядит как общий скачок, хотя проблема сидит в одном потоке.

Просмотр реальных запросов почти всегда полезнее сухой агрегированной метрики. Возьмите несколько примеров с нормальным расходом и несколько из зоны всплеска. Сравните системную инструкцию, историю, вложенный контекст, формат ответа и число tool calls. Иногда один лишний блок логов дает больше токенов, чем весь пользовательский текст.

Потом проверьте саму механику вызовов. После релиза приложение может повторять запрос при таймауте, запускать два параллельных вызова вместо одного или отправлять повтор через очередь. Внешне все выглядит как обычная нагрузка, но частота вызовов LLM уже выросла в полтора-два раза.

Если трафик идет через единый шлюз, разбор обычно проще: можно быстро посмотреть логи на уровне ключа, модели и времени запроса. Так легче отличить длинный промпт от лишних повторов и понять, где сломалась экономика запроса.

Какие метрики держать перед глазами

Проверьте трафик без смены SDK
Замените только base_url и продолжайте работать с тем же кодом и промптами.

Один общий график по расходам почти бесполезен. Он показывает, что деньги ушли, но не объясняет почему. Во время скачка нужны несколько метрик сразу, причем в одном разрезе: по сервису, по API-ключу, по модели и по сценарию.

Первый слой - токены на один запрос. Смотрите отдельно input и output. Рост input tokens на запрос обычно говорит о длинном системном промпте, лишнем контексте, дублях в истории диалога или новой логике, которая отправляет больше данных, чем раньше. Рост output tokens чаще связан с тем, что модель стала отвечать подробнее, перестал работать лимит длины ответа или приложение делает лишние догенерации.

Второй слой - частота вызовов. Даже если длина промпта не изменилась, requests per minute легко удваивают счет. Поэтому полезно держать рядом два графика: запросы в минуту по сервису и запросы в минуту по ключу. Так проще понять, проблема в одном релизе, в одном клиенте или в конкретной интеграции.

Рабочий набор метрик обычно такой:

  • input tokens на запрос по модели и по сценарию
  • output tokens на запрос с p50 и p95
  • запросы в минуту по сервису, API-ключу и важным маршрутам
  • доля ошибок и повторов, включая retry после 429, 500 и таймаутов
  • стоимость по модели и по сценарию, а не только общий дневной расход

Метрика ошибок нужна не для отчета, а для денег. Если после релиза выросла доля 429 или 5xx, клиенты и фоновые задачи часто начинают повторять вызовы. Та же история с таймаутами: один пользовательский запрос может породить две или три LLM-операции вместо одной.

Стоимость лучше считать не только по модели, но и по сценарию. Если поиск по базе знаний внезапно стал дороже, вы сразу увидите, что проблема в этом пути, а не во всем сервисе.

Где команды ошибаются чаще всего

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

Среднее значение тоже часто мешает. Если девять запросов короткие, а десятый внезапно уходит в 20 тысяч токенов, среднее выглядит терпимо. На деле именно такие пики и дают неприятный счет после релиза. Поэтому смотрите не только average, но и верхние хвосты: p95, p99 и максимум по токенам на запрос.

Еще одна частая ошибка - смешивать тестовый и боевой трафик. После релиза QA прогоняет сценарии, разработчики проверяют новые промпты, а автотесты могут ходить в тот же API-ключ, что и прод. Потом команда ищет проблему в пользователях, хотя токены сожгли внутренние проверки. Тут помогают отдельные ключи, теги окружения и раздельные дашборды.

Длинный debug prompt в проде встречается чаще, чем кажется. Его добавляют на пару часов, чтобы собрать больше контекста: сырые логи, полные истории сообщений, служебные инструкции, примеры ответа. Потом фикс выкатывают, а лишний текст остается. Если системный промпт вырос с 900 до 3500 токенов, даже без роста трафика счет улетит очень быстро.

Ограничения на max_tokens и ретраи команды тоже забывают регулярно. Один неудачный релиз легко запускает дорогой цикл: модель не отвечает как надо, приложение делает 3-4 повтора, каждый раз отправляет тот же длинный контекст и еще просит слишком длинный ответ. В логах это выглядит как обычная нестабильность. В счете - уже отдельная статья расходов.

Полезно разделять данные не по одному числу, а по нескольким срезам: prompt и completion отдельно, прод и тест отдельно, успешные ответы и ретраи отдельно, новые и старые версии релиза отдельно, пики по пользователю, фиче или cron-задаче отдельно.

Если в логах есть версия релиза, окружение и тип сценария, причину можно увидеть за 10 минут. Без такой разметки команда обычно спорит по ощущениям и теряет полдня.

Самая обидная ошибка проста: проверять расходы только утром следующего дня. К этому моменту баг уже прогревает весь трафик. Лучше ставить тревоги на резкий рост токенов на запрос, на число ретраев и на необычно длинные completion сразу после выката.

Простой пример из рабочей недели

Оставьте данные в Казахстане
Храните данные внутри страны, если команде важны требования законодательства Казахстана.

Во вторник команда выкатила небольшой релиз для внутреннего помощника поддержки. Ничего рискованного не планировали: чуть подробнее ответы, чуть удобнее поле ввода, пара правок в обработке ошибок. Через час после запуска расход вырос так резко, что это уже нельзя было списать на обычный дневной пик.

Сначала подумали, что дело только в более длинных ответах. И правда, средний ответ стал заметно больше: вместо коротких 120-150 токенов помощник часто уходил к 400-500. Причина оказалась простой: в промпт добавили инструкцию "объясняй подробнее и предлагай следующий шаг". Само по себе это неприятно, но не катастрофа.

Потом посмотрели частоту вызовов и нашли более дорогую ошибку. После правки фронтенда запрос уходил не по нажатию кнопки, а почти на каждый введенный символ. Человек печатал фразу из 40 символов, а система успевала отправить десятки вызовов. Пользователь видел один диалог, а бэкенд обслуживал целую серию лишних обращений.

На этом рост не закончился. В тот же релиз добавили новый слой ретраев. Если модель отвечала медленнее обычного, приложение повторяло запрос, а затем это же делал еще и промежуточный сервис. Один сбой превращался в два или три одинаковых вызова.

За один час выросли сразу несколько метрик:

  • токены на один запрос
  • число запросов на одного пользователя
  • доля повторных вызовов с тем же текстом

Именно такая связка и дает самый неприятный счет. Не один большой промпт, а несколько мелких ошибок, которые усиливают друг друга.

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

Что проверить перед алертом

Найдите лишние ретраи быстрее
Смотрите запросы по времени, модели и ключу и находите причину скачка.

Сигнал стоит поднимать не после первого всплеска, а после быстрой ручной проверки. Часто причина банальна: релиз добавил лишний текст в запрос, поднял лимит ответа или запустил новый фоновый поток, который молча жжет токены.

Начните с нескольких простых вопросов. Текущий system prompt не стал длиннее прошлой версии? В модель не уходит вся история диалога вместо последних 6-8 сообщений? Не изменился ли max_tokens? Не включился ли новый cron, batch или фоновая задача? Нет ли повторов после 429, 500 и таймаутов?

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

На практике такая проверка занимает меньше времени, чем разбор счета постфактум. И почти всегда находит причину раньше, чем ее увидит финкоманда.

Что сделать дальше

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

Полезно настроить не только алерт на общий расход, но и алерт на отклонение от обычного уровня. Если средний ответ вдруг стал вдвое длиннее, проверьте шаблон промпта, системные инструкции и формат ответа. Если длина ответа не изменилась, а запросов стало больше, смотрите фоновые задачи, повторные отправки из фронтенда и лишние вызовы после таймаута.

Обычно хватает четырех правил:

  • следить за токенами на запрос и запросами в минуту отдельно
  • ограничить максимальную длину ответа для каждого сценария
  • зафиксировать допустимое число ретраев
  • разбирать аномалии после каждого релиза по короткому чек-листу

Лимиты лучше ставить заранее, а не после инцидента. У многих команд скачок появляется не из-за одной большой ошибки, а из-за двух мелких сразу: ответ вырос на 40%, а клиент начал делать лишний ретрай. Вместе это дает заметный рост расходов уже за пару часов.

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

Если трафик идет через AI Router, разбор обычно проще. В одном месте видны аудит-логи, расход по моделям и лимиты по ключам, поэтому проще понять, какой сервис дал всплеск и где именно он начался. Для команд в Казахстане это еще и убирает часть операционной путаницы: данные остаются внутри страны, а спорный скачок можно проверить без ручного сбора информации из разных систем.

Если сделать такие проверки частью каждого релиза, скачок токенов редко успевает превратиться в неприятный счет.

Часто задаваемые вопросы

Как быстро понять, что это не обычный рост нагрузки?

Смотрите на токены за одно полезное действие, а не только на общий объем. Если пользователей и запросов стало почти столько же, а токены на диалог, документ или экран выросли в полтора-два раза, это уже похоже на сбой, а не на обычный рост.

Что смотреть первым делом после релиза?

Сначала проверьте три вещи: токены на запрос, запросы в минуту и долю повторов после ошибок или таймаутов. Потом сравните эти цифры с периодом до релиза по тем же сценариям и тем же моделям.

Как отличить длинный промпт от лишних вызовов?

Разделите расход на две части: сколько стало вызовов и сколько токенов уходит на один вызов. Если вырос input, ищите длинный system prompt, лишнюю историю или большой контекст; если выросла частота, ищите повторы, фоновые задачи и лишние запросы из фронтенда.

Какие ошибки чаще всего раздувают расход?

Часто виноваты подробные ответы для всего трафика вместо части пользователей, повторы после таймаута и мусор в промпте вроде логов или сырого JSON. Еще проверьте, не ушел ли трафик на резервную модель с более длинными ответами.

Достаточно ли смотреть на общий дневной счет?

Нет, по дневной сумме вы увидите только факт перерасхода. Причину лучше искать по часам, по релизу, по API-ключу, по модели и по конкретному сценарию, иначе вы потеряете время на догадки.

Какие метрики стоит держать на дашборде?

Держите рядом input tokens на запрос, output tokens на ответ, requests per minute и долю ошибок с повторами. Полезно еще видеть p95 по длине ответа, потому что именно хвосты часто и раздувают счет.

Как проверить, что расход вырос из-за ретраев?

Сравните число таймаутов и 429 или 5xx с числом повторных вызовов за тот же период. Если один пользовательский запрос часто рождает два или три одинаковых обращения, проблема почти наверняка в логике retry, а не в росте аудитории.

Что делать, если модель вдруг стала отвечать слишком длинно?

Проверьте max_tokens, шаблон промпта и саму модель, которую вызывает сервис после релиза. Если задача не требует длинного текста, верните жесткий лимит и уберите инструкции, которые заставляют модель объяснять лишнее.

Какие алерты нужны в первую очередь?

Обычно хватает алерта на резкий рост токенов на запрос, на скачок requests per minute и на всплеск повторов после ошибок. Такие сигналы стоит проверять в день релиза, а не утром следующего дня.

Зачем здесь нужен единый шлюз вроде AI Router?

Единый шлюз дает логи и статистику в одном месте, поэтому команда быстрее видит, где выросли токены: в промпте, в частоте вызовов или в одной проблемной интеграции. Если трафик идет через AI Router, проще связать всплеск с моделью, ключом и временем релиза без ручного сбора данных из разных систем.