Кэширование промптов

Если в каждом запросе повторяется большой одинаковый кусок контекста — за него можно платить почти даром.

Кэширование промптов — механизм, при котором повторяющийся префикс запроса (инструкции, документ, примеры) сохраняется на стороне провайдера, и при следующих запросах за него берут малую долю цены.

Когда это выгодно

Типичный случай: большой системный промпт или документ, одинаковый для тысяч запросов, и лишь короткий вопрос в конце меняется. Без кэша вы платите полную цену за весь префикс каждый раз. С кэшем первый запрос «записывает» префикс (чуть дороже обычного), а последующие «читают» его за ~10% цены.

Главное правило: точное совпадение префикса

Кэш работает по совпадению начала запроса байт в байт. Любое изменение в префиксе (вставили дату, поменяли порядок) — и кэш сбрасывается. Поэтому стабильное (документ, инструкции) ставят в начало, а изменчивое (вопрос, метка времени) — в конец.

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=512,
    system=[{
        "type": "text",
        "text": БОЛЬШОЙ_ДОКУМЕНТ,            # стабильный префикс
        "cache_control": {"type": "ephemeral"}  # пометка кэшировать
    }],
    messages=[{"role": "user", "content": "Короткий вопрос"}],  # изменчивая часть
)
# Проверяем, сработал ли кэш:
print(response.usage.cache_read_input_tokens)   # > 0 если читали из кэша

Экономика кэша

Чтение из кэша ~0,1× цены входа, запись ~1,25×. То есть кэш окупается уже со второго-третьего запроса с тем же префиксом. На больших общих контекстах экономия достигает порядка 90%.

Расчёт экономии (запускаемо)

Сравним стоимость 1000 запросов с одним большим общим префиксом — без кэша и с кэшем. Чистый Python:

base_in = 5.0  # $/1M входных токенов

def per_request(cached_prefix, fresh_tokens, first=False):
    if first:
        prefix_cost = cached_prefix / 1_000_000 * base_in * 1.25  # запись
    else:
        prefix_cost = cached_prefix / 1_000_000 * base_in * 0.1   # чтение
    fresh_cost = fresh_tokens / 1_000_000 * base_in
    return prefix_cost + fresh_cost

prefix = 20_000   # большой общий контекст
fresh = 200       # короткий вопрос

no_cache = (prefix + fresh) / 1_000_000 * base_in
print(f"Без кэша, 1 запрос:        ${no_cache:.5f}")
print(f"С кэшем, первый запрос:    ${per_request(prefix, fresh, first=True):.5f}")
print(f"С кэшем, последующий:      ${per_request(prefix, fresh):.5f}")

total_nocache = no_cache * 1000
total_cache = per_request(prefix, fresh, first=True) + per_request(prefix, fresh) * 999
print(f"1000 запросов без кэша:    ${total_nocache:.2f}")
print(f"1000 запросов с кэшем:     ${total_cache:.2f}")

Вывод:

Без кэша, 1 запрос:        $0.10100
С кэшем, первый запрос:    $0.12600
С кэшем, последующий:      $0.01100
1000 запросов без кэша:    $101.00
1000 запросов с кэшем:     $11.12

Частые ошибки

  • Вставка datetime.now() или случайного id в начало промпта — кэш не срабатывает никогда.
  • Слишком короткий префикс — есть минимальный порог в токенах, ниже него кэш молча не работает.
  • Не проверяют cache_read_input_tokens — и не замечают, что кэш не сработал.

Итог

  • Кэш переиспользует стабильный префикс за ~10% цены — экономия до ~90%.
  • Работает по точному совпадению начала запроса: стабильное — в начало, изменчивое — в конец.
  • Проверяйте cache_read_input_tokens, чтобы убедиться, что кэш сработал.
Проверьте себя
1. На чём основан механизм кэширования промптов?
AНа случайном выборе запросов
BНа точном совпадении префикса (начала) запроса; стабильное ставят в начало, изменчивое — в конец
CНа температуре генерации
DНа числе инструментов
2. Что сломает кэширование, если поместить это в начало промпта?
AДлинный документ
Bdatetime.now() или случайный идентификатор — префикс меняется каждый раз
CСистемную инструкцию
DСписок инструментов
3. Как примерно соотносятся цены чтения и записи кэша с обычным входом?
AЧтение дороже записи в 10 раз
BЧтение ~0,1× цены входа, запись ~1,25×, поэтому кэш окупается за 2–3 запроса
CИ чтение, и запись бесплатны
DЧтение и запись стоят как обычный вход
Поддержать проект