Перейти к содержимому
EN

Кэширование контекста

Агентная сессия — Claude Code над репозиторием, длинный диалог, конвейер с одним и тем же системным промптом — с каждым ходом отправляет модели всё тот же контекст: системный промпт, описания инструментов, накопленную историю. Кэширование контекста (prompt caching) держит этот повторяющийся префикс на стороне модели: повторная часть читается из кэша по сниженной цене вместо полной оплаты входа.

На длинных сессиях это основная статья экономии: чтение из кэша у большинства моделей стоит около 10% цены входа. С записью всё не так однозначно — она зависит от вендора, подробности ниже.

Кэш живёт 5 минут со скользящим продлением: каждое попадание сбрасывает таймер. В плотной сессии, где ходы идут без пауз, кэш доживает от начала до конца. После перерыва дольше 5 минут кэш протухает — первый ход платит полную цену входа плюс надбавку за запись, дальше кэш работает снова. Это нормально и не требует никаких действий.

Чтение кэша — примерно 10% цены входа. Это правило держится у Anthropic, OpenAI и Google: у Claude Sonnet 5 ровно десятая часть, у GPT-6 Astra и Gemini 3.8 Flash — тоже.

Запись кэша зависит от вендора, и интуиция здесь подводит:

Вендор Чтение Запись
Anthropic, OpenAI 10% цены входа 125% — дороже обычного входного токена
Google 10% цены входа ~6% — дешевле, чем чтение

У Anthropic и OpenAI первый ход платит надбавку, а окупается со второго. У Google запись почти ничего не стоит, и кэш выгоден сразу.

У моделей с открытыми весами ставка зависит не от модели, а от того, кто её хостит: у GLM 5.3 разные провайдеры берут за чтение кэша от 0.1 до 0.26 $ за 1 млн токенов при почти одинаковой цене входа — разница в 2.6 раза, — а записи не публикует ни один из них. Цены по каждому провайдеру видны в блоке «Провайдеры и цены» на странице модели в каталоге, выбрать конкретного — параметрами из гайда Выбор провайдера.

Цену для маршрута по умолчанию показывают колонки «Чтение кэша» и «Запись кэша» в каталоге; в API это pricing.cache_read_rub и pricing.cache_write_rub из GET /v1/models. Прочерк означает, что кэш-цена не публикуется, — это не ноль и не «бесплатно».

Клиент Как включается кэш
Веб-чат и Telegram-бот Mixen Автоматически: кэш-маркер на промпте сессии ставится сам, делать ничего не нужно
POST /v1/messages Клиент расставляет брейкпоинты cache_control — на системном промпте, инструментах, сообщениях (Claude Code и Anthropic SDK делают это сами)
POST /v1/chat/completions, POST /v1/responses Управляющих параметров нет: кэш срабатывает автоматически на повторяющемся префиксе запроса

В /v1/messages брейкпоинт — объект {"type": "ephemeral"} на нужном элементе. Кэшируется всё, что стоит до маркера, поэтому его ставят в конец стабильной части — после системного промпта и инструментов, перед меняющимся хвостом:

{
"model": "anthropic/claude-sonnet-5",
"max_tokens": 1024,
"system": [
{
"type": "text",
"text": "Ты — ассистент техподдержки. Правила и база знаний: ...",
"cache_control": {"type": "ephemeral"}
}
],
"messages": [{"role": "user", "content": "Привет!"}]
}

Сколько входа пришло из кэша, видно в usage ответа. Поля у протоколов разные, и семантика тоже — это разница форматов OpenAI и Anthropic, а не особенность Mixen:

Протокол Где смотреть кэш Вход в usage
/v1/chat/completions usage.prompt_tokens_details.cached_tokens prompt_tokens уже включает кэш
/v1/responses usage.input_tokens_details.cached_tokens input_tokens уже включает кэш
/v1/messages usage.cache_read_input_tokens input_tokens — только НЕкэшированный остаток; полный вход = input_tokens + cache_read_input_tokens

Один и тот же запрос — 3 660 токенов контекста, из них 3 644 из кэша — в трёх протоколах:

/v1/chat/completions
{
"prompt_tokens": 3660,
"completion_tokens": 120,
"total_tokens": 3780,
"prompt_tokens_details": {"cached_tokens": 3644}
}
/v1/responses
{
"input_tokens": 3660,
"output_tokens": 120,
"total_tokens": 3780,
"input_tokens_details": {"cached_tokens": 3644},
"output_tokens_details": {"reasoning_tokens": 0}
}
/v1/messages
{
"input_tokens": 16,
"output_tokens": 120,
"cache_read_input_tokens": 3644,
"cache_creation_input_tokens": 0
}

cache_creation_input_tokens в /v1/messages всегда 0: апстрим сообщает только объём чтения, объём записи не отдаёт. На цену это не влияет — надбавка за запись уже учтена в стоимости запроса, — но в клиентской статистике «записано в кэш» будет пусто.

Складывайте поля входа один раз и по семантике протокола: сложение prompt_tokens с cached_tokens в OpenAI-формате посчитает кэш дважды.

  • Держите префикс стабильным. Попадание требует точного совпадения префикса: системный промпт и описания инструментов должны идти в одном порядке и не меняться от запроса к запросу. Правка первой строки промпта или перестановка блоков обнуляет попадание.
  • Ставьте брейкпоинт после стабильной части. В /v1/messages кэшируется всё до маркера: системный промпт, инструменты, начало истории. Часто меняющийся хвост оставляйте после него.
  • Гоняйте сессию плотно. Ходы без пауз дольше 5 минут держат кэш живым за счёт скользящего продления. Каждый перерыв сверх TTL — это снова полная цена входа плюс запись.

Прикидка на витринных ценах Claude Sonnet 5 (за 1 млн токенов): вход 213.90 ₽, выход 1 069.50 ₽, чтение кэша 21.40 ₽, запись кэша 267.40 ₽. Живые значения берите из GET /v1/models — витринные цены обновляются.

Сценарий: системный промпт с инструментами — 10 000 токенов и не меняется; каждый ход добавляет 2 000 токенов контекста и 1 000 токенов ответа. Ход 1 записывает контекст в кэш; ходы 2–10 читают накопленный префикс из кэша — 10 000 + 2 000 × (k−1) токенов за ход k, в сумме 180 000; новые 2 000 токенов каждого хода идут по полной цене входа.

Статья Токены ₽ за 1 млн Сумма
Запись кэша (ход 1) 10 000 267.40 ≈ 2.67 ₽
Чтение кэша (ходы 2–10) 180 000 21.40 ≈ 3.85 ₽
Новые токены входа (по 2 000 на ход) 20 000 213.90 ≈ 4.28 ₽
Выход (по 1 000 на ход) 10 000 1 069.50 ≈ 10.70 ₽
Итого с кэшем ≈ 21.5 ₽

Без кэша те же 10 ходов — это 210 000 токенов входа ≈ 44.92 ₽ плюс те же ≈ 10.70 ₽ выхода, итого ≈ 55.6 ₽. Кэш экономит ≈ 34 ₽, около 60%, — и чем длиннее сессия, тем большую долю контекста забирает кэш: постоянная часть оплачивается один раз, а читается на каждом ходу.