Gemini 顯式快取(cachedContents)
Gemini 的快取分兩種:
- 隱式快取(自動)— 模型自動辨識重複的 prompt 前綴並複用,無需任何設定。這是 提示快取 一文講的預設行為,命中是「盡力而為」(best-effort),前綴有任何微小變化都可能不命中。
- 顯式快取(本文)— 你主動把一段大上下文建立為一個快取物件,拿到一個
cachedContents/{id}控制代碼,之後的generateContent請求顯式引用它。命中是確定性的,只要快取未過期,引用就一定命中。
當你有一份反覆使用、內容穩定的大上下文(長文件、程式碼庫、知識庫、固定 system 指令),且希望命中率可控、計費可預期時,用顯式快取。
OfoxAI 支援 Gemini 原生 cachedContents 的 建立 / 引用 / 查詢 / 刪除,相容 Google GenAI SDK。端點級參考見 cachedContents API。
何時用顯式快取
| 場景 | 推薦 |
|---|---|
| 大段固定上下文反覆問答(文件 QA、程式碼助手) | ✅ 顯式快取 |
| 需要確定命中、不能容忍偶發未命中 | ✅ 顯式快取 |
| 短小、低頻、前綴多變的請求 | ❌ 用隱式快取即可,無需管理快取物件 |
| 上下文每次都變 | ❌ 快取無意義 |
顯式快取要求被快取的內容達到最小 token 門檻(約 2048~4096 token 起,因模型而異)。內容太小建立會失敗或無收益。
端點
OfoxAI 在 Gemini 原生協議下提供完整 cachedContents 端點:
POST https://api.ofox.ai/gemini/v1beta/cachedContents # 建立
GET https://api.ofox.ai/gemini/v1beta/cachedContents/{id} # 查詢
DELETE https://api.ofox.ai/gemini/v1beta/cachedContents/{id} # 刪除引用快取做內容生成,仍走標準 generateContent 端點,只是在請求體裡帶上 cachedContent:
POST https://api.ofox.ai/gemini/v1beta/models/{model}:generateContent認證
與其他 Gemini 端點一致,使用 x-goog-api-key Header:
x-goog-api-key: <你的 OFOXAI_API_KEY>完整流程
下面示範一條完整鏈路:建立快取 → 引用快取生成 → 刪除快取。
1. 建立快取
把要複用的大段上下文放進 contents,指定 model 和 ttl(存活時長):
Python
from google import genai
from google.genai import types
client = genai.Client(
api_key="<你的 OFOXAI_API_KEY>",
http_options={"api_version": "v1beta", "base_url": "https://api.ofox.ai/gemini"},
)
# 一份反覆使用的大文件(需達到最小 token 門檻)
LONG_DOCUMENT = open("knowledge_base.txt").read()
cache = client.caches.create(
model="google/gemini-3.1-pro-preview",
config=types.CreateCachedContentConfig(
contents=[LONG_DOCUMENT],
ttl="600s", # 快取存活 10 分鐘
),
)
print(cache.name) # cachedContents/xxxxxxxx —— 後續引用的控制代碼回傳的 name(形如 cachedContents/xxxxxxxx)是快取控制代碼,請保存它用於後續引用與管理。
2. 引用快取生成
在 generateContent 請求裡透過 cachedContent 引用快取控制代碼,contents 只需放本次新增的問題:
Python
response = client.models.generate_content(
model="google/gemini-3.1-pro-preview",
contents="根據上面的文件,總結三條要點",
config=types.GenerateContentConfig(
cached_content=cache.name, # 引用快取
),
)
print(response.text)
# 快取命中:被快取的部分按更低的「讀」價計費
print(response.usage_metadata.cached_content_token_count)命中時,回應 usageMetadata.cachedContentTokenCount 會顯示走快取的 token 數。同一快取可被任意多次引用,每次都確定性命中,直到過期。
3. 查詢與刪除
查詢快取中繼資料、或在不再需要時主動刪除(無需等 TTL 到期):
Python
# 查詢
info = client.caches.get(name=cache.name)
print(info.expire_time)
# 刪除
client.caches.delete(name=cache.name)查詢 / 刪除不需要再傳 model。OfoxAI 憑快取控制代碼即可定位到這條快取。
生命週期與 TTL
建立時透過 ttl 指定存活時長,格式為以 s 結尾的秒數字串(如 "600s")。
| 參數 | 取值 |
|---|---|
| 最小 / 預設 TTL | 600s(10 分鐘) |
| 最大 TTL | 3600s(1 小時) |
- 快取在 TTL 內可被反覆引用、確定性命中。
- TTL 到期後快取自動失效,再引用會報錯(快取已不存在)。
- 可隨時主動
delete提前釋放。
TTL 過期或已刪除的快取被引用時,請求會失敗。請在用戶端處理「快取失效」的情況(捕捉錯誤後重新建立快取或退回普通請求)。
計費
顯式快取按 token 透明計費,分三部分:
| 階段 | 計費公式 | 說明 |
|---|---|---|
| 建立快取 | totalTokenCount × cache_write 單價 | 按「快取寫入」價計費,totalTokenCount 來自建立回應的 usageMetadata,即被快取的 token 數 |
| 引用命中 | cachedContentTokenCount × cache_read 單價 | 被快取部分按「快取讀取」價計費,約為標準輸入價的 0.10x,大幅低於全量重發 |
| 引用時的新內容 | 本次新增的 prompt / 輸出按標準價 | 即你每次提的新問題、模型的新回答 |
收益模型:建立時付一次「寫」費,之後每次引用被快取的內容都按低價的「讀」價計費,省下「整段上下文按全價重發」的開銷。引用次數越多,越划算。 各模型的 cache_write / cache_read 單價以 模型目錄 與控制台用量統計為準。
在 OfoxAI 上的增強:確定性路由
OfoxAI 在多 GCP 區域 / 多 Vertex 專案間做負載平衡。顯式快取是 region-scoped(區域繫結) 的:快取建立在哪個 GCP 專案,引用就必須命中同一個專案,否則會 404。
OfoxAI 自動處理了這一點:建立快取時記錄該快取繫結的上游實例,後續憑快取控制代碼反查並硬鎖回同一上游。無論你的引用請求是否帶 user 標識、負載如何排程,引用都會被精確路由到建立快取的那個專案,零漂移。你無需關心底層區域分佈。
快取歸屬做了越權保護:快取控制代碼只能被建立它的 API Key(及同歸屬)引用 / 查詢 / 刪除,跨帳戶存取會被拒絕(403)。
顯式快取 vs 隱式快取
| 維度 | 隱式快取(自動) | 顯式快取(cachedContents) |
|---|---|---|
| 觸發方式 | 自動辨識重複前綴 | 主動建立快取物件並引用 |
| 命中確定性 | 盡力而為,前綴微變即可能未命中 | 確定性,未過期必命中 |
| 需要管理 | 無 | 需建立 / 引用 / 刪除控制代碼 |
| 適用 | 短小、前綴偶爾重複 | 大段、穩定、反覆複用的上下文 |
| 計費 | 命中即享讀價折扣 | 建立付寫價 + 引用享讀價折扣 |
兩者可疊加使用。日常請求讓隱式快取自動生效即可;對確定要反覆複用的大上下文,再用顯式快取鎖定命中。隱式快取的細節見 提示快取。