之前有說過,few-shot 範例每次呼叫都要重複送一次,成本會跟著累加。這幾天談的 Write、Select 也有類似的狀況,被 Write 出去、又被 Select 挑回來的內容,很多時候是穩定不變的(system prompt、固定的 few-shot 範例、長期記憶裡的使用者設定),如果這些內容每一輪都要一字不漏地重送一次,等於每次都在為「同樣的東西」重新付費、重新等待處理。今天要談的 prompt caching,就是解決這個問題的機制。
多數主流廠商的 API 都支援某種形式的「快取」,如果這次請求開頭一大段內容,跟上次請求的開頭完全一樣,API 可以直接讀取先前處理過的結果,不用整段重新計算。快取命中時,這段內容的計費通常只要原價的一小部分,速度也快很多。
關鍵字是「開頭」,這種快取機制是按照內容的前綴(prefix)比對的,只要前綴裡有任何一個字元不一樣,快取就整段失效,等於完全沒省到。這也是為什麼快取的位置要放對:越穩定不變的內容(system prompt、固定的 few-shot 範例)放在前面,越常變動的內容(每次都不一樣的使用者提問)放在最後面。
import os
import anthropic
client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
long_system_prompt = "你是一個客服助理……(此處省略一大段固定規則與說明)"
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
system=[
{
"type": "text",
"text": long_system_prompt,
"cache_control": {"type": "ephemeral"},
}
],
messages=[{"role": "user", "content": "退貨政策是什麼?"}],
)
print(response.usage)
在想要標記為「可以被快取」的內容區塊上加一個 cache_control,之後只要同樣這段內容的請求再送進來,就有機會命中快取。實際命中與否,可以從回傳的 usage 裡面確認,通常會有類似「快取寫入用了多少 token」「快取命中省下了多少 token」的欄位可以核對。
快取不是免費的:第一次把某段內容寫入快取,通常要付出比正常價格更高一點的費用(等於是先繳一筆「登記費」)。之後如果同樣內容被重複讀取到,才會用便宜很多的價格計費。也就是說:
回頭看 Day 7 的情境正好符合:那組固定的三個情緒分類範例,如果系統會持續、大量地呼叫同一組 few-shot prompt,就是很適合快取的內容。
Prompt caching 解決的是「重複內容重複付費」的問題,靠的是前綴比對——穩定的內容放前面、多變的內容放後面,才能真正吃到快取的好處。
Part 3 到這裡告一段落:從 context window 的限制與迷思,到 Write、Select、Compress、Isolate 這套管理框架,再到怎麼用快取省成本。明天要進入 Part 4,來看另一個問題——當 LLM 不只是回答一次,而是要反覆呼叫工具、自己決定下一步時,這個「迴圈」該怎麼設計?