跳到主要内容

上下文压缩

上下文压缩在对话或 Agent 任务接近窗口上限时,用更短的表示替换旧内容,让任务能继续执行。压缩一定会丢信息,本文说明几种常见方案、触发时机、必须保留的信息,以及如何检查压缩是否破坏了任务。

1. 面试核心​

先记住这几条,再读正文
  • 常见方案有截断、滑动窗口、摘要、工具结果清理、外部存储加检索。它们在信息保留、成本和实现复杂度上不同,长任务通常组合使用。卡 · 压缩方案
  • 压缩时必须保留的是任务目标、用户约束、已做出的决定、已修改的产物位置、未解决的错误和下一步;可以丢弃的是已被后续结果取代的中间输出和冗长的原始工具结果。卡 · 保留什么
  • 触发方式有按 Token 阈值自动触发、按轮次触发和用户手动触发。阈值要给本轮输入和输出留出空间。卡 · 触发时机与合并
  • 工具结果是长任务中增长最快的部分,优先清理已使用过的旧结果,保留调用记录和结论。卡 · 压缩方案
  • 压缩后的事实以实际状态为准:恢复任务时重新检查文件、测试和外部系统,不把摘要中的“已完成”当成验收结果。

2. 压缩方案​

方案做法优点缺点
截断删除最早的消息简单、无额外调用早期目标和约束会丢失
滑动窗口只保留最近 N 轮成本可控,近期信息完整窗口外信息全部丢失
摘要用模型把旧历史总结成一段文字保留要点,长度可控多一次模型调用;摘要可能遗漏或改写细节
窗口 + 摘要旧内容摘要,最近 N 轮保留原文兼顾远期要点和近期细节需要设计摘要格式和合并方式
工具结果清理把旧工具结果替换为占位或简短结论收益大,不影响对话主线之后需要时要重新调用工具
外部存储 + 检索历史写入数据库或文件,按需检索理论上不丢原文依赖检索质量,增加延迟

摘要失败的典型表现是“细节被平均化”:用户最初说“不要改公共接口”,摘要写成“用户希望改动尽量小”,后续步骤就可能修改接口。因此摘要提示要指定必须逐字保留的内容类型。

3. 保留什么​

压缩前先把信息分类:

  • 必须保留:任务目标和验收条件;用户明确提出的约束和偏好;已经做出的关键决定及原因;已修改或生成的文件、数据位置;未解决的错误信息和失败尝试;当前进度和下一步。
  • 可以摘要:探索过程中读过的代码和文档,只保留结论和位置;讨论过但被否定的方案,保留“已否定及原因”。
  • 可以丢弃:已经被后续结果覆盖的中间输出、重复的工具结果、寒暄。

结构化摘要比自由文本更不容易遗漏:

## 目标
修复 /api/orders 分页在最后一页返回重复数据的问题。
## 约束
- 不修改响应字段(前端已上线)。
## 已完成
- 定位到 OrderRepository.page():offset 计算使用了 page 而非 page-1。
- 已修改 src/order/repo.ts:41,单测 order.repo.test.ts 通过。
## 未解决
- 集成测试 orders.e2e 超时,原因未确认。
## 下一步
- 本地启动数据库后重跑 e2e。

另一种做法是把关键信息写在上下文之外的进度文件或仓库指令中,压缩时不依赖模型记住它们。

4. 触发时机与合并​

  • 按 Token 阈值:当前上下文达到窗口的某个比例时触发,阈值要为下一轮的输入、工具结果和输出预留空间。
  • 按轮次:每 N 轮把最早的一段压缩成摘要,长度增长更平稳。
  • 按任务边界:一个子任务完成时压缩它的过程,只留结论,适合计划明确的长任务。
  • 手动触发:用户在切换话题前要求压缩,并可以说明需要保留的重点。

多次压缩后会产生多份摘要。可以每次把旧摘要和新内容一起重写成一份(长度稳定,但多次重写会累积失真),也可以分段保留多份摘要(不重复改写早期内容,但总长度会继续增长)。常见折中是近期分段保留,远期合并,并始终保留原始的目标和约束段。

5. 常见问题​

5.1 怎样验证压缩没有破坏任务​

建立回归用例:在长对话中途插入约束,触发压缩后检查模型是否仍遵守。对 Agent 任务,比较开启和关闭压缩时的成功率,并抽查失败轨迹中压缩前后的信息差异。

5.2 摘要可以“还原”成原文吗​

6 · 面试题卡片​

6.1 对话超过上下文窗口时,有哪些处理方案?滑动窗口和动态摘要各有什么优缺点?​

出现公司:虾皮、字节跳动、阿里淘天、百度、去哪儿旅行、OPPO

考察重点

  • 截断、滑动窗口、摘要、工具结果清理和外部检索的取舍。
  • 组合方案的设计。

相关内容:压缩方案。

参考回答

方案有:截断最早消息、滑动窗口保留最近 N 轮、用模型把旧历史生成摘要、清理旧工具结果、把历史写入外部存储再按需检索。

滑动窗口实现简单、没有额外调用,近期内容完整,但窗口外的目标和约束会全部丢失。动态摘要能保留远期要点,代价是多一次模型调用,并且摘要可能遗漏或改写细节。常用组合是:系统规则和任务目标固定保留,旧轮次压缩成结构化摘要,最近几轮保留原文,旧工具结果只留结论;原始历史存入外部存储以便检索。

6.2 压缩或摘要一定会丢失信息,如何让信息丢失最小化?​

出现公司:字节跳动、拼多多、安软、腾讯

考察重点

  • 必须保留、可摘要、可丢弃信息的划分。
  • 结构化摘要、外部存储和压缩效果验证。

相关内容:保留什么、怎样验证压缩没有破坏任务。

参考回答

先分类:目标、验收条件、用户约束、关键决定、产物位置、未解决的错误和下一步必须保留;探索过程只留结论和位置;被后续结果覆盖的中间输出可以丢弃。

摘要用固定字段的结构化格式,要求约束和错误信息原文保留。关键信息同时写在上下文之外,例如进度文件、仓库指令或状态存储,压缩时不依赖模型记住它们。原始历史存档,摘要中留引用以便检索。最后用回归用例验证:在长对话中插入约束,压缩后检查是否仍被遵守,并比较开启压缩前后的任务成功率。

6.3 常见的压缩触发机制有哪些?旧摘要和新摘要应该合并还是分别保留?​

出现公司:快手、美团、百度

考察重点

  • 阈值、轮次、任务边界和手动触发。
  • 多次压缩的失真累积与长度增长。

相关内容:触发时机与合并。

参考回答

触发方式有:上下文 Token 达到窗口某个比例时自动触发,并为下一轮输入和输出预留空间;每 N 轮压缩最早的一段;一个子任务完成时压缩它的过程;用户手动触发并指定保留重点。编码 Agent 一般在接近上限时自动压缩,也支持手动命令。

合并重写成一份摘要,长度稳定,但每次重写都可能改变早期内容,失真会累积;分段保留不改写旧摘要,信息更稳定,但总长度会继续增长。常见做法是近期分段、远期合并,并让最初的目标和约束作为固定段落不参与重写。

6.4 Tool Result 如何淘汰或压缩?​

出现公司:字节跳动、4399

考察重点

  • 工具结果在长任务中的增长方式。
  • 结果截断、落盘、清理与保留调用记录。

相关内容:压缩方案、按需加载与渐进式披露。

参考回答

在返回时就控制大小:大结果截断或分页,完整内容写入文件,上下文只放摘要、行数和路径。日志类结果先在程序侧过滤,例如只保留错误级别和相关请求 ID。

在历史中,已经被模型使用过的旧结果替换为简短结论或占位符,保留工具名、参数和调用 ID,使调用记录完整;之后需要原文可以重新调用工具或读取落盘文件。最近几步的结果和包含未解决错误的结果保留原文。

7. 参考资料​