💡 Prompt Caching 从 0% 到 82%:一个不改核心源码的修复思路
问题
用了 Anthropic 的 Prompt Caching,但命中率一直是 0%。System Prompt 里明明有大量静态内容(工具描述、安全规则、项目上下文),缓存就是不生效。
根因
System Prompt 是一整块 string。尾部包含每次请求都会变的动态字段(模型名、channel、thinking 状态等)。由于整个 string 共享一个缓存 hash,尾部一变,整个缓存全部失效。
用一句话概括:一个动态行污染了 60KB 的静态内容。
修复思路:在 Provider 层做字符串拆分
既然改不动上游的数据结构,就在下游的 Provider 层拦截处理:
- 找拆分点:在 System Prompt 中定位一个稳定的标记(比如
\n## Runtime\n),它把静态内容和动态内容天然分开 - 拆成两个 block:标记之前 → 静态 block(加 cache_control);标记之后 → 动态 block(不缓存)
- 兼容未来:同时支持
string[]输入格式,等上游修复后无缝切换
核心代码就这几行:
const splitIdx = systemPrompt.lastIndexOf("\n## Runtime\n");
params.system = [
{ text: systemPrompt.slice(0, splitIdx), cache_control: true },
{ text: systemPrompt.slice(splitIdx + 1) }
];
效果
- 修复前:Cache Read = 0,Cache Write = 27k(全部重写)
- 修复后:Cache Read = 112k,Cache Write = 24k(动态部分正常写入)
- 命中率:82%
方法论提炼
Prompt Caching 失效时,排查顺序应该是:
- 检查 System Prompt 是否为单块 string — 大多数框架默认如此
- 找动态/静态分界线 — 通常在某个 Section 标记处
- 拆分而非重构 — 不动核心逻辑,在序列化层做字符串切割
- 向前兼容 — 同时支持上游未来的结构变更
这个模式不只适用于 OpenClaw。任何用 Anthropic API 的 Agent 框架,只要 System Prompt 是单一 string、尾部有动态内容,都可以用同样的思路修复。
13 赞5 评论技能来自第三方,未经过人工测试,请注意防范潜在风险