Grok 缓存怎么影响计费:省在哪、怎么看命中

2026-08-25
站内工具 大模型 API 价格对比表 → 豆包 / GLM / Kimi / 千问 / DeepSeek 等 9 家厂商单价并排看,可按币种筛选、按价格排序,每行链到官方定价页。

数据截至 2026-08,价格与限额以各官网为准。本文只讲计费与接入机制,不列具体价格数字。

一句话讲完:xAI 的提示缓存是自动生效的,你不需要显式开启,命中的那部分提示 token 会按「缓存提示 token 价」计费,而不是按常规提示 token 价;能不能省钱,只取决于命中了多少 token,而命中数就明明白白写在响应的 usage 里——Chat Completions 走 usage.prompt_tokens_details.cached_tokens,Responses API 走 usage.input_tokens_details.cached_tokens,xAI 官方 SDK 的 gRPC 路径走 response.usage.cached_prompt_text_tokens。真正容易亏钱的不是缓存没开,而是你以为它在生效、其实每一轮都在重新计算全量提示。所以这篇的重点不是「缓存好不好」,而是:读哪个字段、三种取值分别代表什么、单次实际扣费从哪看、命中长期为零时按什么顺序排。

缓存省的是哪一段钱,四类 token 各按什么价

先把计费口径摆清楚,不然后面看命中数也没意义。官方 prompt-caching/usage-and-pricing 那一页给了一张明确的对照表,把一次请求里的 token 分成四类,各自适用不同费率:

  • 非缓存的提示 token:按完整的提示 token 价计费;
  • 缓存命中的提示 token:按「缓存提示 token 价」计费,官方原文的说法是这个价格显著低于常规提示价;
  • 补全 token:按完整的补全 token 价计费;
  • 推理 token:也按补全 token 价计费。

第四条是最容易被忽略的一条。很多人默认「推理过程是模型内部的事,应该另算或者不算」,但官方把 reasoning_tokens 归到了补全侧的费率里。这意味着一件事:缓存再怎么命中,也只影响提示侧,压不住推理侧的开销。如果你的调用是长系统提示 + 短问题 + 深度推理,缓存能帮你省下的比例,和那些长上下文、浅输出的场景完全不是一个量级。具体单价一律以官方定价页为准,本文不列数字,也建议你别把某个时点的价格写进代码注释里。

还有一条更隐蔽的规则写在同一页的备注里:当提示 token 总量(含缓存部分)超过该模型的长上下文阈值时,会切换到长上下文计费档,而且缓存与非缓存两部分都各自适用其长上下文费率。翻译成人话就是——缓存不会帮你把请求「拉回」到普通档位,它只是在长上下文档位里给缓存那部分打了折扣。所以真要控成本,先控上下文长度,再谈提高命中率,顺序不能反。跨厂商的通用口径可以对照缓存计费的通用机制那篇看,Grok 这套属于其中的「自动前缀缓存」流派。

命中数从哪读:三套接口三个位置

这是本文最实用的一节。同一件事,xAI 在三条接入路径上放在了三个不同的字段里,抄错一个就永远读到 None

Chat Completions API,命中数在 usage.prompt_tokens_details.cached_tokens。官方给的响应示例里,prompt_tokens_details 这个对象下面同时还有 text_tokensaudio_tokensimage_tokens 三个兄弟字段,别看错层级。补全侧对应的是 completion_tokens_details,里面有 reasoning_tokensaudio_tokensaccepted_prediction_tokensrejected_prediction_tokens

Responses API,字段路径变了:命中数在 usage.input_tokens_details.cached_tokens,推理 token 在 usage.output_tokens_details.reasoning_tokens。注意这里连外层名字都从 prompt_tokens 变成了 input_tokens。如果你同时维护两条接入路径,最好在自己的埋点层做一次字段归一,否则统计口径迟早对不上。

xAI 官方 SDK 的 gRPC 路径,字段名又不一样,官方示例里读的是 response.usage.cached_prompt_text_tokens。官方对这个字段的说明是:它表示有多少提示 token 是从缓存里取的、而不是被重新计算的,数值越高代表缓存利用得越好、成本越低。官方在同一份 token 用量说明里还单列了 prompt_image_tokens,并写明视觉内容产生的 token 与文本 token 是分开计数的,没有图像或视频时这个值为零。所以带图像输入的请求,两侧用量在文档口径里本来就是分列的,读命中数之前先确认你读的是哪一侧。

顺带说一个坑:官方文档明确写了 Vercel AI SDK 目前不会把成本字段透出到响应元数据里。文档给出的替代路径是改用 OpenAI SDK 或者直接调 REST。这属于「官方明说的限制」,不是猜测,做技术选型时值得先记一笔。

cached_tokens 的三种取值,分别意味着什么

官方在 usage-and-pricing 那一页给了一张判读表,我按实际排查顺序重新讲一遍:

取值为 0,是缓存未命中,整段提示都被从头计算了一遍。官方明确说了,这在首次请求或缓存被驱逐之后是预期行为,不是故障。单次为 0 完全不用惊慌。

取值大于 0,是命中,数值本身就是被复用的 token 数。多轮对话里健康的形态是这个数字随轮次单调上升——第一轮为 0 建立缓存,第二轮命中第一轮的量,第三轮命中前两轮的累计量,以此类推。你可以把这个「是否单调上升」做成一条监控曲线,比盯绝对值有用得多。

取值等于 prompt_tokens,是全量命中。官方给的说明是这种情况罕见,典型场景是你把完全相同的请求又发了一次。如果你在生产环境频繁看到全量命中,那大概率不是缓存太强,而是你的上游有重复提交。

单次到底扣了多少:cost_in_usd_ticks

如果说 cached_tokens 回答的是「命中了多少」,那 cost_in_usd_ticks 回答的就是「这一次实际扣了多少」。官方在成本追踪那一页写得很直接:每一次推理响应的 usage 对象里都带这个字段,Chat Completions、Responses API、图像生成、视频生成四类响应都有。

有三个属性值得记住:

第一,它是按请求粒度的实际扣费,而不是估算值——官方原文强调这是「实际计费金额,已经应用了所有适用的折扣,其中就包括提示缓存带来的减免」,并且包含了服务端工具调用产生的费用。也就是说,你不需要自己拿 token 数乘单价去反推缓存省了多少,直接读这个字段就行。这里要澄清一个常见的误会:缓存没有开关。官方原文写的是 xAI API 自动执行提示缓存,整份文档里也找不到任何用来关掉它的参数,所以并不存在「开缓存前 / 开缓存后」这样一组可以对照的状态。想做对照只有一个官方给过的办法——FAQ 里回答「能不能强制制造一次未命中」时说的是换一个 x-grok-conv-id 或者干脆不带这个头,请求会被路由到另一台没有你这段前缀缓存的服务器上。拿这样一次未命中的请求,和一次正常命中的请求比 cost_in_usd_ticks,才是文档支持的对照方式。

第二,它的单位是 tick 而不是货币单位,是一个整数。官方解释了为什么这么设计:ticks 能表达小于一分钱的精度且不引入浮点舍入误差,当你要把成千上万次请求的费用累加起来对账时,这一点很关键。tick 与货币金额之间的换算系数写在官方成本追踪文档里,本文不复述具体数值。xAI SDK 另外提供了一个便捷属性直接给出换算后的金额,同时也保留原始整数字段供做精确累加。

第三,流式请求要特别处理。用 xAI SDK 流式时,每个 chunk 都携带一个累计值,最后一个 chunk 是本次请求的最终费用;但用 OpenAI SDK 或裸 REST 流式时,必须在请求上加 stream_options: { include_usage: true },而且费用只出现在最后那个 choices 为空的 chunk 里,中间 chunk 完全没有 usage 数据。很多人的埋点在流式场景下统计不到成本,根源就是这个开关没打开,或者读到空 choices 的 chunk 就提前 break 掉了。这条和API 成本监控怎么做里讲的通用埋点原则是一回事,只是 Grok 这边字段名更具体。

命中长期为零,按这个顺序排

单次为 0 是正常的,同一会话里连续多次为 0 才是问题。官方给的排查线索集中在这几条:

第一步查会话路由标识有没有带上。 缓存条目是按服务器存的,官方推荐设置 x-grok-conv-id 这个 HTTP 头(Responses API 则是在请求体里放 prompt_cache_key 字段,官方说明两者作用相同),把同一会话的请求路由到同一台服务器上。SDK 的 gRPC 路径则是把 x-grok-conv-id 作为 gRPC metadata 传入。文档里 FAQ 甚至反过来说了:想强制制造一次未命中,就换一个 conv id 或者干脆不带这个头。所以「不带头」本身就等价于放弃了稳定命中,这一条排第一位。具体配置写法可以看怎么把 Grok 的缓存命中率做上去

第二步查有没有动过历史消息。 官方的警告写得非常重:任何对早先消息的编辑、删除、重排都会打断前缀匹配,只允许在末尾追加。文档专门用四个 curl 例子演示了「追加新消息命中」「改写某条助手消息未命中」「删掉一条消息未命中」「把 system 和 user 调换顺序未命中」。这里最容易踩的其实是那些自作聪明的中间层——比如自己实现的历史裁剪、摘要压缩、敏感词替换,它们改的都是早先消息,一改缓存就归零。

第三步,如果你用的是推理模型,查 reasoning_content 有没有回传。 官方原文把这一条点名为推理模型缓存未命中的首要原因:多轮对话必须把上一轮响应里的加密推理内容带回去,漏掉就断。文档给了两条路径,要么显式回传加密的推理内容(Responses API 侧通过 include: ["reasoning.encrypted_content"] 取得),要么用 previous_response_id 走有状态续话让服务端自己接。

第四步,接受它本来就不保证。 官方明确写了缓存条目可能因为内存压力或服务器重启在任何时刻被驱逐,请求也可能被路由到别的机器,所以缓存命中不是承诺。官方给出的工程建议是:你的应用必须在没有缓存的情况下也能正常工作。把命中率当优化项而不是当依赖,这个心态很重要。

到月底对账:控制台的用量拆解维度

响应字段解决的是单请求可观测,跨天跨 Key 的对账还得回控制台。官方 Usage Explorer 那一页说明这是给团队管理员用的用量查看页,能力边界大致是:

  • 时间粒度可调,官方举的例子是切到按日查看消耗;
  • 统计维度默认按金额口径,也可以切成 token 数量或计费项数量;
  • 分组可以按 API Key 分,官方举的场景就是把测试 Key 和生产 Key 的消耗放在一起对比——这个用法很实在,很多团队的账单异常最后查出来是测试脚本没停;
  • 过滤支持按某个 API Key、某个模型、请求 IP、集群、token 类型来筛。

最后那个「按 token 类型筛」是这篇的落点:它让你能把缓存命中的那部分 token 单独拉出来看趋势。如果某天命中占比突然塌下去,多半是那天上线的某个改动动了系统提示或者历史消息处理逻辑,对着发布记录一比就找到了。账单侧的通用排查思路可以参考API 账单暴涨怎么排查

最后几条容易栽的坑

别指望缓存改善输出质量,也别担心它拖累质量。 官方 FAQ 回答得很干脆:缓存只加速提示处理阶段,模型输出与从头计算时完全一致。所以任何「开了缓存回答变差了」的直觉,八成是别的变量在起作用。

流式和工具调用都支持缓存,不用为此关掉它们。 官方说明流式与非流式都可缓存,流里第一个空 token 对应的就是缓存查找与预填充阶段;工具调用场景下,可缓存前缀包含直到工具调用结果为止的全部消息,只要前缀不变,后续请求照样受益。

结构上把静态内容前置。 官方最佳实践里第四条讲的就是这个:系统提示、few-shot 示例、参考文档放在最前面,让它们构成一段稳定前缀。这是设计期决定的事,等上线后再调整消息顺序,反而会把已有缓存全打断一次。

支持范围以定价页为准。 官方说提示缓存在所有 grok 语言模型上可用,同时又让你去定价页确认哪些模型支持缓存以及各自的缓存 token 价。这两句话并不矛盾——前者说的是能力面,后者说的是计价面,接入前两边都看一眼更稳妥。

下一步建议做一件很小但收益很高的事:在你的调用封装里,把 cached_tokensprompt_tokenscost_in_usd_ticks 三个字段一起落到日志,按会话 ID 聚合。有了这三列,缓存到底有没有在工作、哪一次发布把它打断了、这个月的钱花在哪一段,全都能自己算出来,不用等账单。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。