關於「zero data retention」(零資料保留),即 ZDR 如何適用於此功能,請參閱 API 與資料保留。
提示快取可以大幅降低延遲和成本,但前提是您的提示開頭必須與最近的請求逐位元組完全相同。重新排序的工具、插入到系統提示中的時間戳記,或對較早訊息的編輯,都可能在無聲無息中使快取失效。如果沒有快取診斷,唯一的訊號就是 usage.cache_read_input_tokens 降為零,而沒有任何關於發生了什麼變化的指示。
快取診斷填補了這個缺口。傳入您前一個回應的 id,API 會比較這兩個請求,並告訴您它們在何處出現分歧(模型、系統提示、工具或訊息歷史記錄),讓您可以修正根本原因,而不是靠猜測。
快取診斷目前處於測試版。請在您的 API 請求中包含 beta 標頭 cache-diagnosis-2026-04-07 以使用此功能。
快取診斷目前僅在 Claude API 上提供。Amazon Bedrock 或 Google Cloud 不支援此功能。
當 beta 標頭存在時,API 會儲存每個請求的輕量級指紋(fingerprint),並以回應的 id 作為索引鍵。在您的下一個請求中,將該 id 作為 diagnostics.previous_message_id 傳入。API 會為新請求重建指紋,將其與儲存的指紋進行比較,並在回應中附加一個 diagnostics 物件,描述第一個分歧點。
此比較是關於請求結構的,與快取是否實際命中無關。請參閱結合 usage 解讀診斷結果,了解如何將 diagnostics 結果與 usage.cache_read_input_tokens 結合使用。
指紋僅包含雜湊值和 token 數量估計值(絕不包含原始提示內容),僅保留有限的時間,範圍限定於您的組織和工作區,且不會用於任何其他目的。
在每一輪都傳送 beta 標頭。在第一輪,傳入 "previous_message_id": null 以選擇加入,此時沒有先前的訊息可供比較。在後續的輪次中,傳入前一個回應的 id。
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",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[{"role": "user", "content": "Summarize section 1."}],
diagnostics={"previous_message_id": None},
betas=["cache-diagnosis-2026-04-07"],
)
# 第 2 輪:引用前一個回應的 id
r2 = client.beta.messages.create(
model="claude-opus-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},
betas=["cache-diagnosis-2026-04-07"],
)
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}")在串流回應中,diagnostics 會出現在 message_start 事件上。
# 第 2 輪:串流,並參照前一個回應的 id
with client.beta.messages.stream(
model="claude-opus-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},
betas=["cache-diagnosis-2026-04-07"],
) 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。
此工作流程不太適合以一次性的 shell 指令呈現。請參閱 SDK 分頁以了解迴圈模式;每一輪的 HTTP 請求與基本用法相同。
回應 Message 上的 diagnostics 欄位有四種可能的狀態:
| 值 | 含義 |
|---|---|
| 欄位不存在 | 請求未包含 diagnostics,或缺少 beta 標頭。 |
null | 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 是一個以 type 作為判別依據的聯集(discriminated union)。回應僅報告最早的分歧,因此請先修正它;後面的分歧可能被它隱藏。
| 類型 | 含義 | 需要變更的內容 |
|---|---|---|
model_changed | model 與前一個請求不同(例如,路由器、A/B 測試或備援機制選擇了不同的模型)。快取是以模型為單位的。 | 在快取的對話中保持模型不變。 |
system_changed | system 參數不同。通常是時間戳記、請求 ID 或其他每次請求都不同的值被插入到系統提示中。 | 讓系統提示成為逐位元組穩定的常數,並將動態資料移到快取斷點之後的第一個 user 訊息中。 |
tools_changed | tools 陣列不同:工具在輪次之間被新增、移除或重新排序,或者工具的 input_schema JSON 以非確定性的方式序列化。 | 在每一輪都以固定順序傳送相同的工具清單,並使用確定性序列化的結構描述(例如,對鍵進行排序)。 |
messages_changed | 模型、系統和工具都相符,但 messages 中較早的項目被更改、重新排序或移除,而不是附加在後面。通常是對話歷史記錄被截斷或編輯,或者助理輪次和 tool_result 區塊在重新傳送時以不同的方式重新序列化。 | 將歷史記錄視為僅可附加(append-only);將助理的 content 和工具結果逐字回傳。 |
previous_message_not_found | 提供的 previous_message_id 沒有對應的已儲存指紋。這並不代表您的請求發生了變化。通常是前一個請求未帶有 beta 標頭、來自不同的工作區,或自傳送以來已經過太長時間。 | 在每一輪都傳送 beta 標頭,並讓連續的輪次在時間上保持接近。 |
unavailable | 此請求無法取得診斷資訊。這包括 model、system 和 tools 相符,但另一個影響提示的請求參數(tool_choice、thinking、context_management、output_config、output_format,或作用中的 anthropic-beta 標頭集合)不同的情況,以及分歧超出比較範圍的非常長的對話。您的請求已正常處理。 | 在快取對話的生命週期內保持影響提示的請求參數不變。如果問題持續存在,請套用提示快取頁面上常見問題疑難排解中的手動檢查。 |
四種 *_changed 類型還帶有一個 cache_missed_input_tokens 整數:這是對分歧點之後有多少輸入 token 的估計值,讓您了解損失了多少可快取的前綴。它是在 token 化之前根據位元組長度推導出來的,因此請將其視為量級指標,而非計費數字。它可能與 usage.input_tokens 不同(偶爾甚至會超過)。
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(未產生比較結果)時,此矩陣也不適用。
| 診斷結果 | 快取讀取 token 數 | 解讀 |
|---|---|---|
null | 高 | 運作正常。您的前綴是穩定的,且快取命中。 |
null | 低或零 | 您的請求相符,但快取項目已不再可用。請考慮縮短輪次之間的間隔,或使用 1 小時快取 TTL。 |
cache_miss_reason 為 *_changed 類型 | 低或零 | 您的錯誤。請求發生了變化;請修正 type 所指出的原因。 |
cache_miss_reason 為 *_changed 類型 | 高 | 罕見。變化發生在提示的後段,但較早的 cache_control 斷點仍然命中。值得修正,但影響較小。 |
previous_message_id 查詢的指紋會在短時間後過期。請在時間間隔較近的請求之間執行診斷比較。unavailable,而非精確的位置。unavailable,或在比較仍在執行時回傳 cache_miss_reason: null。快取診斷符合 ZDR 資格(已認證)。Anthropic 不會為此功能儲存您的提示原始文字或 Claude 的輸出。
為每個請求儲存的指紋僅由加密雜湊值和 token 數量估計值組成,以回應的 id 作為索引鍵,範圍限定於您的組織和工作區。指紋會在短時間後過期,且不會用於任何其他目的。
有關所有功能的 ZDR 資格,請參閱 API 與資料保留。
Was this page helpful?