教程Claude Code系列第 2 / 8 篇

提示词缓存为什么这么重要:Claude Code 团队的五条经验

根据 Claude Code 团队的文章整理:他们把整个产品围绕提示词缓存来设计。缓存按前缀匹配,所以提示词的顺序、会话中途换模型、增减工具、压缩上下文的做法,都会决定缓存还在不在。讲清这五条经验,以及对使用者和开发者各有什么用。

发布 · 约 5 分钟读完 · 经人工审核()· 本站的内容怎么来的

本文根据公开分享整理,本站尚未实测。操作前请对照文末的原始来源。

本页目录(8 节)
  1. 先理解一件事:缓存是按前缀匹配的
  2. 经验一:不变的放前面,会变的放后面
  3. 经验二:信息要更新时,用消息,不要改提示词
  4. 经验三:会话中途不要换模型
  5. 经验四:会话中途不要增减工具
  6. 经验五:压缩上下文时,也要沿用同一个开头
  7. 五条经验放在一起
  8. 对你有什么用

这是“Claude Code 开发系列”的第二篇,上一篇是 Claude Code 的工具是怎么设计的。

这一篇解决的问题是:一个要连续工作很久的智能体,怎么才不至于又慢又贵? Claude Code 团队的回答是提示词缓存。原文作者 Thariq Shihipar 说,他们的整个产品是围绕缓存来搭的:缓存命中率高,成本就低,订阅套餐的用量限制才能给得宽。他们给缓存命中率设了告警,命中率太低会按线上事故来处理。

对使用者来说,这篇解释了很多“为什么”:为什么会话中途换模型不划算,为什么计划模式不是换一套工具,为什么 MCP 服务器最好在会话开始时就接好。

先理解一件事:缓存是按前缀匹配的

提示词缓存的规则是:从请求的开头算起,到某个缓存断点为止,内容一模一样才算命中。 前面任何一处变了,它后面的全部作废。

所以顺序非常重要。要让尽可能多的请求共享同一个开头。

经验一:不变的放前面,会变的放后面

Claude Code 的提示词是这样排的:

顺序 内容 能共享到什么范围
1 固定的系统提示词和工具定义 所有会话
2 CLAUDE.md 同一个项目里的会话
3 会话的上下文 同一个会话
4 对话消息 每一轮都在增长

这个顺序很脆弱。作者列了他们自己弄坏过的几种方式:

  • 在固定的系统提示词里放了一个精确的时间戳;
  • 工具定义的顺序每次不一样;
  • 改了某个工具的参数(比如代理工具能调用哪些代理)。

经验二:信息要更新时,用消息,不要改提示词

提示词里的信息有时会过期,比如当前时间,或者用户改了某个文件。直觉是去更新提示词,但那会让缓存失效,对用户来说可能很贵。

Claude Code 的做法是:把更新的信息放进下一条用户消息或工具结果里,用一个 <system-reminder> 标签包起来。前面的内容没有变,缓存就还在。

经验三:会话中途不要换模型

缓存是按模型分开的。这会带来一个反直觉的结果:

你和 Opus 的对话已经有 10 万 token 了,这时想问一个很简单的问题。切到 Haiku 来回答,反而比让 Opus 回答更贵,因为要给 Haiku 把缓存重新建一遍。

确实需要换模型时,最好的办法是用子代理:让主模型准备一段“交接说明”,把要做的事交给用另一个模型的子代理。Claude Code 的 Explore 代理就是这样,它用的是 Haiku。

经验四:会话中途不要增减工具

这是最常见的弄坏缓存的方式之一。直觉上,只给模型当前需要的工具更合理;但工具定义是缓存前缀的一部分,增加或删除一个工具,整段对话的缓存就全部失效。

团队围绕这条限制设计了两个功能。

计划模式

直觉的做法是:用户进入计划模式时,把工具换成只读的那一套。但这会破坏缓存。

实际的做法是:所有工具始终都在请求里,“进入计划模式”和“退出计划模式”本身也是两个工具。用户打开计划模式时,模型收到一条系统消息,说明它现在处于计划模式、该怎么做:探索代码库,不要改文件,计划做好了就调用退出的工具。工具定义从头到尾没变过。

这还带来一个额外的好处:因为“进入计划模式”是模型自己可以调用的工具,它发现问题很难时可以主动进入计划模式,同样不破坏缓存。

工具搜索

Claude Code 可能加载了几十个 MCP 工具。每次请求都带上全部定义太贵,中途删掉又会破坏缓存。

做法是“延后加载”:不删除工具,而是只发一个很轻的占位(只有工具名,标记为延后加载)。模型需要时通过工具搜索“发现”它,这时才加载完整的定义。同样的占位始终以同样的顺序出现,缓存前缀保持稳定。

经验五:压缩上下文时,也要沿用同一个开头

上下文窗口快满时要做压缩:把到目前为止的对话总结一下,带着总结继续。

这里有个容易踩的坑。要压缩就得把整段对话发给模型让它写总结。最简单的写法是单独发一个请求,用一句“请总结这段对话”当系统提示词,不带工具。问题在于:主对话是在另一套系统提示词和工具下缓存的,这个总结请求从第一个 token 起就不一样,缓存一点也用不上。结果是按没有缓存的价格为整段对话付一次钱,而且对话越长(也就是越需要压缩的时候)越贵。

Claude Code 的做法叫“不破坏缓存的分叉”:

  1. 用和主对话完全相同的系统提示词、上下文和工具定义;
  2. 前面放上主对话的全部消息;
  3. 把“请压缩”作为一条新的用户消息加在最后。

对接口来说,这个请求和主对话的上一个请求几乎一样,缓存的前缀照常复用,新增的只有那条压缩指令。

代价是要预留一块“压缩缓冲区”:上下文窗口里得留出空间,放得下压缩指令和输出的总结。

作者补充说,这套做法已经直接做进了 API,开发者不用自己重新踩一遍。

五条经验放在一起

经验 一句话
缓存是前缀匹配 前面任何一处变了,后面全部作废。整个系统围绕这一点设计
用消息代替修改系统提示词 进入计划模式、更新日期这类事,放进对话里的消息
不在对话中途换工具或换模型 用工具来表示状态的切换;工具延后加载,不要删除
像盯可用性一样盯缓存命中率 命中率掉几个百分点,成本和延迟就会明显变差
分叉出去的操作要共用主对话的前缀 压缩、总结、执行 skill 都一样

对你有什么用

如果你只是用 Claude Code

这些设计解释了几条使用上的建议,它们在本站的 Claude Code 怎么省用量 里讲得更细:

  • 一件事尽量一口气做完,中途放太久缓存会过期;
  • MCP 服务器在会话开始时就接好,不要中途接;
  • 要换模型,在会话开头或自然的停顿点换;查资料这类活交给用小模型的子代理,而不是把主对话切到小模型;
  • CLAUDE.md 改了之后,同一个项目里的缓存要从它那里重新建。

如果你在做自己的智能体

  • 把提示词分成几层,按“多久变一次”从前往后排。
  • 检查系统提示词里有没有每次都变的东西:时间戳、随机顺序的列表、会话编号。
  • 工具列表保持稳定、顺序固定。需要“模式”时,用消息和工具来表达,不要换工具集。
  • 任何旁路的调用(总结、分类、子任务)都先想一下:它能不能复用主对话的前缀。
  • 给缓存命中率做监控。

来源

通过 API 中转站使用这些模型?到 Veridrop 免费检测中转站给你的是不是它声称的模型,或者看看中转站排行榜前 100 名。

相关文章