Кэширование ответов LLM — как срезать счёт за API вдвое
В типовом продакшен-LLM 40–60% запросов повторяются дословно или семантически. Разбираем 4 уровня кэша: exact, prompt cache, семантический, на retrieve — и где какие риски.
В типовом продакшен-LLM-сервисе (саппорт-бот, FAQ-поиск, ассистент в админке) 40–60% запросов повторяются дословно или семантически близки. Платить за них $0.005 за тысячу токенов каждый раз — деньги в трубу. Разбираем четыре уровня кэша от простого к рискованному: exact, prompt cache, семантический, кэш на retrieve. Каждый срезает свой кусок счёта, у каждого свои подводные камни.
Уровень 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).
Архитектура: каскад
- Пришёл запрос. Считаем хэш точного промпта → Redis lookup. Hit — отдаём.
- Miss → embed запроса. Semantic cache lookup (cosine > порог). Hit — отдаём с поверхностной валидацией.
- 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%, но требует тестирования и валидации. На очень большом масштабе все четыре уровня окупаются за пару недель.