提示词缓存失效的真相:时间戳放错位置,每次调用都在付全价

提示词缓存依赖前缀精确匹配,任何开头的动态内容都会让缓存失效、按全价计费。
文章从一个“没有报错的性能问题”切入:服务商提供了 prompt caching,但账单和延迟毫无变化,仪表盘显示缓存的 token 接近零。原因在于提示词第一行写着精确到秒的当前时间,导致每个请求从第一个字符起就完全不同,缓存前缀永远无法命中。文章进一步指出,时间戳只是最显眼的例子,系统提示词里的用户名、顺序不固定的工具列表、调试用的 request id、随机挑选的示例,都会以同样隐蔽的方式破坏前缀稳定性。解法是按变化频率重排提示词:不变的指令和文档放最前,会话级内容居中,请求级内容(日期、用户、问题)放最后。改完后应通过响应中的 usage 块核对缓存 token 数并记录成本,快速定位顶部附近的动态内容。更普遍的原则是:系统的排列顺序应反映各部分的变化频率。
一个没有报错的性能问题
提示词很长,而且大部分是固定的:四千个 token 的指令、一份产品手册、十几个示例。用户真正的问题,写在最底部。
服务商提供了 prompt caching(提示词缓存)。有人把它打开了。可账单纹丝不动,延迟也纹丝不动。仪表盘上显示,被缓存的 token 几乎为零。
没有报错,没有告警,只是钱一直照付。问题出在提示词的第一行——那里写着当前的日期和时间,精确到秒。

这行字加得有充分理由:模型需要知道今天是哪一天。但它被放在了最糟糕的位置。
提示词缓存只认前缀,不认相似
理解这个坑,需要先理解缓存的工作方式。
服务商保存的是你提示词开头部分处理后的结果,后续请求只有在前缀 token 完全一致时,才能复用这段缓存。注意,不是“相似”,而是从第一个 token 一直到被缓存的那个点,必须一模一样。
开头哪怕只差一个字符,后面所有内容都会被当作全新内容重新处理,按全价计费。
第一行里的时间戳,让每一个请求从第一个字符开始就各不相同。缓存里存下的前缀,永远不会被再次发送。于是缓存相当于开了个寂寞。
更隐蔽的同类问题
时间戳是最显眼的那个,但不是唯一的。
系统提示词里带上用户名,每个用户都不同;工具列表由字典生成,字典顺序在两次运行之间会变;有人为了调试加进去的 request id;为了让模型看到多样性而随机挑选的示例——这些都会悄悄破坏前缀的稳定性,而且不像时间戳那样一眼可见。
它们的共同点是:位于提示词靠前的位置,却在每次调用时发生变化。
什么是 token:大语言模型并不直接处理字符或单词,而是把它们切分成更小的单元,称为 token。一个英文单词可能对应一个 token,也可能被拆成两三个;中文往往一个汉字对应一到两个 token。模型计费、上下文长度限制、缓存命中判断,全部以 token 为单位进行。文中所说的“四千个 token”,大致相当于三千个左右的英文单词。
前缀缓存的粒度:许多服务商(如 Anthropic、OpenAI、Google)的 prompt caching 都以 token 序列作为匹配单位,而不是字符串。这意味着即便两段文字在人眼看来完全相同,只要底层 token 化结果不同(例如空格、换行或编码方式的细微差异),缓存也无法命中。因此“从第一个 token 开始必须一模一样”这条规则比字面理解还要严格,甚至连格式上的小动作都可能让整段缓存作废。
按“变化频率”重排你的提示词
作者 Serguey Asael Shinder 给出的解法很朴素:按内容变化的频率来排序提示词。
永远不变的内容放最前面:指令、固定顺序的工具定义、参考文档、示例。
每个会话变化的内容放中间。
每个请求都会变的内容放最后:日期、用户、问题本身。
时间戳应该挪到底部,紧挨着它所描述的那个问题。这样前缀保持稳定,缓存才真正生效。
用 usage 字段验证,而不是靠感觉
改完之后,要去看每一个响应里的 usage 块。它会告诉你有多少输入 token 来自缓存。把这个数字和成本一起记录下来。
判断标准很直接:如果提示词大部分是重复的,而缓存 token 数接近零,说明提示词顶部附近有东西在动。顺着这个线索排查,通常能很快定位到那行不该出现的动态内容。
为什么中间层要放会话级内容:会话级内容(例如多轮对话历史、当前任务的上下文)在一次用户会话内是稳定的,但跨会话会变化。把它放在稳定前缀之后,可以在同一会话的多轮请求之间持续复用前半段缓存;一旦会话结束,新的前缀又是从头稳定开始,不会被上一个会话污染。
缓存的 TTL 与命中条件:大多数服务商的缓存有生存时间(通常几分钟到一小时),且需要显式标记缓存断点。即便前缀完全一致,如果两次请求间隔超过 TTL,或者没有在正确位置打上缓存标记,也一样不会命中。排查“缓存失效”时,除了前缀是否稳定,也要确认这两项配置是否正确。
usage 字段通常包含哪些信息:主流 API 的响应里都会返回一个 usage 对象,里面常见几个字段:input_tokens(本次输入总 token 数)、output_tokens(生成 token 数)、cache_creation_input_tokens(本次写入缓存的 token 数)、cache_read_input_tokens(本次从缓存读取的 token 数)。不同服务商命名略有差异,但语义相近。
如何把数字转成判断:比较 cache_read_input_tokens 与 input_tokens 的比值。如果提示词绝大部分是固定内容,而缓存读取量长期接近零,几乎可以断定前缀在每次请求间发生了变化。反之,如果这个比值稳定在较高水平,说明缓存正在生效。把这两个数字和每次调用的实际费用并列记录,就能在不看代码的情况下定位问题发生的时间点。
一条容易被忽视的工程原则
这件事的价值不只是一个省钱技巧。它揭示了一个更普遍的工程规律:系统的排列顺序,应该反映各部分的变化频率。
缓存只能帮到那些你以相同顺序发送两次的内容。把稳定的部分放在前面,并且让它保持不动——这条原则适用于提示词缓存,也适用于任何基于前缀匹配的优化机制。
一行为了“让模型知道今天几号”而加的时间戳,代价是每次调用都按全价重新处理四千个 token。改起来可能只需要几分钟,但前提是,你得先意识到缓存没生效这件事本身。
相关推荐

AGENTS.md 实战指南:让编程 Agent 真正好用
AGENTS.md 和 CLAUDE.md 能显著提升编程 Agent 表现,但研究发现用错反而让成本上升 20%。本文详解该写什么、该删什么、200 行与 32KB 的硬边界、Monorepo 嵌套规则及安全提醒。

花旗AI编程代理Devon:年省30%技术外包费,1.4万工程师已使用
花旗集团利用AI编程代理Devon,一年内削减30%技术供应商费用,1.4万工程师使用,产品发布提速30%-40%。本文分析其对IT外包行业的冲击及未来人机协作模式。

从生日派对到千亿AI帝国:新一代PayPal黑帮崛起
2015年一张生日派对合影,十年后催生Scale AI、Cognition AI等千亿估值AI公司。解析新一代PayPal黑帮的创业路径、互相投资生态,以及Peter Thiel的Founders Fund如何完成代际传承。