这四个项目都是 Apache-2.0,星数都是五位数,而四者都有同一个问题:你会去安装的那个仓库,并不是产出 README 里那些数字的东西。Mem0 把这话直接写出来了:它在 LoCoMo 上的 92.5 来自托管平台,而那个平台「包含开源 SDK 中没有的专有优化」。挑记忆层要看它的仓库单独能干什么、以及将来走有多难——因为榜单量的是别人的产品。
一眼概览
下面的星数与版本都是 2026 年 10 月下旬,从各项目自己的仓库读到的。
| 项目 | 星数 | 存储的形状 | 只跑这个仓库你能得到什么 |
|---|---|---|---|
| Mem0 | 67.8k | 由大模型抽取的事实,存在向量库里 | 完整 SDK 与可自托管的服务端;但被跑分的那些优化只在平台上 |
| Cognee | 32.7k | 从文档与对话构建的知识图 | v1.6.1 可以无密钥、全本地跑;图跑在 Postgres 上是演示功能,生产版需授权 |
| Graphiti(Zep) | 32.2k | 带有效期窗口的双时态实体图 | 整个框架——但它需要一个图数据库,而参考服务器没有认证 |
| Letta | 25.3k | 由智能体自己持有、活在上下文里的记忆块 | V1 服务端在 archive 分支上;开发已挪到 letta-code,默认后端是 Letta Cloud |
四种被叫做「记忆」的不同东西
Mem0 —— 抽取出来的事实,按相似度取回
Mem0 的模型是四者中最容易想清楚、也是采纳成本最低的:你把对话轮次交给它,一个大模型抽出简短的独立事实,这些事实进向量库,在组装提示时按相似度取回。安装是 pip install mem0ai 或 npm SDK,默认用 OpenAI 的 gpt-5-mini 做抽取、text-embedding-3-small 做嵌入,仓库里还带一个有面板和认证的 Docker Compose 服务端。
你放弃的是任何依赖事实之间关系的东西。「我们关于定价定了什么?」检索得很好。「其中哪个决定取代了哪个」就不行,因为取代是一种关系,而这个存储里装的是点。Mem0 自己的数字也是本文所讲那道缝隙最清楚的一例:README 的表格报出 LoCoMo 92.5、LongMemEval 94.4、BEAM-1M 64.1,然后说明这些是平台分数,开源用户应预期「方向相似但数值不同」的收益。这是一条少见地诚实的脚注,而它意味着:你真正想要的那个对比——库对库——根本没人发表过。
Graphiti —— 一个知道某个事实何时不再为真的图
Graphiti 是 Zep 底下那个开源框架,也是四者中唯一一个其数据模型直接回答了「大多数智能体记忆做错的那个问题」的。事实带有效期窗口;当一个新 episode 与旧的矛盾时,旧的边被失效而不是被删除,而每个实体与每条边都能追回它所来自的那个源 episode。检索把语义搜索、BM25 与图遍历合在一起。如果你的智能体需要说「截至上周负责人是他,周二变了」,这就是能做到的那个模型。
代价有两处。第一是基础设施:Graphiti 需要一个图数据库——Neo4j 5.26、FalkorDB 1.1.2、带 OpenSearch Serverless 做全文的 Amazon Neptune,或者 Kuzu 0.11.2(项目现在已把它标为弃用并在导入时发警告)。相对于 Mem0 的一个向量库,这是一笔实打实的运维承诺。第二是与 Zep 的关系:Zep 自身的社区版已弃用,代码挪进了 legacy/ 目录,而 getzep/zep 仓库直白地写着它「不是 Zep 的产品或服务」——它装的是 Zep Cloud 的示例与集成。那个「规模下低于 200ms」的数字属于商业产品,不属于这个框架。Graphiti 作为一个库是真正完整的;Zep 是一个恰好与它同源的托管服务。
Letta —— 由智能体自己编辑的记忆
Letta(前身 MemGPT)把问题反过来问。它不是一个由框架代智能体查询的存储,而是让智能体自己持有可编辑的记忆块,这些块活在它的上下文里,由它随着学习用工具改写。对一个长期存在、其自我描述与工作笔记本就该变化的助手,这是对的形状;而对一个语料库,这是错的形状:这里没有文档摄入的故事,因为它的单位是智能体自己的状态,而不是你的数据。
Letta 也是重心挪得最远的那个项目。那个 25.3k 星的 letta 仓库已把 V1 API 服务端退役到 archive 分支;活跃开发在 letta-code(3.7k 星)——一个把全部上下文(含记忆块)用 git 追踪的智能体框架,而它首次启动时的默认后端是 Letta Cloud。本地运行是提供的,而某些功能(远程机器、密钥)要求登录 Letta。如果你是为了 2025 年读到的那个自托管有状态服务端而选 Letta,先确认那个服务端现在在哪个仓库、哪个分支,再围着它做规划。
Cognee —— 一个你从文档构建出来的图,而且多租户默认开着
如果你的记忆主要是内容而不是对话,Cognee 是该先读的那个。它的四个动词是 remember、recall、improve 和 forget;remember 与 recall 都接 dataset 名字,于是作用域是一个头等参数,而不是一个你要记得传的过滤条件。自 v1.0 起,整个层可以坐在一个 Postgres 实例上,覆盖关系元数据、PGVector 与图状态;而 v1.6.1(2026 年 9 月 24 日)让默认本地路径无密钥运行,用本地 GLiNER 抽取器与本地嵌入——四者中唯一一个不需要模型供应商就能试的。
它也是唯一一个默认就要求已认证用户的:每一次 /api/v1 调用都是多租户的,除非你设 ENABLE_BACKEND_ACCESS_CONTROL=false。而它对自己的评测也最谨慎。README 报出 BEAM 在 100K 词元下 0.79、在 10M 下 0.67,把后者标为探索性的,并提醒这两种设定用了不同的对话、不同的摄入模型与不同的检索选择流程、因此分数不可直接比较——同时指出分布式 10M 摄入仍有一个未关闭的复现缺口。要留神的地方在存储故事里:把 Postgres 当图存储被描述为演示功能,生产版是一个需授权的产品。
横向对比
你会拿来比较它们的每一个数字,都是自报的
在场的三个基准是 LoCoMo、LongMemEval 与 BEAM,而四个项目的任何分数都没有独立复现。Mem0 发表的数字最多,并把它们归于自家平台;Cognee 发表得少些,而且自己附上了告诫;Graphiti 一个没发,只给了一份对比 GraphRAG 的延迟表格、没有方法说明;Letta 一个没发。更糟的是,在最有意思的那一端,样本量小到足以吞掉这些差异:BEAM 的 10M 档大约 200 题,所以仅凭二项计数误差,报出的 48.6% 就带着约 ±6.9 个百分点的 95% 区间。在那个规模上,两家厂商之间 3 个点的差距是噪声。而从 1M 到 10M 掉 15 个点——Mem0 自己报的——不是噪声;而那一跌才是整张榜单里值得带走的发现:所有这些都会随语料增长而急剧退化,而在各子能力中,矛盾消解得分最差。
作用域是调用方传进来的一个参数,不是一个主体
在 Mem0 里作用域是 user_id,传给 add 并作为 search 的过滤条件。在 Graphiti 里是 group_id。在 Cognee 里是 dataset 名字,上面还叠着 session。在 Letta 里是智能体本身。四者中有三个,库里没有任何东西检查调用方是否有权使用它所申报的那个作用域——只要上面有东西在管,这就是一个设计选择而不是缺陷。Graphiti 把后果说得很明确:它的参考 MCP 与 REST 服务器没有认证、没有提示注入防护,调用方可以访问任意 group_id,而项目声明它们不打算用于不受信网络。Cognee 是例外,默认每次调用都要一个已认证用户。如果你要把其中任何一个部署给超过一个人用,请看记忆作用域与多租户——这种失败是静默的,因为一个嵌入向量不携带它的作者。
真正的分水岭是退出成本
问一句:如果你停止付费、或者项目转向了,你能留下什么。Graphiti 留给你的是一个跑在你本来就在运维的数据库里的图,带着回指源 episode 的来源边——四者中最可移植的产物。Cognee 留给你 Postgres 里的行,但要记住生产图路径是需授权的。Mem0 留给你抽取出的事实字符串加嵌入,可移植但有损:抽取时的那些判断没了。Letta 留给你用 git 追踪的记忆块,形式上可移植,但在解释它们的那个 Letta 框架之外没有意义。四者中有两个今年已经把自己的重心挪过一次了——这是关于「这些选择能有多耐久」目前最好的现成证据。
什么时候选哪个
| 情形 | 选 | 为什么 | 代价 |
|---|---|---|---|
| 对话式个性化,这个月就要上 | Mem0 | 采纳成本最低、SDK 覆盖面最广 | 没有关系;发表的数字不属于这个库 |
| 会变、且必须带日期的事实 | Graphiti | 有效期窗口与来源就在数据模型里 | 你要运维一个图数据库;参考服务器前面得加认证 |
| 把文档与代码当记忆 | Cognee | 摄入优先、dataset 作用域、无密钥本地起步 | 生产的图存储是一条需授权的路 |
| 一个长期存在、本就该变化的助手 | Letta | 由智能体持有的可编辑块,而不是一个被查询的存储 | 先确认仓库与分支;Cloud 是默认后端 |
| 第一天就是多租户 | Cognee,或摆在你自己网关后面的 Graphiti | 只有 Cognee 默认到一个已认证主体 | 其余都需要一层你自己写的强制执行 |
还有一种情形是「都不选」:如果你的智能体对记忆的要求只是「记住用户本次会话早些时候说的那五件事」,那么一张带 user id 的表加一个 LIMIT 5 就是正确答案,而值得设计的那部分是写入路径,不是存储。
常见问题
Zep 的开源版本死了吗?
Zep 社区版已弃用,代码挪进了 legacy/ 目录;getzep/zep 仓库现在装的是 Zep Cloud 的示例与集成,并声明它不是 Zep 的产品。底下那个框架 Graphiti 在活跃维护,Apache-2.0。
LoCoMo 与 LongMemEval 的分数可信吗?
当成厂商宣称来看。它们是自报的、未被复现的、由一个身份一变结果就变的大模型裁判打的;而就 LoCoMo 而言,一个长上下文模型把整段对话吞进去就能部分解掉它——这让那个分数既是记忆层的属性,也同样是底座模型的属性。
哪一个需要的基础设施最少?
Cognee 的默认本地路径(无密钥,本地抽取器与本地嵌入)最少,然后是配一个向量库的 Mem0,再是单 Postgres 上的 Cognee,最后是要图数据库的 Graphiti。
我到底需不需要图?
只有当你会去查询关系或时间时才需要。当智能体必须回答「什么变了、何时变的」,或者要走超过一跳时,图才挣回它的运维成本;而对短事实的相似度召回,一个向量库要运维的更少、能搞错的也更少。
我该怎么真正评估它们?
在你自己的语料上,用你自己的问题,并且要包含你故意埋进去的矛盾——那个子能力对所有人都是最差的。指标见评估记忆质量,而为什么在这里你自己写的二十个用例胜过一份公开榜单,见用大白话讲评测。
延伸阅读
本站:
- 记忆存储:向量、键值、图与驱逐 —— 把后端匹配到记忆类型。
- 记忆作用域与多租户 —— 为什么
user_id不是一次授权判定。 - 遗忘与取代 —— 只有 Graphiti 的模型原生表达的那种变更。
- 迁出一家记忆供应商 —— 退出成本的细节。
- 记忆毒化防御 —— 一个共享作用域让攻击者能写进什么。