24 讲路线 · 与 S05 配对
D05: Context Compression 深挖 · 上下文压缩
本讲在 S05 主线之上,聚焦实现细节、边界条件与自测;导图与主线相同模块,便于对照。
建议:先读完 S05,再按下方顺序走读源码与练习。
🔬 深挖目标
压缩是「有损优化」:何时触发、压缩谁、保留什么信号、如何向模型隐瞒损失,决定 Agent 是否突然变笨。
📊 触发与策略
- 常见触发:token 预算、消息条数、工具输出超长、显式配置阈值。
- 策略谱系:截断(硬切)→ 摘要(模型或规则)→ 结构化压缩(只留 error + 尾部)。
⚠️ 信息损失审计
| 内容类型 | 压缩风险 | 缓解思路 |
|---|---|---|
| 测试失败栈 | 丢中间帧 → 无法定位 | 保留首尾 + 关键 assert 行 |
| 大文件 read | 只剩摘要 → 丢 import | 分段 read 或保留 path + checksum |
| 多轮 plan | 目标被冲掉 | 单独 system 小结锚点 |
🔗 与 Loop
压缩发生在「下一轮模型调用前」;若与工具并行交织,确认压缩器看到的消息视图是否包含尚未提交的 tool_result。
🤔 与 D01「消息累积」对照(工程侧答案)
D01 思考题从原理答了危害与解法谱系;本章补实现侧锚点(重建源码中的命名,便于你走读):
- 触发前计量:
compactConversation入口处的tokenCountWithEstimation(messages)——先量化再决定是否压缩。 - 可插桩:
executePreCompactHooks/ post 阶段让自定义策略改写压缩指令,而不是黑箱改数组。 - 切段与重放:通过 compact 边界类消息(参见源码中
createCompactBoundaryMessage、SystemCompactBoundaryMessage)让后续轮次仍知道「哪些历史已被摘要替代」。
完整摘录与走读清单见 专题 · Compact 硬读。
📖 走读顺序
- 搜索
compress、truncate、summary、token相关函数,列调用栈。 - 构造一条超长工具输出,打日志看压缩前后消息长度与结构变化。
- 回答:压缩后的消息是否仍满足 API schema?
✏️ 自测 1 · 参考答案:压缩后必然做错的场景
题干
给出一种「压缩后模型必然做错」的场景,并说明如何改策略避免。
示例场景
摘要把失败测试的唯一关键栈帧行或用户刚约定的接口签名删掉,只保留「测试失败」四字;下一轮模型会按错误假设改代码,越改越偏。
如何避免
- 锚点保留:对含
Error/FAIL的工具输出保留首尾 N 行 + 关键字行;或用边界消息标记 compact(见上文 D05 工程补充)。 - 外置大段:超长 log 写入文件,上下文只保留路径与 checksum,需要时再
read。 - 用户/规则 gate:压缩前若检测到「未闭合任务」关键词,降低压缩强度或跳过该轮。
✏️ 自测 2 · 参考答案:小模型摘要 vs 规则摘要
题干
摘要由「小模型」与「规则」各有什么工程代价?
对比
| 方式 | 代价 / 风险 |
|---|---|
| 小模型摘要 | 多一次推理费用与延迟;摘要质量波动;需防「摘要再幻觉」;要版本化 prompt 与回归测例。 |
| 规则 / 模板 | 开发维护规则表成本高;对非标输出脆弱;但确定性高、可测,适合合规场景。 |
实务上常混合:规则做硬截断与结构化字段提取,小模型只负责把「已截断块」压成短摘要。