当前位置: 首页 > news >正文

上下文压缩如何拯救AI长对话?一文搞懂上下文压缩的四层设计

问题

【本质:上下文空间是有限资源,工具输出会不断挤占这个空间。】

Agent 在大项目中工作时,会读很多文件、跑很多命令,每条工具输出都堆在 messages 列表里。

上下文窗口是有限的,满了之后 API直接报 prompt_too_long,Agent 就卡死了。

解决方案–4层压缩管线

4层压缩管线(便宜的先跑,贵的后跑)

层级策略成本做什么丢什么
L3tool_result_budget0 API大输出写入磁盘,留预览完整输出(磁盘有备份)
L1snip_compact0 API裁掉中间旧消息中段对话历史
L2micro_compact0 API旧工具结果替换为占位符旧工具输出内容
L4compact_history1 APILLM 全量摘要细节(保留关键信息)
兜底reactive_compact1 APIAPI 报错后紧急裁剪大部分(只留最近 5 条)

总体流程

第一步:进入管线

messages[] – 当前完整的对话消息列表。

⬇️

第二步:L3 tool_result_budget(最便宜)

做什么:检查有没有特别大的工具输出(比如 cat 了一个大文件),有就存到磁盘,用短预览(文本形式的summary)替换。

为什么先做:不涉及 LLM 调用,零成本,直接缩小消息体积。

⬇️

第三步:L1 snip_compact(便宜)

做什么:裁剪中间的消息,只保留头和尾。比如保留最近 5 条,前面的全删。

为什么第二做:也是确定性操作,不调 LLM,但比 L3 激进,会丢信息。

⬇️

第四步:L2 micro_compact(便宜)

做什么:把旧的工具结果替换成占位符。比如 10 轮前的 read_file 结果,替换为 “[tool result omitted]”。

为什么第三做:同样不调 LLM,但会丢失具体的工具输出内容。

⬇️

第五步:判断 – token 还超阈值吗?

前三层处理完后,检查消息的 token 数:

  • 没超 → 直接发给 LLM,正常工作
  • 超了 → 进入 L4

⬇️

第六步:L4 compact_history(最贵)

做什么:调用 LLM 对全部历史做摘要,用摘要替换所有旧消息。

为什么最后做:需要一次额外的 LLM API 调用,有成本,而且会丢失细节。但能把 token 数大幅降下来。

⬇️

第七步:L4 之后再调 LLM

L4 摘要完成后,用精简后的消息去调 LLM 做正事。

⬇️

第八步:紧急兜底 – reactive_compact

即使经过 L4,API 仍然返回 prompt_too_long 错误(比如摘要本身还是太长),就触发紧急压缩:再做一次 LLM
摘要,只保留最后几条消息。

L3 tool_result_budget–大结果存磁盘

1. 统计最后一条 user 消息中所有 `tool_result` 的总大小 2. 总量 > 200KB? ├─ 否 → 跳过,不做任何处理 └─ 是 → 按大小从大到小排序 逐个检查: ├─ 单条 ≤ 3 万字符 → 跳过(小的不动) └─ 单条 > 3 万字符 → 存磁盘,上下文替换为预览 直到总大小降到 200KB 以下 → 停止

举例

原始状态:
messages 中有一条工具结果,内容是 5 万字符的 cat 输出

→ 全部在上下文中,占用 5 万字符

L3 处理后:

  1. 完整内容写入磁盘文件:.tool-results/toolu_xxx.txt(5 万字符)

  2. 上下文中的内容被替换为:

    Full output: .tool-results/toolu_xxx.txt
    Preview:
    (前 2000 字符的预览…)

    → 上下文只占约 2000 字符

对比

处理前处理后
上下文中5 万字符完整输出2000 字符预览 + 文件路径
磁盘上完整 5 万字符

L1 snip_compact–裁掉无关的旧对话

1. 判断:消息数 > 50?没超过就跳过 2. 计算:头保留 3 条(初始上下文),尾保留 47 条(当前工作),中间全部裁掉 3. 替换:中间的位置放一条占位符消息,告诉 LLM "这里裁掉了一段对话"

为什么保留头 3 条?

头 3 条通常是用户最初的任务描述和 agent 的初始响应,包含当前目标,丢了就不知道在干什么了。

为什么保留尾 47 条?

尾部是最近的工作上下文,agent 正在做的事情,丢了就没法继续。

举例

假设 messages 有 80 条: 处理前(80 条): [msg0, msg1, msg2, msg3, msg4, msg5, ..., msg76, msg77, msg78, msg79] ←── 头 3 条 ──→ ←──── 中间 74 条 ────→ ←──── 尾 47 条 ────→ 处理后(51 条): [msg0, msg1, msg2, "[snipped 74 messages]", msg33, msg34, ..., msg79] ←─ 头 3 ─→ ←── 占位符 ──→ ←──────────── 尾 47 条 ────────────→

L2 micro_compact–旧工具结果占位

1. 收集:扫描 messages 中所有 `tool_result` 块 2. 判断:`tool_result` 数量 ≤ 3?跳过 3. 替换:除了最近 3 条,更旧的且长度 > 120 字符的替换为占位符

举例

假设 messages 中有 8 条 tool_result: 处理前(8 条 tool_result): [tr1(500字), tr2(800字), tr3(200字), tr4(1500字), tr5(300字), tr6(120字), tr7(900字), tr8(600字)] ←──────────────── 旧的 5 条 ────────────────→ ←──── 最近 3 条 ────→ 处理后: [tr1("[compacted]"), tr2("[compacted]"), tr3(200字), tr4("[compacted]"), tr5(300字), tr6(120字), tr7(900字), tr8(600字)] ←── 替换为占位符 ──→ ← 保留(≤120字)→ ←── 保留(最近 3 条)──→

L4 compact_history–LLM全量摘要

1.保存 transcript(备份)

完整的对话保留

2.LLM生成摘要

把对话历史发给LLM,保留生成summary

  • current goal 当前目标
  • key findings/decisions 关键发现和决策
  • files read/changed 读过/改过哪些文件
  • remaining work 还剩什么没做
  • user constraints 用户的约束条件

3.替换

所有旧消息被替换为一条摘要

举例

场景:Agent 在项目中工作了 30 分钟

处理前(160 条消息,节选)

msg0 [user] 帮我给这个 Flask 项目加上用户登录功能 msg1 [assistant] 好的,我先看看项目结构 ... ... msg158 [tool_call] edit_file("routes.py", old, new) msg159 [tool_result] Edited routes.py

第 1 步:备份

write_transcript(messages)

→ .transcripts/transcript_1748280000.jsonl

160 条消息完整写入,数据不丢


第 2 步:LLM 摘要

summarize_history(messages)

LLM 看到 160 条消息,生成:

当前目标:给 Flask 项目添加用户登录功能 关键发现和决策: - 使用 flask-login 库实现认证 - User 模型已添加 password_hash 字段 - 登录路由使用 @login_required 装饰器 已修改的文件: - models.py:添加 User 模型和密码哈希 - routes.py:添加 /login、/logout 路由 - app.py:初始化 LoginManager - tests/test_auth.py:添加登录测试 剩余工作: - test_login_redirect 测试失败,需修复 routes.py 中的重定向逻辑 - 登录页面模板 templates/login.html 尚未创建 用户约束: - 使用 SQLite 数据库 - 密码用 werkzeug 加密

第 3 步:替换

处理后(1 条消息):

[{ "role": "user", "content": "[Compacted]\n\n当前目标:给 Flask 项目添加用户登录功能\n\n关键发现和决策:\n- 使用 flask-login 库实现认证\n- User 模型已添加 password_hash 字段\n- 登录路由使用 @login_required 装饰器\n\n已修改的文件:\n- models.py:添加 User 模型和密码哈希\n- routes.py:添加 /login、/logout 路由\n- app.py:初始化 LoginManager\n- tests/test_auth.py:添加登录测试\n\n剩余工作:\n- test_login_redirect 测试失败,需修复重定向逻辑\n- 登录页面模板尚未创建\n\n用户约束:\n- 使用 SQLite 数据库\n- 密码用 werkzeug 加密" }]

LLM 拿到摘要后继续工作

LLM 看到摘要 → 知道自己在做什么、做了什么、还剩什么→ 直接去修 test_login_redirect,不用重新读 160 条历史


对比:

处理前处理后
消息数160 条1 条
包含内容每条工具调用的完整输出5 个关键信息摘要
LLM 能做什么能看到所有细节知道目标、进度、剩余工作
token 占用~50000+~500
http://www.rkmt.cn/news/1494362.html

相关文章:

  • NXP KS22/KS20微控制器:高性能ARM Cortex-M4的嵌入式开发实战指南
  • ABAP开发者的Excel革命:abap2xlsx如何高效解决企业报表生成难题
  • 别再只用scatter3了!MATLAB三维数据可视化,plot3和scatter3的隐藏玩法与实战对比
  • 安全生产月别再这么做培训了(安全员看了都泪目)
  • 2026 年 6 月最新 | 私家泳池工程公司哪家靠谱,无边际 / 恒温私家泳池施工服务商哪家好 - 资讯纵览
  • ApkShellext2:让Windows资源管理器智能识别移动应用文件的终极方案
  • 专利申请资格是什么?2026最新个人/企业/发明人申报权限、权属划分、禁报条件、高频误区全解析|广州正规专利代理机构TOP3实测测评 - 资讯纵览
  • 上海黄金回收正当时 每克942元你卖了吗 - 润富黄金回收
  • 工装标准缝纫流程及自动化升级提质增产方案
  • i.MX RT500引脚配置全解析:未用引脚处理与系统稳定性设计
  • 在Apple Silicon Mac上无缝运行Windows应用:深入解析Whisky的技术架构与实践指南
  • Xshell配色方案终极指南:250+专业主题彻底改变您的终端体验
  • 不止于本地:手把手教你用Portainer管理远程服务器和树莓派上的Docker服务
  • 泉州黄金市场观察 6月金价震荡调整 黄金回收如何选靠谱商家 - 润富黄金回收
  • 权威可查!2026年6月欧米茄官方维修网点地址、售后热线完整汇总 - 资讯纵览
  • 人工智能七大核心赛道深度解析:小白程序员必备收藏指南,开启AI学习新篇章!
  • 闲置名表变现怕麻烦?宁波 禹竞名奢汇 资质价格靠谱放心 - 名奢变现站
  • 深耕名表回收领域,济南爱彼、理查德米勒正规商家实地测评 - 开心测评
  • 用Verilog手把手教你搭建一个RISC-V单周期CPU(附完整代码与仿真)
  • 差 3 倍报价!济南 20 家名表回收店实测,真正高口碑商家仅这一家 - 奢侈品回收评测
  • i.MX RT1020引脚配置与数据手册更新深度解析
  • i.MX 6SoloX异构多核处理器实战:从架构解析到物联网网关开发
  • 音乐歌词获取处理工具:三步实现网易云QQ音乐LRC歌词批量下载
  • 终极微信聊天记录导出指南:免费永久备份你的珍贵回忆
  • 2026空格教育专业护航,考证入深户拥抱未来 - 资讯纵览
  • Kinetis K21实战解析:平衡性能与功耗的Cortex-M4开发指南
  • 机器学习模型生产运行态治理:从部署到稳定服役
  • 基于多案例系统学习防洪评价报告编制方法与水流数学模型建模实践技术应用
  • 3种方法轻松搞定RTL8821CU无线网卡Linux驱动:从新手到专家完整指南
  • STM32 HAL库点灯实战:从CubeMX配置到MDK-ARM调试的全流程避坑指南