news 2026/10/28 14:28:16

AI编码代理上下文压缩恢复实验:long_mem与engram记忆机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI编码代理上下文压缩恢复实验:long_mem与engram记忆机制

1. 这个实验到底在折腾什么

先把这个标题拆开看。上下文压缩,指的是 AI 编码代理在长会话里,因为上下文窗口有限,不得不把历史对话、代码片段、工具调用记录做摘要或截断,腾出空间给新内容。AI 编码代理,就是像 Codex 这类能自己读文件、改代码、跑命令的智能体。问题就出在这两者的交界处:压缩之后,代理还记得自己刚才在干什么吗?还接得上之前的思路吗?

我花了 10 天时间,用一套公开可查的记录方式,跑了 430 条实验数据,专门盯这个问题。核心想验证的东西很朴素——当上下文被压缩掉一部分之后,代理能不能靠某种外部记忆机制,把断掉的线索重新接回来。这里涉及两个关键词:long_mem(长期记忆)和engram(记忆痕迹,借用了神经科学里"记忆印迹"的概念)。前者是存储层,后者是检索和激活层。

这个内容适合谁看?如果你正在用 Codex 这类编码代理做实际项目,遇到过"聊到一半它突然忘了前面说啥"的情况,或者你自己在搭带记忆的代理系统,那这篇就是写给你的。不需要你是模型训练专家,但最好对代理的基本工作方式有点概念。我会把每一步为什么这么做讲清楚,参数怎么定、坑在哪、怎么排查,都摊开说。

430 条记录不是随便凑的数。每条记录对应一次"压缩-恢复"的完整循环,包含压缩前的状态、压缩策略、恢复尝试、以及最终代理是否成功接上任务。10 天是因为要覆盖不同类型的任务:单文件重构、跨文件依赖修改、多轮调试、以及长链路的功能开发。任务类型不同,压缩带来的伤害程度完全不一样,这一点后面会细说。

2. 为什么上下文压缩会"断片"

2.1 压缩的本质是信息有损

很多人以为上下文压缩就是把旧对话删掉,其实没那么简单。主流做法有三种:滑动窗口截断、摘要压缩、以及关键信息抽取。滑动窗口最粗暴,直接把最早的对话扔掉;摘要压缩是用模型把历史浓缩成一段话;关键信息抽取则是挑出文件路径、函数名、变量名这些"硬信息"保留。

问题在于,编码任务的信息密度极高。一句"把parse_config的返回值改成 tuple"背后,隐含了函数当前签名、调用它的所有位置、返回值的消费方式。摘要压缩很容易把这些细节揉成一句"修改了配置解析逻辑",代理再看到这句话,根本不知道要改哪个函数、改成什么样。

我实测下来,滑动窗口在短任务里几乎无感,但一旦任务链路超过 15 轮工具调用,断片率飙升。摘要压缩稍好,但摘要本身的质量波动很大,同一个任务跑两次,摘要可能一次保留了关键函数名,一次没有。

2.2 断片的具体表现

断片不是"代理完全懵了",而是更隐蔽的几种情况。第一种是目标漂移:代理还记得要改代码,但忘了最初的需求是"兼容旧配置格式",结果改出一个只支持新格式的版本。第二种是重复劳动:它忘了自己已经改过某个文件,又改一遍,把之前的修改覆盖掉。第三种最坑,叫虚假记忆:代理根据残缺的摘要,脑补出一个不存在的函数签名,然后照着这个假签名去改代码,编译直接报错。

这三种里,虚假记忆最难排查,因为代理表现得非常自信,你不仔细看 diff 根本发现不了。我在第 3 天就踩了这个坑,一个跨 4 个文件的改动,代理在压缩后重新"回忆"出一个错误的接口定义,导致后面 6 轮工具调用全在错误的基础上打转。

2.3 为什么单纯加大窗口不解决问题

有人会说,那就别压缩,把窗口开大不就行了。理论上可以,但实际不行。一是成本,上下文越长,每次调用的 token 消耗越大,长会话下成本是指数级上升的。二是效果,业界普遍观察到一个现象:上下文太长时,模型对中间部分的注意力会下降,也就是所谓的"lost in the middle"。你把 10 万 token 塞进去,模型真正用上的可能还是头尾那部分。

所以压缩不是可选项,是必选项。真正要解决的是:压缩之后,怎么让代理快速、准确地找回它需要的那部分信息。这就是 long_mem 和 engram 要干的事。

3. long_mem 和 engram 的分工设计

3.1 为什么要把存储和检索分开

我一开始想的是搞一个大而全的记忆模块,既存又查。跑了大概 50 条记录之后发现不行。存储和检索的优化目标是冲突的:存储希望信息尽量全、尽量原始,检索希望信息尽量精、尽量快。混在一起,要么存得太多查得慢,要么为了查得快把信息砍得太狠。

所以拆成两层。long_mem负责存,把每次压缩前的关键状态完整落盘,包括文件快照、工具调用序列、以及代理当时的"意图描述"。engram负责查,根据当前上下文,从 long_mem 里激活最相关的几条记忆,注入回代理的上下文。

这个设计借鉴了认知科学里的记忆模型:长期记忆存储量大但提取慢,工作记忆容量小但反应快,两者靠"激活"机制联动。engram 就是那个激活器。

3.2 long_mem 存什么、怎么存

long_mem 的存储单元我定义为一条"记忆条目",每条包含四个字段:

字段内容作用
意图代理当时想完成什么用于语义匹配
状态涉及的文件路径与关键代码片段用于精确恢复
动作已执行的工具调用序列避免重复劳动
时间戳记录生成时间处理新旧记忆冲突

意图字段是核心。它不是简单记录"修改了文件",而是让代理在压缩前用一句话总结"我接下来要做什么"。这句话是后面检索的锚点。实测发现,意图描述越具体,恢复成功率越高。比如"修复登录接口的空指针"就比"改 bug"强太多。

状态字段我做了取舍,不存整个文件,只存被修改的函数或代码块,加上文件路径。这样单条记忆的体积可控,几百条记忆也不会撑爆存储。动作字段记录工具调用的摘要,比如"已读取 auth.py、已修改 validate 函数",用来防止代理重复执行。

3.3 engram 怎么激活正确的记忆

engram 的激活逻辑是整个实验里调参最多的部分。最朴素的方案是关键词匹配,把当前上下文里的词和记忆条目的意图做匹配。但编码场景里,同一个概念可能有多种表达,关键词匹配召回率很低。

我最后用的是"语义相似度 + 硬信息命中"的混合策略。语义相似度用嵌入向量算,负责召回语义相关的记忆;硬信息命中则是检查当前上下文里出现的文件路径、函数名,是否在某条记忆的状态字段里出现过。两者加权求和,取 top-k 注入。

权重这块我试了好几组,最后定的是语义 0.6、硬信息 0.4。为什么硬信息权重不低?因为编码任务里,文件路径和函数名是最强的线索,一个文件名的命中,往往比一段语义相似更能说明问题。这个比例不是理论最优,是我在 430 条记录里试出来的经验值,你可以根据自己的任务类型微调。

4. 430 条记录是怎么跑出来的

4.1 实验设置与任务分类

实验环境是一台本地开发机,代理用的是 Codex 的 CLI 形态,通过标准输入输出交互。任务库我准备了 40 个真实项目任务,分成四类,每类 10 个,每个任务重复跑多次以覆盖不同的压缩触发点,最终累计 430 条有效记录。

四类任务是:

  • 单文件重构:在一个文件内改函数结构,压缩伤害最小,作为基线。
  • 跨文件依赖修改:改一个接口,牵连多个调用方,考验记忆的关联能力。
  • 多轮调试:反复试错,历史里有很多失败尝试,考验代理会不会重蹈覆辙。
  • 长链路功能开发:从需求到实现跨几十轮,考验长期目标的一致性。

每条记录我记录了压缩触发时的轮次、压缩策略、恢复后代理是否走对方向、以及最终任务是否完成。判定"走对方向"的标准是:恢复后的前 3 轮工具调用,是否与压缩前的意图一致。

4.2 压缩策略的对照

我对比了三种压缩策略在有无记忆机制下的表现。这里的数字是任务完成率,不是精确的统计结论,是我这批任务上的实测值:

压缩策略无记忆仅 long_memlong_mem + engram
滑动窗口41%58%79%
摘要压缩53%67%86%
关键信息抽取62%74%88%

几个观察值得说。第一,engram 带来的提升在滑动窗口下最明显,因为滑动窗口丢的信息最多,记忆机制补回来的空间最大。第二,关键信息抽取本身已经不错,加上 engram 后提升有限,说明当压缩策略本身保留了硬信息时,记忆的边际价值下降。第三,无论哪种策略,光有 long_mem 不够,必须配上 engram 的激活,否则存了也白存。

4.3 一个典型的恢复过程

拿一个跨文件依赖修改的任务举例。任务是给一个数据处理管道加一个字段校验,涉及 5 个文件。跑到第 18 轮时触发了压缩,此时代理已经改完了 3 个文件,正在改第 4 个。

压缩后,engram 从 long_mem 里激活了 3 条记忆:一条是"给 record 类加 validate 方法"的意图,一条是"已修改 parser.py 和 model.py"的状态,一条是"待修改 exporter.py"的动作。这三条注入后,代理在第 19 轮直接打开了 exporter.py,没有重新去读已经改过的文件,也没有忘记要加校验这个目标。

对比之下,关掉 engram 只留 long_mem 的那次,代理在第 19 轮重新读了 parser.py,浪费了 2 轮,而且一度想改一个已经改好的函数。这就是激活机制的价值——它不只是"记得",而是"在对的时候想起对的事"。

5. 实操中踩过的坑和排查方法

5.1 记忆污染:旧记忆干扰新任务

跑到第 5 天遇到一个烦人的问题。同一个项目里连续跑多个任务时,前一个任务的记忆会被后一个任务激活。比如刚做完"给用户模块加日志",接着做"给订单模块加日志",engram 把用户模块的记忆也召回了,代理一度想去改用户模块的文件。

根因是记忆条目没有做任务隔离。我的解法是给每条记忆打上任务 ID,engram 激活时先按任务 ID 过滤,只召回当前任务的记忆。如果当前任务没有匹配的记忆,才放宽到全局召回,但权重打七折。这个改动之后,跨任务干扰基本消失。

提示:如果你的代理是长期运行、跨多个任务复用的,任务隔离一定要做,否则记忆越多,干扰越严重。

5.2 意图描述写得太虚

前面提过意图字段的重要性,但实际操作中,代理自己生成的意图描述经常很虚。比如它会写"继续之前的修改",这种描述在检索时毫无区分度,召回一堆不相关的记忆。

我的应对是给意图描述加约束模板,强制包含"动作 + 对象 + 目的"三要素。比如"修改 validate 函数,使其支持空值校验"。模板不是硬编码字符串,而是在提示里给代理几个正例,让它照着格式写。加了模板后,意图描述的平均信息量明显提升,检索准确率跟着涨。

5.3 记忆条目膨胀导致检索变慢

跑到 200 多条记录时,检索开始变慢,单次激活要几百毫秒。排查发现是 long_mem 里堆积了大量低价值记忆,比如"读取了某个文件"这种没有后续动作的条目。

解法是加一个记忆淘汰机制。每条记忆有个"被激活次数"计数,长期不被激活的记忆降权,低于阈值就归档。另外,纯读取类、没有产生修改的动作,不单独存记忆,合并到相邻的意图条目里。这两招下来,活跃记忆条目控制在 100 条以内,检索回到几十毫秒。

5.4 常见问题速查

现象可能原因排查方向
代理重复修改同一文件动作字段缺失或未激活检查 long_mem 是否记录了已执行动作
代理改错函数签名状态字段存了过期快照确认记忆时间戳与当前文件版本
恢复后目标跑偏意图描述太模糊检查意图是否含动作+对象+目的
检索召回不相关记忆任务隔离缺失确认记忆是否带任务 ID
检索变慢记忆条目过多检查淘汰机制是否生效

6. 关于 Codex 这类代理的接入细节

6.1 记忆模块怎么挂上去

Codex 这类 CLI 代理,交互是回合制的:你给它输入,它输出工具调用或文本。记忆模块要挂在这两个点上——压缩触发时写入,每轮开始前检索注入。

写入点比较好办,在检测到上下文接近窗口上限、准备压缩之前,拦截一次,让代理生成意图描述,连同当前状态一起存进 long_mem。检索注入则是在每轮把用户输入或工具返回喂给代理之前,先跑一次 engram,把召回的记忆拼在提示的前部。

这里有个细节:注入的记忆不能太长,否则又挤占上下文。我限制每次最多注入 3 条,每条不超过 200 token。超出的做截断,优先保留意图和状态字段。

6.2 和代理原生记忆的区别

有些代理自带某种形式的记忆,比如把历史对话存到文件里,下次启动时读回来。这跟 long_mem 的区别在于粒度。原生记忆通常是整段对话的堆砌,检索靠全文搜索,噪音大。long_mem 是结构化的,每条记忆有明确的意图、状态、动作,检索靠语义加硬信息,精准得多。

实测对比过,用原生记忆恢复的任务完成率在 60% 出头,换成 long_mem + engram 后到 85% 以上。差距主要来自检索精度,原生记忆经常召回一堆无关的历史,反而干扰代理判断。

6.3 参数配置参考

下面是我最终稳定下来的一套配置,供参考。注意这些值是在我的任务集上调出来的,你换任务类型可能需要重新试:

long_mem: max_active_entries: 100 entry_ttl_days: 7 snapshot_scope: function_level engram: semantic_weight: 0.6 hard_info_weight: 0.4 top_k: 3 max_inject_tokens: 600 task_isolation: true

snapshot_scope设成 function_level 而不是 file_level,是为了控制单条记忆体积。entry_ttl_days是记忆的存活天数,超过就归档,避免无限膨胀。top_k设 3 是权衡,设 5 召回更全但注入变长,设 1 又容易漏。

7. 这套方案适合什么、不适合什么

7.1 适合的场景

跨文件、多轮、有明确目标的编码任务是这套方案的主场。尤其是那种"改一个接口牵连一片"的重构,压缩后最容易断片,记忆机制的价值最大。另外,长时间运行的代理会话,比如你让它跑一整个下午的开发任务,中途必然多次压缩,这时候 long_mem 就是它的"工作日志"。

多轮调试也很受益。调试过程中有大量失败尝试,这些如果不记下来,代理压缩后会重复踩坑。把失败尝试也存成记忆,标注"此路不通",能显著减少无效轮次。

7.2 不适合的场景

短任务、单文件、几轮就结束的,上这套机制是杀鸡用牛刀。记忆的写入和检索本身有开销,任务太短的话,开销占比过高,反而拖慢。我实测 5 轮以内的任务,加记忆机制后总耗时增加约 15%,收益几乎为零。

另外,如果你的任务本身没有明确目标,就是让代理随便探索,那记忆机制也帮不上忙,因为它依赖"意图"这个锚点。没有意图,检索就失去了方向。

7.3 后续可以怎么扩展

一个方向是把 engram 的激活从"被动召回"改成"主动预测"。现在是每轮开始前检索一次,未来可以根据代理当前的动作,预测它下一步需要什么记忆,提前注入。另一个方向是记忆的跨会话复用,把长期有效的项目知识(比如代码规范、架构约定)沉淀成持久记忆,新会话启动时自动加载。

我个人在实际操作中的体会是,记忆机制的价值不在于"记得多",而在于"在对的时候想起对的事"。430 条记录跑下来,最深的感受是:压缩不可避免,断片也不可怕,可怕的是断了之后接不回来。long_mem 和 engram 这套组合,本质上就是给代理装了一个"接得上"的机制。参数可以调,策略可以换,但这个思路——存储与检索分离、意图作为锚点、硬信息加权——是我试过最稳的一条路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/28 14:27:46

邓宁-克鲁格效应与技术认知四阶段:工程识别与成长路径

1. 先把这个被用烂的概念拆开看带过团队的人大概都有过这种体验:一个刚上手三个月的同事,在评审会上对着一套跑了五年的老架构说“这个设计太啰嗦了,我两天能重写一版”;而真正把系统从零扛过三次大促的老手,反而在会议…

作者头像 李华
网站建设 2026/10/28 14:26:56

无人艇编队协同控制:反步法与神经网络补偿技术解析

1. 项目背景与核心挑战水面无人艇(USV)的编队协同控制在海洋勘探、水域监测等领域具有重要应用价值。这个项目针对欠驱动USV编队控制中的三个核心难题展开:欠驱动特性:大多数USV只有推进器和方向舵两个控制输入,却需要…

作者头像 李华
网站建设 2026/10/28 14:26:11

AI科研工具如何提升本科生选题效率与创新

1. AI时代科研选题的变革与机遇在传统科研模式下,选题往往依赖于导师经验、文献调研和个人直觉,这个过程通常耗时数月。2023年Nature期刊调查显示,约67%的本科生在选题阶段就遭遇瓶颈。而现在,AI工具正在彻底改变这一局面。我指导…

作者头像 李华
网站建设 2026/10/28 14:25:17

深度学习分类任务实战:从PyTorch到模型部署

1. 深度学习分类任务概述深度学习分类任务是计算机视觉领域最基础也最核心的问题之一。简单来说,就是让计算机学会像人类一样识别和区分不同类别的图像。比如区分猫狗照片、识别手写数字、判断医学影像中的病灶类型等。我在过去五年的工业实践中,处理过从…

作者头像 李华
网站建设 2026/10/28 14:24:57

hillside不是山+边:英语词族记忆的三维突破法

1. 为什么“hillside”不是“山边”,而是英语词族记忆的钥匙?你有没有试过背了三个月的“mountainside”“lakeside”“doorstep”,结果考试时看到“hillside”还是愣住?我带过不少学生,他们把这类词当成孤立的“单词卡…

作者头像 李华
网站建设 2026/10/28 14:24:42

数值分析第三版答案:从误差与收敛过程看解题参照

简介:这份资源是 Timothy Sauer《Numerical Analysis》第三版(Pearson 2018)的官方教师解答手册,面向正在学习数值分析课程的高校本科生、研究生及授课教师,用于核对课后习题答案、理解算法推导过程。手册按教材章节组…

作者头像 李华