中文翻译暂不可用,显示俄语原文。

Как работает prefix caching и prompt caching у провайдеров?

Краткий тезис

caching|Prefix caching (caching|внутренний кэш KV в инференс-движках vLLM, TGI) и prompt caching (продуктовый кэш KV у провайдеров вроде Anthropic, OpenAI, Gemini) — это техники ускорения генерации и снижения стоимости за счёт повторного использования вычисленных ключей и значений внимания (KV-кэш) для повторяющихся префиксов промпта. Принцип одинаков: если часть промпта (например, system prompt, few-shot примеры) встречается многократно, её KV-кэш сохраняется и переиспользуется для новых запросов, экономя до 90% времени и затрат. Различия — в уровне доступа, времени жизни кэша и API-интерфейсе.


1. Проблема: почему генерация LLM дорогая и медленная?

В основе современных LLM лежит трансформер с механизмом self-attention. При генерации каждого токена модель вычисляет запросы (Q), ключи (K) и значения (V) для всех предыдущих токенов последовательности. Эти вычисления доминируют в задержке (latency) и стоимости (FLOPs, память).

KV-кэш — это матрицы ключей и значений, которые сохраняются в памяти после первого прохода для каждого слоя и головы внимания. При генерации очередного токена модель вычисляет только его Q, а K и V для предыдущих токенов берёт из кэша. Это превращает O(n²) сложность в O(n) на шаг декодирования, но требует памяти ~ O(n) на последовательность.

На практике при работе с длинными системными промптами или однотипными префиксами (сотни/тысячи запросов с одинаковым контекстом) модель тратит ресурсы на пересчёт KV для одного и того же текста снова и снова.

Два подхода к решению:

  • Prefix caching — кэширование KV для идентичных начальных сегментов промпта внутри одного инференс-движка (vLLM, TGI). Прозрачно для пользователя, автоматически.
  • Prompt caching — кэширование KV на стороне API провайдера, которое пользователь может явно запросить через специальные параметры или заголовки (Anthropic, OpenAI). Часто связано с отдельным биллингом.

2. Как работает KV-кэш в трансформерах (напоминание)

Для понимания кэширования важно вспомнить, как устроен decoder-only transformer (GPT-family, LLaMA).

  1. Промпт преобразуется в последовательность токенов.
  2. На каждом слое self-attention вычисляются:
  3. Для каждого токена получаются векторы ключей и значений. Для последовательности длины L — матрицы K (L × d_k) и V (L × d_v).
  4. При генерации первого нового токена (prefill-фаза) вычисляются все K и V за один проход. Затем они сохраняются в KV-кэш.
  5. При генерации каждого последующего токена (decode-фаза) вычисляются только его K и V, которые добавляются в кэш.

Основная идея кэширования префиксов: если новый промпт начинается с той же последовательности токенов, что и предыдущий (например, одинаковый system prompt), то KV для этого префикса можно взять из кэша, не пересчитывая. Это ускоряет prefill-фазу (которая обычно самая долгая для длинных промптов) и экономит вычислительные ресурсы.


3. Prefix caching (vLLM / TGI / TensorRT-LLM)

Prefix caching — это техника, встроенная в инференс-движки (сервера), которые обслуживают множество запросов. Движок вычисляет хэш от префикса промпта (обычно первые N токенов) и сохраняет соответствующий KV-кэш в оперативной памяти (или на GPU). Когда поступает запрос с таким же префиксом, движок находит кэш и дополняет его новыми токенами запроса.

Как реализовано в vLLM:

  • vLLM использует механизм prefix caching (раньше назывался Prefix Caching with PrefixPool).
  • Каждый блок KV-кэша идентифицируется хэшем последовательности токенов.
  • При запросе vLLM разбивает промпт на блоки (обычно фиксированного размера, например, 16 токенов) и для каждого блока проверяет наличие в глобальном кэше.
  • Если блок уже закэширован, vLLM не вычисляет для него KV, а просто ссылается на существующий кэш. Для блоков, которых нет — вычисляет и добавляет.
  • Кэш вытесняется по LRU (Least Recently Used) при нехватке памяти.

Преимущества prefix caching:

  • Прозрачность: пользователь ничего не указывает.
  • Экономия памяти GPU (за счёт повторного использования).
  • Ускорение prefill-фазы для повторяющихся префиксов.

Ограничения:

  • Требует, чтобы префиксы были строго идентичны на уровне токенов (включая пробелы, знаки препинания). Небольшое отличие (например, точка с запятой вместо точки) ломает кэш.
  • Кэш живёт в памяти движка, не сохраняется между перезапусками.
  • Не подходит для очень длинных префиксов, если не хватает GPU-памяти.

4. Prompt caching (Anthropic / OpenAI / Gemini)

Prompt caching — это функция API, которая позволяет пользователю явно указать, что часть промпта должна быть закэширована на стороне провайдера. Провайдер хранит KV-кэш для этих префиксов и переиспользует его при последующих запросах. Важное отличие от prefix caching: пользователь контролирует, что кэшировать, и платит за хранение кэша (обычно дешевле, чем полный пересчёт).

Anthropic (Claude):

  • Использует Prompt Caching для системного сообщения и начала сообщений пользователя.
  • Пользователь добавляет параметр cache_control: {"type": "ephemeral"} к сообщению или системному сообщению.
  • Anthropic вычисляет KV для этого блока и сохраняет его на определённое время (TTL, например, 5 минут с момента последнего использования).
  • Стоимость: закэшированный ввод (cached input) стоит примерно на 90% дешевле, чем полный ввод.
  • Пример (API):
    response = client.messages.create(
        system=[{"type": "text", "text": "Вы — эксперт. Отвечайте коротко.", "cache_control": {"type": "ephemeral"}}],
        messages=[{"role": "user", "content": "Напиши формулу воды."}],
        model="claude-3-5-sonnet-20241022"
    )
    

OpenAI (GPT-4, GPT-4o):

  • В марте 2025 OpenAI анонсировал Prompt Caching для некоторых моделей.
  • Пользователь задаёт параметр caching в запросе (или он включается автоматически для повторяющихся префиксов).
  • Детали: кэшируется весь префикс до первого пользовательского сообщения, если длина превышает порог (например, 1024 токена).
  • Стоимость: до 50% экономии на вводных токенах.

Google Gemini:

  • Имеет Context Caching, где пользователь загружает контекст (документ, системный промпт) и получает уникальный идентификатор кэша.
  • При повторных запросах можно передать этот ID, и модель будет использовать закэшированные KV.
  • Стоимость хранения кэша — почасовая.

Общий принцип работы prompt caching:

  1. Пользователь отправляет запрос с маркированным префиксом (или провайдер автоматически определяет повторение).
  2. Провайдер вычисляет KV для префикса и сохраняет в кластерной памяти с TTL.
  3. При последующих запросах с тем же префиксом провайдер использует сохранённый кэш, начисляя меньшую стоимость.
  4. Если кэш не был использован в течение TTL, он удаляется.

Когда prompt caching особенно выгоден:

  • System prompt длиной в тысячи токенов (например, ролевая настройка, инструкции для RAG).
  • Few-shot примеры — одинаковые пары вопрос-ответ повторяются во многих запросах.
  • Документы для RAG — если один и тот же документ подаётся в контекст многим пользователям (но осторожно с privacy).

5. Сравнение prefix caching (движок) vs prompt caching (API)

ХарактеристикаPrefix caching (vLLM, TGI)Prompt caching (Anthropic, OpenAI)
УровеньСервер инференса (on-premise или managed)API провайдера
ПрозрачностьАвтоматический, не требует изменений в кодеДолжен быть явно указан пользователем
КонтрольДвижок сам решает, что кэшировать (по хэшу)Пользователь выбирает блок для кэширования
Срок жизниПока есть память (LRU вытеснение)TTL (5-10 мин у Anthropic, платное хранение у Gemini)
ЭкономияУскорение инференса (latency снижается на prefill)Снижение стоимости API (до 90%)
ТребованияПрефикс точно совпадает по токенамПрефикс точно совпадает по токенам
ПоддержкаvLLM, TensorRT-LLM, TGIAnthropic Claude, OpenAI GPT-4o, Gemini
Пример тикетаМного однотипных запросов к одному движкуДлинный system prompt в SaaS-продукте

6. Требования и ограничения (важно на собеседовании)

  1. Идентичность префикса на уровне токенов: пробел, перенос строки, пунктуация — всё должно совпадать. Даже разница в токенизации разных моделей (например, Hello vs Hello ) ломает кэш.
  2. Порядок сообщений: в чат-моделях кэш учитывает всю историю сообщений, а не только текст. Если порядок ролей (system, user, assistant) различается, кэш не сработает.
  3. Длина префикса: для эффективности обычно нужен достаточно длинный префикс (сотни токенов). Слишком короткий — выгода минимальна.
  4. Безопасность: кэш может храниться в shared памяти. Провайдеры (Anthropic, OpenAI) заявляют, что изолируют кэши между клиентами, но для чувствительных данных стоит отключать.
  5. Совместимость с streaming: обычно кэш работает и для стриминга, так как KV общий.
  6. Fine-tuning и адаптеры: если модель дообучена или используется LoRA, кэш может быть невалиден из-за изменённых весов.

7. Практические соображения и best practices

  • Для RAG-систем: можно кэшировать system prompt (инструкции для агента) и часто используемые документы (например, описание схемы API). Но при замене документа нужно инвалидировать кэш.
  • Для чат-ботов: кэширование начального приветственного сообщения и системной инструкции снизит latency первого ответа.
  • В локальных инференсах: prefix caching в vLLM может значительно увеличить throughput при batch-обработке однотипных запросов (например, тестирование промптов).
  • Мониторинг: добавьте логирование, чтобы видеть, какие префиксы кэшируются и как часто hit.
  • Инвалидация: при изменении system prompt нужно либо подождать TTL, либо явно сбросить кэш (если API поддерживает).

Пример кода для vLLM (включение prefix caching):

from vllm import LLM, SamplingParams

# Запуск LLM с включенным prefix caching
llm = LLM(model="meta-llama/Llama-2-7b-hf", enable_prefix_caching=True)

# Первый запрос
output = llm.generate("System: Ты помощник.\nUser: Привет", sampling_params)

# Второй запрос с тем же префиксом — кэш сработает
output2 = llm.generate("System: Ты помощник.\nUser: Как дела?", sampling_params)

8. Пет-проект для закрепления

Задача: Создать систему, демонстрирующую экономию от prefix caching на локальном LLM (vLLM) и prompt caching через API Anthropic.

Инструменты: Python, vLLM, Anthropic API, time, psutil.

Шаги:

  1. Часть 1: vLLM:
    • Установите vLLM, запустите модель (например, Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4 для экономии памяти).
    • Сформируйте длинный system prompt (3000 токенов) и 10 разных пользовательских вопросов.
    • Измерьте время ответа с enable_prefix_caching=True и False (или без кэша).
    • Вычислите среднее ускорение.
  2. Часть 2: Anthropic Prompt Caching:
    • Зарегистрируйтесь в Anthropic, получите API-ключ.
    • Отправьте 5 запросов с одинаковым system prompt (длина > 1000 токенов) и разными сообщениями пользователя.
    • Для первых двух запросов не используйте caching, для следующих трёх — добавьте cache_control.
    • Сравните стоимость (из ответа API есть usage.cache_creation_input_tokens, usage.cache_read_input_tokens) и время ответа.

Ожидаемый результат:

  • В vLLM: ускорение prefill-фазы в 2–5 раз для повторяющихся префиксов.
  • В Anthropic: снижение стоимости в 5–10 раз (cached input) и уменьшение latency.

9. Связь с другими вопросами

ВопросТема
208KV-кэш и механизм внимания в трансформерах
219Оптимизация инференса LLM (quantization, speculative decoding)
840Как устроен RAG с длинным контекстом и как уменьшить задержки
841Streaming и буферизация токенов
843Batch-обработка запросов и throughput
844Continuous batching в LLM-движках

Навигация