隐式缓存、显式缓存、主动缓存:六家模型 API 的缓存机制差在哪
数据截至 2026-08,价格与限额以各官网为准。本文只讲计费与接入机制,不列具体价格数字。
六家平台的上下文缓存看上去都叫「前缀命中、命中部分按更低价格计费」,但落到代码里是三种完全不同的东西:智谱 GLM、Kimi、阶跃星辰、Grok 走的是纯自动的隐式缓存,你改不了也关不掉;Gemini 在隐式之外还有一套显式缓存,而且它的计费依据里多了一项别家没有的「缓存 token 的存储时长」;MiniMax 也是两套并存,但它把这两套挂在了不同的兼容路径上——OpenAI 兼容路径上是自动的被动缓存,Anthropic 兼容接口里则是用 cache_control 显式打断点的主动缓存。这个差异直接决定了三件事:你要不要改代码、写入缓存那一笔要不要额外掏钱、以及监控面板上该读哪个字段。跨平台迁移时最容易翻车的也正是最后一条——六家的 usage 字段名互不相同,Grok 一家内部三个 API 面就有三个不同的字段名。
三个词先分清:隐式、显式、主动
这三个词不是同义反复,官方文档里它们指向不同的操作。
隐式缓存是系统自动识别重复前缀、自动复用,调用方什么都不用做。智谱 GLM 的文档把它列在功能特性第一条,原话是「隐式缓存,智能识别重复的上下文内容,无需手动配置」。Kimi 的说法更彻底:Context Caching 对所有模型请求自动启用,无需手动创建、无需引用缓存 ID、无需管理 TTL。阶跃星辰和 Grok 同样是自动触发。
显式缓存是 Gemini 的说法。官方把两种模式并列,隐式缓存对 Gemini 2.5 及更新型号默认启用,而显式缓存需要你自己去建、去引用。这里有一个非常容易踩的接口选型坑:Interactions API 只支持隐式缓存,不支持显式缓存;要用显式缓存,必须改用 generateContent API。也就是说这个选择在你挑接口那一刻就定死了,写到一半再想加显式缓存就得换接口重写。
主动缓存是 MiniMax 自造的词,用来跟它自己的被动缓存做区分。文档原话把「在 anthropic API 中使用的需要显式设置参数的缓存模式」称为主动缓存,对应的是在请求体里写 cache_control 块。所以 MiniMax 语境下的「主动」,约等于 Gemini 语境下的「显式」,但走的是 Anthropic 兼容那条路径,跟 OpenAI 兼容那条路径上的被动缓存是两套东西。
搞混这三个词的直接后果,是你在 A 平台写的「显式建缓存」代码搬到 B 平台后一行都用不上,而 B 平台其实一直在悄悄给你省钱、你却以为缓存没生效。
命中条件:前缀匹配是共同底座,门槛和路由是分岔口
六家的底层逻辑高度一致——都是从消息数组开头往后做前缀匹配。Grok 的文档写得最直白:系统检查请求开头有多少条消息与之前的请求完全一致,那一段就是「前缀」,从缓存里取。阶跃星辰的三步描述是查询、命中、未命中后缓存前缀供下次使用。MiniMax 的被动缓存明确了前缀的构建顺序是「工具定义—系统提示词—历史对话内容」,任意模块内容变更都可能影响缓存效果。
分岔口出现在两处。
第一处是最小输入 Token 门槛。 Kimi、MiniMax、阶跃星辰、Gemini 都在文档里明确说了「短于某个长度就不缓存」。Kimi 的措辞是低于门槛的请求不会被缓存而是被丢弃;阶跃星辰说得更具体,缓存以固定大小的 Token 块作为最小单元,Prompt 短于这个长度不会命中;Gemini 则更麻烦一层——隐式缓存有最低输入 token 门槛,而且门槛因模型而异。具体数值都请以各家官方文档当前版本为准,本文不列。智谱 GLM 与 Grok 的文档里没有找到关于最小 Token 门槛的说明。这条差异的实际影响是:同一段短 system prompt,在 A 家能省钱,在 B 家一分不省,而你从 usage 里只能看到 cached 数是 0,看不出是「太短不给缓」还是「前缀被改了」。
第二处是路由。 这是 Grok 独有的一层。官方明确说缓存条目是按服务器存储的,所以强烈建议设置 x-grok-conv-id 这个 HTTP 头,把同一会话的请求路由到同一台服务器上,从而最大化命中率;Responses API 对应的是请求体里的 prompt_cache_key 字段,gRPC 则把 x-grok-conv-id 作为 metadata 传。反过来,如果你想主动制造一次 cache miss,官方给的办法就是换一个 conv id 或者干脆不带这个头。别家文档里没有找到类似的「粘性路由」机制说明。所以从别家迁到 Grok 的人,最典型的症状就是 cached_tokens 一直是 0——不是代码错了,是少了一个 header。
怎么确认自己命中了:六家的字段名没有一个是完全统一的
这是本篇里最该抄走的一段。想做跨平台的成本监控,就得先把这几个字段名对齐。
- 智谱 GLM:
usage.prompt_tokens_details.cached_tokens - Grok(Chat Completions API):
usage.prompt_tokens_details.cached_tokens - Grok(Responses API):
usage.input_tokens_details.cached_tokens - Grok(gRPC / xAI SDK):响应对象上的
cached_prompt_text_tokens - MiniMax(OpenAI 兼容路径):
usage.prompt_tokens_details.cached_tokens - MiniMax(Anthropic 兼容路径):
cache_read_input_tokens,另有cache_creation_input_tokens - 阶跃星辰:
usage下的cached_tokens - Gemini:响应对象的
usage.total_cached_tokens
Kimi 的文档把计费与用量说明指向了产品定价页,本文引用的这一页里没有直接给出字段名。
注意 Grok 那三行:同一家厂商,换个 API 面字段路径就变。这个坑在做统一封装时特别隐蔽,因为代码不会报错,只会安静地读到 undefined,然后你的成本看板上缓存命中率永远是零。
MiniMax 的 Anthropic 兼容路径还给了一条对账等式,值得单独记下来:总输入 token 等于 cache_read_input_tokens 加 cache_creation_input_tokens 加 input_tokens。其中 input_tokens 只是最后一个缓存断点之后的那部分。第一次看到账单时会觉得输入 token 少得离谱,就是因为大头被挪到前两个字段里去了。
什么动作会打断缓存
各家的说法几乎能合并成同一份禁忌清单,但侧重点不同。
Grok 讲得最狠:任何对早先消息的修改都会打断缓存,只能往末尾追加,编辑、删除、重排一律不行。它还点名了一个推理模型专属的坑——必须把上一轮响应里的 reasoning_content 原样带回来,官方把「漏掉它」列为缓存未命中的首要原因;如果不想自己维护,可以改用 previous_response_id 走有状态续话。这条对做 Agent 循环的人极其致命,因为很多框架默认只把 assistant 的可见文本塞回历史。
智谱 GLM 的提醒偏向格式层面:完全相同的内容命中率最高,轻微的格式差异就可能影响缓存效果。所以那些「在 system prompt 里塞个当前时间戳」的写法,等于每次请求都把整段前缀作废。
MiniMax 的主动缓存有一套更结构化的失效规则:缓存遵循 tools → system → messages 的层次,任一级别的改动都会让该级别以及之后的所有级别失效。它还有一个「回溯窗口」的概念——系统从显式断点往前查找匹配时,只会检查有限个内容块,超出窗口还没匹配上就停止查找并退到上一个断点。窗口大小与一次调用允许的断点数量上限都以官方文档当前版本为准;要点是,块数很多的长对话如果只在末尾放一个断点,前面的内容有可能根本没进缓存。
阶跃星辰的失效来自另一个方向:它明说缓存淘汰采用 LRU 策略,系统请求高峰期不使用的缓存更容易被逐出,低峰期缓存生命周期更长。这意味着命中率会随时段波动,官方的建议是较长的 Prompt 尽量避开高峰。Grok 也提醒缓存条目可能因内存压力随时被逐出,并直接要求「你的应用必须在没有缓存的情况下也能正常工作」——这句话应该写进任何缓存优化方案的第一页。
计费结构:写入要不要钱、存储要不要钱
单价去各家定价页看,这里只讲结构,结构才是选型时真正会影响判断的东西。可以配合缓存计费的通用机制一起理解。
第一个结构差异是写入缓存收不收费。MiniMax 把两套模式的差别摆在同一张表里:被动缓存写入缓存的部分无额外计费,主动缓存首次写入缓存的 token 需要额外计费。也就是说主动缓存不是白送的,它用一笔预付的写入成本换取后续的读取优惠,如果你的前缀复用次数不够多,主动缓存反而可能更亏。别家文档里没有找到关于「写入单独计费」的说明。
第二个结构差异是存储收不收费。Gemini 的计费依据是四项:输入 token 数、输出 token 数、缓存的 token 数,以及缓存 token 的存储时长。最后一项是国产平台文档里普遍没有的——缓存内容放在那儿本身就在按存储时长产生费用。Gemini 长上下文场景的主要优化手段就是上下文缓存,把用户上传的文件缓存起来复用,代价是为存储付费。所以 Gemini 的显式缓存要算的是一笔三方账:省下的输入费、多付的存储费、以及你打算放多久。
第三个结构差异是返还还是优惠价。Gemini 隐式缓存的表述是命中后自动返还节省的费用,其余几家的表述都是命中部分按更低价格计费。两种口径在对账时的呈现方式不一样,看月账单要留意。
第四个是计费范围的例外。智谱 GLM 的文档特意加了一条提示:上下文缓存的差异化计费仅适用于标准 API 计费,不包括资源包和 GLM Coding Plan 套餐。这类「套餐用户不适用」的边界条件在别家文档里没找到对应说明,但它足以让一次成本测算完全跑偏——具体到 GLM 的账单口径可以看GLM 的计费方式。
另外 Grok 提到长上下文档位的判定:当总输入 token(包含缓存的 token)超过模型的长上下文阈值时,适用长上下文价格,缓存与非缓存 token 各自按对应的长上下文费率计。别以为缓存命中就能把你从高价档里拉出来——它不能。
能缓存什么:多模态和工具调用
这一节各家给的信息量差距很大。
阶跃星辰列得最全:完整的对话数组会进缓存,包含 System Prompt、User Message 和 Assistant Message;用户消息里的图片和视频信息也会进缓存,但前后必须是相同的图片、相同的视频;对话中的工具调用信息及其调用结果同样参与缓存。做多模态问答的人应该重点看这条——图片换一张,缓存就断了。
Grok 明确说缓存对流式和非流式请求都生效,并且可缓存前缀包含到工具调用结果为止,只要前缀不变后续请求就能受益。MiniMax 的主动缓存则列出了可以打 cache_control 的块类型:tools 数组里的工具定义、system 数组里的内容块、messages.content 里的文本块,以及 tool_use 和 tool_result 类型的块。MiniMax 的被动缓存把「固定的工具清单」直接列为典型适用场景之一。
Kimi 把系统提示词、知识文档、工具定义并列为会被自动复用的初始上下文,并给了一条排布建议:把固定的大段上下文放在 messages 数组的最前面,用户问题和模型回复追加其后。Gemini 的建议是同一个意思的另一种说法——把较大且常见的内容放在提示开头,并在短时间内发送具有相似前缀的请求。
顺带一提,Kimi 的文档里还有一段少见的横向说明:Context Caching 与 RAG 的取舍。它给的判断是,频繁查询固定内容(比如 FAQ、文档问答)优先用 Context Caching;内容极长且查询方向不固定时,可以考虑 RAG。这个判断不涉及任何价格,跨平台都成立。
命中率不对劲时的排查顺序
把六家文档里的排查建议合并,顺序大致是这样:
- 确认字段读对了。 先按上面那张字段清单核一遍,尤其是同一厂商多个 API 面的情况。看到 0 之前,先确认你读的不是
undefined。 - 确认长度过了门槛。 阶跃星辰的排查清单里第三条就是「验证是否提供了足够长的输入」,Kimi 和 Gemini 也都有门槛。短 prompt 不命中是设计如此,不是故障。
- 确认前缀真的一字未改。 时间戳、随机 ID、JSON 字段顺序、末尾空格,都算改动。GLM 明确说了轻微格式差异会影响效果。
- 确认间隔时间。 阶跃星辰的排查第二条是检查两次请求间隔是否太长导致缓存失效;MiniMax 的主动缓存有固定生命周期、命中后自动续期;GLM 说缓存有合理时效性,过期后重新计算。缓存都是短命的。
- Grok 用户单独查路由。
cached_tokens持续为 0,先看x-grok-conv-id或prompt_cache_key有没有带上。 - 推理模型单独查
reasoning_content。 这是 Grok 点名的首要原因。 - 别指望必中。 阶跃星辰明说不提供保证始终命中的缓存,也不提供手动清除缓存的能力(想不命中就改 prompt);Grok 明说缓存命中并非必然。把缓存当成优化项而不是依赖项。
最后:迁移时最容易失效的三个假设
第一个假设是「缓存都是自动的,代码不用动」。到了 Gemini 的显式缓存和 MiniMax 的主动缓存这里就不成立,而且 Gemini 那个选择还绑死在你选哪个 API 上。
第二个假设是「省下的钱能对得上」。写入是否额外计费、存储是否单独计费、是优惠价还是返还、套餐用户适不适用——四个变量任意一个不同,你上一家的成本模型就搬不过来。这部分建议对照换厂商的迁移清单逐项过一遍。
第三个假设是「监控面板照搬」。六家字段名没有一个完全统一,Grok 一家内部就有三种。真要做统一封装,建议在适配层里为每家单独写一个提取函数,而不是靠一个万能路径去猜。
要动手的话,最省事的起点是先给现有代码加一层缓存命中率的埋点,让面板先跑起来一周,再决定要不要为某家改 prompt 结构。没有数据就调整前缀顺序,改完你也不知道到底有没有变好。