ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AI编码代理上下文压缩接续方案:long_mem与engram实战

AI编码代理上下文压缩接续方案:long_mem与engram实战 1. 这个实验到底在折腾什么先把这个标题拆开看。上下文压缩指的是 AI 编码代理在长会话里因为上下文窗口有限不得不把历史对话、代码片段、工具调用记录做摘要或截断腾出空间给新内容。AI 编码代理就是像 Codex 这类能自己读文件、改代码、跑命令的智能体。long_mem和engram是两种记忆机制的代称前者偏向长期记忆存储与检索后者偏向把关键信息刻进一个可复用的记忆单元。Codex则是这次实验里被反复折腾的主角。问题就出在压缩之后。你让一个编码代理连续工作几十轮它前面读过的文件、改过的函数、踩过的坑一旦被压缩成一段摘要后面再让它接着改它经常接不上——要么忘了之前改过哪个文件要么把已经修好的 bug 又改回去要么重复问你已经回答过的问题。这不是模型笨是记忆断了。这个实验干了什么用 10 天时间跑了 430 条公开记录专门观察上下文压缩之后代理还能不能接得上。所谓公开记录就是把每一轮的输入、输出、压缩动作、后续表现都留痕形成可复盘的数据。430 条不算多但足够看出规律了。适合谁看如果你正在用 Codex 或者类似的编码代理做长任务比如重构一个模块、修一串关联 bug、给老项目补测试那你一定会遇到接不上的问题。这篇就是把这 10 天的观察、踩的坑、试出来的接续方案原原本本讲清楚。新手能看懂原理老手能直接抄配置。我先把结论摆前面压缩本身不是问题问题是压缩之后没有锚点。代理需要一个能快速定位我干到哪了、下一步该干嘛的东西long_mem 和 engram 就是两种不同的锚点思路。下面逐层拆。2. 上下文压缩为什么会把代理截断2.1 压缩的本质是丢信息不是省信息很多人以为上下文压缩是把长文本变短但意思不变这是误解。真实的压缩是有损的。一个编码代理的上下文里通常混着几类东西系统提示和工具定义这部分基本不动用户的需求描述和追问代理自己的思考过程工具调用记录比如读了哪个文件、返回了什么代码 diff 和命令输出压缩的时候系统提示和工具定义一般保留用户需求会被摘要思考过程大量丢弃工具调用记录只留结论代码 diff 可能只留文件名。你想想一个函数你改了 8 行压缩后只剩修改了 utils.py下次代理再动这个文件它根本不知道那 8 行是什么。注意压缩丢掉的往往不是废话而是定位信息。定位信息一丢代理就得重新探索token 反而更费。2.2 代理接不上的三种典型表现10 天记录里接不上的表现高度集中在三类表现具体现象出现频率记忆错位把 A 文件的改动记成 B 文件高频状态回退把已修复的问题重新引入中高频重复探索重新读已经读过的文件、重新问已答的问题高频记忆错位最坑。有一次代理在压缩后坚称已经把 parse_config 函数改成返回 dict 了实际上它改的是另一个同名函数。这种错误不会报错会静默地污染代码。状态回退更隐蔽。代理压缩后忘了自己刚加的一个边界判断下一轮优化时顺手删了测试还全绿因为那个边界条件没被覆盖。重复探索是纯浪费。压缩把我已经读过 config.py这条记录丢了代理又读一遍token 哗哗烧。2.3 为什么单纯加大窗口解决不了有人会说那就别压缩把窗口开大。实测下来窗口再大也有三个问题。第一成本随长度非线性上升长会话烧钱快。第二模型对超长上下文的注意力是衰减的中间部分容易被忽略这就是常说的lost in the middle。第三编码任务天然是长尾的你永远不知道要跑多少轮指望窗口够大是不现实的。所以压缩是必须的关键是怎么在压缩后把接续这件事做好。这就引出了 long_mem 和 engram 两条路线。3. long_mem 与 engram两种记忆锚点的取舍3.1 long_mem 的思路外部存储加检索long_mem 的核心是把记忆放到上下文之外用一个外部存储维护需要的时候检索回来。类比一下就像你写代码时旁边放了个笔记本压缩把脑子里的东西清了但笔记本还在需要时翻一下。具体到编码代理long_mem 通常维护这几类条目文件级记忆每个被改过的文件记录改了什么、为什么改任务级记忆当前任务的目标、已完成步骤、待办决策级记忆做过哪些技术选型为什么这么选检索的时候代理根据当前要干的事去存储里捞相关条目。捞得准接续就顺捞不准等于没存。long_mem 的优点是容量几乎无限可以存很多细节。缺点是检索有延迟而且检索质量依赖查询构造。你查询写不好捞回来的就是一堆不相关的。3.2 engram 的思路把关键信息刻成固定单元engram 这个词借的是神经科学里记忆痕迹的概念。它的思路不是存一大堆再检索而是把最关键的少数信息压缩成固定格式的记忆单元每次压缩后强制保留。一个 engram 单元长这样[任务] 重构 config 解析模块 [进度] 已完成 parse_config 改造返回 dict [关键文件] src/config.py:120-180 [未决] load_config 还没改依赖 parse_config 的新返回值 [禁忌] 不要动 parse_config 的异常处理测试依赖它这种单元的好处是每次压缩后都原样保留不参与摘要代理一睁眼就能看到。缺点是容量有限你不可能把所有细节都刻进去必须挑最关键的。3.3 两条路线怎么选实测下来两者不是二选一而是配合用。engram 负责保命long_mem 负责查细节。维度long_memengram容量大小检索需要查询直接可见延迟有无适合细节回溯状态锚定风险检索不准容量溢出我的做法是engram 只放 5 到 8 条超过就合并或降级到 long_mem。engram 里永远保留当前任务、进度、未决、禁忌这四类其他都可以挪走。提示engram 的禁忌字段最容易被忽略但它最值钱。代理压缩后最容易犯的错就是动了不该动的东西一条禁忌能省你半小时排查。4. 10 天 430 条记录里跑出来的接续方案4.1 实验设置与记录方式实验用的是 Codex 作为编码代理任务选了三类单文件重构、跨文件 bug 修复、给老模块补测试。每类任务都跑到触发压缩为止然后观察压缩后的接续表现。记录方式很土但有效每一轮把代理的输入、输出、压缩前后的上下文长度、engram 内容、long_mem 检索结果都写进一个 JSONL 文件。430 条记录就是这么攒出来的。每条记录包含{ round: 12, context_before: 118000, context_after: 42000, engram: [任务, 进度, 未决, 禁忌], retrieved: [config.py 改动记录], next_action_correct: true }next_action_correct是人工标注的判断代理压缩后的下一步动作是否符合预期。这个字段是整个实验的核心指标。4.2 压缩触发点的选择什么时候压缩直接影响接续质量。实验里试了三种触发策略固定阈值上下文到 80% 就压任务边界完成一个子任务就压混合到 70% 且处于子任务边界时压结果混合策略最好。固定阈值的问题是经常在任务中途压缩代理正干到一半被打断接续最难。任务边界压缩最顺但有时候任务太长等不到边界就爆了。混合策略兼顾两者。具体参数上70% 是个经验值。低于 60% 压缩太频繁浪费高于 85% 压缩留给压缩本身的空间不够容易压出问题。4.3 engram 的生成与维护engram 不是手写的是代理在每轮结束时自己更新的。做法是给代理一个固定的输出格式要求让它每轮末尾输出一个 engram 块系统解析后存起来下轮压缩时强制注入。提示词大概是这样每轮结束前输出一个 engram 块格式如下 [任务] 一句话描述当前任务 [进度] 已完成什么用动词开头 [未决] 还没做什么具体到文件或函数 [禁忌] 哪些东西不能动为什么 只保留最关键的信息总长度不超过 200 字。实测下来200 字是个甜点。太短信息不够太长又变成新的上下文负担。代理自己总结的 engram 质量参差前几轮经常写得太泛比如进度改了一些代码。这时候需要人工纠偏一两次代理就学会了。4.4 long_mem 的检索策略long_mem 的检索不能靠代理自由发挥得给它一个固定的检索时机和查询模板。实验里用的是动作前检索代理每次要动一个文件前先用文件名加动作类型去 long_mem 查一次。查询模板查询{文件名} {动作类型} 返回该文件最近的改动记录、相关决策、已知问题这样检索的命中率比让代理自己组织查询高很多。430 条记录里用固定模板的检索命中率约 78%自由查询只有 52%。4.5 接续质量的量化结果把 430 条记录按策略分组接续正确率如下策略记录数接续正确率无 engram 无 long_mem9641%仅 long_mem10863%仅 engram11271%engram long_mem11486%这个表很说明问题。单用任何一个都不够两个一起用才到 86%。剩下 14% 的错误里大部分是 engram 写得太泛或者 long_mem 检索到了过期记录。注意86% 不是终点。剩下 14% 里有一半可以通过压缩后先让代理复述一遍 engram来救回来这个技巧后面讲。5. 实操把接续方案落到 Codex 上5.1 环境与基础配置Codex 的安装和基础使用网上教程很多这里不重复。重点讲跟接续相关的配置。你需要准备三样东西一个能存 long_mem 的地方本地文件或轻量数据库都行、一个 engram 的注入点、一个压缩触发的钩子。long_mem 用 SQLite 就够了别上重型方案。表结构简单到只有四列时间、文件、动作、内容。查询就是按文件和动作过滤加个时间倒序。engram 的注入点选在系统提示之后、用户消息之前。这样代理一睁眼先看到 engram再看用户这轮要干嘛。压缩钩子挂在上下文达到阈值时触发触发后先更新 engram再执行压缩压缩完把 engram 重新注入。5.2 压缩钩子的实现钩子的逻辑不复杂伪代码大概这样def on_context_threshold(context, threshold0.7): if context.usage_ratio threshold: return context engram agent.generate_engram(context) engram validate_engram(engram) compressed compress(context, keep[engram]) compressed inject_engram(compressed, engram) return compressedvalidate_engram这步别省。代理生成的 engram 经常有格式问题比如漏了禁忌字段、进度写成了名词短语。校验不通过就打回重生成最多重试两次两次还不行就用上一轮的 engram。compress的时候engram 要放在keep列表里确保不被摘要掉。有些压缩实现会把所有内容一视同仁地摘要engram 必须显式保护。5.3 engram 注入的格式细节注入格式直接影响代理能不能读懂。实验里试过几种最后固定成带方括号标签的纯文本不用 JSON。原因是 JSON 的括号和引号在长上下文里容易被模型忽略方括号标签更醒目。 记忆锚点 [任务] 重构 config 解析模块 [进度] 已完成 parse_config 改造 [未决] load_config 待改 [禁忌] 勿动 parse_config 异常处理 锚点结束 前后加分隔线是为了让代理明确知道这是特殊区块不是普通对话。实测加了分隔线后代理引用 engram 内容的概率从 34% 提到 61%。5.4 压缩后复述机制这是把正确率从 86% 往上推的关键一招。压缩完成后不要直接让代理干活先让它复述一遍 engram压缩已完成。请先用一句话复述你当前的任务和下一步要做什么然后再继续。代理复述的过程等于强制它读一遍 engram。如果复述错了你能立刻发现及时纠正而不是等它改错代码才发现。430 条记录里加了复述机制后接续正确率从 86% 提到 92%。复述机制的成本很低就多一轮交互但收益很大。尤其是长任务这一轮交互能省掉后面好几轮的返工。5.5 一个完整的接续流程示例把上面这些串起来一个完整的接续流程是这样的代理干活上下文涨到 70%触发钩子代理生成 engram校验 engram不合格重生成执行压缩engram 强制保留注入 engram 到压缩后的上下文让代理复述 engram复述正确继续干活复述错误人工纠偏后继续这个流程跑顺了代理连续工作几十轮不掉链子。我试过让它连续重构一个 2000 行的模块中间触发 7 次压缩全程没出现状态回退。提示复述机制在任务刚开始的几轮可以省掉因为上下文还没压缩代理记得清楚。从第一次压缩开始启用就行。6. 踩过的坑与排查速查表6.1 engram 写得太泛怎么办这是最高频的问题。代理前几轮生成的 engram 经常是进度完成了部分工作这种废话。解决办法有两个。一是给正反例在提示词里放一个好的 engram 和一个差的 engram让代理照着好的写。二是人工纠偏前三次压缩后手动改 engram代理会从修改里学到标准。实测下来给正反例比纯讲规则有效。代理对例子的模仿能力很强你给它看一个进度已完成 parse_config 改造返回 dict的例子它下次就写得具体了。6.2 long_mem 检索到过期记录long_mem 存久了会有过期记录。比如某个文件三个月前改过现在早就不一样了检索还把它捞回来代理照着过期记录干活就错了。解决办法是给 long_mem 记录加时效标记。查询时优先返回最近的记录超过一定时间的记录降权。具体阈值看项目节奏活跃项目 7 天慢项目 30 天。另外每次文件被改动后把该文件的旧记录标记为已被覆盖检索时跳过。6.3 压缩后代理不认 engram偶尔会出现代理无视 engram 的情况明明注入了它却当没看见。原因通常是 engram 的位置不对被埋在了长上下文中间。解决办法是把 engram 放在上下文的最前面或最后面这两个位置模型注意力最强。实验里放最后面效果最好因为离代理当前动作最近。6.4 常见问题速查表问题可能原因排查动作代理重复读文件long_mem 没记录读过的文件检查读取动作是否入库代理改回已修复的 bugengram 禁忌字段缺失补上禁忌并复述engram 内容为空生成提示词太模糊加正反例压缩后代理答非所问engram 注入位置太靠中移到上下文末尾检索命中率低查询模板不固定改用文件名加动作模板复述机制失效复述提示词被压缩掉复述提示放在 engram 之后6.5 几个反直觉的经验第一个反直觉的点engram 不是越详细越好。我一开始把 engram 写到 500 字结果代理反而抓不住重点。后来压到 200 字以内效果更好。记忆这东西少而准比多而全强。第二个反直觉的点压缩频率高不一定差。只要 engram 维护得好压缩频繁反而让代理每轮都重新锚定一次状态接续更稳。前提是 engram 质量过关。第三个反直觉的点long_mem 检索不是越多越好。一次检索返回 10 条记录代理会挑花眼。返回 3 条最相关的就够多了是干扰。6.6 关于 Codex 的一些实操细节Codex 在长会话里有个特点它对工具调用记录的记忆比对话内容更牢。所以 long_mem 里优先存工具调用相关的信息比如读了哪个文件、改了什么比存对话摘要有用。另外 Codex 的压缩触发有时候不受你控制它自己觉得该压就压了。这时候 engram 的生成就得挂在它的压缩事件上而不是你自己定时触发。具体做法是监听它的压缩回调在回调里插入 engram 生成逻辑。如果遇到 Codex 加载组织设置失败、登录不上这类问题那属于环境配置范畴跟接续方案无关先把基础环境跑通再谈接续。国内使用 Codex 的网络和账号问题按官方文档走就行这里不展开。6.7 这套方案的成本账最后算笔账。加了 engram 和 long_mem 之后每轮多出的开销大概是engram 生成约 300 token检索约 200 token复述约 100 token合计 600 token 左右。相比压缩省下的几万 token这点开销可以忽略。但收益是实打实的。接续正确率从 41% 提到 92%意味着返工大幅减少。返工一次的成本远不止 600 token。所以这套方案在长任务里是稳赚的。短任务就没必要上全套。如果任务跑不到触发压缩engram 和 long_mem 都是负担。判断标准很简单预计轮数超过 10 轮或者上下文会超过窗口的 70%就上否则裸跑就行。我个人在实际操作中的体会是接续问题的本质不是技术问题是代理有没有一个稳定的自我认知。engram 给的就是这个自我认知long_mem 给的是细节支撑。两者到位代理才真正像个能连续干活的同事而不是一个每轮都失忆的临时工。这套东西我还在继续调比如 engram 的自动合并、long_mem 的语义检索都是下一步想试的方向。
返回列表