Головна / Статті / Мінус 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 і лише потім мудруйте.

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