ARTICLE DETAIL

资讯详情

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

Agent记忆系统开发实战:双网络模型、评分衰减与工程避坑

Agent记忆系统开发实战:双网络模型、评分衰减与工程避坑 在单机工具里能闭着眼跑通的记忆逻辑一放到真实Agent产品里就散架——这是我从年初到现在观察到的普遍现象。很多团队做Agent第一版对话体验还行跑几轮业务逻辑之后就开始“失忆”用户十分钟前说过的偏好下个任务就忘了两个子Agent协作信息传到一半就断层跨天会话更是完全归零。问题基本都出在记忆层。最近我们的Agent记忆项目登上了相关榜单这个项目不是什么炫酷的模型创新就是把“记忆”这件事从架构层面彻底想清楚了。这篇就完整拆一下我们踩过的坑、定下的架构以及最终跑通的东西。先说清楚这个项目解决的核心问题是“长上下文之外、多会话之间、多Agent之间怎么可靠地记住该记的事”。关键词就是Agent记忆、双网络记忆模型、记忆评分与时间衰减全部围绕记忆这个方向展开。1. 为什么“Agent有记忆”这件事这么难记忆问题听着简单不就是把对话历史存下来、下次再带进上下文吗真做起来完全不是这么回事几个层面的困难叠在一起让Agent记忆成了业界的普遍难点。1.1 上下文窗口再大也装不下“全部历史”现在大模型的上下文窗口动辄几十万token看起来够用了。但实际使用中你会发现把一堆历史对话全部塞进上下文模型确实不会直接报错可关键信息会被淹没在海量文本里召回精度反而下降。我们团队有位同事做了个测试往上下文里塞了六万字的背景资料之后简单的是否判断题都能做错。更现实的问题是成本。上下文越长单次推理的token开销和延迟就越高。一个跑生产业务的Agent每轮请求都带上一整周的历史记录这个费用和响应速度都不可能落地。所以“记什么、不记什么”必须有一个主动筛选的机制而不是一股脑全存。1.2 Agent的任务形态决定了记忆必须是结构化的大模型单轮的“对话记忆”其实很浅就是上下文里的话。但Agent是一个持续执行任务的系统需要跨步骤、跨会话地记住用户的偏好、业务约束、任务进度、外部工具的状态这些东西形态各异有的是短句有的是结构化参数有的是一段长文档的摘要。如果只用一个“历史消息列表”来承载所有记忆效果会非常差。我们早期版本就是这么干的结果用户改了一次偏好老偏好和新偏好同时出现在记忆里Agent当场“精神分裂”一会儿按旧规则执行一会儿按新规则执行。1.3 记忆必须有“更新”和“遗忘”机制而不只是“存储”这是最容易忽略的一点。人的记忆是有遗忘曲线的长期不用的信息逐渐模糊频繁使用的信息保持清晰。Agent记忆也一样一次性的临时状态比如“当前正在执行的任务ID”和长期稳定的用户画像比如“用户是内容创作者”生命周期完全不同不可能用同一个存储策略。很多文章喜欢提“记忆score时间半衰期”这句话我们实测下来是对的。核心就是每条记忆不仅要记录内容还要记录重要性分值和最后访问时间定期重算出一个“当前价值分”价值分低的慢慢沉底价值分高的在召回时优先出现。2. 双网络记忆模型长期层和短期层各自干各自的活项目核心架构就是我们常说的“双网络记忆模型”。这个名字听起来挺唬人拆开看其实很朴素把Agent的记忆分成两个网络层一个负责长期稳定信息一个负责短期任务状态各管各的互不干扰。2.1 长期记忆层存那些“跨会话不变”的事长期记忆层存的是用户的长期偏好、业务规则、知识库摘要、历史项目结论这类很少变动的信息。这一层的核心诉求是存得稳、查得准、更新慢。我们用向量数据库承担长期记忆的物理存储每条记忆生成embedding向量写入时顺便打上类型标签和重要性分数。召回的时候直接做向量相似度检索取Top-K条插入当前上下文。这个方案的好处是完全不需要模型参与检索几十毫秒就能完成不烧token。这里有第一个值得注意的设计长期记忆不直接存原始对话而是存“提炼后的结论”。比如用户说“以后周报别在周五晚上发”我们不是把这句话原封不动存进去而是用小模型抽取成结构化条目“周报发送时间约束非周五晚上”。这一步非常关键能过滤掉大量口语化的噪声让下游召回更干净。2.2 短期记忆层管住正在进行的任务状态短期记忆层对应人脑的工作记忆存的是当前会话内的任务状态、中间变量、待办事项。你让Agent先查资料再写报告再发邮件这三个步骤之间流转的数据都在短期记忆里。短期记忆的存储不需要向量库我们用的是Redis加一个轻量级状态表。每条记录带session_id和task_id任务完成后自动清理。这一层的要求是读写快、过期明确不跟长期记忆混在一起。双网络最大的好处是隔离了“检索噪声”。如果我们把所有数据都放在一个库里召回时很容易把“上一个任务的临时状态”误当成“用户的长期偏好”带进上下文导致Agent执行逻辑跑偏。网络分开之后长期层只检索长期条目短期层只按任务ID精确取数谁也不会污染谁。2.3 长期和短期的联动工作记忆写入长期记忆的时机双网络不是完全独立的需要一条联动通道短期记忆里的信息在什么条件下升迁到长期记忆里我们定的规则是同一条信息在短期记忆里出现超过两次比如用户连续两次强调同一偏好自动触发“提炼写入长期层”的流程或者用户在会话里明确说“记住以后都这样”也会直接触发长期写入。触发后系统会调用一个轻量的抽取模型把原始语句转成标准化的记忆条目再生成向量入库。这条联动通道是整个记忆系统最出彩的地方。它让Agent不需要把所有内容都永久保存只在信息足够重要时才沉淀到长期层既控制了存储量又保证了关键信息的连续性。3. 记忆的评分、衰减与召回让系统自己判断该记住什么记忆系统能不能用一大半取决于“召回时能不能把最该让模型看到的东西找出来”。前面说了太多存储这块重点讲召回前的排序逻辑也就是热度计算和召回机制。3.1 记忆热度的计算公式score与时间半衰期我们在项目里实践下来的一套热度公式核心就是热搜词里那个“记忆score时间半衰期”当前热度 原始分值 * 衰减系数 ^ (当前时间戳 - 最后访问时间戳) / 半衰期看起来很简单细节在于参数怎么定。原始分值score由两部分构成写入时根据记忆类型给的基准分加上每次被成功召回后加的“命中加分”。基准分我们是这样定的记忆类型基准分说明用户明确要求记住的偏好10最高优先级业务关键约束条件8影响任务正确性提炼出的用户事实画像6中长期稳定信息任务执行中的结论性信息4可参考但非必需临时状态的日志2基本不参与跨会话召回半衰期则是按类型区分的用户偏好类半衰期30天任务结论类7天临时日志类1天。这套参数不是拍脑袋定的是跑了四轮线上A/B测试调出来的。核心规律是半衰期太短隔两周的用户偏好就召不回太长过时信息在库里堆积召回的条目质量会快速下降。3.2 召回时的“热度相似度”双排序很多新手做检索式记忆只按向量相似度取Top-K。实际跑下来问题很大相似度高的条目不一定重要可能只是匹配到了用户随口说的一句话。我们在召回时采用两阶段排序。第一阶段向量检索候选集取Top-50。 第二阶段把50条候选按“当前热度×0.6 相似度×0.4”组合打分重新取Top-5真正塞进上下文。这个双排序机制让“重要但表述不太一样的老记忆”也能排到前面。举个例子用户曾经说过“我一般不用腾讯系的产品”后来再聊到工具选型时向量相似度可能匹配不到这句原话因为检索词是“协同办公软件”但因为这条记忆热度极高重排序之后照样能被带上。这就是热度排序存在的价值。3.3 召回内容的格式控制与上下文预算模型上下文是有限的所以每次召回多少记忆也要严格设预算。我们按token数做预算分配长期记忆召回上限约800token短期记忆精简到300token以内。召回内容统一拼装成一个固定的“记忆区块”放在系统提示词之后、用户消息之前。这个记忆区块的模板是这样的[记忆] - 用户偏好不喜欢周五晚上处理周报需要提前一天发送 - 业务约束报价单必须经过二次审核后才能发给客户 - 任务状态正在进行第三季度的竞品分析已收集6份材料格式统一之后模型解析记忆块的准确率明显提高。早期版本我们直接塞JSON模型有时候会把JSON字段当成业务指令执行出了几次事故换成结构化短句模板才消停。4. 踩过的坑检索漂移、写入风暴与记忆边界争议记忆系统光看架构挺美好真正落地时问题和方案一样多。这块把我认为最值得分享的几个坑原原本本写出来。4.1 向量检索的“失焦”问题怎么修都不如规则兜底第一个深坑是向量检索的失焦。我们的长期记忆库跑了两周后发现一个问题用户问“那个文档的链接呢”向量检索召回的竟然是各种关于“文档格式”的记忆而不是用户实际的文档地址。查下来原因是embedding模型对“链接”这个词的语义理解不够精确把“文档链接”和“文档说明”混为一谈了。我们试过换更强的embedding模型改善了一些但两个问题随之而来。第一个是成本。商业embedding接口按百万token计费换更强模型后单条记忆写入费用翻了三倍。 第二个是延迟。强模型的向量维度更大检索耗时从50毫秒涨到180毫秒感知明显。最后我们的解法是“规则先过滤、向量再排序”——召回时先用关键词和记忆类型做一轮硬过滤把候选集从几万条缩到几百条再做向量检索。比如用户提到“链接”规则层就过滤出类型为“文件引用”的记忆向量层只管在这类记忆里找最相关的。实测下来召回准确率从82.6%提升到了94.1%成本和延迟反而降了。4.2 写入风暴短期记忆高频触发长期写入运营反馈说“Agent变笨了”排查之后发现是写入风暴。我们的短期记忆转长期记忆逻辑触发条件之一是“同信息出现两次”结果某条用户指令在会话中反复出现系统疯狂提炼并写入长期库一周内涨了四万多条垃圾记忆。后来加了两个限制单会话内同一信息触发写入的次数上限为两次长期库中已有相似度高于0.9的条目时不再新增写入而是给原条目的score加一分第二点很重要。它让记忆库始终是“收敛”的。大量重复信息进来时会不断累加到同一条记忆上而不是各自为政地长出无数个同等条目。这直接规避了库的爆炸式增长。4.3 多会话之间记忆串台用户A的偏好跑到用户B身上这是最严重的一个坑。早期我们按全局库来做记忆检索不同用户的数据没有隔离结果用户A问一句话系统把用户B的“我讨厌第三方推送”当成了背景信息导致整个对话风格和决策全错了。这事对我们触动极大。现在所有的记忆表都强制带user_id检索时第一步就是按user_id做数据源隔离规则层校验不过后面的任何召回操作压根不会执行。这种问题说白了就是系统边界没设计清楚越早定好隔离机制后面越省心。4.4 记忆内容的安全边界与业务合规再说一个容易被忽视但很重要的点记忆系统里存的是用户数据涉及信息安全和合规边界。我们上线前专门拉了一轮评审定下了三条红线敏感字段密码、明文密钥、身份证号等不做记忆写入实时拦截记忆删除接口必须支持按user_id全量清理且双写删除日志记忆的使用范围必须在产品说明中展示给用户不能偷偷记录这个也是值得所有做Agent记忆的团队提前考虑的问题产品可以后补但基础能力必须在早期就定清楚。5. 多Agent协作场景下的记忆共享与隔离项目后期我们开始做多Agent协作记忆这块又面临一个更复杂的维度。5.1 Agent之间需要“共享工作区”而不是“共享全部记忆”几个子Agent协作完成一个复杂任务时如果共享全部记忆最先出的问题就是信息量过载。A Agent在检索记忆时会把B Agent的中间状态也捞出来因为相似度高结果两个Agent互相看到对方没整理完的结果产生脏数据。我们的方案是给多Agent场景单独加一层“共享工作区”相当于任务级的黑板。每个任务有一个task_id所有参与该任务的Agent共享这个工作区的读写权限但各自的长期记忆库仍然隔离。工作区里写的是“我正在做什么、已经完成了什么、下一步是什么”。子Agent拿这个工作区作为协作上下文完全够用又不会触及各自隐私化的长期记忆。5.2 主Agent的“决策记忆”与执行Agent的“操作记忆”分离协作场景中主Agent做规划和决策执行Agent做具体操作。我们发现两者的记忆需求完全不同。主Agent需要的是“用户目标的高层记忆”比如用户想要一份竞品分析报告、市场策略建议、执行排期参考执行Agent需要的是“操作过程的具体参数”比如表格要分几列、报告格式是PDF还是PPT、邮件要发给谁。如果混在同一个记忆库里主Agent规划时会看到一堆无关的操作参数执行Agent执行时会看到一堆不必要的高层目标。所以我们在记忆条目的type字段上做了更细的划分并在检索时按Agent角色过滤可见的记忆类型。5.3 记忆共享的权限控制角色白名单多Agent协作必然涉及权限控制。我们的设计是每种记忆类型都维护一个允许读取的Agent角色白名单。比如“用户财务信息”只能由财务类Agent读取“外部沟通口径”只能由对外Agent读取“项目进度”则对项目内所有Agent开放。这套权限设计让多个Agent在保持独立的同时可以高效协作。至少在我们的项目里它让并行任务处理效率提升了大约35%信息误用率降到了1%以下。6. 把记忆系统接进真实业务的关键动作前面讲了很多架构和原理最后落回实操层面。如果你正在做一个原本“无记忆”的Agent想把这套方案接进去最关键的几个动作是什么6.1 第一步永远是梳理记忆类型清单不要上来就建库、配索引。先花一个下午跟业务方坐在一起梳理你的Agent在真实业务里会遇到哪些需要记住的信息把它们一条一条列出来然后归到长期记忆、短期记忆、共享工作区这三类里。这一步决定后续所有设计的边界做的越细后面返工越少。6.2 建立记忆回放与分析机制记忆写得好不好、召回的准不准凭感觉是没有用的。我们上线初期就接了一套回放机制每个会话结束后抽取“Agent实际用到的记忆”和“理论上最应该用到的记忆”两个集合交给评估模型打分。回放分析的耗时不高一个会话大概几毫秒跑在后台即可。但它带来的价值非常大。所有召回精度、时序错误、乱序进入上下文的问题都能通过这套机制快速暴露。6.3 留好记忆擦除的“后悔药”再强调一次开始提到的安全话题。就算你的记忆系统做得再完善也要先想清楚怎么擦除用户想清空记忆怎么办记忆写错了怎么办业务下线了怎么办我们在这个项目里做了两层擦除操作层主动删除的单条记忆和合规层批量清空某个用户或某个项目的全部数据。擦除是异步的先标记失效再物理清理这样即便误删也能在短时间内恢复。此外擦除全程留痕便于跨团队协查定位问题。这套“先想好怎么删再谈怎么存”的思路在真实的业务环境里非常受用。从我们这次登顶项目的实际经验来看Agent记忆不是一个可有可无的辅助功能而是决定Agent能不能真正稳定产出结果的地基。能记住、会遗忘、懂得在合适的时候把合适的信息带进推理这三个能力结合在一起Agent才像一个真的在工作的人而不是一个每轮对话都重新开始的“金鱼”模型。
返回列表