Современные языковые модели способны обрабатывать огромные объемы данных. Передача книг, документации, баз знаний и длинных цепочек диалогов в контекст стала стандартной практикой. Однако регулярная отправка сотен тысяч токенов приводит к двум проблемам: росту затрат на API и увеличению задержки (latency) ответов.
Решить эти проблемы помогает кэширование промптов (Prompt Caching). Эта технология позволяет один раз сохранить часто используемый текст на стороне провайдера и при последующих запросах платить только за его чтение, что в некоторых сценариях снижает стоимость обработки входящих токенов до 90%.
Ниже подробно разобрано, как устроено кэширование на OpenRouter, какие модели его поддерживают и как внедрить его в свой код.
Как OpenRouter оптимизирует кэширование
Для эффективной работы кэша провайдер должен постоянно получать запросы на одну и ту же физическую машину, где этот кэш хранится. OpenRouter решает эту задачу с помощью нескольких механизмов:
- Provider Sticky Routing (Липкая маршрутизация): после первого успешного запроса с использованием кэша OpenRouter автоматически направляет последующие запросы к тому же провайдеру, чтобы поддерживать кэш в «горячем» состоянии.
- Идентификатор сессии (
session_id): вы можете вручную передать параметрsession_idв запросе. Это заставляет систему привязать сессию к конкретному провайдеру с самого первого запроса (еще до фактического кэширования), что полезно для многошаговых агентов, у которых начальные сообщения могут слегка меняться.
Автоматическое vs. Явное кэширование
На OpenRouter поддержка кэширования делится на два типа в зависимости от провайдера и модели:
1. Автоматическое кэширование (Implicit Caching)
Провайдер сам определяет повторяющиеся блоки текста и кэширует их. Никаких изменений в структуре запроса делать не нужно — достаточно лишь преодолеть минимальный порог по количеству токенов (обычно от 1024 до 4096).
- Поддерживается у: OpenAI, DeepSeek, Grok, Moonshot AI, Groq, а также в режиме неявного кэширования для Google Gemini 2.5.
- Экономия: стоимость чтения кэша составляет от 10% (DeepSeek) до 25–50% (OpenAI, Gemini, Grok) от стандартной цены входящих токенов.
2. Явное кэширование (Explicit Breakpoints)
Требует ручной разметки блоков текста, которые нужно сохранить в кэше. Это делается с помощью объекта cache_control.
- Поддерживается у: Anthropic Claude, Alibaba Qwen, а также в явном режиме у Google Gemini.
- Параметры TTL (время жизни кэша): по умолчанию кэш хранится 5 минут (
"type": "ephemeral"). Для моделей Anthropic Claude доступна опция увеличения TTL до 1 часа ("ttl": "1h"), что удобно для редких, но регулярных запросов в рамках одной сессии.
Практические примеры интеграции (Python)
Ниже представлены примеры работы с API OpenRouter с использованием библиотеки requests.
Пример 1. Автоматическое кэширование для Claude (верхнеуровневый cache_control)
Этот подход подходит для длинных многопользовательских диалогов. Достаточно передать cache_control на верхнем уровне запроса, и система будет автоматически продвигать точку кэширования по мере роста истории переписки.
import requests
import json
url = "https://openrouter.ai/api/v1/chat/completions"
headers = {
"Authorization": "Bearer YOUR_OPENROUTER_API_KEY",
"Content-Type": "application/json"
}
payload = {
"model": "anthropic/claude-3.5-sonnet",
# Включаем автоматическое кэширование истории на верхнем уровне
"cache_control": { "type": "ephemeral" },
"messages": [
{
"role": "system",
"content": "Вы — историк-эксперт. Ссылайтесь на следующую информацию в ответах: [ЗДЕСЬ БОЛЬШОЙ СТАТИЧНЫЙ ТЕКСТ НА 2000+ ТОКЕНОВ]..."
},
{
"role": "user",
"content": "Каковы были основные причины упадка Римской империи?"
}
]
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
print(response.json())
Пример 2. Явное кэширование для больших документов (Claude, Gemini, Qwen)
Если у вас есть стабильный контекст (например, свод правил компании или книга) и вы хотите зафиксировать в кэше только его, используйте разметку конкретных блоков данных (breakpoints). Ниже показан пример с использованием 1-часового TTL для экономии при длительных сессиях:
import requests
import json
url = "https://openrouter.ai/api/v1/chat/completions"
headers = {
"Authorization": "Bearer YOUR_OPENROUTER_API_KEY",
"Content-Type": "application/json"
}
payload = {
"model": "anthropic/claude-3.5-sonnet",
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "Используй данный документ для ответов на последующие вопросы:"
},
{
"type": "text",
# Кэшируем именно этот большой блок текста
"text": "[ОГРОМНЫЙ НАБОР ДАННЫХ ДЛЯ RAG ИЛИ СПРАВОЧНИК]",
"cache_control": {
"type": "ephemeral",
"ttl": "1h" # Кэш будет жить 1 час (актуально для Anthropic)
}
},
{
"type": "text",
"text": "Составь краткое содержание первой главы."
}
]
}
]
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
print(response.json())
Пример 3. Привязка сессии через session_id
Если вы строите многошагового агента, где начальные сообщения могут незначительно меняться, укажите session_id в теле запроса (или в заголовке x-session-id), чтобы зафиксировать провайдера с прогретым кэшем.
import requests
import json
url = "https://openrouter.ai/api/v1/chat/completions"
headers = {
"Authorization": "Bearer YOUR_OPENROUTER_API_KEY",
"Content-Type": "application/json"
}
payload = {
"model": "anthropic/claude-3.5-sonnet",
# Указываем уникальный ID сессии для удержания провайдера
"session_id": "agent-session-unique-12345",
"messages": [
{
"role": "user",
"content": "Продолжи наш анализ рынка на основе загруженных ранее данных."
}
]
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
print(response.json())
Как проверить, сработало ли кэширование?
Вы можете узнать точное количество закэшированных токенов прямо из ответа API. OpenRouter возвращает эти данные в объекте usage.prompt_tokens_details:
{
"usage": {
"prompt_tokens": 10339,
"completion_tokens": 60,
"total_tokens": 10399,
"prompt_tokens_details": {
"cached_tokens": 10318, // Токены, прочитанные из кэша (экономия)
"cache_write_tokens": 0 // Токены, записанные в кэш при этом запросе
}
}
}
cached_tokens: указывает объем данных, который был прочитан из кэша. Если это значение больше нуля — вы успешно сэкономили бюджет на этом запросе.cache_write_tokens: показывает количество токенов, которые были записаны в кэш при первом обращении (инициализация кэша).
Лучшие практики
- Сортируйте сообщения: всегда размещайте статичную и тяжелую информацию (инструкции системы, базы знаний, контекст) в самом начале промпта, а динамические данные (вопросы пользователя, текущее время) — в конце. Любое изменение в начале или середине промпта приведет к сбросу кэша для всей последующей части запроса.
- Помните о лимитах: большинство моделей не будут кэшировать запросы короче определенного лимита (для большинства современных моделей порог составляет от 1024 до 4096 токенов). Для коротких диалогов использовать кэширование не имеет практического смысла.
- Следите за расходами при записи: у некоторых провайдеров (например, Anthropic или Alibaba Qwen) операция записи в кэш стоит дороже обычного чтения (в 1.25–2 раза). Кэширование выгодно только тогда, когда к одному и тому же блоку данных вы будете обращаться повторно хотя бы несколько раз в течение действия TTL.

