AI-инжиниринг
Кеширование LLM: semantic cache, prompt cache, KV cache - экономим x10
Цели урока
- Реализовать exact match cache для LLM-ответов в Redis с нормализацией ключей
- Построить semantic cache на основе embeddings с настраиваемым similarity threshold
- Использовать prompt caching API (OpenAI, Anthropic) для экономии на длинных контекстах
- Понять работу KV cache в трансформере и его влияние на стоимость и латентность
- Собрать многоуровневый caching service в NestJS с метриками эффективности
Anthropic prompt caching снижает стоимость повторяющегося контекста на 90%. Один system prompt на 10K токенов, 1M запросов в день - разница USD 180K vs USD 18K в месяц. Это не оптимизация последнего шага - это архитектурное решение, которое принимается в начале проектирования продукта. Без кеша продукт с большим контекстом нежизнеспособен экономически. С кешем - тот же продукт прибылен.
- GPTCache от Zilliz - open-source semantic caching, 7000+ GitHub stars; используется в корпоративных RAG-системах для снижения стоимости на 40-60%
- Anthropic prompt caching даёт 90% скидку - критично для приложений типа "чат с документом" на 200K токенов: USD 0.60 vs USD 0.06 за запрос
- OpenAI prompt caching: автоматически для GPT-4o при prefix 1024+ токенов, 50% скидка - без единой строки кода со стороны разработчика
- Redis Labs фиксирует: 40% enterprise AI-проектов используют Redis как кеш для LLM-ответов; exact match cache - самый быстрый ROI при внедрении
Как кэширование пришло в мир LLM
Кэширование - старая идея, но в применении к LLM оно появилось недавно. **GPTCache (Zilliz, 2023)** популяризировал semantic caching: вместо побайтового сравнения запросов он сопоставляет смысл через embeddings, поэтому перефразированные вопросы могут переиспользовать сохранённый ответ. Затем провайдеры встроили кэширование прямо в API. **Anthropic представила prompt caching (август 2024)**, позволив кэшировать большой повторяющийся контекст и оплачивать его малой долей стоимости. **OpenAI добавила prompt caching (октябрь 2024)**. За считанные месяцы кэширование превратилось из остроумного дополнения в стандартный рычаг экономии для любого продукта с большими промптами.
Предварительные знания
Exact Match Cache: простейший и самый надёжный кеш
Январь 2024. Стартап с AI-чатботом для поддержки получает счёт от OpenAI: USD 47,000 за месяц. Анализ логов показывает - **63% запросов были дублями**. Одни и те же вопросы про доставку, возврат, статус заказа. Каждый запрос тратил ~800 токенов, хотя ответ уже был получен минуту назад. Три часа работы инженера. Счёт следующего месяца: USD 16,000.
Exact match cache - это Redis хеш от нормализованного промпта, который отвечает за 5 миллисекунд вместо 800. Ключ кеша: SHA-256 от messages + model + temperature + system prompt. Правило одно - кешировать только при temperature = 0, где ответ детерминирован.
Подводный камень exact match: «Какая погода в Москве?» и «какая погода в москве?» - два разных ключа. Минимальное отличие в тексте - cache miss. Решение: нормализация до хеширования.
| Метрика | Без кеша | С exact match cache |
|---|---|---|
| Средняя латентность | 800-2000ms | 5-15ms (cache hit) |
| Стоимость /1M запросов (GPT-4o) | $~15,000 | $~5,500 (при 63% hit rate) |
| Нагрузка на API | 100% | ~37% |
| Консистентность ответов | Varies | 100% для cached |
Почему exact match cache не стоит применять при temperature > 0?
Semantic Cache: кеширование по смыслу через embeddings
«Как отменить заказ?», «Хочу отменить покупку», «Где кнопка отмены?» - три разных строки, один intent, три промаха exact match cache. Semantic cache решает это через embeddings: вместо хеша строки вычисляется вектор запроса в 1536 измерениях, и кеш считается hit, если cosine similarity с существующим запросом превышает порог 0.95-0.97.
GPTCache от Zilliz - самая популярная open-source реализация, 7000+ звёзд на GitHub. Принцип внутри: `text-embedding-3-small` (USD 0.02 за 1M токенов) генерирует вектор, который сравнивается с существующими через ANN-поиск в Qdrant или pgvector. Стоимость embedding на три порядка ниже GPT-4o (USD 2.50/USD 10.00 per 1M) - экономия есть даже с учётом overhead.
**Production-версия semantic cache использует vector database (Qdrant, Pinecone, pgvector), а не перебор всех ключей Redis.** Пример выше демонстрирует принцип. При 10,000+ записях линейный поиск станет bottleneck - vector DB обеспечивает O(log n) поиск через ANN-алгоритмы (HNSW).
Критический параметр - **similarity threshold**. При 0.99 кеш срабатывает только для почти идентичных запросов. При 0.90 - слишком широкая сеть, ложные совпадения. Оптимум 0.95-0.97 ловит перефразирования и синонимы, но отсекает семантически разные запросы.
| Threshold | Hit Rate | Точность | Пример |
|---|---|---|---|
| 0.98-0.99 | Низкий (~10%) | Очень высокая | Ловит только перефразирования с минимальными отличиями |
| 0.95-0.97 | Средний (~35%) | Высокая | Ловит перефразирования и синонимы - рекомендуемый старт |
| 0.90-0.94 | Высокий (~55%) | Средняя | Может вернуть ответ на похожий, но не идентичный вопрос |
| < 0.90 | Очень высокий | Низкая | Высокий риск ложных совпадений - не рекомендуется |
Какой similarity threshold рекомендуется для старта semantic cache в production?
Prompt Caching: OpenAI и Anthropic кешируют system prompt
Anthropic prompt caching - это 90% скидка на повторяющийся контекст. Конкретно: system prompt на 10K токенов, 1M запросов в день. Без кеша: USD 30 * 1M / 1M = USD 30,000 в день, USD 900K в месяц. С кешем: USD 3,000 в день, USD 90K в месяц. Разница не в деталях - это решение о жизни продукта.
Механизм: если начало промпта (prefix) совпадает с ранее отправленным запросом, провайдер переиспользует внутренние вычисления. OpenAI - автоматически для GPT-4o (50% скидка). Anthropic - явно через `cache_control` (90% скидка). Google Gemini - явно через `cachedContent` (75% скидка, до 1 часа TTL).
| Провайдер | Механизм | Скидка | Минимум токенов | TTL кеша |
|---|---|---|---|---|
| OpenAI | Автоматический | 50% на cached tokens | 1024 токенов prefix | 5-10 минут |
| Anthropic | Явный (cache_control) | 90% на cached tokens | 1024 (Sonnet) / 2048 (Haiku) | 5 минут |
| Google (Gemini) | Явный (cachedContent) | 75% на cached tokens | 32,768 токенов | До 1 часа |
Архитектурное правило: **статичный контент - в начало промпта**. System prompt, RAG-контекст, few-shot примеры идут первыми. Динамическая часть (вопрос пользователя) - в конце. Кеш работает по prefix match - чем длиннее совпадающий prefix, тем больше токенов захватывает скидка.
**Prompt cache не гарантирует hit.** Кеш может быть вытеснен при высокой нагрузке на провайдера. Не строить бюджет из расчёта 100% cache hit rate - закладывать 50-70% в зависимости от паттернов использования.
Как правильно структурировать промпт для максимальной эффективности prompt caching?
KV Cache: внутренняя оптимизация трансформера
Prompt cache на уровне API даёт 90% скидку. Откуда берётся эта экономия? Ответ внутри GPU провайдера - это KV Cache. При генерации каждого нового токена трансформер пересчитывает attention для всей предыдущей последовательности. Без KV cache: O(n²) операций. С KV cache: O(n), потому что Key и Value матрицы для уже обработанных токенов сохраняются и переиспользуются.
KV cache поедает **GPU память**. Для модели класса GPT-4: ~1-2 MB на токен контекста. При context window 128K токенов - до 256 GB видеопамяти только на кеш. Поэтому провайдеры берут больше за длинные промпты и ограничивают context window - GPU память является физическим bottleneck, не маркетинговым решением.
| Аспект | KV Cache | Prompt Cache (API) | Semantic Cache (приложение) |
|---|---|---|---|
| Уровень | Внутри модели (GPU) | На стороне провайдера | На стороне приложения |
| Контроль разработчика | Нет (автоматически) | Частичный (структура промпта) | Полный |
| Что кешируется | Key-Value матрицы attention | Промежуточные вычисления prefix | Готовые ответы LLM |
| Влияние на стоимость | Косвенное (context window) | Скидка 50-90% | 100% (вызов не выполняется) |
| Влияние на латентность | Ускорение генерации 10-15x | Снижение TTFB на 50%+ | Ответ за ~5ms |
Для разработчика, работающего с API, KV cache - фоновый механизм. Но понимание его работы объясняет сразу три вещи: почему длинные промпты стоят дороже, почему TTFB растёт с длиной контекста, и откуда берётся 90%-ная скидка Anthropic - провайдер экономит GPU-ресурсы на повторном построении KV cache.
Какую проблему решает KV cache в трансформере?
Production: NestJS сервис с многоуровневым кешированием
В production работает **многоуровневый кеш**: exact match → semantic cache → prompt caching API → вызов LLM. Каждый уровень отсекает свою долю запросов. До реального вызова API доходят только уникальные запросы, которых система ещё не видела. Суммарная экономия при хорошем hit rate - 50-80% от бюджета на LLM API.
Итоговая архитектура: **три уровня кеша**, каждый со своей стратегией. Exact match (Redis, ~5ms) ловит повторные запросы. Semantic cache (vector DB, ~50ms) ловит перефразирования. Prompt caching (API провайдера, ~200ms vs ~800ms) снижает стоимость длинных контекстов. В совокупности - экономия 50-80% бюджета на LLM API.
В какой последовательности система проверяет кеши для максимальной эффективности?
Кешировать LLM-ответы опасно - данные устареют, пользователь получит неактуальный ответ
Для стабильных запросов (FAQ, документация, классификация) кеш безопасен и необходим. TTL управляет актуальностью
Кеширование опасно для запросов, зависящих от текущего времени («что сейчас стоит доллар?») или персонального контекста. Но FAQ о возврате товара не меняется каждый час. Документация API - неделями. Классификация тикетов по теме - месяцами. Для этих паттернов кеш с TTL 1-24 часа абсолютно безопасен. Ключевой вопрос не «кешировать или нет», а «какой TTL для этого типа запроса».
Prompt caching провайдера заменяет application-level кеш - достаточно одного из них
Это разные уровни: prompt caching снижает стоимость вызова API, application cache устраняет вызов совсем. Оба нужны
Prompt caching (OpenAI/Anthropic) работает внутри одного API-вызова - он снижает стоимость, но вызов всё равно происходит (~200-800ms). Application-level кеш (Redis exact + semantic) возвращает ответ за ~5ms без вызова API вообще. Полная архитектура использует оба: application cache срезает 60-70% запросов, prompt cache снижает стоимость оставшихся.
Стратегии кеширования LLM
- Exact match cache: Redis + SHA-256 от нормализованного промпта. Работает при temperature = 0. Ответ за ~5ms. Самый быстрый ROI
- Semantic cache: text-embedding-3-small (1536 dim) + cosine similarity 0.95-0.97. Ловит перефразирования. Qdrant/pgvector в production
- Prompt caching API: OpenAI -50% автоматически (1024+ токен prefix), Anthropic -90% явно через cache_control. Статичный контент - в начало промпта
- KV cache: внутренняя GPU-оптимизация трансформера, O(n²) → O(n). Объясняет стоимость длинных контекстов и скидки провайдеров
- Многоуровневый NestJS сервис: exact → semantic → API prompt cache → полный вызов. Суммарная экономия 50-80% бюджета
Что дальше
Кеширование - первый уровень оптимизации расходов на LLM. Следующий шаг - комплексное управление стоимостью: от подсчёта токенов до выбора модели под задачу.
- Cost Management — Кеширование снижает количество вызовов, cost management оптимизирует стоимость каждого вызова
- Rate Limiting для AI API — Rate limiting защищает от перерасхода бюджета и превышения квот провайдера
- Observability — Метрики кеша (hit rate, tokens saved) - часть observability pipeline
Связанные уроки
- aie-09-embeddings — Ключи семантического кэша строятся из embeddings
- aie-29-cost-management — Кэширование напрямую режет стоимость запроса
- aie-30-rate-limiting-ai — Попадания в кэш снижают давление на лимиты
- aie-35-observability — Отслеживаем hit rate, чтобы оценить пользу кэша
- sd-07-caching — Та же слоистость кэша, что и в system design
- db-26-caching