Agent长期记忆的六种工程方案:从LangChain缓存到Zep知识图谱
发布时间:2026/10/31 4:48:43 锦皓数字建站

开头部分前段时间我接了一个客服类Agent的优化需求翻来覆去盯了很久才发现一个扎眼的问题同一个用户隔了三天再回来问“我的订单到哪了”Agent回答得和第一次见面一模一样——用户之前反馈过的事情、主动提过的偏号、上次改单的诉求它全都不记得。换个更强的模型也没用因为问题根本不在理解能力在记忆设计。长期记忆这件事几乎每个做Agent落地的人迟早都会撞上只是撞的姿势不同。这篇文章我想从工程视角拆解六个主流项目——LangChain、Mem0、Letta原MemGPT、AutoGPT、CrewAI、Zep——对Agent长期记忆的设计思路。不是说把这六个项目的API文档抄一遍而是想把一个问题讲透当Agent需要记住超出上下文窗口的信息时每个项目各自选了哪条路、为什么这么选、代价是什么。适合正在做Agent开发、想给现有Agent补记忆能力、或者已经被“上下文爆掉”折腾过的人参考。看完你应该能搞清楚一件事给你的Agent做记忆不是简单塞一个向量数据库就完事。1. 先搞清楚Agent记忆难在哪窗口装不下历史的三个死穴1.1 上下文窗口的“虚胖”陷阱大模型的上下文窗口这两年卷得厉害动辄几十万甚至上百万token看起来什么都能往里塞。但真在工程里跑过就知道窗口大不等于能有效利用。注意力机制的计算复杂度决定了序列越长模型对中间内容的关注质量越容易衰减很多信息放进窗口是一回事真正能被模型注意到并遵循是另一回事。我打了个比方一个人确实可以一口气读完一整本书但合上书后让他复述第三篇第二章出现了什么细节大多数人是做不到的。这也是Agent长期记忆的第一个死穴——把历史粗暴塞进窗口是最直觉也最容易失效的方案。很多人第一版记忆功能就是这么做的每次请求前把全部对话历史拼到系统提示后面token一长模型反而开始“丢三落四”。1.2 暴力拼接历史的三个失效场景我见过不少团队从“每次把历史全部发过去”起步有句话叫这么干能跑通demo但跑不通生产。总结下来三个典型场景长程对话淹没客服Agent聊到第20轮用户在第4轮提过的问题模型在第18轮回答时完全忘了。不是因为模型笨是因为那轮对话被后面十几轮的信息挤到了“有效关注范围”之外。无关信息污染把一年前的订单查询记录和今天的售后投诉混在同一段上下文里模型可能被老信息带偏表现为回答的内容与当前问题弱相关甚至自己把矛盾信息引用出来。令牌费用失控假设你的Agent上下文里攒了10万token历史按当前主流模型输入侧价格算每发一轮新请求光重发历史的成本就不低。聊一小时下来费用比聊十分钟翻几倍而这种浪费完全不产生任何质量价值。1.3 长期记忆要答好的三件事去翻各种Agent框架、记忆开源项目的源码你会发现大家绕来绕去都是在解决三件事存什么原始对话抽取出的结构化信息任务中间态还是几者的混合什么时候写每一轮结束都写达到某种触发条件才写还是由模型自己判断该记哪句怎么取全量回放向量相似度检索按时间倒序取最近还是结合实体关系做图谱查询这三件事的答案不同就直接决定了你会走“聊天缓存路线”还是“抽取式记忆路线”还是“分层记忆路线”。下面六个项目本质上就是对这三件事给出的六种不同答案。2. 六个项目全景图从聊天缓存到知识图谱各自押注不同路线2.1 六个项目的定位与记忆策略速览先看一张总览表把六个项目的核心记忆策略摆在一起后面再逐个拆项目记忆的主要形态写入方式召回方式典型使用场景LangChain对话消息缓存与摘要每轮对话自动追加全量回放/滑动窗口/摘要常规对话链、快速集成Mem0抽取式事实记忆LLM抽取实体/关系入库向量图谱混合检索RAG型Agent、个性化助手LettaMemGPT分层虚拟内存系统主动归档与回写核心块固定加载归档检索长程聊天、持续运营AgentAutoGPT文件系统向量索引任务执行中定期写文件关键词/向量查询任务型自执行AgentCrewAI短期RAG长期SQLite实体记忆任务执行时自动存储检索关系提取多Agent协作工作流Zep时序知识图谱对话事件增量更新时间实体关系查询生产级客服、需要时间感知的记忆2.2 为什么是这六个选择这六个项目不是随机凑数。它们恰好代表了六条不同的技术路线LangChain是“对话缓存派”是最多人上手的第一站Mem0是“独立记忆层派”主张记忆从对话框架里剥离出来LettaMemGPT是“操作系统分层派”把LLM上下文当成虚拟内存管理AutoGPT是“文件即记忆派”简单粗暴但稳定CrewAI是“团队共享派”把记忆上升到多Agent协作层面Zep是“图谱时序派”用带时间的知识图谱做记忆。这六条路线基本覆盖了当前Agent记忆设计的绝大部分业界实践。不管你是想临时给Agent加个记忆功能还是想搭一个正经的记忆中间件都能从这里面找到参照系。2.3 一条时间线看懂记忆方案演进回头看这些项目的出现顺序能明显感觉到一条演进线最早大家觉得“把历史对话存起来、每次塞回去就行”这是LangChain早期Memory模块的思路后来发现塞不下了开始做摘要压缩或滑动窗口这是ConversationSummaryMemory那一批尝试再后来大家意识到“对话原文”本身就很冗余不如直接抽取“事实结论”存进去于是有了Mem0这种抽取式方案同时也要处理“Agent脑子里同时装着当前任务和长期知识”的问题于是MemGPT提出了分层虚拟内存而Multi-Agent兴起后记忆又面临着“共享”语义的挑战CrewAI应运而生最后当记忆要支撑真正的生产级应用时时序和图谱就成了刚需Zep的形态因此出现。3. 逐个拆解六套记忆设计存储、召回、写入策略的门道3.1 LangChain Memory对话链上的缓存式读写先聊最多人用过的LangChain。它在早期版本里提供了一套Memory模块名字起得很直白ConversationBufferMemory就是“把对话原样缓存”ConversationBufferWindowMemory就是“只留最近N轮”ConversationSummaryMemory则是“用LLM把历史压成一段摘要存着”再后来又加了VectorStoreRetrieverMemory支持向量检索。这套设计一看就带着浓浓的“链式思考”味道记忆是挂在对话链Chain侧面的一个配件跟Prompt模板绑在一起用。你在构建链的时候指定一个memory变量对话历史就会被格式化后塞进Prompt里的特定位置。我当年第一版聊天机器人就用的ConversationBufferMemory效果怎么说呢——demo完美一上真实用户就露馅。用户聊二十分钟之后Token开销明显变大回答还经常被前面无关的信息干扰。后来我换成了摘要式确实省了token但丢细节的问题马上暴露用户三天前提的某个具体诉求在摘要里被压缩成了一句话再用的时候根本恢复不出原样。LangChain后来更新也意识到了这个问题在LangGraph时代推荐的做法不再是直接塞全量历史而是用checkpoint机制保存状态、用BaseStore做跨会话存储。这个演进本身就说明了一个道理把记忆当“缓冲附属品”来做天花板很明显。3.2 Mem0像操作数据库一样增删改查记忆Mem0是让我眼前一亮的一个项目。它的出发点非常明确Agent不应该只“回忆对话原文”而应该像人一样“记得结论”。比如用户今天说了一句“我一般晚上十点以后才有空处理文档”它不会是原样缓存这句话而是抽取出一条结构化记忆“用户偏好晚上十点后处理文档”。这就把“聊天记录”和“长期记忆”区分开了。Mem0的写入不是简单的append而是带了一个更新机制。新增一条信息时它会结合已有记忆判断这条是全新的还是对旧记忆的补充还是需要覆盖旧记忆比如用户先说喜欢A方案三天后又改成B方案Mem0会倾向于更新原来的记忆而不是叠一条新的。这个语义层面的增删改查已经非常像一个轻量级的知识库了。核心调用方式也很简洁我用的时候基本就两个操作from mem0 import Memory memory Memory.from_config(config_dict) # 写传入一句用户陈述自动抽取并存储 memory.add(用户说周五我要去上海出差记得提前发行程提醒, user_idu123) # 读传入当前问题召回相关记忆 results memory.search(用户这周有什么出行计划, user_idu123)这套设计的思想在我看来是“记忆是被管理的对象而不是对话的复制品”。Mem0内部通常结合了向量存储和关系型图谱向量负责相似度召回图谱负责实体关系。它还允许带metadata比如用户ID、时间、来源召回时可以用过滤器精确缩小范围。但这条路线也有它的代价抽取依赖模型能力。如果用弱模型去做抽取与更新判断提取出的记忆会破碎、重复甚至错误。简单说Mem0把记忆质量的天花板从“检索算法”转移到了“理解模型的抽取质量”上这是一笔需要认真算的账。3.3 LettaMemGPT核心记忆、工作记忆、归档记忆的三级结构MemGPT的论文标题特别有意思叫“LLMs as Operating Systems”把大模型当成操作系统来设计。这个思路翻译成记忆方案就是非常经典的分层内存管理。你写代码的时候CPU寄存器、内存、磁盘各有分工高频用的放最近的地方不常用的沉到慢速存储里去操作系统负责调度。Letta把同样的逻辑搬到了Agent记忆上。在Letta的设计里记忆分了好几层核心记忆块Core Memory常驻在系统提示里相当于“CPU寄存器”。一般会放两个默认块persona描述Agent自己的性格和身份human块保存关于用户的最基本信息。这些内容一定是精练的、需要在每轮对话都可见的。工作上下文Working Context正在进行的对话和推理过程相当于“内存”。有容量限制超了就得分页。归档记忆Archival Memory长期事实的存储区相当于“磁盘”。通过向量索引需要时才检索出来。回忆历史Recall Memory过往所有对话消息的完整记录按时间或关键词检索。真正让我觉得工程上是这个系统高明的地方在于它的自省机制。Letta会自己盯着上下文占用率当快满的时候它触发一个“归档动作”把不重要的旧对话写进归档区把关键结论提炼回核心记忆块然后清空工作区继续对话。整个过程模拟的是操作系统里的页面置换算法只不过执行者从内核变成了模型自己。但注意这种自省机制的本质是“让模型决定自己该记什么”也就是把一部分记忆策略的执行权交给了模型。好处是灵活坏处是模型没有判断力的边缘情况下归档哪些信息、不归档哪些信息可能出现决策抖动。我自己测试长对话时遇到过它把用户很看重的一个细节归档掉、还从核心块里移出去了用户再问时只能通过检索旧对话捞回来。所以这套方案对模型本身的指令遵循能力要求很高。3.4 AutoGPT把记忆写进文件最朴素也最稳定AutoGPT是“用文件系统做记忆”的代表。它火的早很多人拿它做自动执行任务的Agent。它骨子里的记忆思路其实非常简单状态和中间成果写进本地文件。工具链上它早期会让Agent把任务拆解后的目标、进度、阶段性产出保存到工作空间里同时配合关键词记忆文件。后来引入向量数据库做记忆后端比如Pinecone或Redis主要用来保存“可检索的经验片段”。它的记忆逻辑更偏“任务执行维度”——记住当前目标、已经完成哪些步骤、哪些方向试过没走通而不是面向聊天场景的用户偏好。优点是肉眼可见的透明和可靠。文件就在那里你随时可以打开看Agent到底“记得”什么出问题时排查起来很容易。也不需要依赖复杂的向量检索一个小型任务只要几十KB的JSON就能维持状态。缺点也很明显文件/向量片段的组织方式比较原始面对长时间跨度、多用户、非结构化场景时记忆的辨识度和关联能力不足。AutoGPT那种“一个任务跑很久”的形态里足够用但如果要做一个服务数千人、每人都要维护长期画像的Agent这套就不太行了。3.5 CrewAI Memory多Agent场景下的记忆共享与隔离CrewAI是专注多Agent协作的框架它的记忆设计完全是冲着“团队共享”来的。在单Agent时代记忆是“我的记忆”到了多Agent时代问题就变成同一个任务研究员Agent发现的线索需不需要让写报告Agent知道如果每个Agent的记忆各自为政团队协作就会彻底失效。CrewAI把记忆分成了三类短期记忆ShortTermMemory用向量存储记录最近执行任务的上下文方便同一Crew里后续任务做RAG。长期记忆LongTermMemory跨任务的持久信息存储在SQLite里比如用户偏好、项目历史决定。实体记忆EntityMemory从任务执行中抽取的实体及其属性、关系相当于一个小型知识图谱片段。这套分层设计让我最欣赏的地方是它回答了“记忆的边界在哪”CrewAI的记忆默认是Crew级别的一个Crew的多个Agent可以共享同一份长期记忆。这让每个Agent做决策时能参考到队友“踩过的坑”和“已验证的结论”。但多Agent共享也引出新问题写冲突。多个Agent在同一轮协作中可能同时向记忆里写入信息有的信息相互矛盾有的信息重复。CrewAI目前的实现更多是顺序写入、靠实体去重还没有特别复杂的冲突消解策略。如果你跑Agent数量很多的高并发协作任务这块需要自己兜底。3.6 Zep时间叠加图谱的联想式记忆Zep是我见过把“生产级记忆”这个概念做得最完整的一个。它不是一个库而是一个独立服务专门帮Agent做长期记忆。为了理解它的设计思路你要先想一个问题人回忆一件事的时候脑子里往往不是一条孤立的“事实”而是一张关联网——“老王上个月离职了”关联着“老王之前是客服部主管”关联着“客服部近期人员动荡”。单一一条Vector检索召回的是相似文本但召回不了这种带关系带的记忆。Zep走的是时序知识图谱路线。它在底层维护了一个图谱节点是实体人、事件、地点边是关系去过、提到过、负责。关键的是每条边和节点都带时间属性并且随着新的对话发生这个图谱会“增量更新”——不是每次全部重建而是在已有图谱上局部加边、加属性。这套设计让Zep能回答一些传统RAG答不了的问题“这件事是什么时候发生的”“用户最早提到这个偏好是几月”“这两个实体之间的关系有没有随时间变化”比如客服场景里用户三个月前投诉过物流上周又投诉过一次Zep能把这几个事件在时间轴上串起来让你看到“这位用户对物流的容忍度正在下降”这种隐含信号。代价也很直接图谱的构建和维护比纯粹的向量索引重得多。每条新的对话要经过实体抽取、关系生成、图谱合并这一套流程服务端计算和存储成本明显高于“直接embedding塞进向量库”。它适合的是那种用户长期使用、记忆必须精确到时间和关系的生产环境而不是每个小demo都该上图的。4. 横向硬核对比六套方案在失真度、成本、一致性上的真实差距4.1 六套方案关键维度对比看完各自的思路最容易被忽略的是方案之间的“代差”。下面这张表我按自己的实测体感填的不一定严谨但方向可以参考维度LangChain缓冲/摘要Mem0抽取式Letta分层AutoGPT文件CrewAI共享Zep图谱时序信息保真度摘要有损缓存无损高语义保留中高依赖自省判断中任务导向中实体相关强高关系保留完整存储成本低中低中最低中低最高召回准确性召回全量/窗口靠强塞高混合检索中需要分页触发低关键词为主中高可时空查询时间感知无弱可附加metadata弱无无强原生支持部署复杂度最低中中低中低最高适用场景快速原型个性化助手长程聊天任务自动化多Agent协作生产级长期记忆4.2 同一个场景六种方案的“回忆”差异举一个非常具体的例子用户周三说“我周五要去上海出差请提前一天给我发一条短信提醒”周五上午回来问“我的行程提醒安排好了吗”。这时候六套方案的回复倾向分别是LangChain Buffer如果周三到周五之间的对话还在窗口内记得否则忘得干干净净。LangChain Summary可能记得“用户要去上海”但“提前一天发短信”这个关键偏好大概率被摘要压掉了。Mem0抽取出实体“用户→出差上海→周五”并关联“偏好提前一天短信提醒”。即使中间几百轮对话也能通过向量和图谱召回。Letta如果核心记忆块里写入了“用户近期出差安排”正常工作但这有赖于它自省归档时没把这个关键事件沉到归档区去。AutoGPT如果你给它的任务里明确写了“把行程存到文件”能找到否则没有记忆。CrewAI如果是同一个Crew里别的Agent写入过用户偏好能共享到但多Agent协作时重复写入可能造成版本混乱。Zep不但记得行程还能答“用户的出差计划是从周三开始录入的”“这是本月第二次提到上海出差”——因为时间和关系都在图里。4.3 容易被忽略的记忆一致性问题项目对比里还有一个深水区记忆一致性。第一种是覆盖型冲突。用户先说“我喜欢邮件沟通”后来又说“还是微信吧”如果记忆系统没有更新语义两条矛盾信息会同时存在。召回时模型看到两条冲突记忆行为就会随机。Mem0和Zep都做了不同程度的覆盖与失效处理但LangChain那种纯追加的方案完全没有这个能力。第二种是重复累积。多轮对话里用户反复表达同一偏好如果没有去重逻辑记忆库里会堆满相似度极高的重复记录。召回时top-k被同类记忆霸屏真正需要的信息反而不见了。这一块实话说很多项目都处理得不够好生产里往往需要自己做一层合并。第三种是时间衰减。人对很久以前的记忆天然会模糊Agent也一样需要“旧得差不多了就可以淡出”的机制。目前六套方案中只有Zep把时间做成了核心维度其他的基本要靠业务侧自己标记过期。5. 结合项目形态选记忆方案一份可以直接抄的决策清单5.1 选型前先回答的五个问题别急着选技术栈先想清楚下面几个问题记忆需要跨越多长时间只聊当天忘掉没事还是三个月后还要想起来单用户还是多用户多用户意味着必须做用户维度隔离记忆不能互相污染。记忆是原文型还是结论型你需要回放“当时说了什么”还是想直接问“这个用户喜欢什么”是否多Agent协作如果多个角色共享上下文记忆系统要支持共享与权限边界。成本还是效果优先预算紧张优先选轻量方案效果优先就要接受抽取/图谱的计算开销。5.2 不同业务场景的组合推荐我分几个典型场景给推荐都是我验证过或者拆解过的组合客服类Agent生产级建议Zep提供长期人物画像和关系记忆再配合Mem0管理“用户结论型知识”不差钱的话这两者组合非常能打。如果预算紧单独上Mem0也可以。个人效率/写作助手首选Mem0抽取式记忆很贴合“记住用户的风格偏好和事实信息”这类需求。长程陪伴聊天AgentLetta是最契合的。它本身就是为长对话和持续交互设计的分层记忆能托住几十轮以上的对话不崩。自动化任务Agent类似AutoGPT场景不需要花里胡哨的记忆任务状态文件和向量库就够。重点做好工作区管理和文件持久化。复杂多Agent业务流程用CrewAI的Memory框架搭底然后自己补一层“关键结论写入长期存储”的机制避免纯靠SQLite撑整个过程。5.3 从0到1落地一个记忆层的参考步骤如果你不想直接套用某个项目而是自己搭一个轻量记忆层我建议按这个顺序走第一步定义“记忆单元”。不要存原始句子定义一个JSON结构比如{ entity, relation, fact, timestamp, confidence, user_id }。想清楚每种记忆的粒度。第二步确定写入时机。一般有两种写策略每轮结束后用LLM判断“这轮有没有值得记的新信息”有就写或者定期扫描一段时间内的对话统一抽取。第一种更实时第二种成本更低。我在项目里通常用第二种设置一个定时任务批量抽取。第三步决定召回接口。给Agent暴露一个memory_search(query, user_id, top_k)函数内部先走向量召回再做规则过滤最后用LLM判断哪些记忆真的与当前问题相关。第四步设计遗忘策略。没有遗忘系统的记忆库会越用越脏。可以给每条记忆带created_at和last_accessed_at超过阈值就降权或归档。6. 实测踩坑记录记忆污染、召回时机和调参细节6.1 记忆污染的三个真实来源我在自己项目里踩过的第一个坑是“把用户的气话当成了长期偏好”。用户在某个节点抱怨了一句“你们系统真难用”抽取模型把它记成了“用户对产品不满”。之后每次对话启动这条负面记忆都参与召回直接影响后续所有回复的语调和策略让Agent显得非常“小心翼翼地迎合用户”。后来我加了置信度过滤规则只有用户主动陈述、没有情绪化词汇、且连续出现过两次以上的信息才允许进入长期记忆。第二个坑是时间戳缺失导致的覆盖错误。用户上个月说“我喜欢喝茶”这周偶然提了一句“最近改成喝咖啡了”如果系统没有严格区分“长期偏好”和“近期状态”很容易把旧记忆覆盖成“用户喜欢咖啡”。实际上两个信息可能都对只是时间维度不同。解决方式是记忆里显式区分“persistent_preference”和“current_state”两种类型不放在同一个更新维度下。第三个坑是摘要式记忆的副作用。用ConversationSummaryMemory做压缩时摘要模型为了精简经常把用户对话里的具体数字、时间、专有名词悄悄丢掉。你得到了一段很通顺但毫无操作价值的摘要。后来对于包含数字和时间的语句我坚持“原始保存摘要增强”双轨制保障关键信息零丢失。6.2 召回时机的取舍记忆不是每次对话都必须参与的。早期我图省事每条用户消息都触发一次记忆检索结果顶级模型被一堆相关信息包围回复风格都变了——它太“依赖”背景了连简单问题都绕圈子。后来我把触发策略改成对话开始时预取用户的静态画像基础偏好、关键标识比如称呼、地址只有当前消息里出现了“实体名词”地点、产品、人名或者时间相关词才触发深度检索检索结果最多取top-3且加一句系统提示“以下为辅助背景不作为事实依据除非用户明确确认”。这样记忆从“主导回复”变成“参考材料”效果稳了很多。6.3 两个值得立刻用上的小技巧第一个技巧是给记忆加可解释性。不管用哪个记忆系统都把“Agent这次回复参考了哪条记忆”显示在调试日志里。一旦用户反馈“你这段话莫名其妙”立刻能追溯到它是不是被某条过时记忆带偏了。我在生产环境见过太多团队Agent行为出了问题却查不到原因就是因为记忆召回完全是黑盒。第二个技巧是定期做“记忆翻新”。每隔一段时间比如一周用LLM扫描整个记忆库把语义重复的合并、把确证无疑的升级为高置信度永久记忆、把长期未命中的降权归档。这一步相当于给记忆库做“碎片整理”。免费方案可以用定时任务自己写个脚本实现生产规模大一点就直接上Mem0这类有内置管理能力的服务。我这里没有给你一个“唯一正确答案”因为我确实没见过一套万能方案。更务实的思路是先认清自己的Agent形态——是长聊天、任务型、还是客服型然后找最贴合的一两个项目做原型跑上一两周看召回质量和成本账单。我自己最后落地的时候是Mem0加Zep的分工组合Mem0管用户结论型记忆Zep管带时间轴的关系记忆。希望这篇文章能帮你把踩坑的时间省下来。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。