Ваш счет за LLM API - это не смешно
Открываете отчет от OpenAI за месяц и видите пятизначную сумму. Сердце замирает. Вы платите за тысячи запросов, но 80% из них - это одни и те же системные инструкции, контекст, шаблоны. Каждый раз модель заново 'проглатывает' идентичные токены, а вы за это платите. Это все равно что покупать билет на метро каждый раз, когда проезжаете одну станцию, вместо того чтобы купить абонемент.
По данным на март 2026, даже с учетом оптимизаций OpenAI, стоимость обработки входных токенов для GPT-5-Turbo составляет значительную часть счета. Повторяющиеся промпты - это дыра в бюджете.
Что такое Prompt Caching и почему он не магия
В двух словах: это техника, при которой вы не отправляете повторяющуюся часть промпта (например, системную инструкцию) в LLM при каждом запросе. Вместо этого модель получает ссылку на уже обработанный 'кэшированный' контекст. Провайдеры вроде OpenAI и Anthropic начали предлагать это на уровне API, но понимание механики критично, чтобы не попасть в ловушку, как в истории с кэшированием в Claude.
1Разбираемся в основах: токены, контекст и цена
Прежде чем кэшировать, нужно понять, за что именно вы платите. Если коротко, то стоимость запроса = (входные токены + выходные токены) * цена за токен. Кэширование атакует первую часть уравнения. Тут поможет глубокое погружение в механику токенизации.
- Статический префикс: Системный промпт, инструкции по формату ответа, контекст продукта. Идеальный кандидат для кэша.
- Динамическая часть: Вопрос пользователя, уникальные данные из базы. Это меняется и кэшированию не подлежит.
- История диалога: Сессия чата. Тут есть варианты - можно кэшировать цепочки, но осторожно.
2Как работает кэширование на стороне провайдера
OpenAI, начиная с определенного обновления API в 2025, позволяет передавать параметр cache_control. Вы отправляете промпт с флагом, система вычисляет хеш, и если такой хеш уже есть в ее кэше, она не вычисляет эмбеддинги и внимание заново. Вы платите только за использование кэша (дешевле) и генерацию ответа.
# Пример для OpenAI API (актуально на март 2026)
response = client.chat.completions.create(
model="gpt-5-turbo",
messages=[
{"role": "system", "content": "Ты эксперт по DevOps. Отвечай кратко.", "cache_control": {"type": "ephemeral", "key": "devops_expert_v1"}},
{"role": "user", "content": "Объясни continuous deployment"}
],
)
Ключевой момент: cache_control работает только для сообщений с ролью 'system' и 'assistant' в истории. Динамичный user-контент не кэшируется. Всегда проверяйте актуальность документации вашего провайдера.
3Свой кэш: когда провайдерского мало
А что если вы используете модель через OpenAI-совместимый API (Llama, Mistral) или ваш промпт слишком сложен для простого хеша? Тогда строим свой слой кэширования. Цель: не отправлять запрос к LLM, если идентичный (или достаточно похожий) уже был обработан.
Базовый алгоритм:
- Принимаем входящий запрос (промпт + параметры).
- Генерируем ключ кэша: хеш от промпта + model_name + temperature (да, temperature влияет на вывод!).
- Проверяем ключ в Redis/Memcached/PostgreSQL.
- Если попадание (hit) - возвращаем сохраненный ответ.
- Если промах (miss) - идем в API LLM, сохраняем ответ, возвращаем его.
import hashlib
import json
import redis
import openai
redis_client = redis.Redis(host='localhost', port=6379, db=0)
def get_cached_completion(prompt, model="gpt-5-turbo", temperature=0.7):
# Создаем уникальный ключ
key_data = json.dumps({"prompt": prompt, "model": model, "temp": temperature})
cache_key = hashlib.sha256(key_data.encode()).hexdigest()
# Пробуем получить из кэша
cached = redis_client.get(cache_key)
if cached:
return json.loads(cached)
# Иначе идем в API
response = openai.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
temperature=temperature
)
result = response.choices[0].message.content
# Сохраняем в кэш на 1 час
redis_client.setex(cache_key, 3600, json.dumps(result))
return result
Это наивная реализация. В реальности нужно учитывать стоимость хранения (особенно для длинных ответов) и стратегию инвалидации. Подробный расчет реальной экономии есть в нашей статье про формулу effective cost.
Подводные камни, о которых молчат
Кэширование - не серебряная пуля. Вот что может пойти не так.
| Ошибка | Последствие | Как избежать |
|---|---|---|
| Кэширование без учета seed и temperature | Пользователи получают детерминированные ответы, когда ожидается творчество. | Включайте все параметры генерации в ключ кэша. |
| Слишком долгий TTL (время жизни) | Информация устаревает. Ассистент рассказывает про вчерашние цены. | Настраивайте инвалидацию по событию или короткий TTL для динамичных данных. |
| Игнорирование стоимости хранения | Счет от облачного провайдера за Redis превышает экономию на токенах. | Считайте ROI. Используйте сжатие ответов или двухуровневый кэш. |
Особенно коварна работа с неанглийскими языками. Из-за раздувания токенов один и тот же смысл на русском может дать разный хеш из-за синонимов или опечаток. Подумайте о семантическом кэшировании (похожесть эмбеддингов), но это уже отдельная история.
Частые вопросы, которые задают после внедрения
Вопрос: Не нарушает ли кэширование условий использования API?
Ответ: Нет, если вы кэшируете на своей стороне. Использование провайдерского cache_control явно разрешено. Всегда уточняйте в ToS.
Вопрос: Как кэшировать в streaming-режиме?
Ответ: Полный стриминг и кэширование не дружат. Можно кэшировать финальный ответ после полной генерации. Или использовать неполные ключи для предсказуемых первых токенов (рискованно).
Вопрос: Prompt Caching vs Continuous Batching - в чем разница?
Ответ: Это разные уровни оптимизации. Кэширование экономит вычисления для идентичных входов. Continuous Batching оптимизирует обработку разных запросов на GPU для увеличения пропускной способности. Их можно комбинировать.
Что будет дальше? (Спойлер: кэширование умрет)
Вот вам неочевидный прогноз. По мере того как модели становятся эффективнее, а аппаратура дешевеет, экономия от Prompt Caching будет снижаться. Провайдеры будут включать базовое кэширование по умолчанию в тариф. На первое место выйдет кэширование не промптов, а решений - цепочек рассуждений (Reasoning Cache) для многошаговых задач. Уже сегодня экспериментальные функции вроде OpenAI o1 cache используют эту логику.
Но пока счет приходит, а токены стоят денег, действуйте. Начните с аудита: какие промпты повторяются чаще всего. Внедрите провайдерское кэширование. Если его нет - разверните свой Redis (или используйте управляемый сервис вроде Redis Cloud для простоты). Замеряйте экономию не в процентах, а в абсолютных цифрах. И помните, что иногда дешевле заплатить за токены, чем поддерживать сложную систему кэширования. Особенно если ваш сервис - не гигант масштаба Facebook. И да, иногда выбор локальной модели может быть ошибкой с точки зрения ROI. Считайте все.