Lovely RouterДокументация
Получить ключ
Models API

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

Платите лишь долю цены ввода за повторяющиеся префиксы промптов. Используйте кеширование каждого вендора, а шлюз будет держать каждый разговор на канале, где лежит его кеш.

Кеширование промптов позволяет модели переиспользовать работу, уже проделанную над префиксом промпта, который она недавно видела. Кешированный ввод стоит лишь долю обычной цены ввода: для claude-sonnet-5.5 чтение из кеша стоит $0.10 за миллион токенов против $2.00 за некешированный ввод. У агентов и длинных чатов, где каждая реплика заново отправляет всю историю, большую часть входных токенов можно обслужить из кеша.

Через Lovely Router кеширование работает благодаря двум вещам:

  1. Кеширование вендора. Вы используете кеширование каждого вендора ровно так, как описано в его документации. Поля запроса вроде cache_control и prompt_cache_key передаются без изменений.
  2. Привязка разговора к каналу. Кеш живёт на канале, который его записал. Шлюз распознаёт реплики одного разговора и отправляет их на тот же канал, поэтому к приходу следующей реплики кеш на месте.

Anthropic#

Claude кеширует только то, что вы отметили. Поставьте cache_control на последний блок стабильного префикса (инструменты, системный промпт, предыдущие реплики). Можно задать до четырёх точек разрыва или один cache_control на верхнем уровне запроса, чтобы кешировать всё до последнего блока.

response = client.messages.create(
    model="claude-sonnet-5.5",
    max_tokens=1024,
    system=[{
        "type": "text",
        "text": SYSTEM_PROMPT_AND_REFERENCE_DOCS,
        "cache_control": {"type": "ephemeral"},
    }],
    messages=history,
)
print(response.usage)

Ответ сообщает cache_creation_input_tokens (записано, тарифицируется по цене записи в кеш) и cache_read_input_tokens (прочитано, тарифицируется по цене чтения из кеша). Префиксы короче минимальной длины модели не кешируются. Где ставить точки разрыва и что сбрасывает кеш, описано в руководстве Anthropic по кешированию.

OpenAI#

Модели GPT кешируют длинные префиксы промптов автоматически; отмечать ничего не нужно. Ставьте стабильную часть промпта в начало, а изменяющуюся — в конец. Если задать prompt_cache_key стабильным значением для каждого разговора или пользователя, доля попаданий вырастет, а шлюз заодно использует это значение, чтобы держать разговор на одном канале.

response = client.chat.completions.create(
    model="gpt-6.1-sol",
    messages=history,
    prompt_cache_key="conv_8f2a91",
)
print(response.usage.prompt_tokens_details.cached_tokens)

usage.prompt_tokens_details.cached_tokens тарифицируется по цене чтения из кеша, а остальная часть prompt_tokens — по цене ввода. Отдельной платы за запись в кеш у моделей GPT нет. См. руководство OpenAI по кешированию.

Gemini#

Модели Gemini сами кешируют повторяющиеся префиксы (неявное кеширование). Кешированные токены отражаются в usageMetadata.cachedContentTokenCount и тарифицируются по цене чтения из кеша, без платы за запись. Явное кеширование контекста через API cachedContents недоступно.

Как распознаются разговоры#

Шлюз присваивает каждому разговору отпечаток. Он берёт первое совпадение из этого списка:

ИсточникФормат API
Заголовок x-session-idВсе
Заголовок x-lovely-sessionВсе
Заголовок x-claude-code-session-id (его отправляет Claude Code)Все
metadata.user_id в телеAnthropic
prompt_cache_key в телеOpenAI
user в телеOpenAI
Системный промпт плюс первое сообщение пользователяВсе

Последнее правило ничего от вас не требует. Последующие реплики разговора только добавляют сообщения, поэтому системный промпт и первое сообщение пользователя не меняются, и каждая реплика получает тот же отпечаток. Сравниваются только первые 4000 символов каждого из них.

Отпечатки привязаны к вашему API-ключу, модели и группе каналов. Тот же разговор, отправленный с другим ключом или к другой модели, начинает новое закрепление.

Как долго разговор остаётся закреплённым#

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

  • Длительность. Закрепление действует до одного часа и продлевается, пока разговор активен. После 30–60 минут без запросов оно истекает, и следующая реплика размещается как новый разговор.
  • Истёкший кеш. В формате Anthropic Messages закрепление также прекращается, если разговор простаивал дольше, чем живёт его кеш промптов: 5 минут или 1 час, если ваши точки разрыва cache_control задают ttl: "1h". Защищаемого кеша к этому моменту уже нет, поэтому следующая реплика размещается как новый разговор, а не ждёт канал, который обслуживал последним.
  • Занятый канал. Если закреплённый канал загружен полностью, реплика недолго его ждёт (около секунды для коротких промптов, до десяти секунд для длинных), а не переходит на другой канал с оплатой новой записи в кеш. Если канал всё ещё занят, реплика переходит на другой.
  • Сбойный канал. Если закреплённый канал даёт сбои, реплика переходит на исправный канал, и закрепление следует за ней. Эта реплика записывает свежий кеш; следующие снова читают из него.

Явный id сессии#

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

curl https://lovelyrouter.com/v1/messages \
  -H "x-api-key: $LOVELY_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "x-session-id: conv_8f2a91" \
  -H "content-type: application/json" \
  -d '{"model": "claude-sonnet-5.5", "max_tokens": 1024,
       "messages": [{"role": "user", "content": "Continue the report."}]}'

Поля тела тоже работают: metadata.user_id в формате Anthropic, prompt_cache_key в формате OpenAI. Используйте один id на разговор; если повторно использовать один id во многих несвязанных разговорах, все они окажутся на одном канале.

Использование кеша в логах и оплате#

Логи показывают для каждого вызова:

ПолеЗначение
ВходНекешированный ввод плюс записи в кеш.
Из кешаВходные токены, прочитанные из кеша.
Запись кеша (подробности)Входные токены, записанные в кеш.
Попадание в кеш (подробности)Доля кешированных токенов среди всех входных токенов.
Affinity (подробности)explicit: вы отправили id сессии. sticky: разговор был закреплён и вернулся на свой канал. new: первый вызов разговора, либо его закрепление истекло, либо канал был недоступен. none: построить отпечаток не удалось.

Обзор на панели показывает долю попаданий в кеш по всем вызовам. Каждый вид токенов тарифицируется по своей цене; см. Как тарифицируется вызов.

Проверьте низкую долю попаданий

Если разговор показывает new на каждой реплике, его системный промпт или первое сообщение пользователя меняются между репликами. Обычная причина — временная метка в системном промпте, и она заодно ломает кеш вендора: перенесите её в последнее сообщение пользователя или отправляйте явный id сессии. Если реплики показывают sticky, но Из кеша остаётся пустым, проверьте, что префикс достигает минимальной длины для модели и, в случае Claude, что на нём стоит cache_control.