编码智能体上下文压缩:AutoCompact如何防止AI失忆
发布时间:2026/10/26 6:24:06 锦皓数字建站

最近在折腾编码智能体的时候我发现一个很有意思的现象很多人选模型时盯着上下文窗口大小看1M、200K、128K觉得窗口越大越安心却几乎没人提前考虑上下文会被用完这件事。1M token听着很宽裕但真到了连续开发三四个小时、中间贴过几段源码、跑过几轮测试、试过两种方案之后该爆还是爆。等窗口真的满了要么强硬截断要么手动粘贴摘要结果AI开始失忆把之前否掉的需求又捞回来反复讨论。AutoCompact这套方案的出发点就是把上下文压缩从“临终抢救”变成日常整理。这篇文章我会把它的触发机制、内容分级、压缩流程和配置参数全部拆开讲清楚适合正在用编码智能体做长任务的人也适合想给自己搭一套上下文管理工具的朋友。1. 别等上下文爆了才开始抢救先看真实的“爆掉”现场1.1 一次多轮重构任务里上下文是怎么被吃光的设想一个典型场景早上十点你准备把一个单体服务的支付模块拆出去做成独立的微服务。这活儿涉及接口梳理、依赖分析、数据表变更、迁移脚本任何一个有经验的工程师都不会指望一轮对话搞定。任务开始后你让编码智能体先梳理模块现有的接口和依赖关系。它会读好几个源码文件把关键代码片段贴出来生成一张依赖清单这一轮大概消耗1500到3000 token。接着你要求它对比两种拆分方案按领域边界拆和按数据表归属拆。它会列出各自的优缺点、影响面、迁移成本这一轮直接消耗4000到6000 token。你拍板选了方案一让它开始实现第一个接口的抽取它要把Controller、Service、Mapper三层代码分别读取、摘录、改写又是七八千token。“感觉还好”你可能这么想。但别忘了这过程中还夹杂着它的工具调用记录、你纠正它理解偏差的对话、两次测试运行的输出。到中午十二点半累计消耗可能已经到6万到8万token。128K窗口还剩下一半多看着安全。真正的爆点往往出现在下午。你发现有个核心表被三个服务共同引用原本的方案有风险不得不再讨论一次调整策略。你为了让它快速理解直接复制了一段数据库迁移脚本和线上索引信息进对话又是两万多token。到下午三点左右窗口使用量悄悄越过75%模型开始出现“早期结论被忽略”的迹象——你明明上午已经排除过方案二它却又把方案二提出来当成新思路。这不是段子是我实际见过很多次的轨迹。上下文的使用不遵循匀速增长它更接近指数抬升前期是方案讨论、代码摘录中期是调试输出、报错日志后期为了补救前期信息丢失还要额外花token把旧结论重新解释一遍。1.2 被动压缩为什么总是让人抓狂等模型终于提示“会话上下文接近上限”时多数人会做一件事手动整理。把之前的方案讨论删掉把报错日志清掉把早先粘贴的代码删掉。这个动作看起来合理问题在于删除的人其实并不总能判断哪些信息对模型的后续决策仍然有意义。举个例子你在上午的讨论里否决方案二的理由是“它会把订单表和支付表拆到不同事务边界补偿机制成本太高”。这个理由在当时的对话里只出现了一次之后没有再被引用。整理上下文时你顺手删掉了一大段方案对比分析包括这句话。模型在下午继续设计数据迁移时不知道事务边界这个约束存在于是再次提出了跨服务事务方案。被动压缩的另一个问题是它本质上打断思路。手动整理往往发生在你正在处理一个复杂问题、上下文恰恰最稀缺的时刻就像打仗打到一半突然要清点弹药库最耽误事。而且每手动压缩一次模型短期内会出现一轮“适应期”表现明显下降因为前后的信息分布变了。1.3 “1M上下文”为什么不是免死金牌有人会说“那我换支持1M token的模型总可以吧”窗口大了确实能延缓问题但解决不了问题本身原因有三。第一成本不是线性的。上下文从128K涨到1M单位token的推理成本不一定等比上涨但单次请求必须包含全部历史输入单轮调用费用和响应延迟都会明显增加。对一个需要频繁交互的编码智能体来说每次都背负几十万token的历史每轮响应时间会从几秒拉到几十秒体感通常难以接受。第二注意力会被稀释。深度学习模型对长上下文并不是一视同仁的已有研究反复提到“lost in the middle”现象处在超长上下文中间位置的信息被模型“看见”的概率显著低于开头和结尾。就算你把所有对话都塞进去模型也可能忽略掉夹在中间的关键决策。第三信息过载本身就增加幻觉风险。当模型面对太长的输入它更倾向于基于最近一段内容做推断早期约束自然会被遗忘。这不是模型不够聪明而是注意力的有限分配决定的。所以1M窗口的真实意义是给你留出“不压缩的缓冲期”而不是让你理直气壮地不整理。真正健康的用法恰恰是在长窗口里也要设置压缩水位——这比在小窗口里做压缩回报更明显因为单次压缩释放的token量更大。2. 编码智能体需要记忆的其实不是对话本身2.1 上下文是工作台不是仓库要设计好压缩方案先得弄清楚编码智能体的上下文里到底什么信息有价值。我的类比是上下文是操作员面前的工作台面而不是仓库。仓库你的代码仓库、文件系统、数据库里的东西任何时刻需要都能重新去取。比如某个文件的完整源码、某次运行的日志、某个接口的完整定义——想拿的时候再读就行没必要一直摆在上下文中。工作台面上的东西是当前决策必须随时可见的材料用户定下的最终目标、当前正在使用的方案、已经完成的事项、接下来要做的步骤。这些信息一旦被清走模型就无法理解“现在处于任务的哪个阶段”后面的每句话都会产生偏差。所以压缩算法的第一原则就是区分这两类信息。可重建的东西大胆清不可重建的东西小心护。2.2 编码任务的状态机拆开看才知道什么不能删一个编码任务本质上是一台状态机。我是这样拆的第一层需求层。用户最终想要什么效果订单超时自动退款、支付模块独立部署、日志链路完整。这层信息优先级最高任何压缩都碰不得。第二层决策层。当前采用什么技术方案以及为什么采用它。包括选型理由、排除掉的替代方案和否定的原因。“不改A表的索引结构”这种决策比“A表索引当前长什么样”更重要因为后者随时可以从库里查前者一旦丢失就只能靠猜。第三层执行层。改过哪些文件、加过哪些接口、哪些测试通过了、哪些还有问题。这层是任务进度条可以压缩但必须保留成清晰的清单不能用“已完成相关工作”这种模糊表述糊弄过去。第四层噪音层。调试时的报错堆栈、临时日志、工具返回的原始JSON、试错过程中的废弃代码。这层信息密度低需要的时候重跑一遍就能重新拿到是压缩的首要对象。这四层划分是AutoCompact做内容分级的基础。2.3 顺手澄清执行上下文和模型上下文不是一回事搜索热词里有个“执行上下文”还有一个“中断上下文”得说清楚这两个是操作系统领域的概念和编码智能体讨论的“上下文”层级完全不同。操作系统里执行上下文是指CPU切换任务时保存的寄存器、程序计数器、栈指针等一套运行状态中断上下文则是处理中断时内核需保存的环境信息。它们强调的是“程序运行到哪一步了”。编码智能体说的上下文指的是模型输入序列中的全部内容——系统指令、用户历史消息、助手回复、工具调用记录、观察结果。它的本质是模型做下一个token预测时能“看到”的文本范围。两者的共同点只有一个都在描述“当前状态需要保留哪些信息才能继续”。但因为底层技术完全不同做管理时不要混用系统层面的方案来对付模型上下文。这一点在学习资料时特别容易踩坑搜索“上下文压缩”经常搜出操作系统课程别被带偏了。3. AutoCompact如何实现主动「断舍离」3.1 触发机制在半满的时候整理而不是等全满再抢救AutoCompact最关键的设计调整是把压缩时机从“上下文即将溢出”提前到“上下文用到一半”。我采用的触发条件是双阈值水位阈值加增量阈值。水位阈值设为45%意思是当上下文用量首次达到45%时触发第一轮压缩。压缩完成之后并不是立刻进入等待状态后续每当窗口使用量再增加10个百分点也就是达到55%、65%、75%就再做一轮增量压缩。为什么是45%而不是80%两个原因。第一压缩本身需要消耗token。让模型阅读当前上下文、生成摘要、归档信息这个过程会先把窗口塞得更满一些如果启动水位太高压缩还没完成窗口就满了操作直接失败。第二45%时窗口里通常已经积累了足够多的噪音层内容日志、输出、重复讨论又还留有充足空间做压缩操作这是个安全的操作窗口。触发阈值不能设太低。如果设在20%上下文里根本还没积累多少可压缩内容每几轮就触发一次压缩每次只能释放一点点空间但付出的模型调用成本却一点不少还会打断对话节奏。我在实验里的经验是40%到50%之间是比较合理的水位区间。3.2 内容价值分级不是所有内容都配占窗口压缩动作之前先要对当前上下文做一次内容审计。我把它分成五个等级每个等级对应不同的处理方式优先级内容类型处理方式S级系统指令、任务最终目标、当前方案决策原样保留永不压缩A级任务进度清单、已完成/待办事项保留只做精简表述B级关键分析过程、方案对比讨论压缩为决策摘要C级报错日志、调试输出、工具返回数据只留关键摘要详情归档D级废弃方案细节、早期重复讨论直接删除或一句话带过这个分级不是设计者拍脑袋定的而是依据“不可重建性”来排序的系统指令和任务目标不可重建必须永久保留报错日志和工具输出随时可以再生成所以大胆压缩。价值分级是压缩策略的核心“断舍离”的“舍”也是按这个标准在执行。3.3 三步压缩流程摘要、归档、对齐AutoCompact的压缩动作分三步走每一步有明确产出。第一步语义摘要。对B级和C级内容模型要生成一段固定格式的摘要目标、结论、依据。为什么用三段式而不用自由文本因为压缩后的上下文是给后续模型看的它必须能在下一秒快速检索到关键事实。三段式结构相当于给它一个稳定的检索索引后续对话如果需要某个决策理由直接去摘要里找“依据”字段就行。第二步信息归档。被摘除的完整内容不能简单丢弃。尤其是调试日志和报错堆栈可能之后还要复盘。AutoCompact会把完整内容写入工作目录下的隐藏文件夹比如 .compact_history/并在上下文里只留下一个指针式引用“完整日志见 .compact_history/run_003.log”。模型需要细节时可以按需读取文件而不是让所有细节一直占着窗口。归档这一步相当于给清走的物品找了个仓库柜子而不是直接扔进垃圾桶。第三步状态对齐。压缩动作完成后AutoCompact会把当前任务状态重新写到上下文最前部任务目标是什么、已完成哪些、剩余待办是哪些、下一步先做什么。这一步是为了抵消压缩带来的“上下文断层”。有了状态对齐段落后续对话即使面对全新的信息分布也能立刻知道自己在哪要去哪。这三步流程里最容易忽略的是第三步。很多人只做摘要和归档结果压缩后模型虽然还记得零散信息却丢失了“整体进度感”话语开始变得飘。状态对齐相当于给压缩后的工作台贴了一张任务便签价值很大。3.4 防“失忆”自检压缩不能靠赌压缩做完了怎么知道有没有压坏AutoCompact的做法是加一轮自检。压缩完成后模型需要回答三个问题当前任务目标是什么已经完成了哪些工作下一步要做什么把这三个答案与压缩前记录的任务状态做一致性比对。如果答案一致说明压缩过程没有破坏核心信息压缩成功。如果不一致说明压缩掉了关键信息触发回滚——恢复到压缩前的完整上下文并且调整压缩策略把刚才触发问题的内容提升一个保留等级。这套自检机制的价值在于它把“压缩是否成功”从不可控变成了可验证。不用赌压缩会不会让模型失忆而是每次压缩后主动确认。一开始我嫌这个自检麻烦跳过了结果有一次压缩后模型忘了任务里“不做跨库事务”的约束白白浪费了两个小时的对话。后来老老实实加回来再没出过类似问题。4. 触发参数怎么配、压缩效果实测、踩过的坑4.1 一套可以直接抄的初始配置给出我目前在用的配置供参考触发水位45%首轮之后每增长10%触发一轮最小压缩释放量单轮压缩至少释放15%的窗口空间否则放弃本轮压缩摘要格式目标-结论-依据三段式归档路径工作目录/.compact_history/自检要求三个问题一致性得分低于0.8时回滚永久保留层S级与A级几点说明。最小压缩释放量这个参数是为了避免“空转压缩”——比如当前窗口里只有5000 token的C级内容压缩后只能省2000 token还不到总窗口的2%这种压缩没有意义跳过更划算。归档路径建议放进代码仓库忽略列表别让这些临时文件污染版本管理我见过有人把日志归档文件提交进仓库后面清理起来很狼狈。4.2 压缩前后的实测对比拿一个真实跑过的中型任务做展示。任务是把一个Spring Boot项目里的支付模块拆分成独立服务涉及二十多个文件、三次方案调整、两轮回归测试。不压缩的基准组窗口128K。跑到第65轮对话时上下文使用量到80%模型开始明显遗忘早期决策把已经否掉的方案重新提出。到第95轮窗口彻底塞满对话被强行中断主持人手动总结历史、新开对话重新交代背景前后多花了大约30分钟。开启AutoCompact的实验组同样任务、同样模型第一轮压缩发生在第42轮窗口使用量45%当时上下文里大约有22000 token的C级内容调试日志、测试输出、工具返回压缩归档后释放了约15000 token。后续在55%、65%水位各触发一轮增量压缩每轮释放量在8000至12000 token之间。任务最终跑了140轮对话窗口使用量始终压在70%以内全程没有中断。更重要的是把第130轮时模型对早期决策的记忆做了抽查——“当初为什么排除按数据表归属拆分方案”它能准确回答出“订单表和支付表会落到不同事务边界补偿成本太高”。这个细节在原始对话里出现过两次一次是第8轮方案对比一次是第31轮调整策略时重提。如果没有压缩保护这个信息大概率会被后续大量日志淹没。当然要说明压缩不是降本神器它本身就是一种开销。实验组多了四次压缩动作每次压缩大概耗掉2000到4000 token的调用量整体token用度其实比基准组还高一些。但它是划算的多花一两万token换来任务不中断、记忆不失真远比重新交代背景省心。4.3 我踩过的坑和对应的处理第一个坑摘要写得太“节约”。早期版本给压缩指令加了一个“尽可能简短”的约束结果B级内容被压成一行“讨论了方案一和方案二决定用方案一”。后面模型反复追问“方案一是什么”又回到原始内容找细节token反而花得更多。后来把压缩指令改成“信息密度优先长度其次”并强制使用目标/结论/依据三段式问题才消失。注意压缩的目标不是把token压到最低而是保住后续对话检索所需的信息密度。压得太过后续为找回细节付出的token比省下的还多。第二个坑压缩抖动。参数表里最初只设了水位阈值没设增量阈值。结果上下文在44%到46%之间反复横跳每几轮就触发一次压缩对话节奏被不断打断。加了“每增长10%才触发下一轮”的门槛并且要求距离上次压缩至少隔五轮对话抖动才消失。第三个坑动过系统指令。不是每次压缩都一定不能碰系统指令但我试过把工具使用说明压缩成摘要结果模型在调用工具时出现了格式错误——摘要把关键参数格式的示例给丢了。从那以后S级内容设置成永不压缩自定义的格式说明永远保留原文。教训是文法层的格式约束不属于可摘要内容它需要一字不差的精确性。第四个坑归档文件不清理。压缩产生的归档日志在完成一个大任务后能攒出几百MB。别等磁盘满了再想起来我养成的习惯是任务收尾时把.compact_history/里超过七天的归档文件清一遍。一行命令就能解决find .compact_history/ -type f -mtime 7 -delete如果你希望清理逻辑更可控也可以用简单的Python脚本封装定期在任务完成后跑一次。如果你也在用编码智能体做长任务我的建议是别等窗口报警再动手从下一次任务开始就配上一套主动压缩机制。第一版参数不用完美跑一两次任务再调都来得及。我自己的下一步计划是把压缩归档和代码提交记录打通让模型恢复旧任务时能直接从归档点继续。这算是在“断舍离”之后再给清走的内容找好归处。等这套流程跑通了再单独写一篇分享出来。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。