第 11 章 · 压缩、摘要与上下文腐化
本章目标:理解长任务为什么会越做越不可靠,以及压缩应保留哪些不变量、舍弃哪些过程噪声。
1. 长对话为什么会变质
每轮工具调用都会产生新消息。早期需求、临时假设、失败日志、已经撤销的方案和最新事实混在一起,模型需要从越来越长的序列中判断“现在什么才是真的”。即使窗口没有满,注意力也可能被重复和冲突信息稀释。
上下文腐化的表现包括:忘记用户早期约束,重新尝试已经失败的方案,把旧文件内容当成当前版本,或者在回答中混合两个阶段的结论。
2. 先清理再摘要
压缩不应一上来让模型总结全部历史。先做确定性清理通常更安全:
- 删除已经被新结果取代的旧工具输出;
- 把完整日志移到文件,只保留索引和关键片段;
- 合并重复状态事件;
- 保留用户消息、审批决定和当前文件版本;
- 最后再对剩余过程做语义摘要。
确定性清理不会改写事实,摘要则可能遗漏,因此顺序很重要。
3. 一份可恢复摘要的结构
好的摘要不是散文,而是任务快照:
目标:
- 修复过期 token 仍被接受的问题
必须遵守:
- 不修改公开 API
- 使用现有测试框架
已确认事实:
- validate_token 位于 src/auth.py
- 失败测试 tests/test_auth.py::test_expired
已做修改:
- 增加 expires_at 判断
验证:
- 单测通过;全量测试尚未运行
下一步:
- 运行全量测试并审查 diff
这份结构让新的模型调用甚至新的会话都能继续,而不必读取全部历史。
4. PreCompact 与 PostCompact
成熟 Runtime 可以在压缩前后触发生命周期事件。压缩前保存关键状态、任务计划和未提交 diff;压缩后检查摘要是否包含目标、边界和下一步。如果缺失,补充一条系统消息。
Hooks 可以在这里运行确定性检查,例如将 transcript 归档、统计 Token、把长期价值信息提取为候选记忆。不要让 Hook 随意把大量内容重新注入上下文,否则压缩立即失效。
5. 避免压缩抖动
如果单个文件或工具输出本身就接近窗口上限,系统可能压缩后下一轮立刻再次满载,形成抖动。解决办法是从源头分页读取、限制工具输出、把大任务切分给子 Agent,而不是反复摘要。
Runtime 应记录连续压缩次数。如果几轮内多次触发,应停止自动压缩并告诉用户哪类内容占用异常。
6. 怎样检验摘要质量
可以用恢复测试:只给另一个 Agent 摘要和当前工作树,看它能否准确回答目标、已完成事项、下一验证步骤和不能触碰的边界。不能恢复任务的摘要,即使语言通顺也不合格。
设计原则
压缩的目标不是复述所有发生过的事,而是保留做出下一步正确决定所需的最小充分状态。