Главная / Статьи / Минус 90% к стоимости повторяющихся промптов одной строкой кэширования

Минус 90% к стоимости повторяющихся промптов одной строкой кэширования

Как включить автоматическое кэширование промптов одним полем, проверить попадания в блоке usage и не попасть в ловушки с префиксом и минимальной длиной, которые незаметно съедают экономию.

914 слов

Снова платим за текст, который не меняется

Где-то в вашем коде лежит кусок текста, за который вы заплатили десять тысяч раз, хотя он ни разу не изменился. Откройте панель использования и сравните вчерашние входные токены с числом запросов. Если соотношение близко к размеру вашего системного промпта, это про вас. Вы платили полную цену за то, чтобы снова и снова отправлять одну и ту же стену инструкций, а модель каждый раз читала её с нуля, будто видит вас впервые.

Возьмём бота поддержки, у которого в системном промпте около 9000 токенов документов с правилами, и примерно 40 000 вызовов в месяц. Каждый вызов тащил весь этот блок по сети. Исправление занимает одну строку. Но есть и ловушка, из-за которой эта строка ничего не даёт, о ней ниже, и именно на ней большинство теряет экономию, которую, как им кажется, они включили.

На сервере ничто не помнит ваш контекст

Messages API не хранит состояние. Нигде не висит сессия, которая держала бы ваш промпт наготове между вызовами. Каждый запрос собирает промпт заново, токенизирует его, прогоняет через модель и выбрасывает результат. Следующий вызов повторяет ту же работу по той же цене.

without caching

call 1   [ 9,000 tok system ][ 40 tok question ]   full price
  call 2   [ 9,000 tok system ][ 35 tok question ]   full price
  call 3   [ 9,000 tok system ][ 52 tok question ]   full price
            ^^^^^^^^^^^^^^^^^
            same bytes, billed three times

Изменение в одну строку

Вот как этот вызов пишет большинство:

resp = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,
    system=DOCS,
    messages=[{"role": "user", "content": q}],
)

А вот всё исправление — одно дополнительное поле над system:

cache_control={"type": "ephemeral"},

Это поле верхнего уровня включает автоматическое кэширование. API ставит точку разрыва на последний кэшируемый блок и сдвигает её вперёд по мере роста диалога.

Проверьте блок usage

Не верьте ощущению, что стало быстрее. Смотрите данные об использовании, которые API возвращает с каждым ответом:

creation    read    input
  call 1  cold          9012       0       40
  call 2  warm             0    9012       35

Вся суть во второй строке. Девять тысяч токенов отданы из кэша за десятую часть цены, а input_tokens сократились до части после точки разрыва.

Ловушка

Поставьте в начало системного промпта метку времени, имя пользователя или текущую дату, потому что это казалось безобидным, и префикс будет меняться в каждом запросе. Хэш никогда не совпадёт, вы будете бесконечно платить надбавку за запись и не получите ни одного чтения. Это хуже, чем ничего не делать.

Для API важен фиксированный порядок. Стабильное содержимое идёт первым, всё изменчивое — последним:

tools  ->  system  ->  messages

[ stable stuff ----------------- | volatile ]
                                    ^
                               breakpoint lives here

Когда чтений из кэша нет

Есть минимальная длина, и если до неё не дотянуть, вам никто об этом не скажет. Минимум — 512 токенов для Opus 5, 1024 для Sonnet 5 и 4096 для Haiku 4.5. Ниже кэширования нет, ошибки тоже нет, есть только счёт, которого вы пытались избежать.

Кэш живёт 5 минут и бесплатно продлевается при каждом попадании, так что ровный трафик сам держит его тёплым. Если вызовы идут реже, запросите TTL на час. И помните, что совпадение проверяется до байта: один лишний пробел, переставленное определение инструмента или изменённая настройка возвращают вас к полной цене без всякого предупреждения.

Дальше одной строки

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

В циклах агентов эффект накапливается. Задача с десятью вызовами инструментов читает один и тот же префикс десять раз, так что к последнему проходу кэширование уже не немного экономит, а делает фичу вообще по карману.