Кэширование ответов LLM — как срезать счёт за API вдвое

В типовом продакшен-LLM 40–60% запросов повторяются дословно или семантически. Разбираем 4 уровня кэша: exact, prompt cache, семантический, на retrieve — и где какие риски.

В типовом продакшен-LLM-сервисе (саппорт-бот, FAQ-поиск, ассистент в админке) 40–60% запросов повторяются дословно или семантически близки. Платить за них $0.005 за тысячу токенов каждый раз — деньги в трубу. Разбираем четыре уровня кэша от простого к рискованному: exact, prompt cache, семантический, кэш на retrieve. Каждый срезает свой кусок счёта, у каждого свои подводные камни.

Кэш LLM: exact match, prompt cache, семантический кэш, кэш retrieve
Каждый уровень кэша срезает свой кусок счёта. Exact — самый простой и безопасный, семантический — самый рискованный.

Уровень 1. Exact-match кэш

Самый простой и безопасный. Ключ — хэш от полного промпта (system + user + параметры: модель, температура, max_tokens). Если хэш найден в Redis — отдаём готовый ответ.

Что ловит. Повторные вопросы «сколько стоит доставка», «как вернуть товар», «когда приедет заказ #X». В FAQ-боте — 30–50% запросов.

Грабли.

  • TTL: ответ про «время работы магазина» не вечен. Ставить TTL по типу контента (вечнозелёные — 30 дней, динамика — час).
  • Персонализация: если в промпт залит user_id или username — каждый кэш индивидуальный, hit rate падает. Чистить персональные поля из ключа.
  • Параметры модели в хэше. temperature=0.7 и temperature=0.8 — разные ключи. С детерминированной температурой 0 — нет.

Экономия. 30–50% на счёте.

Уровень 2. Prompt cache (нативный, на стороне провайдера)

Anthropic Claude, OpenAI, GigaChat, YandexGPT — все ввели нативное кэширование промптов. Длинная фиксированная часть (system + RAG-контекст + few-shot примеры) кэшируется на 5–60 минут, оплачивается дешевле или бесплатно.

Что ловит. Когда у вас 4000 токенов system+context и 200 токенов user-вопроса — повторные обращения снижают input billing в 5–10 раз.

Грабли.

  • Префикс должен быть точно тот же до байта. Любая правка системного промпта — кэш сброшен.
  • Минимальный размер кэшируемого блока (обычно 1024 токена). Маленькие system-промпты не кэшируются.
  • TTL — короткий. Если промежутки между запросами больше 5 минут, кэш не успевает работать.

Экономия. До 90% на input-токенах при стабильной нагрузке.

Уровень 3. Семантический кэш

Embed входного вопроса, ищем в кэше похожие (cosine similarity > 0.95), отдаём предзаписанный ответ. Если ничего не нашли — идём в LLM и сохраняем результат с эмбеддингом.

Что ловит. Перефразы. «Как вернуть товар» vs «как оформить возврат покупки» — exact-кэш промахивается, семантический ловит.

Грабли.

  • Порог critical. 0.95 — консервативно, мало false-positive. 0.90 — больше hit rate, но кэш начинает отвечать «не на тот вопрос».
  • Embed стоит денег и времени (50–200 мс). Если запросов мало — overhead не окупается.
  • Изменчивые данные ловятся как кэш-хит ошибочно. «Какой остаток на складе» — два пользователя задают одно и то же, остатки разные. Нужен whitelist типов вопросов под семантический кэш.
  • Метрика качества. Без оценки на золотой выборке — летите вслепую. Минимум 100 пар «вопрос → ответ из кэша» прогнать через ручную проверку и/или LLM-судью.

Экономия. 20–35% сверх exact-кэша.

Уровень 4. Кэш на retrieve (для RAG)

Если используете RAG (см. отдельную статью), один запрос — это embed + векторный поиск + LLM. Embed и поиск можно кэшировать отдельно от LLM-ответа.

Что ловит. Запросы, где LLM-ответ зависит от контекста сессии, но retrieve одинаков для одинаковых вопросов.

Реализация. Ключ кэша retrieve = эмбеддинг входа (округлённый). Хранится в Redis с TTL ~7 дней. Hit rate в FAQ-сценариях — 40–60%.

Экономия. Не на LLM-биллинге, а на латентности (50–200 мс) и на векторных запросах (если managed).

Архитектура: каскад

  1. Пришёл запрос. Считаем хэш точного промпта → Redis lookup. Hit — отдаём.
  2. Miss → embed запроса. Semantic cache lookup (cosine > порог). Hit — отдаём с поверхностной валидацией.
  3. Miss → запрос в LLM с нативным prompt cache. Получаем ответ, пишем в exact + semantic cache.

На входе бесплатный exact, потом эмбеддинг (дешёвый), и только если оба промахнулись — LLM.

Что не кэшировать

  • Запросы с временной чувствительностью («курс сегодня», «новости», «остатки»). Whitelist по типу intent.
  • Персонализированные ответы (рекомендации с user_id внутри генерации).
  • Транзакции (создание заказа, отправка письма) — там вообще нет смысла повторять.

Мониторинг

Минимум метрик: hit rate по каждому уровню, p50/p95/p99 латентности с кэшем и без, доля кэш-ответов в обращениях с пометкой «бесполезно» от пользователя. Без этого экономия превращается в потерю качества, которая всплывёт через месяц по падению NPS.

Итог: типовой стек — exact + native prompt cache закрывают 60–80% экономии без рисков. Семантический кэш даёт +20%, но требует тестирования и валидации. На очень большом масштабе все четыре уровня окупаются за пару недель.