Claude Code 的五级压缩流水线
2026/7/3 6:36:46 网站建设 项目流程

Claude Code 的五级压缩流水线:由轻到重的上下文管理艺术

引言:每个 AI Agent 都绕不开的“桌面困境”

想象你有一张固定大小的办公桌(上下文窗口),随着工作时间拉长,各种文件、资料、草稿纸会不断堆上来,直到桌面完全被占满。这时,你再想放新东西就放不下了——对应的现实是,AI 会遗忘最早的内容,甚至开始在有限的记忆里自相矛盾

Claude 的上下文窗口高达100 万个 token,听起来很充裕。但一次真实的编程会话可以轻松产生数倍于此的数据:几十次文件读取、数百次工具调用、数千行npm test输出、反复的grep搜索结果。更棘手的是另一个现象:上下文越长,模型越蠢(官方称之为“上下文腐烂”)。那些 2 小时前读的配置文件、1 小时前调试失败的日志,全都挤在窗口里,像噪音一样持续干扰当前的注意力。

为了应对这个问题,Claude Code 在源码的src/services/compact/目录下(超过 3,960 行 TypeScript 代码)构建了一套精密的五级渐进式压缩流水线。它不是等到“快满了”才做一次暴力摘要,而是把多种上下文管理策略串成一条前置压缩链,再补一条调用后的兜底恢复链

这套系统的核心设计哲学只有一句话:能用轻量手段解决的,绝不动用重武器。

五级全景图

在讲解每一级之前,先看整体结构:

┌─────────────────────────────────────────────────────────────────────┐ │ 前置压缩链(每次 API 调用前评估) │ │ │ │ 第一级:Snip(历史剪除)—— 删“脚手架”,最轻量 │ │ ↓ 不够就进入下一级 │ │ 第二级:Microcompact(微压缩)—— 清理“旧工具结果”,轻量 │ │ ↓ 不够就进入下一级 │ │ 第三级:Context Collapse(上下文折叠)—— 分段摘要,中等 │ │ ↓ 不够就进入下一级 │ │ 第四级:Autocompact(自动压缩)—— 全量摘要,重量级 │ │ │ │ ════════════════════════════════════════════════════════════════ │ │ 被动恢复链(API 报错后才触发) │ │ │ │ 第五级:Reactive Compact(响应式压缩)—— 紧急救援,最后防线 │ └─────────────────────────────────────────────────────────────────────┘

前四级像漏斗一样层层过滤,第五级是安全网。下面逐级深入。

前置压缩链(主动预防)

第一级:Snip(历史剪除)

成本:零(纯内存数组操作,不调用模型,不做摘要)

它解决什么问题?

对话进行中,消息数组里会积累大量“对话的脚手架”——比如重复出现的 assistant 回复框架、系统内部记账用的元数据、早期已经完成的任务标记等。这些东西就像施工结束后留在现场的脚手架,除了占地方,毫无价值。

它具体怎么做?

直接从消息数组中移除那些陈旧的、不再影响后续决策的特定消息片段。它不涉及任何字符串截断,不做摘要生成,只是纯粹地从数组中删除冗余条目。

一个关键的微妙之处在于:REPL(交互界面)侧仍保留这些消息用于 UI 滚动展示,但发给 API 的消息载荷已经被剪除了。用户看到的聊天记录是完整的,但发给模型的上下文是剪裁过的。

设计思维:账本必须对得上

这一级真正的技术难点不在“删除”,而在记账准确性。当 Snip 删除了某些消息后,它会把snipTokensFreed(本次剪除释放的 token 数)记录下来,传递给后续层级的阈值计算。

为什么这么重要?因为如果没有这个校正,AutoCompact(第四级)在计算“当前上下文用了多少 token”时,拿到的会是剪除之前的旧 usage 数据——它可能错误地认为上下文仍然很满,从而在已经释放了空间的情况下仍然强行触发全量摘要,白白浪费一次 LLM 调用和费用。

这是一个极其容易被忽略的细节:压缩不仅仅是“删东西”,还要确保后续的决策建立在正确的数据之上。

第二级:Microcompact(微压缩)

成本:极低(纯本地字符串替换 / 服务端 cache_edits,不调用模型)

它解决什么问题?

在 AI 编程过程中,工具调用(Bash、Read、Grep 等)会产生海量的tool_result。许多结果——比如一次性的find搜索结果、已经执行完的ls -la输出——用过一次后就再也没有价值了,但依然死死占着上下文空间。

它具体怎么做?有两种工作模式:

模式一:时间窗模式(Time-window)

检查每条tool_result的时间戳。如果某条tool_result产生的时间距离当前对话超过 60 分钟,系统就把它替换成一个简短的占位符:[old tool result cleared]

模式二:Cache 编辑模式(Cache edits)

Anthropic API 支持Prompt Cache机制——如果请求的开头部分相同,这部分 token 可以享受高达 90% 的计费折扣。粗暴地删除消息可能会打碎缓存前缀,导致缓存命中率暴跌——省了 token 空间,却亏了钱。

在 Cache 编辑模式下,系统通过 API 侧的cache_edits功能,在服务端精准删除旧工具结果,同时小心翼翼地保留 prompt cache 前缀的结构完整性。这是一种“微创手术”——不改变缓存前缀的哈希特征,只切除内部冗余的旧结果。

设计思维:缓存感知的“微创”压缩

为什么区分两种模式?因为缓存是钱。如果用户在对话中频繁调用工具且间隔很长,时间窗模式更简单直接;如果用户处于高密度工具调用中且缓存命中率很高,Cache 编辑模式就更经济。这个设计表明:压缩决策不仅要看 token 数,还要看成本结构。

第三级:Context Collapse(上下文折叠)

成本:中等(后台异步处理,不阻塞主流程)

它解决什么问题?

前两级解决的是“删除垃圾”,但当上下文真正由“有效历史对话”组成时,就不能再删了——需要对对话本身进行结构化重组

它具体怎么做?

将历史消息切分成多个片段,每个片段独立生成一份摘要,然后用这些摘要替换掉原始消息。与“一次性全量摘要”不同,Context Collapse 保留了比全量摘要更细粒度的上下文结构——每段都保留了自己的主题标记,而不是把所有东西搅成一大锅粥。

整个过程在后台异步执行,用户完全感知不到压缩的发生。

如果折叠后 token 已经达标(降到了安全水位以下),第四级的 AutoCompact 就不会被触发。换句话说,第三级是第四级的“缓冲垫”——能通过分段摘要解决的问题,就不走全量摘要。

设计思维:把“同步阻塞”变成“异步保洁”

传统的全文摘要有一个致命缺点:压缩那一刻会阻塞用户——你可能要等 3~5 秒才能继续对话。而 Context Collapse 把这个过程拆解成多个小任务在后台排队执行。这就像五星级酒店的保洁:你不会看到保洁员推着车在你门口站着等你出门,她是在你离店期间悄悄打扫的。

第四级:Autocompact(自动摘要压缩)

成本:高(调用 LLM 生成全量摘要,消耗真实 token 和费用)

它解决什么问题?

当前三级都无法把上下文降到安全水位以下时,意味着“垃圾”已经清理干净、“碎片”已经整理完毕,但桌面还是满的——唯一的办法就是把整个对话浓缩成一篇精华摘要

它具体怎么做?

  1. 触发阈值:有效上下文窗口 -13,000 个 token(即上下文使用超过80%时触发)。预留 13,000 个 token 是为了给模型的回复留出充足的生成空间。
  2. 执行方式fork 一个独立的子 Agent,让它通读整个对话历史,生成一份完整的对话摘要。
  3. 替换逻辑:用这份摘要替换掉全部历史消息——对话记录清零,只留下摘要作为新的“历史上下文”。

摘要生成的优化路径

  • 优先路径tengu_compact_cache_prefix特性开启时):复用主 Agent 的 prompt cache,摘要生成近乎零额外的 token 开销
  • 降级路径:优先路径失败时,直接直连 API 生成摘要(成本相对更高)。

熔断机制(Circuit Breaker):连续失败3 次后自动熔断,不再重试。这是为了防止在异常情况(如 API 持续超时、模型持续报错)下反复浪费资源和费用,陷入无限重试的死亡循环。

设计思维:把 LLM 调用放在最后一步

在整条流水线中,前三级都是“免费”的本地操作,只有这一级才开始真正花钱。LLM 调用是最昂贵的资源,把它放在“万不得已”的最后一步——这就是整条流水线成本优先哲学的终极体现。

被动恢复链(响应式压缩)

第五级:Reactive Compact(响应式压缩)

成本:最高(紧急状态下调用 LLM + 强制数据处理)

触发条件:前置压缩链(第一级到第四级)全部未能阻止上下文超限,API真的返回了prompt_too_long(413)错误

它具体怎么做?分三步执行,呈“阶梯式救援”:

第一步:尝试 Context Collapse drain(排空暂存折叠)

什么叫“drain”?在前三级中,Context Collapse 可能只是打了标记、生成了摘要草稿、但尚未正式提交到消息数组中。这一强制把所有待提交的折叠操作一次性全部落实——就像开闸放水,把蓄水池里所有的水一次性排空。

第二步:还不够则紧急触发完整对话摘要

如果第一步释放的空间仍然不够,立即强制执行一次完整对话摘要(相当于强行再跑一遍第四级 AutoCompact)。

第三步:都失败则报错退出

如果连摘要都生成不了(或压不下去),系统放弃本次请求,明确向用户报错:“上下文太长了,无法处理。”

额外细节:prompt_too_long的重试机制

当收到prompt_too_long错误时,系统会尝试通过丢弃最旧的消息组来恢复:

  • 如果能从错误响应中解析出tokenGap(超出了多少 token),就精确计算需要丢弃多少条最旧的消息。
  • 如果无法解析(比如错误信息不完整),则按比例丢弃最老的 20% 消息组

设计思维:诚实失败优于悄悄丢数据

第五级的设计非常克制——它不会无限重试,也不会为了“把请求发出去”而偷偷丢弃用户的关键指令。当它确认自己救不了的时候,选择诚实告知用户。这在工程上是一种优雅的降级:宁可报错让用户手动处理(比如开启新对话),也不要自作主张地篡改用户的原始意图。

总结:一条精打细算的防御体系

将这五级和应急链放在一起看,整个系统的结构就清晰了:

层级名称成本核心操作触发时机
第一级Snip(历史剪除)删除冗余“脚手架”消息每次 API 调用前
第二级Microcompact(微压缩)极低时间窗 / Cache 编辑,清理旧工具结果每次 API 调用前
第三级Context Collapse(上下文折叠)中等后台异步多段摘要每次 API 调用前
第四级Autocompact(自动压缩)fork 子 Agent 生成全量摘要上下文超 80% 阈值
第五级Reactive Compact(响应式压缩)最高Drain + 紧急摘要 + 报错退出API 返回 413 错误后

这套机制真正的精妙之处在于四个设计维度

  1. 成本排序:把上下文管理变成一条严格按成本递增排列的流水线——能本地解决的不调 API,能字符串替换的不跑模型。

  2. 缓存感知:整个设计都围绕 Anthropic 的 Prompt Cache 展开,第二级的 Cache 编辑模式和第四级的缓存复用路径,都是在“释放 token”和“保住缓存命中率”之间做精细权衡。

  3. 记账正确性:第一级释放的 token 会一路传递到第四级的阈值计算,防止“空间已经释放了却还要触发全量摘要”的逻辑乌龙。

  4. 异步非阻塞:第三级在后台默默工作,用户几乎感知不到压缩正在进行。

正如 Claude Code 团队所说:你在管理会话、上下文和压缩时的方式,对最终结果的影响比你预期的要大。这五级压缩流水线,就是 Claude Code 在这个维度上交出的答卷——不是简单粗暴的截断,也不是凌乱的、全量摘要,而是一条精打细算、层层过滤的智能流水线

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询