- Article -

理解 CLAUDE CODE 三层上下文压缩策略

分类于 Ai 标签 Claude Code AI Agent 上下文管理 token压缩 LLM 发表于2026-03-29 00:00

深入理解 Claude Code 三层上下文压缩策略

背景

在阅读 learn-claude-code s06 章节 时,作者介绍了一套三层上下文压缩方案。本文整理了对这套方案的几个关键疑问及解答,帮助更深入地理解其设计逻辑。


核心问题:为什么要压缩上下文?

上下文窗口是有限的。Claude Code 在执行任务时会频繁调用工具:

读 30 个文件、跑 20 条命令,轻松突破 100k token。不压缩,AI Agent 根本没法在大型项目里持续工作。


三层压缩策略详解

Every turn:
+------------------+
| Tool call result |
+------------------+
        |
        v
[Layer 1: micro_compact]        (静默,每轮执行)
  将 3 轮前的旧 tool_result
  替换为 "[Previous: used {tool_name}]"
        |
        v
[Check: tokens > 50000?]
   |               |
   no              yes
   |               |
   v               v
continue    [Layer 2: auto_compact]
              保存完整对话到 .transcripts/
              LLM 做摘要,替换全部消息
                    |
                    v
            [Layer 3: compact tool]
              LLM 主动调用,触发同样的摘要机制

疑问一:第一层替换为占位符,LLM 不就丢失信息了?

这是最自然的疑虑,答案是:确实丢失了原始内容,但大多数情况下没关系。

核心假设:信息已经被"消化"进后续对话

当 LLM 读完一个文件后,通常会紧接着输出分析:

tool_result: "def foo(): ... [1000行代码] ..."
        ↓
assistant: "这个文件实现了 X 功能,关键逻辑在第 42 行,有个潜在 bug 是..."

这段 assistant 回复本身就是对文件内容的提炼和压缩。 3 轮之后,即使原始 tool_result 被替换成占位符,LLM 依然能从后续消息里"记起"分析过什么。

但这个假设并不总是成立

场景 是否有信息损失
读了文件,立刻做了详细总结 ✅ 基本无损
读了文件,只说了"好的,继续" ❌ 有损,细节丢了
需要反复对照某文件的原始内容 ❌ 有损,需重新读取
命令输出很长但只用到其中一行 ✅ 压缩大部分没关系

工程上的取舍

不压缩 → 上下文撑满,LLM 无法继续工作
压缩旧结果 → 损失部分细节,但至少还能干活

如果 LLM 发现需要某个被压缩掉的内容,它可以再调用一次工具重新读取。而完整历史通过 transcript 保存在磁盘上,信息没有真正丢失,只是移出了活跃上下文。


疑问二:上下文足够大的未来,这套方案还有必要吗?

上下文变大确实会让压缩"不那么紧迫",这个趋势已经在发生:

但有几个原因让压缩机制可能永远有存在价值:

1. 成本问题不会消失
上下文越大,每次推理费用越高。即使技术上"装得下",把 100 万 token 的历史每轮全量送给 LLM,成本是指数级的。

2. 注意力机制的"中间遗忘"问题
研究发现,LLM 对超长上下文里中间段的内容注意力会显著下降(Lost in the Middle 现象)。窗口大不等于全部内容都被有效利用。

3. 任务规模会跟着扩张

上下文从 8k 涨到 200k,人们就开始让 LLM 处理整个项目;涨到 1M,就开始让它处理整个公司的代码库和文档。

窗口变大,任务也变大,瓶颈只是后移,不会消失。

4. 这套思路会演化成更高级的形态
与其说"压缩会消失",不如说它会进化成记忆系统——把不活跃的信息存到外部数据库,用 RAG 按需检索。本质是压缩思路的升级版,而不是被淘汰。

上下文变大,会让"压缩"从必须变成可选,但只要有成本、有注意力瓶颈、有更大的任务,它就不会真正消失——只会换一种更高级的形式继续存在。


疑问三:第二层和第三层好像没有区别?

两层用的是完全相同的压缩机制,区别只有一个:谁来触发

第二层 auto_compact 第三层 compact tool
触发者 系统自动检测 token 数 LLM 主动调用工具
触发时机 token 超过阈值(如 50000) LLM 自己判断"该压缩了"
用户可见 无感知,静默发生 LLM 会明确说"我要压缩一下"

为什么要分两层?

因为阈值检测是个粗糙的信号,不够聪明:

第二层是被动防御(到上限才压),第三层是主动规划(LLM 自己预判并决策)。


总结

这套三层压缩策略体现了一个工程设计上的经典模式:

同一个机制,配两种触发方式——一个兜底、一个灵活。

类似的例子比如 GC(垃圾回收):内存到阈值自动触发,但程序也可以手动调用 System.gc()。本质是一回事,但给了开发者(或 LLM)一个"主动干预"的口子。

理解了这个模式之后,再看其他系统设计会发现到处都是这个思路。