Кэширование промпта Prompt Caching
Если в запросах повторяется длинный стабильный префикс (системный промпт, длинный документ, few-shot примеры, история диалога), кэширование позволяет тарифицировать попавшую в кэш часть примерно в 10 раз дешевле и отвечать быстрее. Реализация различается у провайдеров.
Сравнение провайдеров
| OpenAI | Claude | Gemini | |
|---|---|---|---|
| Триггер | автоматически | ручная метка cache_control | неявно (best-effort) |
| Плата за запись | нет (0×) | 1.25× (5 мин) / 2× (1 ч) | нет |
| Чтение из кэша | 0.1× | 0.1× | скидка (до −90%) |
| Мин. префикс | 1024 | 1024–4096 | 4096 (сер. 3) / 2048 (сер. 2.5) |
| Поле попадания | cached_tokens | cache_read_input_tokens | cached_content_token_count |
| Гарантия | детерминированно | детерминированно | не гарантировано |
OpenAI — полностью автоматически
Никаких меток. Если начало запроса (префикс) совпадает с недавним и не короче 1024 токенов — сервер сам переиспользует кэш: попавшая часть тарифицируется по 0.1×, задержка падает до −80%. Записи в кэш бесплатна, поэтому окупаемость наступает уже со 2-го запроса.
- Длина попадания растёт ступенями по 128 токенов (1024, 1152, 1280…), поэтому
cached_tokensобычно чуть меньше полной длины префикса — это нормально. - Попадание видно в
usage.prompt_tokens_details.cached_tokens.
{
"usage": {
"prompt_tokens": 2048,
"prompt_tokens_details": { "cached_tokens": 1920 }
}
}
Claude — ручная метка
Кэширование только в нативном формате /v1/messages. Нужна явная
метка cache_control на кэшируемом блоке (чистая строка не кэшируется), длина не ниже
порога модели, и побайтово одинаковый префикс. Множители: запись 1.25× (TTL 5 мин) или 2× (1 ч),
чтение 0.1×. Полный разбор условий, лимита из 4 точек и полей usage —
на странице Claude.
"content": [
{"type": "text", "text": LONG_STABLE_TEXT, "cache_control": {"type": "ephemeral"}},
{"type": "text", "text": question}
]
Gemini — неявное
Включено автоматически, без меток: при совпадении достаточно длинного префикса попавшая часть
идёт со скидкой, поле cached_content_token_count возвращается как есть. Но порог
высокий (4096 токенов для серии 3) и попадание не гарантировано. Явный
серверный кэш cachedContents на этом канале не поддерживается. Подробнее —
на странице Gemini.
Общее правило: стабильное — в начало
Кэш у всех работает по префиксу: сравнение идёт с первого символа до первого отличия. Любая динамика в начале (таймстамп, имя пользователя, порядок полей JSON) ломает попадание для всего, что идёт дальше. Кладите неизменное (системный промпт, документ) в начало, а изменяемое (вопрос пользователя) — в конец.
# ✗ динамика в начале — префикс меняется каждый раз, попадания не будет [{"role": "system", "content": f"Сейчас {now}. " + INSTRUCTIONS}, ...] # ✓ стабильная инструкция в начале, переменное — отдельным сообщением в конце [{"role": "system", "content": INSTRUCTIONS}, {"role": "user", "content": question}]