OpenAI、Claude 与 Gemini 三家的提示词缓存对比
三家提供方都会缓存提示词前缀以削减输入成本与延迟,但控制方式各不相同:自动缓存、显式断点、隐式缓存。一份实用对比。
如果你的多次提示词共享一个又长又稳定的前缀——一大段系统指令、一份工具目录、一份你反复追问的文档——提示词缓存能让提供方跳过对该前缀的重新处理,并以陡峭的折扣计费。OpenAI、Anthropic 和 Google 三家都提供了这一能力,而且各处的收益都一样:更低的输入成本,以及被缓存部分更快的首字时间。区别在于由谁决定什么被缓存。OpenAI 按前缀自动缓存。Anthropic 让你显式标记缓存点。Gemini 默认隐式缓存,同时也暴露了一个显式的缓存对象。本文将梳理这三种控制方式、各自返回的用量字段,以及如何组织一个提示词才能让缓存真正命中。
最后核对:2026-07-15。各模型的最小尺寸、TTL 和定价倍率会变动;在依赖某个具体数字之前,请对照每家提供方所链接的定价与缓存页面确认。
三家共享的唯一规则:缓存前缀,变化后缀
每家提供方缓存的都是提示词的前缀,并按精确字节匹配。实际后果在各家都一样:把保持不变的部分放在前面,把会变化的部分放在最后。系统提示词、少样本示例、工具定义和一份大的参考文档属于顶部;用户当前的问题属于底部。把它们重新排序,你就移动了"可缓存"与"不可缓存"之间的边界,而一个靠前的单次编辑——哪怕只是注入系统消息里的一个时间戳——就会让其后的一切失效。这是你能做的杠杆率最高的改动,而且它是免费的。
缓存也有一个最小尺寸。短提示词不值得缓存,提供方也干脆不缓存,所以只有当被缓存的前缀跨过一个随模型而异的阈值时,折扣才会出现。低于它,你付的是正常输入费率,看到的缓存 token 是零。
OpenAI:自动、基于前缀、由 prompt_cache_key 微调
OpenAI 的缓存是自动的——你无需选择加入。对于长度达到 1024 token 或以上的提示词会自动启用缓存,匹配依据是提示词前缀。当一个请求复用了一个已被缓存的前缀时,被复用的 token 会以打折的缓存输入费率计费,并出现在用量对象中的 cached_tokens 里:在 Chat Completions 上位于 usage.prompt_tokens_details 下,在 Responses API 上位于 usage.input_tokens_details 下。低于阈值的请求报告的 cached_tokens 为零。
你无法直接控制缓存,但可以用 prompt_cache_key 影响路由。共享一个长公共前缀、但来自不同用户或路径的请求可能落到不同的缓存后端;在相关请求上设置相同的 prompt_cache_key,会与前缀哈希结合起来把它们路由到一处,从而提升命中率。在较新的模型上,这个 key 正是让匹配变得可靠的东西,而且 OpenAI 建议把每个 key 的流量保持适度,而不是每分钟通过单个 key 猛灌数千个请求。
保留时间是可控的。较新的模型接受带 ttl 的 prompt_cache_options(30 分钟是支持的最短生存期,也是默认值),而较早的模型使用 prompt_cache_retention,其内存中的条目通常在几分钟无活动后仍保持活跃,并可延长至最多 24 小时。在最新的模型上,写入缓存的 token 会作为 cache_write_tokens 单独报告,并按未缓存输入费率的 1.25 倍计价;较旧的模型不额外收取写入费。网关会把 prompt_cache_key 和 prompt_cache_retention 直接透传给上游,因此你能在同一个基础 URL 背后保留同样的旋钮。
Anthropic:cache_control 标记,可自动也可显式
Anthropic 只缓存 cache_control 标记所覆盖的内容,但你不必手工放置每一个断点。它有两种模式。自动缓存在请求顶层添加一个 cache_control 字段;系统会把断点放在最后一个可缓存内容块上,并随着对话增长向后移动,适合低维护成本的多轮聊天。显式断点则把 cache_control 直接放到各个内容块上,让你精确控制缓存范围。下面的示例在一份稳定的操作手册后放置显式断点:
import anthropic
client = anthropic.Anthropic(base_url="https://your-gateway.example.com", api_key="AVE_GATEWAY_API_KEY")
client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
system=[
{"type": "text", "text": "You are a contract analyst."},
{
"type": "text",
"text": LONG_STATIC_PLAYBOOK, # the expensive, stable prefix
"cache_control": {"type": "ephemeral"},
},
],
messages=[{"role": "user", "content": "Summarize the indemnity clause."}],
)
你最多可以定义 4 个缓存断点(顶层自动标记会占用其中一个),从而缓存变化频率不同的区段——例如把很少修改的系统提示词放在一个断点后,把每次会话的文档放在另一个断点后。最小可缓存长度取决于模型(许多当前模型,包括 Claude Opus 4.8 和 Sonnet 5,从 1,024 token 起缓存;部分层级要求 2,048 或 4,096),而短于最小值的提示词会被静默地按未缓存方式处理——不会报错,只是没有折扣。
用量记账是显式的,值得仔细读。响应会返回三个独立的计数:cache_creation_input_tokens(写入一个新缓存条目的 token)、cache_read_input_tokens(从缓存提供的 token),以及 input_tokens(最后一个断点之后的一切)。总输入是这三者之和,如果两个缓存计数都为零,那就是什么都没缓存。默认缓存生存期是 5 分钟,每次条目被使用时免费刷新,因此一个被活跃命中的缓存实际上会一直保持温热;一个 "ttl": "1h" 选项能以更高的写入成本延长它。定价倍率是公开的:一次 5 分钟缓存写入的成本是基础输入的 1.25 倍,一次 1 小时写入是 2 倍,而每次缓存读取的成本是基础输入的 0.1 倍。那个 10 倍的读取折扣,正是值得费这个劲的原因。
Gemini:默认隐式,需要控制时转为显式
Google 的默认最省事:隐式缓存对 Gemini 2.5 及更新的模型自动启用,当一个请求命中缓存时会自动传递成本节省。你把提示词组织成公共内容在前,把前缀相似的请求在时间上凑近发送,然后从用量元数据里读取被缓存的 token 计数。这里同样有最小值——当前的 Flash 和 Pro 层级从数千 token 的低位开始缓存,而更新的一代要求更大的前缀。
当你需要有保证的缓存和显式的生存期控制时,Gemini 的 generateContent API 通过一个 CachedContent 对象提供显式上下文缓存:你把内容上传一次,收到一个句柄,设置一个 TTL,然后在后续调用中引用这个句柄。对于你确知会复用的内容(一份长 PDF、一段视频、一套固定指令),显式缓存保证了折扣,而不是把它交给隐式启发式去碰运气。被缓存的 token 计数会出现在 usageMetadata 中(在 generateContent 上作为 cachedContentTokenCount),网关会把它归一化成它为其它提供方所报告的同一个缓存 token 字段。
网关能归一化什么、不能归一化什么
在一个 OpenAI 兼容端点背后,网关会转发每家提供方能够理解的缓存控制项,并把不同的用量字段折叠成统一的记账形态——读取用 cached_tokens,另加缓存创建计数——因此无论上游是谁,缓存请求都能以同一种方式出现在使用日志中。网关还会应用可配置的计费比率:缓存读取按低于正常输入费率计费,缓存写入使用缓存创建比率(默认 1.25 倍),并在公开的 定价页 上按模型发布。
不过要把边界说清楚。三家提供方并不暴露相同的旋钮,因此归一化在两个方向上都是有损的:
- 控制并非一一对应。 OpenAI 按前缀缓存,没有显式断点的概念;Anthropic 要求
cache_control标记(自动标记或最多四个显式断点),也没有 OpenAI 式的隐式前缀缓存;prompt_cache_key对 Gemini 毫无意义。透传会转发上游支持的内容,并忽略它不支持的字段。 - TTL 语义不同。 OpenAI 的
ttl是一个最短生存期,Anthropic 的是一个使用时刷新的固定 5 分钟(或 1 小时)窗口,而 Gemini 的显式 TTL 是按缓存对象设置的。"一小时"在三家上并不是同一个意思。 - 用量词汇不同。 Anthropic 把 5 分钟和 1 小时的缓存创建分开;OpenAI 只在较新的模型上把读取和写入分开;Gemini 报告单一的缓存内容计数。网关会把这些映射成公共字段,但无法凭空造出一个提供方从未报告过的区分。
把网关当成那个给你一个统一计费视图和一条透传路径的地方,而不是一个让三种不同缓存设计表现得完全一致的层。拿不准时,就读网关记录的原始用量,并把它与提供方自己的文档对账。
让缓存真正命中
有四个习惯决定了缓存是帮上忙还是悄无声息地毫无作为:
- 把稳定内容前置。 指令、工具和参考材料在前;用户轮次在最后。这是最重要的那一条规则。
- 让前缀保持字节稳定。 在被缓存的区域里不要有时间戳、请求 ID 或被打乱顺序的工具排列。靠前的一个字节改动就会让其余部分失效。
- 把相关请求在时间上凑近发送。 缓存会过期;在 TTL 窗口内把相似的工作批量处理能让条目保持温热。一个空闲的缓存就是一个冷缓存。
- 用用量数据验证,而不是凭感觉。 在宣称有节省之前,先确认
cached_tokens(或提供方的等价物)非零。你假定却从未测量的缓存,是想象中的成本削减的一个常见来源。
提示词缓存是 降低 LLM API 成本 这份更广的成本工作清单上回报最高的一项,而且它与 LLM 上下文窗口管理天然相配:你所缓存的那个稳定前缀,往往正是你本会在每一轮重新发送并重新计费的上下文。
常见问题
缓存也会降低输出 token 成本吗?
不会。缓存只作用于输入(提示词)token——那个提供方可以复用的前缀。输出 token 每次调用都是全新生成的,无论缓存状态如何都按正常输出费率计费。如果你的成本由长生成而非长提示词主导,缓存动的是错误的那个数字;去看输出长度和模型选择吧。
如果缓存读取和缓存写入计数都为零,是缓存失败了吗?
它意味着那个请求什么都没缓存——通常是因为前缀低于模型的最小可缓存尺寸、前缀自上次调用以来变了,或者(对显式方案而言)你没标记断点。提供方不会对一个不可缓存的提示词报错;它们只是按标准输入费率计费。读用量字段去确认,而不要假定命中了。
只要我重发完全相同的前缀,缓存命中就有保证吗?
没有。缓存是尽力而为且有时间界限的。条目在其 TTL 之后过期,而命中还取决于路由——这正是 OpenAI 暴露 prompt_cache_key 来把相关请求引向同一后端的原因。把缓存设计成一个通常有帮助的优化,而不是一个你能据以计费的保证。
一个网关请求能不能可互换地使用 OpenAI、Anthropic 和 Gemini 的缓存?
你可以通过一个端点发送缓存控制项,但每一个都只被它自己的上游理解:cache_control 抵达 Anthropic,prompt_cache_key 抵达 OpenAI,一个显式的 CachedContent 句柄抵达 Gemini。网关会把被报告的用量归一化成公共字段;它无法让一家提供方去遵守另一家的缓存指令。
测量一次真实的前后对比
挑出最常重复的提示词——也就是固定前缀最大的那个——在一分钟内通过网关运行两次。第一次调用把前缀写入缓存;第二次应该从缓存读取。检查使用日志,确认第二个请求报告了非零缓存 token,并且输入费用低于第一次。基于你自己流量的这组前后对比,比任何公开倍率都更能说明真实节省。