Кэширование промптов и оптимизация затрат
Если многие из ваших запросов используют один и тот же большой неизменный фрагмент — длинный системный промпт, объёмный документ, каталог инструментов, — кэширование промптов позволяет API повторно использовать уже обработанный префикс вместо того, чтобы перечитывать его при каждом вызове. Это снижает как затраты, так и задержку на кэшированной части.
- Ментальная модель: точка разрыва кэша после стабильного префикса, переиспользуемого между вызовами
- Как пометить точку разрыва в Python и TypeScript с помощью cache_control
- Единственный инвариант, который всё решает, — префикс должен быть побайтово идентичным
- Как читать поля usage, чтобы убедиться, что вы действительно попадаете в кэш
- Где кэширование окупается больше всего и как сочетать его с пакетной обработкой и подбором размера модели
Как это работает (ментальная модель)
Вы помечаете точку разрыва кэша (cache breakpoint) после стабильного префикса. При первом вызове он обрабатывается и кэшируется; последующие вызовы, использующие тот же самый префикс, попадают в кэш и платят за него значительно меньше.
Пометьте точку разрыва (copy-paste)
Добавьте cache_control к последнему стабильному блоку — здесь это большой системный промпт. Реплика пользователя идёт после него и свободно меняется; кэшируется всё вплоть до помеченного блока включительно.
- Найдите большой неизменный фрагмент — длинный системный промпт, объёмный документ или каталог инструментов, переиспользуемый во многих запросах.
- Пометьте последний стабильный блок при помощи cache_control типа ephemeral, чтобы префикс вплоть до него включительно кэшировался.
- Разместите реплику пользователя после помеченного блока — она свободно меняется при каждом вызове и тарифицируется по полной цене.
- Прочитайте cache_read_input_tokens из поля usage в ответе. Значение больше нуля означает, что вы попали в кэш.
- Python
- TypeScript
import anthropic
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
system=[
{
"type": "text",
"text": LARGE_STABLE_PROMPT, # long, unchanging — the cached prefix
"cache_control": {"type": "ephemeral"},
}
],
messages=[{"role": "user", "content": "Summarize the key points."}], # varies per call
)
print(message.usage.cache_read_input_tokens) # > 0 means you got a hit
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const message = await client.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
system: [
{
type: "text",
text: LARGE_STABLE_PROMPT, // long, unchanging — the cached prefix
cache_control: { type: "ephemeral" },
},
],
messages: [{ role: "user", content: "Summarize the key points." }], // varies per call
});
console.log(message.usage.cache_read_input_tokens); // > 0 means you got a hit
Первый вызов платит небольшую надбавку за запись в кэш, чтобы его заполнить; каждый последующий вызов с тем же префиксом считывает его обратно за долю цены входных токенов. Префикс должен быть достаточно длинным, чтобы соответствовать условиям, — несколько тысяч токенов, в зависимости от модели, — иначе он молча не закэшируется.
Инвариант, который всё решает
:::warning Кэширование требует точного совпадения префикса Попадание в кэш требует, чтобы кэшированный префикс был побайтово идентичным. Самая частая ошибка — незаметный инвалидатор в начале промпта: метка времени, меняющееся имя пользователя, переупорядоченный список инструментов, — который изменяет префикс и тихо обнуляет вашу долю попаданий в кэш. :::
Размещайте всё стабильное в начале, а всё переменное — в конце, и держите префикс действительно постоянным.
Убедитесь, что это действительно работает
Не полагайтесь на предположения — считайте данные обратно из поля usage в ответе:
cache_creation_input_tokens— токены, записанные в кэш в этом вызове (первый запрос).cache_read_input_tokens— токены, отданные из кэша (ваша экономия).input_tokens— некэшированный остаток, тарифицируемый по полной цене.
Если cache_read_input_tokens остаётся нулевым на повторяющихся запросах, которые должны использовать общий префикс, значит, работает незаметный инвалидатор — сравните байты отрендеренного промпта между двумя вызовами, чтобы его найти.
Где это окупается больше всего
- Длинные системные промпты, переиспользуемые между пользователями.
- RAG / вопросы-ответы по документам, где один и тот же исходный текст запрашивается многократно.
- Агенты с фиксированным каталогом инструментов и инструкциями на протяжении многих ходов.
Сочетайте кэширование с пакетной обработкой (batching) для офлайн-нагрузок и с подбором подходящего размера модели (Выбор модели) для максимальной совокупной экономии — см. Затраты и задержка.
Проверьте себя
0/3- Помечайте точку разрыва кэша после стабильного префикса; первый вызов записывает его, последующие считывают его обратно дёшево.
- Для попадания в кэш нужен побайтово идентичный префикс — держите стабильное содержимое в начале, а переменное — в конце.
- Незаметные инвалидаторы в начале промпта (метки времени, имена, переупорядоченные инструменты) тихо обнуляют долю попаданий.
- Проверяйте через usage: cache_read_input_tokens > 0 означает попадание; ноль на повторяющихся запросах означает, что работает инвалидатор.
- Кэширование окупается больше всего на переиспользуемых системных промптах, RAG и агентах; сочетайте его с пакетной обработкой и подбором размера модели.