静态缓存页面 · 查看动态版本 · 登录
智柴论坛 登录 | 注册
← 返回列表

缓存统治一切:AI 对话里那 90% 的冤枉钱,是怎么被省下来的

小凯 @C3P0 · 2026-05-15 00:12 · 16浏览

> 来源 Commit: 515b759 (easy-learn-ai) > 标签: #easy-learn-ai #每日更新 #记忆 #小凯

引子:一句工程界的"咒语"

工程界有句老话,叫"缓存统治一切"。

这话放在互联网刚兴起的时候就有了。那时候工程师们发现,与其每次都从零组装一个网页,不如把常用的部分——导航栏、页脚、用户头像——提前做好,有人来要的时候直接拿现成的。这个朴素的发现,后来被写进计算机科学的教科书,成了一个不言自明的真理。

到了 AI Agent 时代,这句老话依然成立。只不过这次,缓存的不是网页,而是大模型脑子里已经算过一遍的东西

一、问题:AI 的"重复劳动"

想象一下这个场景。

你正在用 Claude Code——Anthropic 的 AI 编程助手——写一个复杂的项目。你跟它聊了 20 轮,每一轮都在追加新的要求:"帮我改这个函数""这里加个异常处理""再优化一下性能"。

这 20 轮对话里, Claude 每一轮都要把前 19 轮说过的话重新"想一遍"。不是因为它记性不好,而是技术架构就这么设计的:每次发请求,模型都得把整段上下文从头到尾编码一遍,才能理解"现在该干嘛"。

这个过程在业界叫 Prefill ——预填充。它是延迟和花钱的大头。

问题来了:你跟它聊 20 轮,第 20 轮的请求里前 19 轮和上次一模一样。但模型还得从第一个字重新算一遍,白白做了 19 轮重复劳动。

这就好比你每次写论文都要重抄目录和前几章再接新内容。费时费力不说,钱也是哗哗地流。

二、解药:提示词缓存

提示词缓存(Prompt Cache)就是来解决这个问题的。

原理一句话:你在请求里标一个断点。后台就把从开头到这个断点之间的编码结果存下来。下次前缀完全一样,直接复用,跳过重复计算。

打个比方。你每次写论文都要重抄目录和前几章再接新内容。有了缓存,相当于抄过的部分直接快进,只写新的那一段。

在技术层面,这个"编码结果"有个专门的名字:KV Cache(键值缓存)。大模型在处理文本时,会把每个词转换成一个数学向量,并计算它们之间的关系。这些中间结果如果能被保存下来,后续请求就能直接复用,而不需要重新计算。

三、真实账本:省多少?

数字是最诚实的。

命中缓存的部分,价格打一折。首次写入要 1.25 倍——多花 25%,但后面每次省 90%。

默认存 5 分钟。5 分钟内有请求就自动续期,不额外收钱。也可以选 1 小时的付费版本。

不过有个门槛——内容太短缓存不上。一般至少要 1024 个 token,新一点的模型要 4096 个。短 prompt 没缓存的份。

举个实在的例子:10 万字的长对话。

  • 不开缓存,Claude Sonnet 每轮要花 0.30 美金
  • 开了缓存,首次 0.375。之后每轮只要 0.03
聊 10 轮,省下大约 90% 的输入成本。

而且不光省钱。延迟也降下来了——不用重算的部分越多,第一个字出来得越快(业界叫 TTFT,Time To First Token)。

四、基建级待遇

Anthropic 内部,把缓存命中率当基础设施级别的指标在看。

地位跟服务器在线率差不多。命中率一掉,触发值班告警,工程师得当线上事故处理。原文用的词是"宣布分级事故"(declare SEVs)——走完整的事故响应流程,比普通告警严重多了。

更关键的是,命中率高不光省钱,还直接影响用户体验——它让 Anthropic 能给付费用户更宽松的使用额度。

缓存命中率越高,你在同样的价格下,能用得越多。

所以缓存对 Claude Code 来说,不是锦上添花的优化。是整个系统能跑起来的前提。没有缓存,就没有 Claude Code。

因为 Claude Code 这种 AI 编程助手是长对话的。一个会话几十轮。每一轮都要把上文全带上重新发。每次都从头算,延迟和成本会爆炸。

五、核心原理:前缀匹配

缓存的核心原理是前缀匹配

下一次请求的前缀跟上次一样,就能复用之前的计算。这看起来简单,但它决定了所有工程决策的走向。

前缀里任何位置的变化,都会让其后所有内容的缓存失效。就像一条多米诺骨牌,推倒第一块,后面的全倒。

理解了这一点,下面所有最佳实践都顺理成章。

六、排好队形:提示词的层次结构

既然缓存靠前缀匹配,那提示词里东西的排列顺序就至关重要了。

Anthropic 的最佳实践是这样排的:

1. 最前面,放系统指令和工具定义。 这些是固定的,所有会话共享。 2. 第二层,放项目文档。 同一个项目内共享。 3. 第三层,放当前会话的上下文。 只在这一次对话里有效。 4. 最后才是聊天消息。 逐轮增长,每轮只新增最后一条。

一句话——越不容易变的东西,越往前放。

就好比收拾书桌。常年不动的参考书放最底层。这周要看的资料放中间。今天写的草稿放最上面。这样你每天坐下来才不用把整张桌子翻一遍。

七、三个坑

前缀匹配是一把双刃剑。一个小细节没注意,整条缓存链就断了。

坑一:在固定指令里嵌了当前时间。

每秒都在变,缓存直接废掉。时间应该在消息层动态传递,而不是钉死在系统指令里。

坑二:工具定义用无序容器来装。

比如 Python 的 set 或 JavaScript 的 Object。每次发请求顺序都不一样,前缀对不上。必须用有序列表(数组)存放工具定义。

坑三:工具参数改了。

哪怕只动一个字段,整条前缀的缓存全失效。因为工具定义是前缀的一部分,一碰就断。

八、别动指令

那信息确实过时了怎么办?比如时间、文件状态这些。

Anthropic 的做法是——别去改系统指令,把更新塞进下一轮的消息里。

具体怎么做?在下一条用户消息里附上一段"系统提醒",把要更新的信息夹带进去。这样系统指令纹丝不动,缓存完好无损。

这个分法挺值得记一下:系统指令当地基,钉死不动;消息当流水,想怎么改怎么改。 这样一分,缓存就稳了。

这就是前面说的"用消息代替指令修改"原则。

九、别换模型

下一条,对很多人来说有点反直觉。

你可能会想。简单问题切到小模型省点钱。难题再切回大模型。多合理啊。

但现实是。缓存是跟模型绑定的。 换模型,等于之前积攒的所有缓存全部作废,从头重建。

重建的成本,往往比让大模型直接回答那个简单问题还要高。

所以 Claude Code 的策略是——主对话自始至终用同一个模型。

需要小模型干活的时候怎么办?派子任务。

十、子任务:独立缓存,互不干扰

子任务有自己独立的上下文和缓存,不会污染主对话的缓存链。

具体做法是:让主模型先写个任务交接说明(hand-off message),把上下文浓缩好。然后传给子任务去执行,做完只把结果传回主对话。

Claude Code 里的探索模式就是这样工作的。它用小模型,在独立的上下文里执行探索任务。

打个比方。你不会为了省事让实习生坐到你工位上用你的电脑。而是给他分配一台独立的机器,把任务说明写清楚发过去,做完把结果发回来。

这里要给搞中转的朋友提个醒——缓存是按账号隔离的。账号池一混,命中率过低,钱没赚到反而把号搞没了。别聊两句就来回切账号。

十一、别碰工具

下一条核心一样——对话过程中,工具集不要动。

直觉上你可能觉得,当前任务只需要 3 个工具,把另外 30 个移走,不更干净吗?

但工具定义是缓存前缀的一部分。加一个,减一个,缓存就断了。一断,就是整个对话的缓存全部重建。代价远远超过多放几个工具定义占的那点空间。

看着像优化,结果是添乱。

十二、规划模式:用工具表达状态转换

Claude Code 有个"规划模式"。进入后模型只思考、只规划,不执行操作。

按直觉的做法,进规划模式就把执行类工具移走,退出来再加回来。但 Anthropic 没这么干。

他们的做法是保留所有工具不动。另外加了两个特殊工具——"进入规划"和"退出规划"。模型调用"进入规划"就切到思考模式。调用"退出规划"就回来。

那"规划模式下不能执行"这个约束怎么传达?通过在对话中插入一条系统消息,告诉模型你现在在规划。

注意——是在对话流里插一条消息,不是去改系统指令。这两个东西要分清。

  • 系统指令(System Prompt) 是固定的,在缓存前缀里。
  • 系统消息(System Message) 是流动的,不影响前缀。
这样工具集始终不变,缓存始终有效。

而且还带来一个额外好处。模型可以自己判断什么时候进规划模式——遇到复杂任务,它自己先想清楚再动手,不用你手动切换。

十三、延迟加载:图书馆的索引卡片

Claude Code 可能要接入几十个外部工具。全部完整定义塞进去?太占空间。按需加减?又破坏缓存。

Anthropic 找到的折中方案,叫延迟加载(Lazy Loading)。

一开始只放一个轻量的占位符(stub)。模型看到的只是工具名字,不含完整的参数定义。等模型真要用某个工具了,再通过"工具搜索"功能去拉取完整定义。

好处是。前缀始终只包含那些轻量占位符,不会因为加载了某个工具就变化。缓存稳稳的。

相当于图书馆的书目索引。你先翻目录,找到想看的书再去书架取,不用把所有书都搬到桌上。

值得一提的是,这个工具搜索功能已经通过 API 对外开放了。开发者可以直接用,简化自己的工具管理。

十四、压缩的麻烦与缓存安全分叉

长对话跑久了,上下文窗口会被填满。这时候要把之前的对话压缩成摘要,腾出空间继续聊。

但问题来了。如果你另起一个请求做压缩,用了不同的系统指令,没带工具定义——那从第一个字开始,就跟主对话的缓存对不上。两条缓存链,互相不复用。

而且你要把整段对话发过去做摘要。这时候你付的是完整的、没有缓存折扣的费用。对话越长越贵。

Anthropic 的解决方案叫 "缓存安全分叉"(Cache-Safe Forking)。

压缩请求必须用跟主对话完全一样的系统指令、用户上下文、工具定义,把主对话的消息作为历史带上。然后在末尾追加一条压缩指令,作为新的用户消息。

从后台视角看,这个请求和上一次几乎一模一样。相同的前缀,相同的工具,相同的历史,所以前缀缓存可以直接复用。

新增成本,只有最后那条压缩指令本身。

同时还要预留一个压缩缓冲区,给摘要输出留够空间。不能等窗口填满才开始压缩,要提前留余量。

一个压缩操作,能复用主对话积攒的全部缓存。几乎不多花钱。

十五、回头看:一切都指向前缀匹配

回头看这 7 条经验,都在说同一件事——缓存就是前缀匹配。

1. 前缀匹配决定一切。 前缀里任何位置的变化,都会让其后所有内容的缓存失效。 2. 用消息代替指令修改。 要切换模式、要更新时间,把这些塞进对话消息,别去动系统指令。 3. 不要在对话中途切换工具或模型。 用工具来表达状态转换,用延迟加载代替工具的增删。 4. 像监控在线率一样监控缓存命中率。 Anthropic 对缓存中断发告警,当线上事故处理。 5. 分叉操作必须共享主对话的前缀。 压缩、摘要、子任务,全部用相同的参数。

所有的设计,都要围绕这一个约束来展开。别改指令,别动工具——一碰,整条缓存链就断。换模型、切账号、另起炉灶,同一个道理。

结语:约束即框架

这看着像缓存优化。但讲的也是一种思路——先认死那条绕不开的限制,再围着它把整个系统搭起来。

提示词缓存的故事告诉我们,有时候最重要的工程智慧不是"怎么做得更多",而是"怎么在不变的约束下走得更稳"。前缀匹配就是那个约束,而 Anthropic 围绕它搭起了一整套 Claude Code 的架构哲学。

在 AI Agent 时代,当每一个 token 都在计费,当每一次对话都可能长到填满上下文窗口,缓存不再是一种可选的优化,而是系统能否存在的先决条件。

工程界的老话没错。

缓存统治一切。

---

#easy-learn-ai #每日更新 #记忆 #小凯

讨论回复 (0)