AI 记忆框架调研与实测
本文最后更新于 2026-10-09
AI 的长期记忆,可以先理解为:把对后续交流有用的信息保存下来,下一次需要时再找回来。 比如你告诉一个助手“以后叫我阿林”,换一次对话,它仍然知道怎么称呼你,而不是每次都重新问。
不过,“记住了”只是第一步。过两天你又说“还是叫我小林吧”,它应该改用新称呼,而不是把两个名字一起丢给大模型,让模型猜。偏好也会变:之前喜欢苹果,后来不喜欢,再后来又喜欢了,这时该保留什么?
我这次调研,就是想给一个对话助手接上这样的记忆能力。看了九个开源项目,也跑了几轮实际测试。结果里,比“能不能存进去”更值得展开的,是存进去以后,能不能更新对、找对人,以及真的忘掉。
- 第一次我喜欢苹果形成一条当前偏好
- 第二次最近不喜欢苹果了修订同一个偏好,而非多加一条矛盾事实
- 第三次现在又喜欢了当前答案应使用这次确认的信息
当前状态和历史记录可以同时保留,但用途不同。问“现在喜欢什么”和问“以前怎么变化的”,不能拿同一堆旧句子不加区分地回答。
先给一个阶段判断:简单的用户事实与偏好,我会继续以 Mem0 做基线,同时验证 MemOS;需要关系与时间推理时,再单独评估图记忆。 这不是九个项目的通用排行榜,而是下面这些需求和接法下的选择。
这篇保留的是 2026 年 9 月 29 日的研究快照。后续部署版本有变化,不能把新版本功能直接算进这轮测试。
先拆开记忆
记录不等于记忆
聊天记录回答的是“说过什么”,长期记忆还要判断“哪些话值得以后继续使用”。
“我平时喜欢太空故事”,适合成为一个内容偏好;“今天先讲这个”,可能只是当次选择。“我在故事里是一名船长”,也不能直接存成真实职业。如果把所有句子都当事实,记得越多,反而越容易答错。
把全部历史对话直接放进提示词,也是一条可以尝试的路线。对话短、人数少时,没必要一上来就搭复杂框架。但随着历史变长,需要处理输入长度、费用、隐私范围和旧信息冲突。摘要能缩短内容,也要检查它有没有省略条件、把临时要求压缩成长期偏好。
我在这轮里更关注:从对话中提取少量有来源的记忆,并能单独查询、修订和删除。
写入与读取
可以先分成两条路,不必认为每说一句话,系统就要立刻重新整理整个记忆库。
- 确认来源与主体谁说的、何时说的,是现实信息还是故事角色
- 判断并对照旧记忆长期信息还是当次指令;新增、更新、忽略或待确认
- 保存并核对结果正文、条件与证据同步;确认新版本实际可读
- 先限定可访问范围用户、产品或设备范围;权限由业务系统验证
- 找相关且适用的信息按字段、关键词或语义检索,检查条件与当前状态
- 交给模型组织回答只使用有依据的信息;冲突或缺失时不补猜测
写入解决“以后该记什么”,读取解决“现在该用什么”。 两条路都要有自己的失败处理,不能只看搜索接口有没有返回内容。
这里容易混在一起的,还有三样东西:
| 部分 | 在做什么 | 不能替它包办什么 |
|---|---|---|
| 大模型 | 理解对话,提取事实,判断新旧信息的关系 | 不能保证每次主体和长期性都判断正确 |
| 记忆框架 | 组织写入、更新、检索,以及来源或时间等信息 | 不会天然知道产品的全部业务规则 |
| 数据库与索引 | 保存记录,按条件或相似度找到记录 | 不决定“这句话是否应该被记住” |
Embedding(向量嵌入) 是把文字转成便于比较的一组数字,用来找语义相近的内容。它是检索工具,不等于记忆本身。搜到一句“我不喜欢苹果”,也不能仅凭相似度判断这是不是最新状态、是不是同一个人说的。
分类也一样。基本资料、偏好、经历、关系、备忘、图片关联,可以作为整理入口;但给句子贴上“偏好”标签,并不会自动解决真假、主体、适用条件和权限。
框架各自管什么
九个项目的方向
这些项目都叫“记忆”,实际关注点并不相同。下面按官方定位和本轮阅读的实现路径简要整理,链接可以直接去看源码。
| 项目 | 值得看什么 |
|---|---|
| Mem0 | 事实记忆的新增、查询与管理,以及不同存储适配。适合作为直接接入的一条基线。 |
| Hindsight | 保存信息、召回和基于记忆进一步思考的区分,以及多路检索。 |
| MemOS | 记忆容器、读写管理、检索与可选调度组件。需要先明确自己用哪条路径。 |
| Graphiti | 用实体和关系组织事实,保留来源片段与时间,适合研究关系如何变化。 |
| EverOS | 本轮阅读路径以 Markdown 为源记忆,再生成检索索引,便于理解源记录与索引的关系。 |
| LangMem | 可嵌入程序的提取与更新工具,存储由应用选择;它不是一套固定数据库服务。 |
| Memobase | 将用户画像与经历事件分开管理,适合观察当前状态和发生过的事情怎样共存。 |
| VoiceMem | 语音交互中的记忆编排:说话期间预取、后台写入。这个思路值得看,但本轮没跑完整语音链路。 |
| SimpleMem | 先把对话整理为较独立的信息,再检索;需要检查它怎样区分历史条目与当前事实。 |
例如 Graphiti 的实体、事实边和来源片段,比一张“偏好表”更适合表达关系。但有了图结构,不等于短句一定提取得出来。反过来,一个只保存当前偏好的系统,也不一定需要图数据库。
先问要记住什么,再决定需要哪些结构。 项目名字和功能清单只能帮助缩小范围,最终还得把自己的场景跑一遍。
实际怎么接的
后面展开的共同测试,集中在四条路径:
| 框架版本 | 本轮存储 | 接入方式 |
|---|---|---|
| Mem0 2.1.0 | Milvus 2.5.16 | 外部模型先决定原子事实与操作,再显式新增、更新或删除 |
| Hindsight 0.10.1 | PostgreSQL | 同样先做业务判断,保存时仍保留框架自身的再次提取与召回 |
| MemOS 2.0.33 | PostgreSQL 与 pgvector | 同步 fast 路径,补充分类过滤与既有记录更新的衔接 |
| Graphiti 0.30.2 | Neo4j 5.26.12 Community | 保留实体与关系提取,补分类约束、过滤和向量请求适配 |
前三家尽量共用外部提取规则,Graphiti 则保留自己的实体、关系处理方式。因此测的是当前接通的完整路径,不是把同一份事实塞给四个数据库,再比较数据库谁快。
有些能力也不能算成框架开箱即用:本轮 MemOS 的 PostgreSQL 接口没有按传入分类条件过滤,我补了 SQL 条件;Graphiti 的分类与过滤也用了本地兼容层。这些代码将来都要维护,不能在选型时藏起来。
Mem0 这条路径有一个版本细节:2.1.0 的自动提取不能理解为“任何改口都会自动更新原 ID”。这轮需要覆盖旧事实时,明确调用更新接口。预先整理事实后使用 infer=false,只是绕过内部提取判断,不代表检索不再需要向量模型。
MemOS 的后台调度与额外整理功能没有启用。测试同步读写跑通,不能顺便宣布后台整理也验证完成。
测试里的几个问题
怎样检查是否记对
只问一句“我喜欢苹果”,再问“我喜欢什么”,很容易做出一个成功演示。所以测试里加了改口、不同时间条件、当次指令、虚构角色、访客换人、冲突和删除。
每个案例沿着实际结果往下看:输入是什么,模型提取了什么,数据库里留下什么,查询拿到什么,最后回答有没有用对。最后回答不带近期对话,避免模型直接照着刚说过的话回答,让一个没写好的记忆库看起来也能记住。
此外,四家各回放了同一批 50 段已有会话,流程完成数分别是 Mem0 47、Hindsight 45、MemOS 44、Graphiti 48。这里没有人工确认的完整标准答案,这四个数字只是流程完成数,不是准确率。Graphiti 完成得多,也不能据此说它记得最好。
更能解释问题的是 16 个共同针对性场景,以及后面单独补的一次 Graphiti 删除验证。下面挑几个展开。
这些结果来自本地小样本;跨日期由日志或输入时间模拟,不代表生产并发、真实长期运行或记忆衰减的验证结果。
刚写入却没读到
早期 Mem0 测试里,有一次刚写入称呼,立即回读没看到新记录。下一次用户改称呼,提取模型拿到的旧记忆是空的,于是判断应该新增。稍后再查,两个称呼都在。
表面看是“模型不会更新”,实际是它根本没看到要更新的对象:
写入第一条 → 立即回读为空 → 再次改口被判为新增 → 两条称呼并存。
复测时,我先按实际 ID 和最新正文确认记录可读,再处理下一次变化。此轮额外等待约 228~458 ms,称呼与偏好的四组更新案例随后用到了最新值。
复测改变的是核对步骤,没有修改 Mem0 源码或切换读取的一致性配置。轮询是这次测试的核对办法,生产里还需要确定可靠的写后读取、当前记录管理与幂等策略,也就是重复请求不要产生重复记录。不能为了把接口耗时测得更低,就忽略下一次读到的还是旧值。
正文更新还不够
Hindsight 的苹果偏好案例里,正文已经改了,但保存的证据、业务版本和确认时间还停在第一次。最终回答没有确认最新偏好。
证据:第一次表达
业务版本:1
确认时间:第一次
证据:仍是第一次
业务版本:仍是 1
确认时间:仍是第一次
正文、证据和时间各自都可能是合法字段,但放在一起已经不一致。下游一旦依赖这些字段判断新旧状态,问题就会出现。
在这个固定版本的接法里,官方 PATCH(局部更新接口)能更新正文,却不接受我们要同步的 metadata(证据、版本等附加字段)和 tags(标签)更新。如果业务依赖这些字段,就要设计额外记录或其他可验证的同步路径,不能只在展示页上写“版本 2”。
同一个“喜欢 → 不喜欢 → 又喜欢”案例,Mem0 与 MemOS 使用了最新偏好;Graphiti 漏掉了首次与最后的事实,回答仍是不喜欢。这个结果比“支持时间图谱”更具体:时间机制可以处理已经形成的事实,却不能替代前面的正确提取。
条件和临时指令
“晚上小声一点,白天可以大声”,不是两条互相冲突的音量要求。它们有不同的适用条件,应该共存。
这组指定案例里,Mem0、Hindsight 和 MemOS 保留了条件;Graphiti 没有形成对应事实边,没能回答。另一个当次小声的案例中,MemOS 路径却把它保存成长期偏好。
后一个错误发生在共用的外部提取模型,不是 PostgreSQL 自己创造了偏好。这里换一家数据库没有用,要修的是:怎样区分“以后一直这样”和“这次先这样”。
分类规则最好带正反例,而不只是写几个目录名。比如“长期音量习惯可以保存;因当前环境临时调小音量,不直接保存成长期习惯”。然后仍然要测,提示词里写清楚不等于模型必然执行正确。
谁说的与怎样忘掉
访客换人的案例中,前三条受控路径把新说话人的信息错绑到账号本人。Graphiti 没提取出对应事实,也不能算它正确识别了身份。
这说明账号、设备和实际说话人不是同一个概念。在多人使用的对话产品里,主体确认和权限规则得单独设计。给查询加一个用户字段,只能过滤已经正确归属的记录,救不了写入时就绑错的人。
删除也不能只检查一次搜索。Graphiti 第一次删除用例,在删除前根本没形成事实边,那次验证无效;补例确实形成了 4 条事实边,删除后回读与召回为空,但仍留有 5 个实体或来源片段节点。Mem0 的历史接口里也还保留着旧正文。
搜不到,不等于所有隐私数据都已删除。 需要分别检查当前事实、历史、来源原文、实体摘要、索引,以及业务侧保存的文件和日志。
还有一个没完成的地方:年级冲突的案例返回了“待确认”,却没把候选事实存进可跨会话查询的待确认库。下次回答不知道,只代表它没使用一个确定事实,不代表冲突已经被管理好了。
检索时间花在哪
先分段再比较
这轮另做了每家 30 次只读检索,带一级与二级分类条件。采用小库热态,运行时还有其他研究任务;包含问题向量化、检索和框架整理,不含最终回答或语音处理。
P50 是中位数,P95 用来看较慢那部分请求。下面把整体召回和其中的问题向量化分开展示,先看通常要等在哪一步。
两条柱分别取各阶段的中位数,不是堆叠构成图,不能相减当成数据库耗时。不同路径还有并行或嵌套步骤,不能把各阶段的 P50、P95 直接相加。
| 路径 | 整体召回 P50 | 整体召回 P95 | 问题向量化 P50 | 问题向量化 P95 |
|---|---|---|---|---|
| Mem0 | 194.1 ms | 557.9 ms | 178.0 ms | 548.5 ms |
| Hindsight | 191.3 ms | 483.7 ms | 165.3 ms | 445.6 ms |
| MemOS | 204.3 ms | 602.5 ms | 176.9 ms | 582.1 ms |
| Graphiti | 186.0 ms | 402.7 ms | 168.0 ms | 387.8 ms |
分段记录里,Mem0 的稠密检索数据库步骤 P50 为 4.95 ms,Hindsight 并行检索为 19.78 ms,MemOS 按向量查询为 18.10 ms,Graphiti 数据库驱动计时为 8.97 ms。它们的步骤定义不同,还包含连接、取回或解码,不是纯 SQL 的排名。
这组数据支持的判断是:当前小库路径里,远程问题向量化是一个很显眼的等待来源。 如果只换数据库,很可能没有碰到主要等待点。至于换成本地向量模型、做缓存或提前检索能改善多少,要另测质量、命中率和实际延时,不能从这张图直接推算。
也别把这里的约两百毫秒写成“语音助手响应时间”。麦克风输入、语音识别、回答生成和语音合成都不在这个计时里。
现在怎么选
我的选择
这轮需求主要是用户事实、偏好、条件和可追溯更新,还没有复杂关系推理。在这个范围里,我的选择是:
- Mem0 保留为基线。 受控操作、业务字段和现有 Milvus 接法比较直接,几个改口案例能使用最新记忆。写后可见性、删除历史、主体规则仍然要补。
- MemOS 继续做部署候选。 同步读写与分类查询已接通,也值得继续看它的管理方式。但本地兼容代码和可选后台功能的维护、验证成本不能省略。
- Hindsight 保留为检索对照。 多路检索和严格分类 tags 有价值;若需要频繁同步业务证据、时间与分类,要先解决这轮暴露的更新边界。
- Graphiti 不作为当前首版默认。 短句漏事实、偏好变化漏边,会影响这类问答。若问题变成“谁与谁有什么关系,这段关系什么时候改变”,再用相应案例评估它,而不是沿用偏好测试的结论。
其余路线也不是被判定为“不行”。想自己控制提取与存储,可以考虑 LangMem,但要承担应用侧适配;重视可读源记录,可以继续看 EverOS;画像和经历要分开管理,可以研究 Memobase;关心语音等待的编排,VoiceMem 值得看;希望先压缩会话信息,可以看 SimpleMem,并单独验证当前状态的更新。
我不准备把这些都接进同一个产品。选型是找一条适合当前需求、问题可以查清、成本能承担的路线,不是把功能最多的几个框架叠起来。
如果自己动手试,我建议先拿几段构造对话跑完整过程:改一次称呼,反复改变一个偏好,加一个白天与夜晚的条件,再试一次临时指令、换人和删除。不要只截取模型最终回答,把实际存下来的记录也打开看。
能记住一句话,是一个好的开始。能解释为什么保存它、现在该不该用它,以及怎样修正或删除它,才是我判断一个记忆系统是否合用的依据。