当前位置: 首页 > 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.jsqmd.com/news/982626/

相关文章:

  • 新开道:AI信任成为数字商业新基建——从流量租赁到数字资产的范式革命 - GrowthUME
  • NXP KS22/KS20微控制器:高性能ARM Cortex-M4的嵌入式开发实战指南
  • 【反八股 01】HashMap 的设计参数是怎么来的
  • 小程序毕设项目:基于springboot+微信小程序的热门游戏商城小程序 (源码+文档,讲解、调试运行,定制等)
  • 三大智能学习场景:开源工具如何重塑B站知识获取体验
  • 青岛闲置大牌包包回收哪家好?2026正规靠谱商家排名推荐 - 名奢变现站
  • ABAP开发者的Excel革命:abap2xlsx如何高效解决企业报表生成难题
  • 别再只用scatter3了!MATLAB三维数据可视化,plot3和scatter3的隐藏玩法与实战对比
  • 【2026年06月】回收石墨板厂家优选指南|回收石墨棒,回收石墨板,回收废碳棒优质企业推荐 - 多才菠萝
  • 2026 年 6 月最新 | 私家泳池工程公司哪家靠谱,无边际 / 恒温私家泳池施工服务商哪家好 - 资讯纵览
  • PyFluent技术解析:Python驱动CFD仿真的架构革新与工程实践
  • 2026年南通全屋定制精选品牌,照着选不踩雷 - 高定
  • 5步从零掌握DeepLabV3Plus-Pytorch:新手友好的语义分割实战指南
  • 大麦网抢票脚本终极指南:Python自动化购票实战教程
  • 2026 成都二手表实测:欧米茄主流系列与法穆兰特色款变现解析 - 奢侈品回收评测
  • 4K60 over IP 方案简介
  • 巨有科技智慧营销平台|精准破局,解锁景区低成本高效增长模式
  • 安全生产月别再这么做培训了(安全员看了都泪目)
  • 实测辟谣:网传 ChatGPT 5.5 偷偷降智?真实结果来了
  • 终极指南:如何在Qt应用中轻松集成专业级PDF查看器
  • 碱基互补配对驱动的无监督语法诱导与语言建模实验报告
  • Java数据结构(四):List的介绍
  • 嵌入式MCU模拟外设设计:从K51振荡器与ADC规格到实战避坑指南
  • i.MX 6SoloX接口时序深度解析:从建立时间到PCB布局实战
  • 小说游玩辅助功能开发
  • 嵌入式硬件工程师必读:JN516x芯片电气参数与接口时序深度解析
  • 郑州回收百达翡丽暗藏猫腻,资深表友都在避开这 4 个陷阱 - 奢侈品回收评测
  • 首岸热销背后的港漂置业逻辑 - 博客湾
  • 2026 年哈尔滨治理烧机油维修推荐:花大修 1/5 费用免拆修复,不拆发动机不贬值 - 资讯纵览
  • 上海黄金回收正当时 每克942元你卖了吗 - 润富黄金回收