LLM 中的 Prompt Caching:清晰解析
LLM 中的 Prompt Caching:清晰解析
這是一份關於 Claude 如何達成 92% 快取命中率的案例研究
每當 AI Agent 採取一個步驟時,它都會將整個對話歷史紀錄傳送回 LLM。
這包含了系統指令、工具定義,以及它在三個回合前就已經處理過的專案背景資訊。所有這些內容在每一個回合中都會被重新讀取、重新處理並重新計費。

對於長時間運行的 Agent 工作流程而言,這種冗餘的運算通常是你整個 AI 基礎設施中最昂貴的項目。
一個包含 20,000 個 token 的系統提示詞(System Prompt)在運行 50 個回合後,意味著有 100 萬個 token 的冗餘運算以全價計費,卻沒有產生任何新的價值。而且這種成本會隨著每一位使用者和每一次對話而疊加。
解決方案就是 Prompt Caching(提示詞快取)。但要妥善運用它,你需要了解底層實際發生了什麼。
靜態與動態 Context
在優化提示詞之前,你需要先了解哪些部分會變動,哪些不會。
每個 Agent 的請求都包含兩個截然不同的部分:

靜態前綴(Static prefix):在各個回合中保持不變的部分,例如系統指令、工具定義、專案背景資訊和行為準則。
動態後綴(Dynamic suffix):隨著每個回合不斷增長的部分,例如使用者訊息、助理回應、工具輸出和終端觀察結果。
這種拆分方式使得 Prompt Caching 成為可能。基礎設施會儲存靜態前綴的數學狀態,以便後續共享完全相同前綴的請求可以完全跳過運算,直接從記憶中讀取。
一旦你理解了這一點,本文中提到的每一項架構決策都會變得顯而易見。
KV Cache 是如何運作的?
要理解為什麼快取如此有效,你需要知道 Transformer 在處理你的提示詞時實際做了什麼。
每個 LLM 推論請求都有兩個階段:

預填充階段(Prefill phase):處理整個輸入提示詞。它會對 Context 中的所有 token 執行密集的矩陣乘法,以建立模型的內部表示。這個階段受限於運算能力且成本高昂。
解碼階段(Decode phase):一次生成一個 token。每個新生成的 token 都會被加入序列中,模型再預測下一個 token。這個階段受限於記憶,因為它主要是在讀取歷史狀態,而不是進行繁重的運算。
在預填充階段,Transformer 會為每個 token 計算三個向量:Query(查詢)、Key(鍵)和 Value(值)。注意力機制(Attention mechanism)利用這些向量來決定每個 token 與其他所有 token 之間的關聯。任何給定 token 的 Key 和 Value 向量僅取決於它之前的 token,一旦計算完成,它們就永遠不會改變。
如果沒有快取,這些 Key 和 Value 張量(Tensors)會在每次請求後被丟棄,下一次請求時又會從頭開始重新計算。對於一個 20,000 個 token 的前綴來說,這意味著有 20,000 個 token 的注意力運算本來是不需要重複進行的。
KV Cache 透過將這些張量持久化在推論伺服器上來解決這個問題,並透過 token 序列的加密雜湊值(Cryptographic hash)進行索引。當一個帶有相同前綴的新請求進來時,雜湊值匹配成功,張量會直接從記憶中載入,這些 token 的預填充運算便完全被跳過。
這將運算複雜度從每個生成 token 的 O(n²) 降低到了 O(n)。對於重複 50 個回合的 20,000 個 token 前綴來說,這是一個巨大的縮減。
經濟效益
定價結構使得這項架構決策變得至關重要。
快取讀取(Cache reads)的成本是基礎輸入價格的 0.1 倍,這意味著每個快取的 token 都有 90% 的折扣。快取寫入(Cache writes)的成本則是 1.25 倍,即儲存 KV 張量需要支付 25% 的溢價。延長一小時的快取則需要 2.0 倍的成本。
以下是 Anthropic 的 Claude 模型在價格上的表現:

這套數學邏輯只有在快取命中率保持在高水準時才成立。目前生產環境中最好的例子就是 Claude Code。
使用 Claude Code 進行 30 分鐘的程式開發
Claude Code 的設計完全圍繞著一個目標:保持快取處於熱門狀態(Keep the cache hot)。
從計費的角度來看,一次 30 分鐘的程式開發過程如下:
第 0 分鐘:Claude Code 載入其系統提示詞、工具定義以及專案的 CLAUDE.md 檔案。這個負載超過了 20,000 個 token,由於每個 token 都是新的,這是整個過程中成本最高的一刻。但你只需要支付一次這筆費用。
第 1 到 5 分鐘:你開始給出指令,Claude Code 指派其 Explore Subagent 來瀏覽程式庫、開啟檔案並執行 grep 指令。所有這些動作都會附加到動態後綴中。但現在那 20,000 個 token 的靜態前綴是從快取中讀取的,價格為每百萬 token $0.30,而不是 $3.00。
第 6 到 15 分鐘:Plan Subagent 接收到的是摘要後的簡報,而不是原始結果,因為傳遞原始輸出會不必要地增加動態後綴的負擔。它產生了一個實作計畫,你批准後,Claude Code 開始進行變更。每個回合都從快取中讀取靜態前綴,命中率攀升至 90% 以上,且每次存取都會重置 TTL(存活時間)以保持快取熱度。
第 16 到 25 分鐘:你要求變更,這意味著更多的工具呼叫、更多的終端輸出,以及更多累積在動態後綴中的 Context。到目前為止,該對話已經處理了數十萬個 token,但每一個回合都從快取中讀取了那 20,000 個 token 的基礎內容。
第 28 分鐘:你在終端機執行 /cost。如果沒有快取,以 Sonnet 4.5 的費率計算 200 萬個 token 將花費 $6.00。而在快取效率達到 92% 的情況下,有 184 萬個 token 是透過快取讀取的,總成本降至 $1.15。這意味著單一任務的成本降低了 81%。

這就是熱門快取的樣子。你只需要為靜態基礎內容支付一次費用,之後就可以免費讀取它。只有動態尾部(Dynamic tail)的部分才會被計費。
基於雜湊(Hash-based)快取的脆弱性
關於 Prompt Caching,最反直覺的一點是:
「1 + 2 = 3」可以運作,但「2 + 1」會導致快取未命中(Cache miss)。
基礎設施會對從開頭開始的完整 token 序列進行雜湊處理。如果該序列中的任何內容發生變化,哪怕只是兩個元素的順序改變,雜湊值就會改變,整個前綴就會以全價重新計算。

這不是一個微小的實作細節,而是 Claude Code 中每一項工程決策所圍繞的核心限制。
以下是生產環境中導致快取失效的真實案例:
注入到系統提示詞中的時間戳記(Timestamp)導致每次請求都產生唯一的雜湊值。
JSON 序列化器在不同請求之間對工具 Schema 的鍵進行了不同的排序,導致前綴失效。
一個在對話中途更新了參數的 AgentTool 抹除了整個 20,000 個 token 的快取。
由此得出三條規則:
不要在對話期間修改工具。工具定義是快取前綴的一部分,因此新增或移除工具會導致後續所有內容失效。
永遠不要在中途切換模型。快取是針對特定模型的,這意味著在中途切換到更便宜的模型需要從頭開始重建整個快取。
永遠不要為了更新狀態而變更前綴。與其編輯系統提示詞,不如在下一個使用者訊息中附加一個提醒標籤,這樣前綴就能保持不變。
將此應用於你自己的 Agent
無論你是使用 Claude Code 還是從頭開始建構自己的 Agent,同樣的規則都適用。
請依照以下順序建構你的提示詞:
系統指令和行為準則放在最上方。不要在中途變更它們。
預先載入所有工具定義。不要新增或移除它們。
接著是檢索到的 Context 和參考文件。在對話期間保持它們穩定。
對話歷史和工具輸出放在最下方。這是你的動態後綴。

在 Anthropic API 上啟用自動快取後,快取斷點會隨著對話的增長自動推進。如果沒有自動快取,你需要手動追蹤 token 的邊界,而錯誤的邊界意味著完全錯失快取。
當你接近 Context 上限需要進行 Context 壓縮時,請使用「快取安全的分叉」(Cache-safe forking)。保持相同的系統提示詞、工具和對話歷史,然後將壓縮指令作為新訊息附加在後面。這樣快取的前綴會被重複使用,唯一會被計費的新 token 只有壓縮指令本身。

要驗證你的快取是否正常運作,請監控每次 API 回應中的這三個欄位:
cache_creation_input_tokens:寫入快取的 token 數量。cache_read_input_tokens:從快取中讀取的 token 數量。input_tokens:未經快取處理的 token 數量。
你的快取效率計算公式為:cache_read_input_tokens / (cache_read_input_tokens + cache_creation_input_tokens)。請像追蹤系統正常運行時間(Uptime)一樣追蹤這個指標。
重點總結
Prompt Caching 不是一個你可以隨意開關的功能,而是一種你需要圍繞它進行設計的架構準則。
核心概念很簡單:建構你的提示詞,讓靜態內容位於上方,動態內容在下方增長。基礎設施會對前綴進行雜湊處理,儲存 KV 張量,並為你隨後的每次讀取提供 90% 的折扣。
但準則在於細節。不要將時間戳記注入系統提示詞中,不要打亂工具定義,不要在中途切換模型,也不要變更快取斷點之前的任何內容。
Claude Code 展示了這在大規模應用下的效果:92% 的快取命中率和 81% 的成本降低。如果你正在建構 Agent 卻沒有圍繞 Prompt Caching 進行設計,那麼你等於放棄了大部分的利潤空間。
以上就是本次分享!
如果你喜歡這篇教學:
找到我 → @_avichawla
我每天都會分享關於 DS、ML、LLM 和 RAG 的教學與見解。
