# Gemini 显式缓存 — cachedContents API Source: https://ofox.ai/zh/docs/develop/advanced/gemini-explicit-cache Gemini 的缓存分两种: - **隐式缓存**(自动)— 模型自动识别重复的 prompt 前缀并复用,无需任何配置。这是 [提示缓存](https://ofox.ai/zh/docs/develop/advanced/prompt-caching) 一文讲的默认行为,命中是「尽力而为」(best-effort),前缀有任何微小变化都可能不命中。 - **显式缓存**(本文)— 你**主动**把一段大上下文创建为一个缓存对象,拿到一个 `cachedContents/{id}` 句柄,之后的 `generateContent` 请求显式引用它。命中是**确定性**的,只要缓存未过期,引用就一定命中。 当你有一份**反复使用、内容稳定的大上下文**(长文档、代码库、知识库、固定 system 指令),且希望**命中率可控、计费可预期**时,用显式缓存。 OfoxAI 支持 Gemini 原生 `cachedContents` 的 **创建 / 引用 / 查询 / 删除**,兼容 Google GenAI SDK。端点级参考见 [cachedContents API](https://ofox.ai/zh/docs/api/gemini/cached-contents)。 ## 何时用显式缓存 | 场景 | 推荐 | |------|------| | 大段固定上下文反复问答(文档 QA、代码助手)| ✅ 显式缓存 | | 需要**确定**命中、不能容忍偶发未命中 | ✅ 显式缓存 | | 短小、低频、前缀多变的请求 | ❌ 用隐式缓存即可,无需管理缓存对象 | | 上下文每次都变 | ❌ 缓存无意义 | 显式缓存要求被缓存的内容达到**最小 token 门槛**(约 2048~4096 token 起,因模型而异)。内容太小创建会失败或无收益。 ## 端点 OfoxAI 在 Gemini 原生协议下提供完整 cachedContents 端点: ```http 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`: ```http POST https://api.ofox.ai/gemini/v1beta/models/{model}:generateContent ``` ## 认证 与其他 Gemini 端点一致,使用 `x-goog-api-key` Header: ```bash x-goog-api-key: <你的 OFOXAI_API_KEY> ``` ## 完整流程 下面演示一条完整链路:**创建缓存 → 引用缓存生成 → 删除缓存**。 ### 1. 创建缓存 把要复用的大段上下文放进 `contents`,指定 `model` 和 `ttl`(存活时长): **Python** ```python filename="create_cache.py" showLineNumbers 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.8-flash", config=types.CreateCachedContentConfig( contents=[LONG_DOCUMENT], ttl="600s", # 缓存存活 10 分钟 ), ) print(cache.name) # cachedContents/xxxxxxxx —— 后续引用的句柄 ``` **TypeScript** ```typescript filename="create_cache.ts" showLineNumbers import { GoogleGenAI } from '@google/genai' import fs from 'node:fs' const ai = new GoogleGenAI({ apiKey: '<你的 OFOXAI_API_KEY>', httpOptions: { apiVersion: 'v1beta', baseUrl: 'https://api.ofox.ai/gemini' }, }) const longDocument = fs.readFileSync('knowledge_base.txt', 'utf-8') const cache = await ai.caches.create({ model: 'google/gemini-3.8-flash', config: { contents: [longDocument], ttl: '600s', // 缓存存活 10 分钟 }, }) console.log(cache.name) // cachedContents/xxxxxxxx —— 后续引用的句柄 ``` **cURL** ```bash filename="Terminal" curl "https://api.ofox.ai/gemini/v1beta/cachedContents" \ -H "x-goog-api-key: $OFOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "google/gemini-3.8-flash", "contents": [ { "role": "user", "parts": [{ "text": "<这里放一大段需要复用的上下文>" }] } ], "ttl": "600s" }' ``` 返回的 `name`(形如 `cachedContents/xxxxxxxx`)是缓存句柄,请保存它用于后续引用与管理。 ### 2. 引用缓存生成 在 `generateContent` 请求里通过 `cachedContent` 引用缓存句柄,`contents` 只需放**本次新增的问题**: **Python** ```python filename="use_cache.py" showLineNumbers response = client.models.generate_content( model="google/gemini-3.8-flash", contents="根据上面的文档,总结三条要点", config=types.GenerateContentConfig( cached_content=cache.name, # 引用缓存 ), ) print(response.text) # 缓存命中:被缓存的部分按更低的「读」价计费 print(response.usage_metadata.cached_content_token_count) ``` **TypeScript** ```typescript filename="use_cache.ts" showLineNumbers const response = await ai.models.generateContent({ model: 'google/gemini-3.8-flash', contents: '根据上面的文档,总结三条要点', config: { cachedContent: cache.name, // 引用缓存 }, }) console.log(response.text) // 缓存命中:被缓存的部分按更低的「读」价计费 console.log(response.usageMetadata?.cachedContentTokenCount) ``` **cURL** ```bash filename="Terminal" curl "https://api.ofox.ai/gemini/v1beta/models/google/gemini-3.8-flash:generateContent" \ -H "x-goog-api-key: $OFOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "cachedContent": "cachedContents/xxxxxxxx", "contents": [ { "role": "user", "parts": [{ "text": "根据上面的文档,总结三条要点" }] } ] }' ``` 命中时,响应 `usageMetadata.cachedContentTokenCount` 会显示走缓存的 token 数。同一缓存可被**任意多次**引用,每次都确定性命中,直到过期。 ### 3. 查询与删除 查询缓存元信息、或在不再需要时主动删除(无需等 TTL 到期): **Python** ```python filename="manage_cache.py" showLineNumbers # 查询 info = client.caches.get(name=cache.name) print(info.expire_time) # 删除 client.caches.delete(name=cache.name) ``` **TypeScript** ```typescript filename="manage_cache.ts" showLineNumbers // 查询 const info = await ai.caches.get({ name: cache.name }) console.log(info.expireTime) // 删除 await ai.caches.delete({ name: cache.name }) ``` **cURL** ```bash filename="Terminal" # 查询 curl "https://api.ofox.ai/gemini/v1beta/cachedContents/xxxxxxxx" \ -H "x-goog-api-key: $OFOX_API_KEY" # 删除 curl -X DELETE "https://api.ofox.ai/gemini/v1beta/cachedContents/xxxxxxxx" \ -H "x-goog-api-key: $OFOX_API_KEY" ``` 查询 / 删除**不需要**再传 `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` 单价以 [模型目录](https://ofox.ai/zh/models) 与控制台用量统计为准。 ## 在 OfoxAI 上的增强:确定性路由 OfoxAI 在多 GCP 区域 / 多 Vertex 项目间做负载均衡。显式缓存是 **region-scoped(区域绑定)** 的:缓存创建在哪个 GCP 项目,引用就必须命中同一个项目,否则会 404。 OfoxAI 自动处理了这一点:**创建缓存时记录该缓存绑定的上游实例,后续凭缓存句柄反查并硬锁回同一上游**。无论你的引用请求是否带 user 标识、负载如何调度,引用都会被精确路由到创建缓存的那个项目,**零漂移**。你无需关心底层区域分布。 缓存归属做了越权保护:缓存句柄只能被创建它的 API Key(及同归属)引用 / 查询 / 删除,跨账户访问会被拒绝(403)。 ## 显式缓存 vs 隐式缓存 | 维度 | 隐式缓存(自动)| 显式缓存(cachedContents)| |------|---------|---------| | 触发方式 | 自动识别重复前缀 | 主动创建缓存对象并引用 | | 命中确定性 | 尽力而为,前缀微变即可能未命中 | 确定性,未过期必命中 | | 需要管理 | 无 | 需创建 / 引用 / 删除句柄 | | 适用 | 短小、前缀偶尔重复 | 大段、稳定、反复复用的上下文 | | 计费 | 命中即享读价折扣 | 创建付写价 + 引用享读价折扣 | 两者可叠加使用。日常请求让隐式缓存自动生效即可;对**确定要反复复用的大上下文**,再用显式缓存锁定命中。隐式缓存的细节见 [提示缓存](https://ofox.ai/zh/docs/develop/advanced/prompt-caching)。 ## 相关文档 - [提示缓存(隐式缓存 / 各协议通论)](https://ofox.ai/zh/docs/develop/advanced/prompt-caching) - [Gemini generateContent API](https://ofox.ai/zh/docs/api/gemini/generate-content) - [模型目录与定价](https://ofox.ai/zh/models)