跳到内容
AI Coding Guideline
Esc
导航打开⌘J预览
本页内容

避免大上下文反复重建缓存

全面详细介绍破坏上下文缓存的常见因素与实用规避方法,以及保持缓存命中的实践守则,有效降低大上下文重建的高额成本

缓存原理篇讲过:前缀一致才命中,变一个字节全重建。上下文越大,一次重建越昂贵——200K 前缀重建一次相当于几十轮命中的费用;1M 模式下更是灾难。本篇讲实践中最常见的“缓存杀手”和对策。

缓存杀手清单

1. 把动态内容放进了前缀

时间戳、随机数、每轮变化的状态,只要出现在系统提示或早期消息里,每一轮的前缀都不一样,缓存永远无法命中

❌ system: "当前时间:2026-08-22 21:35:07。你是..."   ← 每轮都变,缓存全废
✅ system: "你是..."(稳定)
✅ 时间等动态信息放到最新一条 user 消息末尾,或让模型调工具查询

自己搭 Agent 时这是头号陷阱。检查方法 diff,前缀必须逐字节一致。

2. 中途修改系统提示 / CLAUDE.md / 工具集

toolssystem 排在最前面,改动它们等于把整条缓存链从头炸掉:

  • 会话中途编辑 CLAUDE.md/memory、更换 output style ⇒ 前缀变化;
  • 中途接入或断开 MCP 服务器、增删工具 ⇒ tools 段变化,全量重建;
  • 切换模型 ⇒ 缓存按模型隔离,等于从零开始。

对策:把配置变更放在会话边界。要改 CLAUDE.md、要挂新的 MCP,先改完、/clear 或重启会话再开始干活;不要在一个 50 轮的长任务中间做这些事。

3. 修改、删除历史消息

一些自制 Agent 框架喜欢“整理”历史、给旧消息瘦身、滑动窗口丢掉最早的消息。每次整理都改变了前缀 ⇒ 全量重建。

对策:

  • 对话保持只追加(append-only);
  • 确实需要瘦身时,一次性大幅压缩(比如把前 80% 历史换成一段摘要),而不是每轮小修小补——压缩一次付一次重建成本,之后在新前缀上继续累积命中;
  • 这正是 Claude Code /compact 的做法,一旦压缩就是一次到位。

4. TTL 过期

默认缓存 5 分钟不访问就过期。开发时被打断 10 分钟,回来第一轮必然是全额写入。

对策:

  • 高频交互期不用管,每轮命中都会刷新 TTL;
  • 可预期的长间隔(批处理、低频定时任务)用 1 小时 TTL(ttl: "1h");
  • 别为了“保温”去空转请求——5 分钟一次的心跳请求本身也要花钱,算一下通常不划算。

5. 并发分叉

同一个前缀同时开多个分支请求,缓存写入尚未完成时,后到的请求会各自重建。自制多分支/并行采样系统时,先发一轮把缓存建好,再放并发。

Claude Code / Codex 用户的实用守则

官方 CLI 已自动管理断点,你的职责是别破坏前缀:

  1. 改配置在会话边界做.md、MCP、模型切换,改完再开新会话;
  2. 一个任务一个会话、切风格;新任务用 /clear 重开,既清上下文又从干净前缀重建缓存;
  3. 控制单次输出物大小 20 万 token 的命令输出不但吃窗口,还会把后续每轮的增量计算变贵——用 | tail--quiet、写入文件后局部读取;
  4. 长任务优先交给子代理,主窗口前缀保持小而稳(见工具爆炸篇);
  5. 观察指标 用户看 cache_read_input_tokens 占比,健康的长会话应在 90% 以上;Claude Code 用户可用 /cost(API 计费时)和 /context 观察。

自建 Agent 的检查清单

□ tools / system / 早期消息中没有任何每轮变化的内容
□ 对话 append-only,不回头改历史
□ 断点打在稳定层级末尾(tools 末、system 末、倒数第二条消息)
□ 相邻两轮请求 diff,前缀逐字节一致
□ usage.cache_read_input_tokens > 0 且占比随轮次上升
□ 长间隔场景用 1h TTL;压缩历史一次到位而非每轮微调

最后更新于 2026年8月31日

这个页面有帮助吗?