模式矩阵 /模式白皮书/P2
P2 · Semantic Compaction · 语义压缩
| 字段 | 值 |
|---|---|
| 双轴坐标 | 感知 Perception × 链式 Chain(传) |
| 成本档 | ②(摘要用便宜模型即可,按阈值触发) |
| 课程对应 | 02-03 |
| 目录归属 | 全集 33 模式之一 · 感知模块 4 模式之一 |
| 一句话 | Agent 跑久了 context 装满,得压;压的时候保留什么、丢什么、保到什么程度,决定它接下来还能不能想清楚。 |
它解决什么问题
上下文分诊解决的是哪些信息能进 context,语义压缩解决的是后面那个问题:信息已经进来了,Agent 跑过几十轮 context 也满了,得压一压才能继续。压什么、保什么听起来像小细节,做不好代价很大——一段 487-token 的连接池耗尽 stack trace 被压成"a database error occurred"之后,Agent 不知道加大 pool、加 retry 已经被排除过,于是反复重试已被否决的方案,时间和 token 就这么烧着。
语义压缩把这件事工程化:用三层级联(清理冗长 tool 结果 → 摘要老对话 → 进一步压缩)按 context 占用阈值递进触发,每层比前一层激进。它管的是单 session 内 context window 的容量,不追求无限压缩,而追求每一段历史都由高质量推理产出,不毒化下一段。
为什么坐标是「感知 × 链式」
- 纵轴 · 感知:压缩处理的是"已经看进去"的输入历史,做的是输入→语义保留压缩。它不是把信息记到跨会话的存储里(那是记忆),也不是想清楚一道题(那是推理),而是决定当下窗口里保留哪些证据。
- 横轴 · 链式:三层压缩是级联结构,每层接前一层的输出,原文经清理、摘要、再压缩一路传下来,一层比一层紧。流在 chain 上的是被压缩的历史。
核心机制
压缩按 context 占用从轻到重分层触发,错误堆栈跨整个流程受保护:
| 层级 | 动作 | 典型压缩比 |
|---|---|---|
| Level 1 截断 | 清理冗长 tool 输出(保留指针,标注可重取) | ~2× |
| Level 2 摘要 | 把老对话合并进持久 anchor,不重新生成完整摘要 | ~14× |
| Level 3 深压 | 老错误压成清单但保留每条核心数字,最近几条完整保留 | ~30× 以上 |
两个机制是工业级压缩的关键。第一,触发阈值。Claude Code 默认 95% 触发,但质量退化早在 70%-80% 就开始,等到 95% 才压意味着最后那段推理本身就是低质量推理,再被压进历史会毒化整条链。社区共识是调到 60%-70% 早压,舍掉部分窗口空间换推理质量稳定。第二,持久 anchor。重新压缩每次都丢一点(像反复放大照片的颗粒),迭代合并不会丢已记住的东西。anchor 维护四个固定字段——意图、已做改动、已做决策、下一步——其中"已排除方案"这一项最关键,Agent 反复试已否决方案的根因就是缺它。
适合的生产场景
- 长会话客服 Agent:用户报复杂故障,Agent 跟用户对话加调内部工具,4 小时跑下来 80-120 轮必撞压缩。anchor 字段还能直接导出成给二线工程师的交接单。
- 多步调试与代码 Agent:跑 40 轮以上、tool 输出经常很长(log、数据查询、API 响应),适合保留"做过什么"而 mask 老的"看到什么"。
- 研究助手、数据分析、咨询顾问类长 session Agent:任何 session 超过 20-30 轮、context 占用超过 60% 的任务,都该启动压缩。
容易出错的地方
- 摘要丢关键信息:把 "line 47, max_connections=20, queue_depth=347" 压成"a database error occurred",三个定位数字全没了,Agent 几个循环后又得重读日志。摘要 prompt 要写死"必须保留所有数字、文件路径、函数名"。
- 错误边界压缩:在 Agent 活跃推理中段触发压缩,比如刚把 bug 缩到两个候选文件正要决策,压缩一来推理上下文丢失,从头来过。只压已完成、Agent 已 move on 的对话段。
- 反复压缩导致漂移:压缩压缩过的内容会把信息放大到失真。同一段历史不允许被压超过两次,再不够就转人或开新 session,不要硬上 Level 3。
- 95% 太晚:默认阈值意味着压缩发生在"已经低质量推理过一段"之后。调到 60%-70%。
- 永远不该压错误堆栈:错误堆栈是 Agent 的反馈回路,丢了等于失忆。它必须跨整个压缩流程受特殊保护。
关键指标
- Level 3 触发率(健康区 < 5%):最激进层级的占比。每次 L3 都意味着信息漂移概率 +30%,某类 session 反复进 L3 说明它的 token 预算配错了或该早退场。
- 平均压缩比(健康区 0.30-0.50):after/before。低于 0.20 是过度压缩,关键信息丢失概率高;高于 0.60 是没压够,很快又得压。
- 每次压缩保留的错误堆栈数(任何零保留都触发 P0 报警):最关键的一个指标。零保留意味着错误识别 patterns 漏了,下次 Agent 撞同一个 bug 时没记忆。
最小骨架
should_compact(total, budget): total / budget >= 0.60 # 60% 早压
compact(turns, target):
切分:老的可压 | 受保护(最近 N 轮 + 所有错误堆栈,永不压)
Level 1:清理冗长 tool 输出 → 够了就返回
Level 2:老 turns 摘要合并进 anchor(intent/changes/decisions/excluded/next)→ 够了就返回
Level 3:老错误压成清单但留核心数字,最近 3 条完整保留
每次压缩落一条 CompactionEvent(level / 前后 token / 保留的错误堆栈数)
anchor 的"已排除方案"字段要在摘要 prompt 里写死"已排除的方案必须保留,新决策追加而非覆盖"。摘要调用用便宜模型即可。
企业落地一例
一个企业客户报了 P1 级 API 网关故障,客服 Agent 接单,会话从下午两点开始跑 4 小时、80-120 轮,context 占用爬到 150K-200K。节律按三个时点设计:约 100K(55%)第一次压缩走 Level 1 只清理冗长 tool 输出,anchor 第一次写入已做诊断和已排除方案;约 120K(67%)第二次压缩走 Level 2,老对话 verbatim 没了,anchor 成为后续唯一历史记忆;进入 SLA 倒计时区主动触发 Level 3 并 export handoff,把 anchor 加已排除方案全部导出给二线工程师。关键纪律是 Level 3 之后不再让 Agent 推理重要决策——L3 是 Agent 该退场的信号,不是再压一次的意思。这份交接单让人工客服 5 分钟就能读完接手。
与其他模式的关系
- 上下文分诊(P1):互补。分诊管未来 token(哪些进),压缩管过去 token(已经进的怎么压不丢关键),P1 的"P2 级压缩后加载"正是两者衔接点。
- 渐进发现(P3):三者按 token 的不同时间维度分工。分诊管未来、压缩管过去、发现管未知,生产 Agent 三个都要做,少做一个就在那个维度上漏。
- 分层记忆(Memory 模块):边界要守住。压缩管单 session 内窗口容量,session 一结束所有压缩事件清零;要记住"上周这个用户报过类似 bug"就是记忆的事,别让 compactor 去做记忆的活。
一句话记住它
好的压缩本身就是一种认知——Agent 选择保留什么,决定它接下来能想清什么;压掉一段错误堆栈,就像 refactoring 时把测试也删了,下次回归你不会知道哪里坏了。
本页属于 ADPS 33 模式白皮书。返回 模式矩阵与白皮书目录, 或查看配套 可运行代码目录。