文件

文件

提示快取

使用 cache_control 將穩定的提示前綴標記一次;或者使用 OpenAI 格式(此格式沒有該欄位)呼叫 Claude 模型,Kunavo 會為您設定快取斷點。後續每次重複使用此前綴的呼叫,都會以輸入價格的一小部分計費 — 大多數聊天模型按輸入價格的 10% 計費,最低可至 2.5%。Kunavo 的路由層會將對話固定到相同的上游金鑰,讓快取保持暖機狀態。

使用 Claude Sonnet 5 處理 30K token 的系統提示時,快取讀取的費用為 $0.14 / 1M,而非 $1.4 / 1M。 對於每個工作階段會重送相同上下文 50 次的代理程式,快取可節省約 90% 的輸入費用。

如何啟用

在任何系統區塊、訊息或工具定義上加入 cache_control: { type: "ephemeral" } 斷點。模型會在第一次呼叫時快取至該斷點為止的內容;之後只要呼叫共用相同的前綴位元組,就會命中快取。

cache_example.py
from openai import OpenAI

client = OpenAI(
    api_key="sk-kn-...",
    base_url="https://api.kunavo.com/v1",
)

# Mark the large, stable prefix once with cache_control.
# Every subsequent call that sends the same prefix reads it back
# from cache at 0.10× the input rate on Claude Sonnet 5.
# Per-model rates are in the pricing table below.
SYSTEM = [
    {
        "type": "text",
        "text": open("long_system_prompt.txt").read(),
        "cache_control": {"type": "ephemeral"},
    },
]

resp = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[
        {"role": "system", "content": SYSTEM},
        {"role": "user", "content": "Summarize the doc above in 3 bullets."},
    ],
)

u = resp.usage
# OpenAI-compat fields populated by Kunavo:
# - prompt_tokens_details.cached_tokens — read from cache
# - cache_creation_input_tokens          — written to cache this call
print(u.prompt_tokens_details.cached_tokens,
      getattr(u, "cache_creation_input_tokens", 0))

在原生 Messages API 上使用完全相同的傳輸格式 — cache_control 會原樣傳遞給 Claude,不經翻譯:

messages_api.sh
# Native Anthropic Messages API — cache_control passes through untranslated.
curl https://api.kunavo.com/v1/messages \
  -H "Authorization: Bearer $KUNAVO_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "system": [
      {
        "type": "text",
        "text": "<your large stable system prompt>",
        "cache_control": { "type": "ephemeral" }
      }
    ],
    "messages": [
      { "role": "user", "content": "Summarize the doc above in 3 bullets." }
    ],
    "max_tokens": 1024
  }'
位元組必須保持一致。快取鍵是以內容定址的。前綴中的任何位置只要有一個字元不同,就會使該段內容的快取失效。請將動態內容(時間戳記、使用者名稱、每次呼叫的 ID)放在快取區塊之後,不要放在區塊內。

在 OpenAI 格式端點上自動插入斷點

OpenAI Chat Completions 和 Responses 格式完全沒有 cache_control 欄位 — OpenAI 會在自己的伺服器上自動進行隱式快取。Claude 則不會:只有斷點標記的內容才會被快取。因此,使用 OpenAI 格式的用戶端無法要求快取;若只是直接翻譯請求,送到 Claude 的請求就不會帶有任何斷點 — 長對話的每一輪都會以完整輸入費率,重新計費整段對話歷史。

因此,當您透過 /v1/chat/completions 或 /v1/responses 呼叫 Claude 模型時,Kunavo 會補上該協定無法承載的斷點。您不需要另外啟用任何設定。這只適用於 Claude 模型 — 其他所有模型系列都使用供應商會自動隱式快取的協定,因此不需要插入斷點。

no_cache_control.py
# Plain OpenAI Chat Completions — no cache_control anywhere in the body.
# The format has no field for one; Kunavo inserts the breakpoints instead.
resp = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[
        {"role": "system", "content": LONG_SYSTEM_PROMPT},
        {"role": "user", "content": "first question"},
        {"role": "assistant", "content": "...previous answer..."},
        {"role": "user", "content": "follow-up"},
    ],
)

u = resp.usage
# Turn that writes the cache:
#   u.cache_creation_input_tokens            -> 18,000
#   u.prompt_tokens_details.cached_tokens    ->      0
# Next turn, same prefix, inside the 5-minute window:
#   u.cache_creation_input_tokens            ->    240   (only the new turn)
#   u.prompt_tokens_details.cached_tokens    -> 18,000
#
# Both stuck at 0 on a conversation well over the threshold? The prefix is
# changing between calls — a timestamp or request id inside the cached span.

斷點會插入的位置,以及預算的使用順序:

  • 在最後一則訊息上放置滾動斷點 — 放在最後一則訊息的最後一個內容區塊上,讓它快取之前的所有內容;如果請求以一則留在對話中的 system 訊息結尾(見下文),則改放在該訊息前面緊鄰的內容區塊上。只有在 messages 已有 assistant 回合時才會加入:快取寫入會按 1.25× 輸入計費,因此標記不會再次傳送的提示,會多花四分之一費用卻毫無節省。先前的 assistant 回合表示這個完全相同的前綴即將再次送出。
  • 在 system 放一個,在 tools 放一個 — 提示中的穩定開頭。即使是只呼叫一次的請求,也值得標記,因為呼叫方若送過一次系統提示,幾乎總會在下次呼叫時送出相同的提示。
  • 在留在對話中的 system 訊息前面 — 滾動斷點和 system、tools 上的斷點用剩的額度,會放在最後一則後面還有內容的此類訊息前面緊鄰的內容區塊上,接著是再前面的一則。它排在最後填入,因為只有會在不同回合之間移動此類訊息的用戶端才需要它;沒有此類訊息的對話(幾乎所有對話都是如此)就沒有這個位置。

有兩項限制。若提示內容少於 8,192 個字元 — 包含訊息、system 和工具結構描述 — 系統完全不會插入斷點:Anthropic 會靜默忽略低於其最低可快取長度(1,024 個 token,Haiku 為 2,048 個 token)的前綴上的斷點,也不會收取寫入或讀取費用,因此在此插入斷點沒有作用。另一項限制是,Anthropic 每個請求最多接受 4 個斷點 — 第五個斷點會直接觸發 400 錯誤,不會被靜默忽略。

模型首次回答之後送出的 system 或 developer 訊息會留在對話中,留在它送出時所在的那個回合,而不會被提到 system 中:那樣做會在加入它的那個回合改變提示的開頭,並把整段歷史重新寫入快取。在上游接受的情況下,Claude 會以 system 訊息的形式收到它;否則,它會成為該使用者回合中的文字,放在 <system-reminder> 標籤之間。在模型首次回答之前送出的 system 訊息,或其自身斷點要求一小時快取的訊息,仍會放入 system。

您自行設定的斷點絕不會被移動或移除。它們會占用相同的 4 個斷點額度,而 Kunavo 只會填入您留空的位置。如果您自行設定 4 個斷點,系統就不會再新增;如果您設定 1 個,系統最多會在其他位置再加 3 個。額度有限時,系統會優先填入最深處的位置 — 提示後段的斷點會快取之前的所有內容,因此滾動斷點最有價值。使用原生 /v1/messages 端點時,系統完全不會插入斷點:您的主體會依原樣傳遞,其中的每個斷點都由您設定。
斷點不代表快取命中。它只標記可快取的前綴;要命中快取,仍須在 Anthropic 的暫存快取有效期間內(五分鐘,每次讀取都會重新計時)再次傳送相同的前綴位元組,並且路由至相同的上游金鑰;下方介紹的親和性路由就是為此設計。全新前綴的第一次呼叫一定是寫入,不會是讀取;無論斷點放在哪裡,每一回合都改變的提示都不會命中快取。

報告方式不變:無論斷點是由您還是閘道設定,在 回應欄位一節所述的相同 cached_tokens 和 cache_creation_input_tokens 欄位都會填入資料,因此您可透過用量物件確認自動插入的斷點是否確實命中快取。

定價

快取費率會依各模型的輸入價格,按照供應商規定的比例計算 — 以下表格是定價依據,當中每個費率都是根據該模型的輸入價格計算,而非手動輸入。Anthropic 和 OpenAI 的快取讀取費率皆為輸入費率的 0.10×,其中有2 個例外:0.025× on Claude Fable 5.1, 0.05× on Claude Opus 5.5。快取寫入在所有 Claude 模型上 ,以及在 GPT-6 Astra、GPT-6 Sol、GPT-6 Luna、GPT-5.6 Sol和GPT-5.6 Terra 上皆按輸入費率的 1.25× 計費。Kunavo 對 Claude 的 1 小時 TTL 寫入也按相同的 1.25× 費率收費,低於 Anthropic 的 2×。其他所有模型皆無單獨的寫入價格:寫入會按一般輸入費率計費。無論如何,前綴只要重用一次,快取費用就會低於以未快取內容重新傳送的費用。每種快取類別都沿用模型本身的折扣,因此其快取價格相對於供應商牌價的折扣幅度,與輸入和輸出價格的折扣幅度相同。

Anthropic

ModelInputCache readCache write
Claude Fable 5.1$7$0.175 0.025×$8.75 1.25×
Claude Fable 5$7$0.7 0.10×$8.75 1.25×
Claude Opus 5.5$2.8$0.14 0.050×$3.5 1.25×
Claude Opus 5$3.5$0.35 0.10×$4.375 1.25×
Claude Opus 4.8$3.5$0.35 0.10×$4.375 1.25×
Claude Opus 4.7$3.5$0.35 0.10×$4.375 1.25×
Claude Opus 4.6$3.5$0.35 0.10×$4.375 1.25×
Claude Sonnet 5$1.4$0.14 0.10×$1.75 1.25×
Claude Sonnet 4.6$2.1$0.21 0.10×$2.625 1.25×
Claude Haiku 4.5$0.7$0.07 0.10×$0.875 1.25×

OpenAI

ModelInputCache readCache write
GPT-6 Astra$4$0.4 0.10×$5 1.25×
GPT-6 Sol$0.8$0.08 0.10×$1 1.25×
GPT-6 Luna$0.04$0.004 0.10×$0.05 1.25×
GPT-5.6 Sol$2$0.2 0.10×$2.5 1.25×
GPT-5.6 Terra$0.7$0.07 0.10×$0.875 1.25×
GPT-5.5$2$0.2 0.10×$2 1×
長提示會按供應商的長上下文級別計費。超過門檻後,整個請求會按模型輸入與輸出價格的倍數計費,也包含快取讀取和寫入:超過 272K 個輸入 token 時,GPT-6 Astra、GPT-6 Sol、GPT-6 Luna、GPT-5.6 Sol、GPT-5.6 Terra和GPT-5.5 的費率為(輸入 2×,輸出 1.5×)。 Claude 沒有長上下文附加費:其 1M 上下文按標準費率計費。
目錄價格底線已納入快取費率。Kunavo 每次呼叫收取 max(catalog_cost, upstream × markup) — 底線是按快取輸入費率計算,而非未快取費率,因此節省的費用會直接反映在您支付的價格上。
上述費率是目錄價格。每次呼叫的實際費用,會先根據模型實際耗用的上游額度計算(再加上加價),然後以目錄價格作為底線。命中快取時,上游收取的額度較少 — 因此「上游費用乘以加價」通常會低於目錄價格,最後由目錄價格這一項決定費用。簡言之,目錄價格是您的最高價格;快取呼叫可能低於此價格,但絕不會更高。

親和性路由讓快取保持暖機

上游提示快取是依 API 金鑰分開計算的。如果每個請求都隨機路由至不同的上游金鑰,快取命中率就會是 ~1/N。Kunavo 會根據您的系統提示和第一則使用者訊息產生穩定雜湊,並將具有相同前綴的所有呼叫路由至相同的上游金鑰 — 採用加權 Rendezvous 雜湊,因此變更金鑰池時,重新對應的金鑰僅約為 1/N。

您不需要設定任何項目。親和性路由會自動套用至所有聊天呼叫。(圖片/影片/TTS 使用隨機路由 — 這些模態沒有依金鑰區分的快取。)

儀表板指標

呼叫開始命中快取後,/app/usage 會顯示所選時間範圍的兩項彙總指標:

  • 命中率 — 快取輸入 token ÷ 總輸入 token。此數值依每次呼叫的 token 數精確計算。
  • 節省金額 — 這段期間節省的 USD,按模型分別計算,使用模型實際的快取讀取費率(不採用統一平均值估算)。此數值是以目錄費率估算 — 由於實際費用以目錄價格為底線,且快取呼叫的費用可能低於底線,因此此數字是實際節省金額的緊密上限。一般聊天工作負載的兩者差距在幾個百分點以內。

每次呼叫的詳細頁面(/app/usage/<id>)會在快取與快取寫入 token 數不為零時顯示其數量,以及實際計費金額。

回應欄位

Kunavo 會在兩種回應格式中提供快取 token 資訊。在 OpenAI 相容的 /v1/chat/completions 端點:

欄位意義
usage.prompt_tokens輸入 token 總數(包含快取與快取寫入 token)。
usage.prompt_tokens_details.cached_tokens由快取提供的輸入 token 子集。
usage.cache_creation_input_tokens這次呼叫寫入快取的 token(按上方表格所列的模型快取寫入費率計費)。

在 /v1/messages 的原生 Messages API 上,Anthropic 原有欄位會直接傳遞:

欄位意義
input_tokens未快取的新輸入。
cache_read_input_tokens由快取提供,按 0.10× 輸入價格計費(在Claude Fable 5.1上的比例為0.025×,在Claude Opus 5.5上的比例為0.05×)。
cache_creation_input_tokens本次呼叫寫入快取的內容(按輸入費率的 1.25 倍計費 — 也包含 1 小時 TTL 寫入,費率低於 Anthropic 的 2 倍)。

接下來可以查看

  • Messages API 參考 — Anthropic 原生格式,附有完整的快取範例。
  • Claude 提示快取 — 用量物件中用於診斷快取的數值,以及透過閘道進行路由時造成命中率下降的三種情況。
  • 計費與帳本 — 快取感知的 max() 底線如何與上游成本互動。
  • 完整定價表 — 所有聊天模型的未快取輸入/輸出價格,表格底部另附快取價格表。