Prompt Caching: как сократить расходы на LLM API на 50–90% без изменения логики (2026)

Prompt Caching: как сократить расходы на LLM API на 50–90% без изменения логики (2026)

Большинство разработчиков, которые интегрируют LLM API, не используют prompt caching. Не потому что не хотят экономить — просто не знают, что оно уже есть, уже работает и иногда включается вообще без единой строки лишнего кода.

TL;DR: Prompt caching позволяет сократить расходы на входные токены на 50–90% при повторяющихся системных промптах или длинном статическом контексте. Claude требует явного cache_control, GPT-5.4 кэширует автоматически (без дополнительных параметров), Gemini — тоже. Через OfoxAI всё это работает без дополнительной настройки.

Почему это вообще важно

Возьмём типичный сценарий: корпоративный чат-бот с системным промптом на 2 000 токенов. Каждый пользователь в день делает 20 запросов. При 500 активных пользователях — 20 миллионов входных токенов в день только на системный промпт.

С Claude Opus 4.7 (через OfoxAI) это $5 за миллион входных токенов → $100 в день на системный промпт.

С prompt caching и хорошим hit rate (85%) — около $15 в день. Экономия $85/день, или $31 000 в год, без изменений в бизнес-логике.

Это и есть суть кэширования промптов.

Как работает кэш

Механизм простой. При первом запросе провайдер обрабатывает весь промпт и сохраняет его в кэш. При следующем запросе — если префикс идентичен — кэшированная часть не обрабатывается повторно. Вместо полной стоимости входного токена вы платите кэш-тариф (значительно ниже) или вообще ничего.

Два ключевых условия:

  1. Префикс должен быть идентичным побайтово. Одна лишняя пробельная строка — промах.
  2. Запрос должен успеть до истечения TTL. У большинства провайдеров это 5–10 минут.
Запрос 1: [Системный промпт 2000 токенов] + [Вопрос 50 токенов]
→ Провайдер кэширует системный блок
→ Стоимость: 2050 * $5/M = $0.01025

Запрос 2 (в течение 5 минут): [Тот же системный промпт] + [Другой вопрос 50 токенов]
→ Cache hit: системный блок не тарифицируется по полной ставке
→ Стоимость: 50 * $5/M + 2000 * $0.5/M = $0.00025 + $0.001 = $0.00125
→ Экономия ~87%

Claude API: явное управление кэшем

Claude Anthropic требует явного указания, что кэшировать. Для этого используется параметр cache_control.

Работает только через Anthropic-совместимый эндпоинт. Через OfoxAI — тот же формат:

import anthropic

client = anthropic.Anthropic(
    api_key="sk-ваш-ключ-ofoxai",
    base_url="https://api.ofox.ai/anthropic"
)

SYSTEM_PROMPT = """Вы — ассистент технической поддержки крупной SaaS-компании.
[... длинный системный контекст: 1500–2000 токенов ...]
"""

response = client.messages.create(
    model="anthropic/claude-opus-4.7",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": SYSTEM_PROMPT,
            "cache_control": {"type": "ephemeral"}
        }
    ],
    messages=[
        {"role": "user", "content": "Как сбросить пароль?"}
    ]
)

# Проверяем статистику кэша
usage = response.usage
print(f"Входные токены: {usage.input_tokens}")
print(f"Создан кэш: {usage.cache_creation_input_tokens}")
print(f"Прочитано из кэша: {usage.cache_read_input_tokens}")

При первом вызове cache_creation_input_tokens будет ненулевым — кэш создаётся. При следующем вызове в течение TTL — cache_read_input_tokens покажет количество сэкономленных токенов.

Важно: ephemeral — единственный поддерживаемый тип. Это кэш с TTL ~5 минут, не постоянный.

GPT-5.4: автоматическое кэширование

OpenAI не требует явных маркеров. Если вы повторяете идентичный системный промпт длиной от 1024 токенов, GPT-5.4 кэширует его автоматически — никаких изменений в коде не нужно (официальная документация).

from openai import OpenAI

client = OpenAI(
    api_key="sk-ваш-ключ-ofoxai",
    base_url="https://api.ofox.ai/v1"
)

SYSTEM = "Вы — опытный разработчик Python. [... длинный системный промпт ...]"

response = client.chat.completions.create(
    model="openai/gpt-5.4",
    messages=[
        {"role": "system", "content": SYSTEM},
        {"role": "user", "content": "Объясни разницу между list и tuple"}
    ]
)

# Метрики кэша в usage
usage = response.usage
if hasattr(usage, "prompt_tokens_details"):
    cached = usage.prompt_tokens_details.cached_tokens
    print(f"Токенов из кэша: {cached}")

Ключевой момент: SYSTEM должен быть буквально одинаковым от запроса к запросу. Если вы динамически форматируете строку с датой или именем пользователя — кэш не сработает.

GPT-5.4 кэширует промпты автоматически — TTL составляет 5–10 минут при активных запросах. Никаких дополнительных параметров не требуется.

Практика: что кэшировать и что нет

Хорошие кандидаты для кэширования:

  • Длинный системный промпт с инструкциями для роли агента
  • База знаний или документация, которая меняется раз в неделю
  • Стандартные few-shot примеры, которые идут перед каждым запросом
  • Большой контекст разговора (для многоходовых диалогов)

Плохие кандидаты:

  • Всё, что включает текущее время, дату или имя пользователя
  • Динамически изменяемые инструкции
  • Короткие промпты (кэш окупается только от ~500 токенов)

Правило большого пальца: статическое — в начало, динамическое — в конец.

# Правильная структура: статика впереди, динамика в конце
messages = [
    {"role": "system", "content": STATIC_SYSTEM_PROMPT},  # кэшируется
    # ... история диалога (тоже частично статична) ...
    {"role": "user", "content": user_message}  # уникально каждый раз
]

Метрики и мониторинг

Без метрик вы не знаете, работает ли кэш. Простой счётчик:

class CacheStats:
    def __init__(self):
        self.total_input = 0
        self.cached = 0

    def record(self, usage):
        self.total_input += usage.input_tokens
        if hasattr(usage, "cache_read_input_tokens"):
            self.cached += usage.cache_read_input_tokens or 0

    def hit_rate(self):
        if self.total_input == 0:
            return 0
        return self.cached / self.total_input * 100

stats = CacheStats()

# После каждого запроса:
stats.record(response.usage)
print(f"Hit rate: {stats.hit_rate():.1f}%")

Если hit rate ниже 60% при одинаковом системном промпте — значит, что-то меняется в префиксе. Проверьте форматирование строк и убедитесь, что промпт не пересобирается с каждым запросом.

Сколько сэкономить по моделям

Данные из документации OfoxAI (источник: ofox.ai/en/docs/develop/advanced/prompt-caching):

МодельСтандартная цена входных токеновЭкономия при cache hit
Claude Opus 4.7$5/M~90%
Claude Opus 4.6$5/M~90%
GPT-5.4$2.5/M~50%
Gemini 3.1 Pro$2/M50–75%
DeepSeek V3.2$0.29/Mзависит от конфигурации

Для Claude эффект наиболее заметен именно из-за высокой базовой стоимости. При hit rate 85% и системном промпте 2 000 токенов — каждый запрос стоит в 7 раз меньше по части системного блока.

Ограничения, о которых стоит знать

TTL — не навсегда. Кэш живёт около 5–10 минут. Если ваши пользователи делают запросы реже — кэш будет постоянно протухать. Для таких сценариев (редкие но тяжёлые запросы) кэширование почти не помогает.

Первый запрос всегда полный. Создание кэша стоит столько же или немного дороже обычного запроса. Экономия появляется только при повторных запросах в рамках TTL.

Не все модели поддерживают. Через OfoxAI поддерживаются Claude, GPT-4o и Gemini серии. DeepSeek V3.2 — зависит от конкретного провайдера бэкенда.

Идентичность префикса критична. Разница даже в одном байте — промах. Не форматируйте системный промпт с f-строками, если в него попадают переменные.

Как подключиться через OfoxAI

Если вы уже используете OpenAI SDK с эндпоинтом OfoxAI — всё уже работает для GPT и Gemini. Для Claude с явным cache_control нужна Anthropic SDK:

pip install anthropic
import anthropic

client = anthropic.Anthropic(
    api_key="ВАШ_КЛЮЧ_OFOXAI",
    base_url="https://api.ofox.ai/anthropic"
)

Получить ключ можно на ofox.ai — работает из России, принимает криптовалюту.

Итог

Prompt caching — одна из немногих оптимизаций, которая требует минимальных изменений в коде и даёт заметный эффект на нагрузке. При правильной структуре промпта и достаточной частоте запросов экономия составит 50–90% на входных токенах.

Три шага для старта:

  1. Переместите статическую часть промпта в начало
  2. Добавьте cache_control: {type: ephemeral} для Claude или просто повторяйте идентичный системный блок для GPT
  3. Смотрите в usage — если cache_read_input_tokens растёт, всё работает