Оптимизация расходов и ускорение работы LLM при помощи Prompt Caching на OpenRouter

Prompt Caching

Современные языковые модели способны обрабатывать огромные объемы данных. Передача книг, документации, баз знаний и длинных цепочек диалогов в контекст стала стандартной практикой. Однако регулярная отправка сотен тысяч токенов приводит к двум проблемам: росту затрат на 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.

Метки:

Claude, Claude Code, DeepSeek, Google Gemini, Grok, Groq, Moonshot AI, OpenAI, OpenRouter, Prompt Caching, Qwen

Почему обычный веб-поиск в ИИ больше не работает и как это исправить за одну команду на примере плагина last30days в Claude Code

В статье рассматривается инструмент (skill) last30days для Claude Code и других AI-агентов. Вы узнаете, как этот плагин решает проблему поверхностного веб-поиска и ресурсозатратного глубокого исследования (Deep Research), собирая актуальные отзывы, тренды и комментарии пользователей на Reddit, X (Twitter), YouTube и Hacker News за последние 30 дней.

Интеграция локального проекта Claude Code с репозиторием кода SourceCraft

Практическое руководство по интеграции существующего локального проекта с Git-хостингом SourceCraft. Разбираем пошаговый процесс создания репозитория в организации, генерацию SSH-ключей для устранения ошибок авторизации и настройку ИИ-ассистента Claude Code для фиксации изменений строго по вашему запросу.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *