> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apimart.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Руководство по контекстному кэшу Claude

> Кэшируйте многократно используемые префиксы промптов через Claude Messages API или OpenAI-совместимый Chat Completions API, чтобы снизить затраты на токены при повторной обработке длинного контента.

Контекстный кэш Claude (Context Cache) подходит для многократного использования длинных префиксов: системных промптов, документов, кодовых баз или истории диалога. Добавьте `cache_control` к стабильному префиксу: при первом запросе будет создан кэш, а последующие запросы смогут прочитать его до истечения срока действия.

Перед началом работы задайте API-ключ:

```bash theme={null}
export API_KEY="ваш API-ключ"
```

<Note>В примерах этого руководства используется `claude-sonnet-5`. Сведения о поддержке контекстного кэша другими моделями см. в описании моделей на платформе.</Note>

## Сценарии использования

Если в нескольких запросах многократно передаётся один и тот же большой фрагмент контента, можно кэшировать его стабильный префикс, например:

* длинный system prompt
* неизменяемую базу знаний или документацию продукта
* стабильную историю сообщений в многошаговом диалоге
* многократно используемые кодовые базы, определения и описания инструментов

Контекстный кэш подходит для запросов, в которых «начальный контент остаётся неизменным, а последний вопрос постоянно меняется».

## Claude Messages API

### Кэш на 5 минут

Добавьте `cache_control` в content block, который требуется кэшировать:

```bash theme={null}
curl "https://api.apimart.ai/v1/messages" \
  -H "x-api-key: $API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "system": [
      {
        "type": "text",
        "text": "Здесь размещается длинный префикс для многократного использования……",
        "cache_control": {
          "type": "ephemeral"
        }
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "Ответьте на вопрос на основе приведённого выше контента."
      }
    ]
  }'
```

<Warning>`system` должен быть массивом content block. В строковую форму `system` нельзя добавить `cache_control`.</Warning>

Если `ttl` не указан, по умолчанию срок действия кэша составляет 5 минут.

### Кэш на 1 час

Чтобы использовать кэш на 1 час, добавьте заголовок запроса `anthropic-beta` и задайте для `ttl` значение `1h`:

```bash theme={null}
curl "https://api.apimart.ai/v1/messages" \
  -H "x-api-key: $API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: extended-cache-ttl-2025-04-11" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "system": [
      {
        "type": "text",
        "text": "Здесь размещается длинный префикс для многократного использования……",
        "cache_control": {
          "type": "ephemeral",
          "ttl": "1h"
        }
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "Ответьте на вопрос на основе приведённого выше контента."
      }
    ]
  }'
```

Поддерживаемые значения TTL:

| TTL  | Значение                                                                                 |
| ---- | ---------------------------------------------------------------------------------------- |
| `5m` | кэширование на 5 минут; это значение используется, если `ttl` не указан                  |
| `1h` | кэширование на 1 час; также требуется соответствующий заголовок запроса `anthropic-beta` |

### Поля использования в ответе

Claude Messages API раздельно возвращает в `usage` токены обычного ввода, записи в кэш и чтения из кэша:

```json theme={null}
{
  "usage": {
    "input_tokens": 23,
    "cache_creation_input_tokens": 2619,
    "cache_read_input_tokens": 0,
    "cache_creation": {
      "ephemeral_5m_input_tokens": 2619,
      "ephemeral_1h_input_tokens": 0
    },
    "output_tokens": 24
  }
}
```

Общее количество входных токенов рассчитывается следующим образом:

```text theme={null}
input_tokens
+ cache_creation_input_tokens
+ cache_read_input_tokens
```

Эти три значения не пересекаются. При первом запросе обычно возвращается `cache_creation_input_tokens > 0`. При повторной отправке того же стабильного префикса должно возвращаться `cache_read_input_tokens > 0`.

## OpenAI-совместимый API

### Пример запроса

При использовании кэша через `/v1/chat/completions` формат `cache_control` почти не отличается от Claude Messages API:

```bash theme={null}
curl "https://api.apimart.ai/v1/chat/completions" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "messages": [
      {
        "role": "system",
        "content": [
          {
            "type": "text",
            "text": "Здесь размещается длинный префикс для многократного использования……",
            "cache_control": {
              "type": "ephemeral"
            }
          }
        ]
      },
      {
        "role": "user",
        "content": "Ответьте на вопрос на основе приведённого выше контента."
      }
    ]
  }'
```

### Кэш на 1 час

OpenAI-совместимый формат также поддерживает кэширование на 1 час. Добавьте в запрос заголовок `anthropic-beta` и задайте `ttl: "1h"` в `cache_control`:

```bash theme={null}
-H "anthropic-beta: extended-cache-ttl-2025-04-11"
```

```json theme={null}
"cache_control": {
  "type": "ephemeral",
  "ttl": "1h"
}
```

### `content` должен быть массивом

В OpenAI-совместимом формате `cache_control` должен находиться в конкретном content block. Его нельзя добавить к сообщению, в котором контент задан строкой.

```json theme={null}
{
  "role": "system",
  "content": "Здесь размещается длинный префикс……",
  "cache_control": {
    "type": "ephemeral"
  }
}
```

Приведённый выше формат не включает кэширование, при этом запрос не возвращает ошибку. Правильный формат:

```json theme={null}
{
  "role": "system",
  "content": [
    {
      "type": "text",
      "text": "Здесь размещается длинный префикс……",
      "cache_control": {
        "type": "ephemeral"
      }
    }
  ]
}
```

<Warning>Если `content` задан строкой, маркер кэша игнорируется, а контент обрабатывается как обычный ввод. Чтобы подтвердить попадание в кэш, проверьте поля использования кэша в ответе.</Warning>

### Кэширование content block пользователя или ассистента

`cache_control` также можно добавить к content block в сообщении `user` или `assistant`, чтобы кэшировать длинный документ или префикс многошагового диалога:

```json theme={null}
{
  "role": "user",
  "content": [
    {
      "type": "text",
      "text": "Здесь размещается длинный документ для многократного использования……",
      "cache_control": {
        "type": "ephemeral"
      }
    },
    {
      "type": "text",
      "text": "Кратко изложите три ключевых положения приведённого выше документа."
    }
  ]
}
```

Разделите стабильный контент и текущий вопрос на разные content block и добавьте `cache_control` только к стабильному content block.

### Поля использования в ответе

В OpenAI-совместимом формате для данных об использовании кэша применяются другие поля:

```json theme={null}
{
  "usage": {
    "prompt_tokens": 1942,
    "completion_tokens": 22,
    "prompt_tokens_details": {
      "cached_tokens": 1921,
      "cache_write_tokens": 0
    },
    "claude_cache_creation_5_m_tokens": 0,
    "claude_cache_creation_1_h_tokens": 0
  }
}
```

Соответствие полей:

| Значение                | Claude Messages API                        | OpenAI-совместимый API                                                                            |
| ----------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| Общий ввод              | сумма трёх полей ввода                     | `prompt_tokens`                                                                                   |
| Чтение из кэша          | `cache_read_input_tokens`                  | `prompt_tokens_details.cached_tokens`                                                             |
| Общее поле записи в кэш | `cache_creation_input_tokens`              | `prompt_tokens_details.cache_write_tokens` (заполняется только при отсутствии детализации по TTL) |
| Запись в 5-минутный кэш | `cache_creation.ephemeral_5m_input_tokens` | `claude_cache_creation_5_m_tokens`                                                                |
| Запись в 1-часовой кэш  | `cache_creation.ephemeral_1h_input_tokens` | `claude_cache_creation_1_h_tokens`                                                                |
| Вывод                   | `output_tokens`                            | `completion_tokens`                                                                               |

<Note>Если `prompt_tokens_details.cache_write_tokens` равен `0`, также проверьте `claude_cache_creation_5_m_tokens` и `claude_cache_creation_1_h_tokens`. При наличии полей с детализацией по TTL объём записи в кэш возвращается в соответствующем поле.</Note>

<Note>В именах `claude_cache_creation_5_m_tokens` и `claude_cache_creation_1_h_tokens` цифры и единицы разделены символами подчёркивания. Используйте имена полей в точности так, как они возвращены в ответе.</Note>

<Warning>OpenAI-совместимый интерфейс может вернуть потоковый SSE-ответ, даже если `stream: true` не был явно передан. Клиент должен поддерживать разбор `chat.completion.chunk`; сведения об использовании находятся в последнем блоке данных, содержащем `usage`.</Warning>

## Условия попадания в кэш

### Префикс достигает минимальной длины

Для модели из примеров префикс кэша обычно должен содержать не менее примерно 1024 токенов. Если префикс слишком короткий, маркер кэша может быть проигнорирован без сообщения об ошибке.

### Префикс полностью совпадает на уровне байтов

Текст, пробелы, переводы строк и порядок content block в префиксе кэша должны совпадать. Не добавляйте в стабильный префикс отметки времени, случайные ID, счётчики запросов или другой динамический контент.

### Запрос не вызывает отказ модели

Если запрос вызывает отказ модели, в ответе всё равно могут быть указаны токены создания кэша, но при следующем запросе этот кэш не будет прочитан. При диагностике промаха кэша также проверьте, не равен ли `stop_reason` значению `refusal`.

### Срок действия кэша не истёк

Срок действия кэша составляет 5 минут или 1 час и отсчитывается от последнего обращения. Попадание в кэш обновляет срок действия.

## Тарифицируемое использование

Использование кэша делится на три категории:

| Использование  | Когда возникает                         |
| -------------- | --------------------------------------- |
| Запись в кэш   | при первоначальном создании кэша        |
| Чтение из кэша | когда последующий запрос попадает в кэш |
| Обычный ввод   | ввод за пределами префикса кэша         |

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

## Минимальный воспроизводимый пример

Следующий скрипт создаёт достаточно длинный стабильный префикс и дважды подряд отправляет один и тот же запрос. Во втором ответе должно возвращаться `cache_read_input_tokens > 0`.

```bash theme={null}
python3 - <<'PY' > /tmp/claude-cache-request.json
import json

paragraph = (
    "Кэширование промпта сохраняет префикс запроса, чтобы последующие запросы "
    "могли повторно использовать побайтово идентичный префикс без повторной обработки. "
)

system_text = (
    "Вы — помощник по работе с документацией. Ниже приведены справочные материалы.\n\n"
    + paragraph * 40
)

print(json.dumps({
    "model": "claude-sonnet-5",
    "max_tokens": 32,
    "system": [{
        "type": "text",
        "text": system_text,
        "cache_control": {"type": "ephemeral"}
    }],
    "messages": [{
        "role": "user",
        "content": "Одним предложением укажите, что должно оставаться неизменным."
    }]
}))
PY

for request_number in 1 2; do
  echo "Запрос ${request_number}"
  curl -s "https://api.apimart.ai/v1/messages" \
    -H "x-api-key: $API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "Content-Type: application/json" \
    --data @/tmp/claude-cache-request.json \
  | python3 -c "import json, sys; print(json.load(sys.stdin)['usage'])"
done
```

Ожидаемый результат:

```text theme={null}
Запрос 1: cache_creation_input_tokens > 0, cache_read_input_tokens = 0
Запрос 2: cache_creation_input_tokens = 0, cache_read_input_tokens > 0
```

## Контрольный список для диагностики

Если запрос не попадает в кэш, проверьте по порядку:

* равен ли `stop_reason` значению `refusal`
* достигает ли префикс кэша минимального количества токенов, требуемого моделью
* полностью ли совпадает стабильный префикс в двух запросах на уровне байтов
* является ли `content` массивом в OpenAI-совместимом формате
* находится ли `cache_control` в конкретном content block
* заданы ли для 1-часового кэша одновременно `ttl: "1h"` и соответствующий заголовок запроса `anthropic-beta`
* не истёк ли TTL кэша
* используются ли поля данных о кэше, соответствующие текущему интерфейсу
