Диагностика кэша
Диагностируйте неожиданные промахи кэша подсказок, сравнивая последовательные запросы и точно определяя, где разошёлся префикс подсказки.
Кэширование подсказок (prompt caching) значительно снижает задержку и стоимость, но только когда начало вашей подсказки побайтово идентично недавнему запросу. Переупорядоченный инструмент, временная метка, подставленная в вашу системную подсказку (system prompt), или правка более раннего сообщения могут незаметно сделать кэш недействительным. Без диагностики кэша единственным сигналом является падение usage.cache_read_input_tokens до нуля без какого-либо указания на то, что изменилось.
Диагностика кэша закрывает этот пробел. Передайте id вашего предыдущего ответа, и API сравнит два запроса и сообщит вам, где они разошлись (модель, системная подсказка, инструменты или история сообщений), чтобы вы могли устранить первопричину, а не гадать.
Как работает диагностика кэша
Для каждого запроса, включающего объект diagnostics, API сохраняет облегчённый «fingerprint» (отпечаток), привязанный к id ответа. Для запросов без этого объекта ничего не сохраняется. В следующем запросе укажите id предыдущего ответа в diagnostics.previous_message_id. API заново строит отпечаток для нового запроса, сравнивает его с сохранённым и прикрепляет к ответу объект diagnostics, описывающий первую точку расхождения.
Сравнение касается структуры запроса и не зависит от того, произошло ли фактическое попадание в кэш. См. раздел Чтение диагностики вместе с usage, чтобы узнать, как сочетать результат diagnostics с usage.cache_read_input_tokens.
Отпечатки содержат только хэши и оценки количества токенов (никогда — исходное содержимое подсказки), хранятся ограниченное время, ограничены вашей организацией и рабочим пространством и не используются ни для каких других целей.
Базовое использование
Включайте объект diagnostics в каждый ход. Сам объект является согласием на участие: API сохраняет отпечаток только для запросов, которые его включают. В первом ходе передайте "previous_message_id": null, чтобы включить функцию без предыдущего сообщения для сравнения. В последующих ходах передавайте id из предыдущего ответа. Бета-заголовок cache-diagnosis-2026-04-07 больше не требуется, а запросы, которые всё ещё его отправляют, работают как прежде.
client = anthropic.Anthropic()
SYSTEM = "You are an AI assistant analyzing a large document. <document>...</document>"
# Ход 1: включаем функцию с previous_message_id=None
r1 = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[{"role": "user", "content": "Summarize section 1."}],
diagnostics={"previous_message_id": None},
)
# Ход 2: ссылаемся на id предыдущего ответа
r2 = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[
{"role": "user", "content": "Summarize section 1."},
{"role": "assistant", "content": r1.content},
{"role": "user", "content": "Now summarize section 2."},
],
diagnostics={"previous_message_id": r1.id},
)
diagnostics = r2.diagnostics
if diagnostics is None:
print("No divergence detected.")
elif diagnostics.cache_miss_reason is None:
print("Comparison still pending.")
else:
print(f"cache_miss_reason: {diagnostics.cache_miss_reason.type}")Потоковая передача
В ответах с потоковой передачей (streaming) diagnostics появляется в событии message_start.
# Ход 2: потоковая передача со ссылкой на id предыдущего ответа
with client.beta.messages.stream(
model="claude-opus-5-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[
{"role": "user", "content": "Summarize section 1."},
{"role": "assistant", "content": r1.content},
{"role": "user", "content": "Now summarize section 2."},
],
diagnostics={"previous_message_id": r1.id},
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
print()
r2 = stream.get_final_message()
diagnostics = r2.diagnostics
if diagnostics is None:
print("No divergence detected.")
elif diagnostics.cache_miss_reason is None:
print("Comparison still pending.")
else:
print(f"cache_miss_reason: {diagnostics.cache_miss_reason.type}")Событие message_start содержит полное поле diagnostics; возможные значения см. в разделе Формат ответа.
Передача диагностики через цикл диалога
В многоходовом диалоге передавайте id последнего ответа дальше как previous_message_id на каждом ходе. Первая итерация передаёт null для включения функции; каждая последующая итерация передаёт id из предыдущего ответа.
client = anthropic.Anthropic()
SYSTEM = "You are an AI assistant analyzing a large document. <document>...</document>"
messages = []
prev_id = None
for i, user_message in enumerate(
["Summarize section 1.", "Now section 2.", "Now section 3."]
):
messages.append({"role": "user", "content": user_message})
r = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=messages,
diagnostics={"previous_message_id": prev_id},
)
if r.diagnostics is not None and r.diagnostics.cache_miss_reason is not None:
print(f"Turn {i + 1} cache_miss_reason: {r.diagnostics.cache_miss_reason.type}")
messages.append({"role": "assistant", "content": r.content})
prev_id = r.idФормат ответа
Поле diagnostics в ответе Message имеет три возможных значения:
| Значение | Смысл |
|---|---|
null | Запрос не включал объект diagnostics, previous_message_id был null (первый ход, сравнивать не с чем), или сравнение было выполнено и не обнаружило расхождений. |
{"cache_miss_reason": null} | Сравнение ещё выполнялось, когда ответ был сериализован. Это может произойти, когда ответ начинается очень быстро. Считайте результат неопределённым и проверьте следующий ход. |
{"cache_miss_reason": {...}} | Прикреплён cache_miss_reason. Для типов *_changed он указывает первую точку расхождения; previous_message_not_found и unavailable — это случаи, когда сравнение не было произведено. |
Когда cache_miss_reason не равен null, он выглядит так:
{
"id": "msg_01Xyz...",
"type": "message",
"role": "assistant",
"content": [{ "type": "text", "text": "..." }],
"usage": {
"input_tokens": 42,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 41850,
"output_tokens": 210
},
"diagnostics": {
"cache_miss_reason": {
"type": "system_changed",
"cache_missed_input_tokens": 41850
}
}
}Типы причин промаха кэша
cache_miss_reason — это размеченное объединение (discriminated union) по полю type. Ответ сообщает только о самом раннем расхождении, поэтому исправьте его первым; более поздние могут быть скрыты за ним.
| Тип | Что это означает | Что изменить |
|---|---|---|
model_changed | model отличается от предыдущего запроса (например, маршрутизатор, A/B-тест или резервный механизм выбрал другую модель). Кэш ведётся отдельно для каждой модели. | Сохраняйте модель неизменной в рамках кэшируемого диалога. |
system_changed | Параметр system отличается. Обычно в системную подсказку была подставлена временная метка, идентификатор запроса или другое значение, уникальное для запроса. | Сделайте системную подсказку побайтово стабильной константой и перенесите динамические данные в первое сообщение user после вашей точки разрыва кэша. |
tools_changed | Массив tools отличается: инструменты были добавлены, удалены или переупорядочены между ходами, либо JSON input_schema инструмента был сериализован недетерминированно. | Отправляйте один и тот же список инструментов на каждом ходе в фиксированном порядке с детерминированно сериализованными схемами (например, сортируйте ключи). |
messages_changed | Модель, system и tools совпадают, но более ранняя запись в messages была изменена, переупорядочена или удалена, а не дополнена. Обычно история диалога была усечена или отредактирована, либо ходы ассистента и блоки tool_result были повторно сериализованы иначе при повторной отправке. | Относитесь к истории как к допускающей только добавление; возвращайте content ассистента и результаты инструментов дословно. |
previous_message_not_found | Для указанного previous_message_id не существует сохранённого отпечатка. Это не свидетельствует о том, что ваш запрос изменился. Обычно предыдущий запрос не включал объект diagnostics, был выполнен в другом рабочем пространстве или с момента его отправки прошло слишком много времени. | Включайте объект diagnostics в каждый ход и отправляйте последовательные ходы с небольшими интервалами. |
unavailable | Диагностическая информация была недоступна для этого запроса. Сюда входит случай, когда model, system и tools совпадают, но отличается другой влияющий на подсказку параметр запроса (tool_choice, thinking, context_management, output_config, output_format или набор активных заголовков anthropic-beta), а также очень длинные диалоги, где расхождение находится за горизонтом сравнения. Ваш запрос был обработан в обычном режиме. | Сохраняйте влияющие на подсказку параметры запроса неизменными на протяжении всего кэшируемого диалога. Если проблема сохраняется, примените ручные проверки из раздела Устранение распространённых проблем на странице кэширования подсказок. |
Чтение диагностики вместе с usage
diagnostics отвечает на вопрос «изменился ли мой запрос?», а usage.cache_read_input_tokens — на вопрос «произошло ли попадание в кэш?». Их сочетание подсказывает, где искать.
Эта матрица применима к ходам, на которых вы передали реальный previous_message_id. На первом ходе (previous_message_id: null) diagnostics всегда равен null, а cache_read_input_tokens обычно равен нулю, поскольку кэш записывается, а не читается; устранение неполадок не требуется. Матрица также не применима, когда cache_miss_reason равен null (сравнение ещё выполняется; проверьте следующий ход) или когда его type — previous_message_not_found или unavailable (сравнение не было произведено).
| Результат диагностики | Токены чтения из кэша | Интерпретация |
|---|---|---|
null | много | Работает как ожидается. Ваш префикс стабилен, и произошло попадание в кэш. |
null | мало или ноль | Ваши запросы совпадают, но запись кэша больше не была доступна. Рассмотрите сокращение промежутков между ходами или использование TTL кэша в 1 час. |
cache_miss_reason имеет тип *_changed | мало или ноль | Ваша ошибка. Запрос изменился; устраните причину, указанную в type. |
cache_miss_reason имеет тип *_changed | много | Редко. Изменение произошло ближе к концу подсказки, но более ранняя точка разрыва cache_control всё же сработала. Стоит исправить, но влияние невелико. |
Ограничения
- Только Claude API: Недоступно на Amazon Bedrock или Google Cloud.
- Ограниченное хранение: Отпечатки для поиска по
previous_message_idистекают через короткий период. Выполняйте диагностические сравнения между близко расположенными по времени запросами. - То же рабочее пространство: Предыдущий запрос должен был выполняться в той же организации и рабочем пространстве. Для проверки сравните заголовок ответа
anthropic-workspace-idв двух ответах. - Горизонт сравнения: Для очень длинных диалогов, где единственное изменение находится глубоко в списке сообщений, ответ может быть
unavailableвместо точного местоположения. - По мере возможности: Диагностика никогда не блокирует и не приводит к сбою вашего запроса. Если диагностическая информация недоступна, ответ возвращает
unavailableилиcache_miss_reason: null, если сравнение ещё выполнялось.
Хранение данных
Диагностика кэша соответствует требованиям ZDR (с оговорками). Anthropic не хранит исходный текст ваших подсказок или выходных данных Claude для этой функции.
API сохраняет отпечаток только для запросов, включающих объект diagnostics. Отпечаток состоит только из криптографических хэшей и оценок количества токенов, привязан к id ответа и ограничен вашей организацией и рабочим пространством. Отпечатки истекают через короткий период и не используются ни для каких других целей.
Сведения о соответствии ZDR для всех функций см. в разделе API и хранение данных.
См. также
Compatibility
- Supported platforms
- Claude API
Was this page helpful?