Почему цена одного вызова почти ничего не говорит
Команда видит строку расходов API и пытается выбрать модель с более низкой ценой токена. Но пользователь платит не за токен и даже не за ответ модели. Ему нужен завершённый результат: правильно классифицированное обращение, заполненная карточка, найденный пункт договора или готовый черновик.
Дешёвый вызов может оказаться дорогим, если его приходится повторять, исправлять вручную или отправлять в более сильную модель. Поэтому базовая метрика - cost per successful task.
Полная формула стоимости LLM-функции
Для запуска workflow сложите стоимость обычных входных токенов, кэшированного ввода, выходных токенов, reasoning-токенов, если провайдер учитывает их отдельно, embeddings, retrieval и внешних инструментов. Добавьте повторы, fallback-вызовы, хранение кэша, наблюдаемость и ручную проверку.
Стоимость успешной задачи = (input + cached input + output + embeddings + retrieval + tools + storage + retries + fallback + ручная проверка) / число успешно принятых результатов
Тарифы храните в конфигурации с датой действия. Уточняйте актуальные условия на официальном сайте сервиса.
Какие поля логировать для управления расходами
Без связного trace нельзя понять, какая оптимизация сработала. Общего количества токенов недостаточно: оно не показывает сценарий, версию промпта и причину повторного вызова.
- request_id, trace_id, workflow_id и tenant_id.
- Сценарий, класс сложности и итоговый статус.
- Провайдер, model alias и фактическая модель.
- Prompt version, retrieval version и инструменты.
- Input, cached input, output и доступные usage-поля.
- Latency, попытки, причина retry и fallback.
- Результаты схемы, бизнес-валидатора и eval.
- Расчётная стоимость и версия тарифов.
- Ручная проверка и её исход.
Не записывайте полный prompt по умолчанию: часто достаточно хеша версии, размеров блоков и разрешённых диагностических полей.
Базовый отчёт: где именно сгорает бюджет
| Срез | Что считать | Решение |
|---|---|---|
| Сценарий | Цена успешной задачи | Убрать слабые use cases |
| Prompt version | Токены и ошибки | Сократить шаблон |
| Модель | Качество, latency, цена | Настроить route |
| Retry | Доля и добавочная цена | Исправить причину |
| Контекст | Токены и полезность | Удалить или точнее извлекать |
Смотрите не только среднее. Длинные документы и зацикленные агенты формируют дорогой хвост, заметный в P95 и P99.
Самая выгодная оптимизация - не делать ненужный вызов
До сокращения токенов проверьте, нужен ли LLM вообще. Точный парсер, поиск по ключу, JSON Schema, правила маршрутизации и обычный шаблон дешевле и предсказуемее там, где задача детерминирована.
Правила
Формат, enum, диапазон и обязательные поля.
Поиск
Точное извлечение известного факта.
Шаблон
Фиксированный текст с проверенными переменными.
Токен-бюджет: назначьте предел каждому блоку
Разложите ввод на system-инструкции, examples, историю, retrieved context, данные пользователя и tool results. Для каждого блока задайте максимальный размер и действие при переполнении.
Проведи аудит токен-бюджета workflow [название]. Для блоков system, examples, history, RAG, user data и tools укажи: пользу для решения, текущий и целевой предел, что удалить, способ сжатия, поведение при переполнении и eval-кейсы. Не предлагай экономию, которую нельзя измерить.
Не обрезайте документ механически. Сначала удаляйте дубли, устаревшую историю и низкорелевантные фрагменты.
Prompt caching: стабильный префикс впереди
Кэш полезен, когда запросы разделяют большой одинаковый префикс: инструкции, описание инструментов, примеры или документ. OpenAI и Google рекомендуют располагать повторяемое содержимое в начале, а переменную часть - после него. Конкретные модели, минимальный размер, TTL и тарифы различаются и меняются.
| Плохо для cache hit | Лучший порядок |
|---|---|
| Уникальный ID и время в начале | Стабильная policy |
| Пользовательский ввод до инструкций | Tool definitions и examples |
| Постоянно меняющийся общий блок | Переменные данные в конце |
Измеряйте cached tokens по usage API. Включённая функция не гарантирует экономию.
Экономика кэша: хранение, TTL и инвалидирование
Явный context cache может иметь стоимость хранения. Он оправдан, когда экономия повторных обращений превышает создание и хранение объекта. Для редко используемого контекста длинный TTL способен увеличить счёт.
- Оцените число повторов за TTL.
- Разделяйте общий corpus и данные клиента.
- Добавьте версии документа, policy и tool schema в ключ.
- Инвалидируйте после изменения фактов или прав.
- Не обходите требования к удалению данных.
- Проверяйте поддержку режима выбранным API.
Google документирует implicit и explicit caching, а OpenAI - prompt caching и его usage-метрики. Не переносите настройки между API без проверки.
RAG дешевле только при точном retrieval
RAG не экономит автоматически. Если top-k велик, chunks перекрываются, а в prompt попадают целые страницы, ввод становится дороже и шумнее. Цель - минимальный набор фрагментов, достаточный для проверяемого ответа.
- Удалить дубли и boilerplate до индексации.
- Выбирать chunk по структуре документа.
- Фильтровать по tenant, версии и правам.
- Настроить retrieval и reranking отдельно.
- Передавать только цитируемые фрагменты.
- Измерять recall на реальных вопросах.
- Добавить ответ «данных недостаточно».
Routing моделей: классифицируйте сложность
Routing связывает класс задачи, риск, требуемые возможности и критерий эскалации. Простое извлечение можно направить в компактную модель, сложное рассуждение - в более сильную, а высокорисковое действие - на ручное подтверждение.
Спроектируй policy routing для [workflow]. Для каждого класса запроса определи primary route, проверяемый сигнал уверенности, причины эскалации, fallback, максимальное число попыток и quality/latency/cost SLO. Не используй самооценку модели как единственный сигнал.
Каскад моделей и проверяемая эскалация
Каскад выгоден, если первая модель закрывает заметную долю запросов, а проверка результата надёжна. Если почти каждый ответ эскалируется, система платит дважды.
| Сигнал | Действие | Проверка |
|---|---|---|
| JSON не проходит schema | Repair или эскалация | Validator |
| Нет обязательной цитаты | Повторный retrieval | Provenance |
| Высокий риск | Сильная модель и approval | Policy |
| Неизвестный intent | Безопасный handoff | Закрытая taxonomy |
Ограничьте выход и используйте структурированный контракт
Лишние выходные токены увеличивают цену и задержку, а затем становятся входом следующего шага. Задайте JSON Schema, обязательные поля, допустимую длину и критерий остановки. Не просите «максимально подробно», если downstream использует три значения.
- Возвращайте ID и решение вместо пересказа записи.
- Разделяйте machine output и текст для человека.
- Запрашивайте краткое обоснование и источники только когда они нужны контракту.
- Останавливайте генерацию после заполнения схемы.
- Проверяйте усечение обязательных данных.
Batch API для несрочных независимых задач
Классификация архива, embeddings, массовое обогащение и ночные evals не требуют синхронного ответа. Официальные Batch API OpenAI и Gemini предназначены для асинхронной обработки больших объёмов. На дату публикации оба документа указывают скидку 50% относительно стандартного интерактивного режима, но условия и поддерживаемые модели необходимо перепроверять.
Собрать
Независимые запросы с уникальными ID.
Отправить
Один раз, с защитой от дублей.
Сверить
Результаты и ошибки по ID.
Retries, rate limits и идемпотентность
Повтор оплачивается как новый вызов и может повторно выполнить tool. Retry нужен для временных ошибок, с exponential backoff, jitter и верхней границей. Ошибку валидации нельзя лечить бесконечным повтором.
- Разделить transient и permanent errors.
- Задать max attempts и deadline.
- Уважать Retry-After.
- Применять backoff с jitter.
- Защитить внешние операции от дублей.
- Открывать circuit breaker при системном сбое.
- Логировать цену каждой попытки.
Агенты: ограничьте шаги, токены, время и деньги
У агента стоимость растёт по циклу: модель планирует, вызывает инструмент, получает результат и снова отправляет историю. Без ограничений ошибка навигации создаёт дорогую петлю.
| Лимит | Политика | При достижении |
|---|---|---|
| Шаги | Предел по классу задачи | Остановить и показать статус |
| Токены | Бюджет на trace | Сжать состояние или handoff |
| Деньги | Hard cap на run | Запретить новые вызовы |
| Время | Workflow deadline | Отменить операции |
| Tools | Allowlist и предел | Запросить approval |
Передавайте структурированное состояние, а не всю стенограмму. Крупный tool result храните отдельно и возвращайте только нужный фрагмент.
Quality floor: экономия не должна ломать результат
Смена модели, top-k, prompt, лимита выхода или routing policy изменяет поведение. Прогоните один версионированный eval-набор до и после. Зафиксируйте качество, критические ошибки, latency и стоимость успешной задачи.
- Golden cases для ключевых сценариев.
- Regression cases из обезличенных сбоев.
- Редкие форматы, языки и длинные входы.
- Grounding, цитаты и права доступа.
- Tool-use и безопасность действий.
- Доля отказов, исправлений и эскалаций.
Заранее задайте quality floor и ошибки, при которых релиз запрещён.
Runtime budget controller и FinOps
Контроллер знает остаток бюджета trace, приблизительный размер контекста и максимальный выход. Он может запретить дорогой route, сократить необязательный контекст, переключить задачу в batch или запросить подтверждение.
Опиши budget controller для [workflow]. Входы: tenant quota, task/risk class, tokens used, estimated next input/output, tool costs, deadline. Выходы: allow, cheaper_route, trim_optional_context, queue_batch, require_approval, stop. Hard cap нельзя превышать; безопасность нельзя отключать; решение и версия policy попадают в trace.
Разделите бюджеты по продукту, среде, tenant и workflow. Уведомления стройте по темпу расхода, отклонению от baseline и стоимости результата.
Дашборд экономики LLM
| Метрика | Зачем | Проблема |
|---|---|---|
| Cost/success | Связывает расходы с результатом | Растёт при прежнем качестве |
| Success rate | Защищает качество | Падает после релиза |
| Tokens by block | Находит источник | History или RAG разрастается |
| Cache hit share | Проверяет prefix | Ниже ожидаемого |
| Escalation rate | Оценивает каскад | Первая модель лишняя |
| Retries/success | Находит скрытую цену | Скачок по ошибке |
| P95 cost | Видит дорогой хвост | Зацикленные runs |
План оптимизации на 30 дней
- Дни 1 - 3: определить единицы успеха и владельцев.
- Дни 4 - 7: собрать usage, retries, fallback и проверки.
- Дни 8 - 10: построить baseline и найти лидеров затрат.
- Дни 11 - 14: удалить ненужные вызовы и контекст.
- Дни 15 - 18: стабилизировать prefix и измерить cache hits.
- Дни 19 - 21: вынести несрочные задания в batch.
- Дни 22 - 25: проверить routing на eval-наборе.
- Дни 26 - 27: установить agent limits и quota.
- Дни 28 - 29: провести canary с quality floor.
- День 30: сравнить cost/success и оформить решение.
Итоговый чек-лист перед релизом
- Определена единица успешного результата.
- Учтены попытки, fallback, tools и ручной труд.
- Тарифы версионируются.
- Ненужные LLM-вызовы удалены.
- Контекстные блоки имеют бюджет.
- Стабильный prefix отделён от переменных.
- Cache hits, TTL и invalidation измеряются.
- RAG проверен на recall.
- Routing основан на eval.
- Batch рассмотрен для несрочных задач.
- Retry и agent loops ограничены.
- Quality floor блокирует плохой релиз.
- Есть canary, владелец и rollback.
Главный принцип: оптимизируйте систему, а не счётчик токенов. Экономия появляется, когда продукт реже вызывает модель, передаёт только нужные данные и принимает результат с первой попытки.