☰
Agent长期记忆方案横向对比:Mem0、Zep、Graphiti等六大方案选型指南
2026/10/31 12:21:16 网站建设 项目流程

1. 为什么 Agent 的“记忆”是个绕不开的硬骨头

做 Agent 开发的朋友大概率都经历过这样一个阶段:Demo 跑得挺欢,一旦让它连续处理几天任务,或者跨会话接着上次的活儿干,它就开始“失忆”——昨天确认过的用户偏好今天全忘了,上周踩过的坑这周原样再踩一遍。这不是模型不够聪明,而是长期记忆这个基础设施没搭好。

我最早做 Agent 项目时,图省事直接把对话历史塞进上下文窗口,结果 token 成本飙升不说,一旦超出窗口就得截断,截断就意味着丢信息。后来尝试用向量库存历史对话,检索出来的东西又经常答非所问——因为纯向量检索丢掉了时间关系和实体之间的关联。踩了几轮坑之后我才意识到,Agent 的长期记忆不是“存下来”这么简单,它至少包含四件事:写入什么、怎么组织、如何检索、何时遗忘。这四个环节任何一个设计得糙,整个记忆系统就会退化成“看起来能用、实际很鸡肋”的状态。

这篇文章我想把目前社区里讨论度比较高的六个主流记忆方案拉出来做个横向对比,包括Mem0、Zep、Graphiti,以及另外三个同样有代表性的思路(向量库自建方案、分层记忆架构、事件流记忆)。重点不是告诉你“哪个最好”,而是拆解每个方案在记忆写入、存储结构、检索策略、遗忘机制上的设计取舍,让你能根据自己的业务场景判断该抄哪份作业。不管你是刚接触 Agent 开发的新手,还是已经在做企业级 Agent 平台的老手,这些设计思路的对比都能帮你少走弯路。

2. 先搞清楚:Agent 长期记忆到底要解决什么问题

2.1 短期记忆和长期记忆的边界在哪

很多人把“上下文窗口”和“长期记忆”混为一谈。上下文窗口是模型单次推理能看到的 token 范围,它本质上是工作记忆(working memory),容量有限、生命周期短、随会话结束就消失。而长期记忆是跨会话、跨任务持久化的信息,它需要外部存储支撑,并且要能被主动检索回来注入到当前上下文里。

打个比方:上下文窗口是你办公桌上摊开的文件,长期记忆是你身后那个文件柜。桌子就那么大,你不可能把所有文件都摊开;但文件柜可以很大,关键是你得知道什么时候去柜子里翻哪份文件。Agent 记忆系统的核心难点,恰恰就在这个“翻文件”的动作上——翻得准,Agent 就显得聪明;翻不准,还不如不翻。

2.2 一个合格的记忆系统要回答的四个问题

我在设计自己的 Agent 记忆模块时,习惯用四个问题来检验方案是否完整:

  • 写入策略:哪些信息值得记?是每轮对话都写,还是抽取关键事实再写?写入时要不要做去重和冲突消解?
  • 存储结构:用纯向量、纯图、还是向量加图的混合结构?结构化字段(时间、实体、关系)怎么存?
  • 检索策略:靠语义相似度召回,还是结合时间衰减、实体关联、图遍历?召回后怎么排序和裁剪?
  • 遗忘机制:旧信息是一直留着,还是按时间衰减、按重要性淘汰、或者做摘要压缩?

下面这张表是我对六个方案在这四个维度上的初步印象,后面会逐个展开。

方案写入策略存储结构检索策略遗忘机制
Mem0事实抽取+去重向量+图(可选)语义+元数据过滤更新覆盖
Zep会话摘要+实体抽取时序知识图谱混合检索+时间加权时间衰减
Graphiti事件抽取+实体消解时序知识图谱图遍历+语义边失效标记
向量库自建原文分块写入纯向量语义相似度手动清理
分层记忆分层抽取工作/情景/语义三层分层路由检索层级淘汰
事件流记忆追加事件事件日志+索引时间范围+语义快照压缩

3. Mem0:把记忆做成“事实抽取流水线”

3.1 Mem0 的核心设计思路

Mem0 是我最早接触的记忆方案之一,它的定位很明确:不做通用存储,只做“记忆层”。你把它插在 Agent 和 LLM 之间,它负责从对话里抽取值得记的事实,存起来,下次对话时按需召回。它的设计哲学是“记忆应该是被提炼过的”,而不是把原始对话一股脑塞进去。

这个思路的好处很直接:存储量小、检索精度高、token 消耗低。因为存进去的是“用户喜欢喝美式咖啡”这样的事实,而不是“用户说:我今天想喝点东西……哦对了美式不错”这样的原始对话。但代价是抽取环节可能丢信息,如果抽取模型判断失误,一条重要信息可能就永远进不了记忆库。

3.2 写入流程:抽取、去重、冲突消解

Mem0 的写入流程大致分三步。第一步是事实抽取,用 LLM 从当前对话轮次里提取出独立的事实陈述。第二步是去重,拿新事实去已有记忆里检索,看有没有语义重复的。第三步是冲突消解,如果新事实和旧事实矛盾(比如用户之前说喜欢美式,现在说改喝拿铁了),就更新旧记录而不是简单追加。

这里有个实操细节值得注意:Mem0 的去重和冲突消解都依赖向量相似度阈值。阈值设高了,重复记忆会堆积;设低了,可能把不同事实误判为重复而覆盖掉。我在自己的项目里一般把相似度阈值设在 0.85 到 0.9 之间,并且对“更新”操作加了一层人工确认逻辑——涉及用户核心偏好的变更,宁可多存一条带时间戳的记录,也不轻易覆盖。

# Mem0 写入的简化逻辑示意 from mem0 import Memory m = Memory() # 添加记忆,内部会自动做抽取、去重、冲突消解 m.add("用户表示最近改喝拿铁了,不再喝美式", user_id="u123") # 检索时按语义召回 results = m.search("用户喜欢喝什么咖啡", user_id="u123")

3.3 检索与遗忘:更新即遗忘

Mem0 的检索是语义相似度为主,可以叠加 user_id、agent_id 这类元数据过滤。它的“遗忘”机制比较轻量——主要靠更新覆盖来实现。旧事实被新事实取代,就等于被遗忘了。它没有内置的时间衰减或重要性淘汰,这意味着如果你不主动清理,记忆库会一直增长。

提示:Mem0 适合“用户偏好”“个人事实”这类高频变更、结构简单的记忆场景。如果你的 Agent 需要记住复杂的任务执行历史和多跳关系,单靠 Mem0 会有点吃力。

4. Zep:把对话变成时序知识图谱

4.1 Zep 的记忆观:关系比事实更重要

Zep 的设计思路和 Mem0 有明显差异。Mem0 关注“记了什么事实”,Zep 关注“事实之间怎么关联、随时间怎么变化”。它把对话历史构建成一张时序知识图谱(Temporal Knowledge Graph),节点是实体(人、地点、事件、概念),边是关系,而且每条边都带时间戳。

这个设计的好处在于,它能回答“用户三个月前对某个功能的态度是什么”这类带时间维度的问题。纯向量检索做不到这一点,因为向量相似度不感知时间。Zep 的图谱结构让时间成为一等公民,检索时可以按时间范围过滤,也可以做时间衰减加权。

4.2 写入流程:摘要、抽取、图谱构建

Zep 的写入分两层。第一层是会话摘要,把一段对话压缩成摘要,保留整体语义。第二层是实体和关系抽取,从对话里识别出实体,判断它们之间的关系,写入图谱。这两层是并行的,摘要用于粗粒度召回,图谱用于细粒度推理。

我实测下来,Zep 的图谱构建质量很依赖抽取 prompt 的设计。如果 prompt 太宽松,会抽出一堆无意义的边;太严格又会漏掉隐含关系。建议在正式接入前,先用一批真实对话做抽取测试,人工检查图谱质量,再调整 prompt。

4.3 检索策略:混合检索加时间加权

Zep 的检索是混合式的:先用语义相似度召回一批候选,再用图谱关系做扩展,最后按时间衰减对结果排序。这个“语义+图+时间”的三重组合,是它相比纯向量方案最大的优势。

时间加权的具体做法通常是给每条记忆算一个分数:score = 语义相似度 × 时间衰减因子。时间衰减因子可以用指数衰减,比如半衰期设成 7 天,那么一周前的记忆权重就降到一半。这个半衰期要根据业务定——客服场景可能 3 天就够,个人助理场景可以设 30 天。

参数建议范围说明
语义相似度阈值0.7-0.8低于此值不进入候选
时间半衰期3-30 天按业务时效性调整
图谱扩展跳数1-2 跳跳数越多噪声越大
返回记忆条数5-15 条太多会挤占上下文

5. Graphiti:事件驱动的时序图谱记忆

5.1 Graphiti 和 Zep 的关系与差异

Graphiti 和 Zep 都用时序知识图谱,但 Graphiti 更强调事件驱动。它把每条记忆看作一个“事件”,事件有发生时间、参与者、上下文。这种建模方式特别适合任务型 Agent——因为任务执行本身就是一系列事件。

Graphiti 的一个关键设计是边的失效标记而不是删除。当一条旧关系被新关系取代时,旧边不是被删掉,而是标记为失效并保留。这样做的好处是保留了完整的历史轨迹,你可以回溯“这个关系是什么时候变的、为什么变”。对于需要审计或调试的 Agent 场景,这个特性非常有用。

5.2 实体消解:记忆系统最容易翻车的地方

Graphiti 在实体消解上下了不少功夫。所谓实体消解,就是判断“张三”“老张”“张经理”是不是同一个人。如果消解做不好,图谱里会出现大量重复节点,检索时召回一堆碎片,记忆就废了。

Graphiti 的做法是结合名称相似度、上下文共现、属性匹配多个信号来做消解。但我要提醒一句:实体消解没有银弹。我在项目里遇到过用户用不同昵称指代同一事物的情况,纯自动消解准确率大概在 80% 左右,剩下 20% 需要人工规则兜底或者接受一定误差。如果你的场景对准确性要求极高,建议加一层人工审核队列。

5.3 图遍历检索的实操要点

Graphiti 的检索以图遍历为主。从一个种子实体出发,沿关系边扩展,收集相关事件。这里的关键参数是遍历深度和边的时间过滤。遍历太浅召回不全,太深则噪声爆炸。我的经验是深度控制在 2 跳以内,同时对边加时间窗口过滤,只保留最近 N 天内的有效边。

# Graphiti 检索的简化示意 # 从实体出发,限制跳数和时间窗口 results = graphiti.search( seed_entity="用户_123", max_hops=2, time_window_days=30, only_valid_edges=True )

6. 另外三种思路:向量库自建、分层记忆、事件流

6.1 向量库自建方案:简单但容易踩坑

最朴素的方案就是拿一个向量库(比如 FAISS、Milvus、Qdrant),把对话分块、embedding、存进去,检索时按相似度召回。这个方案上手快,但坑也多。

第一个坑是分块策略。按固定长度切会把一句话切断,按语义切又需要额外模型。第二个坑是没有时间感知,三个月前的记忆和昨天的记忆权重一样。第三个坑是没有去重,同一件事说三遍就存三份。我早期项目就吃过这个亏,后来不得不加了一层时间戳过滤和相似度去重才勉强能用。

6.2 分层记忆架构:模仿人的记忆系统

分层记忆的思路是把记忆分成三层:工作记忆(当前会话)、情景记忆(具体事件经历)、语义记忆(抽象知识)。检索时先查工作记忆,不够再查情景记忆,最后查语义记忆。这个架构的好处是检索有优先级,不会一上来就大海捞针。

实现上,工作记忆可以直接放上下文,情景记忆用向量库,语义记忆用结构化数据库或图谱。层与层之间要有晋升机制——比如某个情景被反复召回,就抽象成语义记忆。这个晋升逻辑是分层方案的核心,也是最难调的部分。

6.3 事件流记忆:追加日志加快照压缩

事件流记忆把每次交互当作一个事件追加到日志里,检索时按时间范围和语义过滤。它的优势是写入极快、天然有序、便于审计。缺点是日志会无限增长,需要定期做快照压缩——把旧事件合并成摘要,原始事件归档。

这个方案适合任务执行轨迹类的记忆,比如 Agent 做了一连串操作,你需要回溯它每一步做了什么。对于“用户偏好”这类记忆,事件流就不太合适,因为偏好是状态而不是事件。

7. 六个方案的横向对比与选型建议

7.1 按场景选方案

选型没有绝对优劣,关键看场景。我把常见场景和推荐方案整理成下表:

场景推荐方案理由
个人助理、偏好记忆Mem0事实抽取精准,存储轻量
客服、带时间维度的对话Zep时序图谱,时间加权检索
任务型 Agent、需审计Graphiti事件驱动,边失效保留历史
快速原型、预算有限向量库自建上手快,依赖少
复杂认知型 Agent分层记忆检索有优先级,贴近人类记忆
执行轨迹回溯事件流记忆天然有序,便于审计

7.2 混合方案往往比单一方案更实用

实际项目里,我很少只用一种方案。比较常见的组合是:Mem0 管用户偏好 + Graphiti 管任务关系,或者向量库管粗召回 + 图谱管精排。混合方案的关键是明确每种记忆的职责边界,避免同一信息在两处重复存储导致不一致。

7.3 成本与性能的权衡

记忆系统不是免费的。向量检索有延迟,图谱遍历更慢,LLM 抽取还要花 token。我的经验是:写入可以异步,不阻塞主流程;检索要设超时,比如 200ms 内没返回就用降级策略;抽取要批量化,攒一批对话一起抽,比每轮抽一次省不少钱。

8. 实操中踩过的坑与排查技巧

8.1 记忆污染:错误信息被反复强化

最常见的坑是记忆污染。如果某次抽取抽错了,错误信息进了记忆库,之后每次检索都召回它,Agent 就会一直基于错误信息行动。排查方法是定期抽样检查记忆库,发现错误及时清理。预防方法是在写入环节加置信度评分,低置信度的记忆标记为“待确认”,不直接参与检索。

8.2 检索召回率低:先查 embedding 再查阈值

召回率低通常有三个原因:embedding 模型不适合当前语言或领域、相似度阈值设太高、分块策略把关键信息切碎了。排查顺序建议是:先换一个更强的 embedding 模型试试,再调阈值,最后检查分块。我遇到过中文场景用英文 embedding 模型导致召回率腰斩的情况,换成多语言模型后立刻好转。

8.3 记忆库膨胀:没有遗忘机制迟早出事

不设遗忘机制的记忆库,半年后就会大到检索变慢、噪声变多。我的做法是给每条记忆加一个“最后访问时间”,超过一定时间没被召回的记忆进入冷存储,检索时默认不查,需要时再手动捞。这样既控制了热数据规模,又不丢历史信息。

8.4 常见问题速查表

问题现象可能原因排查方向
Agent 反复忘记同一件事写入失败或检索不到检查写入日志和检索阈值
召回内容答非所问embedding 不匹配换模型或调阈值
记忆库增长过快无去重无遗忘加去重和冷存储
图谱节点重复实体消解失败加消解规则或人工审核
检索延迟高图遍历太深限制跳数和返回条数

9. 我个人的一些经验体会

折腾了这么多记忆方案,我最大的体会是:记忆系统的价值不在于“记得多”,而在于“记得准、取得对”。很多团队一上来就想做全量记忆,结果存了一堆用不上的东西,检索时噪声比信号还多。不如先把一个场景做透,比如只记用户偏好,把抽取和检索调到高准确率,再逐步扩展。

另外,记忆系统一定要有可观测性。每次检索召回了哪些记忆、为什么召回、Agent 用了哪条,这些都要能查到。不然出了问题你根本不知道是记忆错了还是模型错了。我在项目里加了一个记忆追踪面板,调试效率提升非常明显。

最后分享一个小技巧:新接入一个记忆方案时,先别急着上生产,拿一批历史对话做离线回放测试。把记忆写入和检索都跑一遍,人工评估召回质量,确认没问题再接入。这一步花的时间,远比上线后救火要少。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询