Skip to content

03.5 Prompt Caching 与成本工程

同一份上下文,布局不同,成本能差一个数量级。

读完你能做什么:设计出高缓存命中率的提示词结构,并知道哪些操作会意外击穿缓存。


一、缓存的基本原理

大模型推理时,处理输入 token 需要计算并存储中间状态(KV cache)。Prompt Caching 的核心思想:

如果这次请求的前缀和上次完全一样,就复用上次算好的中间状态,不用重算。

关键词是前缀(prefix)。

text
请求 1:[A][B][C][D]  →  全量计算
请求 2:[A][B][C][E]  →  A、B、C 命中缓存,只算 E   ✅ 省

请求 3:[X][A][B][C]  →  前缀从第一个 token 就不同  ❌ 全量重算

推论:只要在上下文前面插入任何内容,后面所有内容的缓存全部失效。


二、缓存友好的上下文布局

2.1 基本原则:稳定的在前,变化的在后

text
┌──────────────────────────────────┐
│ 【永不变化】                       │ ← 缓存命中率 100%
│  · 系统提示词                      │
│  · 工具定义                        │
├──────────────────────────────────┤
│ 【很少变化】                       │ ← 高命中率
│  · CLAUDE.md / 项目规范            │
│  · 长参考文档                      │
│  · Few-shot 示例                  │
├──────────────────────────────────┤
│ 【每轮变化】                       │ ← 不缓存
│  · 对话历史                        │
│  · 本轮问题                        │
└──────────────────────────────────┘

2.2 一个常见的反模式

text
❌ 每轮都在最前面注入当前时间戳
   系统提示词:「当前时间:2026-07-29 14:32:15」
   → 每一轮时间戳都不同 → 整个缓存永远命中不了

修复:把时间戳移到上下文末尾,或者只精确到日期。

Claude Code 提供了一个专门的 flag 解决这类问题:

bash
claude -p --exclude-dynamic-system-prompt-sections "your query"

它把「工作目录、环境信息、记忆路径、git 状态」这些每台机器都不同的段落,从系统提示词移到第一条用户消息里。这样不同用户、不同机器跑同一个任务时,系统提示词部分的缓存可以共享。在多用户的脚本化工作流中,这个 flag 能显著降本。


三、什么会击穿缓存

操作是否击穿说明
在末尾追加新消息❌ 不击穿前缀不变,理想情况
修改系统提示词✅ 全部击穿前缀第一段就变了
编辑历史消息([Edit] (编辑)✅ 从该消息起击穿该消息之后全部重算
/compact✅ 击穿历史被重写成摘要
/clear✅ 击穿但之后重新建立新缓存
新增/移除 MCP server✅ 击穿工具定义在前部
修改 CLAUDE.md✅ 击穿下次会话生效时前缀改变
切换模型✅ 击穿缓存不跨模型
在文档开头插入内容✅ 击穿所以要追加到末尾

3.1 实践建议

批量操作时,不要中途改配置。

bash
# ❌ 每次都改 system prompt
for f in *.md; do
  claude -p --append-system-prompt "处理文件 $f" "..." 
done

# ✅ system prompt 保持一致,变化的信息放在用户消息里
for f in *.md; do
  claude -p --append-system-prompt "$(cat ./common-rules.txt)" "处理文件 $f:..."
done

四、成本的三个乘数

理解成本,需要理解它是三个因素的乘积:

text
总成本 ≈ 上下文长度 × 轮数 × 模型单价系数

乘数 1:上下文长度

这是最容易被忽略、也最容易优化的。

一个 5 万 token 上下文的会话,跑 20 轮,处理的输入 token 总量大致是:

text
5万 + 5.2万 + 5.4万 + ... ≈ 110 万 token(不算缓存)

而如果你把上下文控制在 1 万:

text
1万 + 1.2万 + ... ≈ 24 万 token

差 4.5 倍。 这就是 /clear 和精简 CLAUDE.md 的真实价值。

乘数 2:轮数

减少轮数的方法:

  • 一次说清需求,而不是挤牙膏式追问
  • 用结构化提示词减少澄清轮次
  • 让它一次并行做完多个独立操作,而不是一件一件问
text
✅ 请同时做三件事(它们互不依赖,可以并行):
   1. 读 src/api/routes.ts
   2. 跑 npm run typecheck
   3. 查 git log 最近 10 条提交
   全部完成后一起汇报。

乘数 3:模型单价

text
Haiku : Sonnet : Opus ≈ 1 : 5 : 25(数量级参考)

混合模型策略是最大的省钱杠杆:

markdown
---
name: scanner
description: 在大型代码库中快速定位相关文件。用于需要广泛搜索但不需要深度分析的场景。
model: haiku
tools: Glob, Grep, Read
---

你只做定位,不做分析。返回文件路径 + 匹配到的行 + 一句话说明。

主会话用 Opus 做决策,扫描交给 Haiku。同样的任务,成本可能降到 1/5。


五、Claude Code 的成本控制工具

5.1 查看消耗

text
> /usage

在 Pro / Max / Team / Enterprise 计划上,会按 skill、subagent、plugin、MCP server 分类展示 —— 直接告诉你哪个自动化在烧钱。

5.2 设置硬性上限

bash
# 单次运行的美元上限(含子代理开销)
claude -p --max-budget-usd 3.00 "重构 src/legacy"

# 最大轮数
claude -p --max-turns 15 "修复 CI"

v2.1.217+ 在达到预算上限后会停止仍在运行的后台子代理,避免"主任务停了但子代理还在烧"。

5.3 在 Pro / Max 上设置支出限制

text
> /usage-credits

打开 CLI 内的对话框,可以购买额度、设置月度上限。


六、成本优化 Checklist

按收益从高到低排序:

优先级动作预期收益
🔴 高CLAUDE.md 压到 200 行以内每次会话省数千 token
🔴 高启用 MCP tool search(工具多时)可能省数万 token
🔴 高默认模型从 Opus 降到 Sonnet约省 80%
🔴 高切换任务时用 /clear 而不是继续避免上下文复利
🟡 中扫描类子代理改用 Haiku该部分省 80%
🟡 中工具输出加管道过滤每次省数百到数千 token
🟡 中长文档改成索引 + 按需读取大幅降低单轮成本
🟡 中--exclude-dynamic-system-prompt-sections提升多用户场景缓存命中
🟢 低减少无效 [Retry] (重新生成)视习惯而定
🟢 低--bare 跑简单脚本任务跳过 hooks/skills/MCP 加载

6.1 --bare 模式

对于简单的脚本化调用,跳过所有自动发现:

bash
claude --bare -p "把这段 JSON 转成 YAML: $(cat input.json)"

它会跳过 hooks、skills、plugins、MCP servers、auto memory 和 CLAUDE.md 的加载,只保留 Bash、文件读、文件编辑工具。启动更快,上下文更小。


七、一份成本友好的默认配置

~/.claude/settings.json

json
{
  "model": "sonnet",
  "fallbackModel": "haiku",
  "effortLevel": "medium",
  "autoMemoryEnabled": true
}

项目级 .claude/settings.json

json
{
  "claudeMdExcludes": [
    "**/monorepo/other-team/**"
  ]
}

配合一份精简的 CLAUDE.md(< 200 行)和按需加载的 Skills。


八、一个真实的对比

同一个任务「为一个中型项目补充单元测试」:

做法上下文均值轮数模型相对成本
把整个 src 读进来,Opus 一路聊到底12 万40Opus100×
精简 CLAUDE.md + 按文件分批 + Sonnet2 万45Sonnet
上面 + 用 Haiku 子代理做文件扫描1.5 万45混合
上面 + 每个模块一个独立短会话8 千60(分散)混合

结论:优化上下文长度的收益,通常远大于优化模型选择。


延伸阅读

基于 VitePress 构建 · 内容采用原作者授权