Ch08: Prompt Caching 架构
Ch08: Prompt Caching 架构
理解 Prompt Caching 的工作方式,才能明白为什么 CLAUDE.md 越稳定越好。
理论框架
Prompt Caching 是 Claude API 层面的优化机制,核心原理简单直接:缓存按前缀匹配工作。
每次请求发给 Claude 的完整输入大致是这样的结构:
[系统提示] + [CLAUDE.md] + [工具 schema] + [对话历史] + [最新消息]
如果两次请求的"前缀"相同——即从第一个 token 开始到某个位置完全一致——第二次请求可以复用缓存,跳过对这段前缀的重新处理。缓存命中时,这部分输入 token 的成本降低约 90%。
这意味着内容的排列顺序至关重要:
| 位置 | 应该放什么 | 原因 |
|---|---|---|
| 最前面 | 系统提示 | 几乎不变,缓存命中率最高 |
| 其次 | CLAUDE.md 规则 | 变化频率低,构成稳定前缀 |
| 再次 | 工具 schema(MCP 等) | 会话内不变 |
| 最后 | 对话历史 + 工具结果 | 每轮都变,不参与前缀缓存 |
Claude Code 的系统设计已经遵循了这个顺序。系统提示、CLAUDE.md、工具定义构成"稳定前缀",对话历史和工具结果放在最后。你不需要手动调整顺序,但你需要理解这个机制对日常操作的影响。
CLAUDE.md 的稳定性影响缓存
CLAUDE.md 处于稳定前缀的核心位置。如果你在会话中途修改了 CLAUDE.md(比如让 CC 往里写新规则),从那一刻起,前缀发生变化,之前的缓存全部失效。之后的每一轮对话都要重新处理完整的前缀,直到新的缓存建立。
这不是说不能改 CLAUDE.md——而是说改了之后有成本。高频修改 = 低缓存命中率 = 更高的 token 消耗。
defer_loading 延迟加载
MCP 工具的 schema 会被包含在工具定义中,作为稳定前缀的一部分。如果你装了很多 MCP Server,每个 Server 暴露多个工具,这些 schema 加起来可能有几千甚至上万 tokens。
defer_loading 参数可以延迟加载某些 MCP 工具的 schema——只在首次调用时才加载,而不是每次会话启动就加载。这减少了初始 token 开销,但代价是首次调用该工具时会有额外延迟。
实际成本影响
以一个典型会话为例:
稳定前缀(约 20K tokens):
├── 系统指令 ~8K
├── CLAUDE.md ~3.5K(全局 + 项目级)
├── Memory ~1.5K
├── 工具 schema ~5K
└── MCP 定义 ~2K
如果缓存全部命中:
20K tokens * 0.1(缓存价格)= 2K tokens 等价成本
如果缓存失效(修改了 CLAUDE.md):
20K tokens * 1.0(全价)= 20K tokens 成本
差异:每轮对话多花 18K tokens 的等价成本
一个长会话可能有 50-100 轮对话。如果中途修改 CLAUDE.md 导致缓存失效,后续每轮都多花 18K tokens,累计影响可观。
已有经验与关联实践
虽然没有专门针对 Prompt Caching 做过实验,但现有的工作方式中已经有几个做法天然有利于缓存。
三层 CLAUDE.md 体系本身就是缓存友好的设计
当前的三层上下文体系:
全局 CLAUDE.md (~2K tokens) → 跨所有项目稳定
项目级 CLAUDE.md (~1.5K tokens) → 跨同一项目的会话稳定
Memory 文件 (~1.5K tokens) → 偶尔更新
来源:
~/Learn/claude-code/Layer1-长期上下文.md第七章
这个设计把通用规则("用 Streamlit""Python 用 miniforge3")放在全局层,项目特有规则("PARA 目录结构""投标单位名称禁止出现")放在项目层。全局层几乎不变,项目层在同一项目内也很稳定。这意味着在同一个项目目录下启动的所有会话,前缀的大部分内容是一致的,缓存命中率高。
CLAUDE.md 的写作原则已经在控制体积
Layer 1 教学中总结的写作原则——"短、硬、可执行"——不仅让 CC 更容易理解规则,也无意中控制了 CLAUDE.md 的体积:
| 好规则 | 坏规则 | 对缓存的影响 |
|---|---|---|
| "技术栈用 Streamlit,不用 React" | "我们的技术栈比较灵活,通常用 Streamlit,但有时候也考虑 React......" | 好规则更短,占用更少 tokens |
| "任务超 5 分钟必须拆分" | "大任务建议拆分,具体可以根据情况判断......" | 好规则没有废话 |
来源:
~/Learn/claude-code/Layer1-长期上下文.md第二章
Layer 1 教学中还提到了一条经验法则:"如果一条规则在 3 个以上的会话中都要用到,就该写进 CLAUDE.md。如果只在某个会话中用一次,别写进来。" 这条规则的效果是让 CLAUDE.md 只包含真正需要的内容,避免膨胀——既减少了每次会话的固定 token 开销,也维持了前缀的稳定性。
Token 成本意识已经建立
Layer 1 教学中明确算过固定开销:
固定开销(每次会话):
├── 系统指令 ~8K
├── Skill 描述 ~5K
├── MCP 工具定义 ~2K
├── 全局 CLAUDE.md ~2K
├── 项目 CLAUDE.md ~1.5K
├── Memory 文件 ~1.5K
└── 合计 ~20K
来源:
~/Learn/claude-code/Layer1-长期上下文.md第七章
这 20K 的固定开销就是 Prompt Caching 要缓存的"稳定前缀"。已经有的意识是"不要随便加 MCP Server,每个约 4-6K tokens"——这本质上就是在管理缓存前缀的体积。
可以做的优化
基于 Prompt Caching 的原理,有几个可以改进的方向:
-
会话中途避免修改 CLAUDE.md。如果 CC 提议往 CLAUDE.md 加规则,可以记下来,等会话结束后再统一加。这样当前会话的缓存不会被破坏。
-
审计 MCP Server 列表。每个不常用的 MCP Server 都在增加稳定前缀的体积。如果某个 Server 一个月用不到几次,考虑移除或使用
defer_loading。 -
Compact Instructions 与缓存的关系。Layer 1 教学中 Compact Instructions 被列为 TODO。需要注意:Compact Instructions 本身也是稳定前缀的一部分,写进去后就会持续占用缓存空间,所以要写得精简。
-
控制 CLAUDE.md 在 2.5K tokens 以内(Layer 1 已经提出的上限)。超过这个上限不仅浪费 context 窗口,也增加了缓存前缀的体积,每次缓存失效时的重建成本更高。
关键收获
-
Prompt Caching 的核心是前缀匹配。 稳定的前缀 = 高缓存命中率 = 低成本。系统提示、CLAUDE.md、工具 schema 构成稳定前缀,对话历史放最后——Claude Code 已经帮你做好了这个排列。
-
CLAUDE.md 的修改频率直接影响成本。 每次修改都会使缓存失效。在长会话中途改 CLAUDE.md,后续每轮对话都会为此多付 token 成本。好的做法是把修改记下来,会话结束后统一更新。
-
三层体系天然缓存友好。 全局层跨项目稳定,项目层跨会话稳定,Memory 偶尔更新。这个分层设计的一个隐含收益就是最大化了缓存命中率。
-
"短、硬、可执行"不只是写作原则,也是缓存原则。 CLAUDE.md 越精简,前缀越短,缓存建立越快,失效时的重建成本越低。废话不仅浪费 context,也浪费缓存空间。
-
MCP Server 数量需要节制。 每个 MCP Server 的工具 schema 都会加入稳定前缀。不常用的 Server 可以移除或延迟加载(
defer_loading),减少初始开销。