Agent 记忆系统学习笔记(一):从 Mem0 看懂记忆与召回链路
用 Mem0 作为第一个样本,系统理解 Agent Memory 的写入、存储、实体链接、多信号召回、排序和上下文注入链路。
写在前面:这不是 Mem0 产品介绍,而是记忆系统入门
这个系列我想解决一个问题:AI Agent 的记忆和召回到底是怎么设计的?
如果只看表层,很多系统都在说自己有 memory:有的接一个向量库,有的保留聊天历史,有的做 GraphRAG,有的让 Agent 自己调用工具搜索记忆。但这些方案背后的关键问题其实是同一组:
什么内容值得被记住?
它被存到哪里?
未来怎么找到它?
找到以后怎么排序?
什么时候应该忘掉、降权或保留历史?
最后怎么把记忆交给模型使用?这一篇先从 Mem0 开始。原因很简单:Mem0 是一个比较典型的工程化 Agent Memory 案例,它把长期记忆拆成了写入、存储、实体链接、多信号召回、时间推理和排序等模块。学完它之后,再看 Zep、Letta、LangGraph、Cognee,会更容易建立统一的分析框架。
我对这篇笔记的定位是:不是教你怎么接入 Mem0,而是用 Mem0 学会拆解一个记忆系统。
一、先建立心智模型:记忆不是聊天记录
很多人第一次理解 Agent Memory,会把它等同于“保存历史聊天”。但这只是最低级的记忆。
聊天记录是原始材料,记忆是被提炼后的可复用事实。
比如用户说:
我不太喜欢惊悚片,最近更想看科幻电影。原始聊天记录只是这句话本身。但一个记忆系统真正应该沉淀的是:
用户不喜欢惊悚片。
用户偏好科幻电影。以后用户问“今晚看什么”,Agent 不需要用户重复偏好,而是能主动召回这两条记忆。这才是长期记忆的价值:让每一次交互都能沉淀成未来可用的上下文。
所以,记忆系统不是一个日志系统。日志系统记录“发生过什么”;记忆系统要判断“未来什么会有用”。
二、Mem0 的整体位置和写入链路
Mem0 在 Agent 架构中的位置
Mem0 可以理解成应用和大模型之间的一层长期记忆基础设施。
它有两个最核心的动作:
add :把新的对话或事实写入记忆系统
search :在未来根据 query 召回相关记忆这两个 API 看起来简单,但背后分别对应一条完整链路。
记忆写入链路:从对话到可召回事实
先看写入。
Mem0 不是简单把整段对话塞进数据库,而是要先做一层“蒸馏”:从对话中抽取值得保留的事实。
举个例子:
用户:我下个月要去东京,我比较喜欢住在涩谷附近,也不吃贝类。
助手:好的,我会记住你的旅行偏好。比较理想的 memory extraction 结果是:
用户下个月计划去东京。
用户偏好住在涩谷附近。
用户不吃贝类。这一步是 Agent Memory 和普通 RAG 的核心区别之一。
传统 RAG 往往默认资料已经存在,重点在检索;Agent Memory 需要先判断什么内容值得被写成记忆。
ADD-only:为什么 Mem0 不急着覆盖旧记忆?
Mem0 新版算法里一个重要取舍是 ADD-only extraction。也就是写入阶段主要做新增,而不是让 LLM 在每次写入时决定 ADD、UPDATE、DELETE。
这件事一开始看起来有点反直觉:如果只新增,记忆不是会越积越多吗?
会。但这是有意为之。
因为很多事实不是互相冲突,而是随时间演化。
2025 年:用户住在纽约。
2026 年:用户搬到了旧金山。如果系统把“用户住在纽约”直接更新成“用户住在旧金山”,那它就丢掉了历史。以后用户问:
我搬家之前住在哪里?系统可能就答不上来。
所以 Mem0 的思路是:
写入时尽量保留事实
召回时再判断当前问题需要哪条事实这个设计很关键。它把复杂度从写入阶段转移到了召回阶段。
写入阶段少做破坏性判断,可以降低误删、误合并、误覆盖的风险;召回阶段再根据语义、实体、时间和新旧程度决定哪条记忆更应该出现。
这也是我认为 Mem0 最值得学习的地方之一:长期记忆不应该只保存“当前状态”,还应该保存“状态如何变化”。
三、Mem0 的存储与 Graph Memory
Mem0 的存储:向量库只是其中一层
很多人会把记忆系统想象成一个向量数据库。但 Mem0 的结构不止这一层。
从官方文档和评估说明看,它至少可以拆成三类存储:
Vector Store 负责“意思像不像”。Entity Store 负责“是不是和同一个人、地点、项目、概念有关”。History Store 则更偏系统内部的事件记录和上下文管理。
这个分层说明一件事:一个好的记忆系统不能只靠 embedding。
Embedding 适合语义相似,但它对专有名词、时间、实体关系、精确关键词并不总是稳定。记忆系统需要更多索引结构共同工作。
Graph Memory:Mem0 的图更像“实体增强检索”
Mem0 现在的 Graph Memory 是内置的,不再要求使用 Neo4j、Memgraph、Kuzu 这类外部图数据库。
它的基本逻辑是:
之后用户问:
Alice 现在和什么项目有关?系统就不只看语义相似,也会看哪些 memory 和 Alice 这个实体连接。相关 memory 会获得排序加权。
但要注意:Mem0 的 Graph Memory 不是完整知识图谱。它不会严格记录:
Alice -- 管理 --> Bob
Alice -- 就职于 --> Acme它更像:
Alice 这个实体连接了哪些 memories?
哪些 memories 共同提到了 Alice?所以我会把 Mem0 的图理解成 entity-aware retrieval,也就是实体增强召回,而不是强 schema 的图推理系统。
这个判断很重要。因为如果你只是想让 Agent 更容易召回和某个人、项目、公司相关的历史,Mem0 的图已经很有用;但如果你要做复杂关系推理、路径查询、关系约束,那就需要看 Zep/Graphiti 或传统图数据库方案。
四、Mem0 的召回链路
召回链路总览:Mem0 怎么“想起来”?
记忆系统最难的不是存,而是召回。
因为长期记忆会越来越多,里面会有旧信息、相似信息、冲突信息、不同 session 的信息、不同用户的信息。真正的问题是:当前这一刻,哪几条记忆最应该进入上下文?
Mem0 的召回链路可以这样理解:
这条链路里,每一步都在减少错误召回的概率。
第一步:先确定搜索边界,而不是全局乱搜
记忆召回首先要解决隔离问题。
如果一个系统里有多个用户、多个 Agent、多个应用、多个 session,搜索时不能直接全局检索。否则很容易出现“串记忆”。
Mem0 用这些字段来划分记忆空间:
| 字段 | 作用 | 例子 |
|---|---|---|
| user_id | 某个用户的长期记忆 | 用户偏好、历史行为 |
| agent_id | 某个 Agent 的记忆 | 旅行助手、客服助手、学习助手 |
| app_id | 某个应用或租户 | 白标应用、不同产品线 |
| run_id | 某次任务或会话 | 一张客服工单、一次旅行规划 |
所以一个典型 search 应该像这样:
client.search(
query="用户有什么饮食禁忌?",
filters={"user_id": "alice"}
)这一层不是锦上添花,而是安全底线。
我建议以后拆所有 memory 系统时,都先问:
它的记忆隔离模型是什么?
按用户隔离,还是按会话隔离?
多 Agent 共享记忆时怎么防止串上下文?没有 scope 的记忆系统,很难进入生产。
第二步:语义检索,解决“意思相近”
语义检索是最基础的一层。
query 会被转成 embedding,然后和 memory embedding 做相似度匹配。
适合的问题是:
用户喜欢什么类型的电影?
用户对旅行有什么偏好?
之前这个项目有哪些背景?
用户对远程办公怎么看?这类问题不一定有精确关键词,但语义上可以匹配。
不过,语义检索不是万能的。它常见的问题是:
专有名词可能召回不稳
订单号、会议名、项目名可能被弱化
时间问题容易混淆
实体关系不够清晰
相似但不相关的内容可能被召回所以 Mem0 后面又叠了关键词、实体和时间信号。
第三步:BM25,解决“精确词命中”
有些查询不是语义问题,而是关键词问题。
比如:
Q1 roadmap
Alice
invoice-38291
San Francisco
March 10这些词对用户来说非常关键,但在向量空间里不一定有足够稳定的表达。BM25 的价值就是让这些关键词能影响排序。
所以 Mem0 的召回不是只看:
这条 memory 和 query 意思像不像?还要看:
这条 memory 有没有命中 query 里的关键字?不过 Mem0 文档里有一个细节值得记住:在 OSS v3 的说明中,BM25 更像是 boost signal,不一定是独立扩展候选池。也就是说,它主要提高相关候选的排序,而不是完全替代向量召回。
这说明 Mem0 的多信号召回更像:
先通过语义找到候选
再用关键词和实体信号调整排序第四步:实体匹配,解决“和谁有关”
实体匹配是 Mem0 召回链路中最值得关注的一层。
用户问:
Alice 相关的项目有哪些?系统会从 query 中识别实体:
Alice然后去 Entity Store 中找 Alice,找到和 Alice 连接的 memories,并给它们加权。
流程大概是:
这类能力对长期记忆很重要。因为真实问题经常围绕实体展开:某个人、某家公司、某个项目、某个地点、某个概念。
向量检索能找到语义类似的内容,但实体匹配能帮助系统找到“围绕同一对象分散在不同对话里的记忆”。
第五步:时间推理,解决“什么时候为真”
长期记忆系统一定会遇到时间问题。
用户的偏好会变,住址会变,工作会变,项目状态会变。
以前住在纽约,现在住在旧金山。
以前喜欢咖啡,现在戒咖啡了。
上个月在做 A 项目,现在转到 B 项目。所以召回时不能只问:
哪条 memory 最像 query?还要问:
这条 memory 在时间上是否适合当前问题?Mem0 Platform v3 的 Temporal Reasoning 处理的就是这类问题:
last week
next month
right now
currently
as of March 2025
since when
upcoming比如:
用户问:我现在住在哪里?系统应该更偏向:
用户 2026 年搬到了旧金山。而不是:
用户 2025 年住在纽约。但如果用户问:
我搬家之前住在哪里?旧记忆又应该被召回。
这就是为什么 ADD-only 和时间推理要放在一起理解:ADD-only 保留历史,Temporal Reasoning 决定在当前问题下哪段历史更相关。
第六步:Memory Decay,解决旧记忆污染
长期记忆还有一个问题:旧记忆会越来越多。
有些旧记忆仍然重要,比如过敏信息;有些旧记忆只是临时信息,比如上季度的项目名称。如果所有记忆永远平等,旧信息就会污染召回。
Mem0 的 Memory Decay 可以理解成一种搜索时的轻量排序偏置:
刚被召回过的记忆 → 得到轻微增强
长期没被触达的记忆 → 得到轻微降权注意,它不是删除,也不是硬过滤。
这很像人类记忆:我们不是彻底忘掉过去,而是最近频繁使用的信息更容易浮现。
不过 decay 不能太强。因为低频信息不代表不重要,比如医疗过敏、法律约束、安全偏好。一个好的 memory decay 应该是“温和影响排序”,而不是决定生死。
第七步:Criteria Retrieval,让“相关性”变成业务定义
Mem0 还有一个高级能力叫 Criteria Retrieval。它的核心思想是:有些应用里,“相关”不只是语义相似。
比如一个心理健康助手,可能更想优先召回带有情绪信号的记忆;一个学习助手可能更关心“好奇心”和“挫败感”;一个客服 Agent 可能更关心“紧急程度”和“风险”。
也就是说,普通检索问的是:
这条 memory 和 query 有多像?Criteria Retrieval 问的是:
这条 memory 是否符合我这个应用定义的重要性?可以把它理解成业务层的 relevance shaping。
这说明记忆召回最后一定会走向业务定制。因为不同 Agent 对“重要记忆”的定义不一样。
第八步:Rerank,解决 top 结果顺序
前面的语义、关键词、实体、时间、衰减都可以产生一个综合分数。但在一些高风险或高体验要求的场景里,还需要 rerank。
Rerank 的作用是把候选结果重新排序,让最应该进入上下文的 memory 排在前面。
适合开启 rerank 的场景:
用户只能看到少量结果
第 1 条结果的质量非常关键
医疗、客服、付费用户体验等高精度场景
复杂 query 需要更强语义判断不适合无脑开启的原因也很简单:它会增加延迟。
所以 rerank 应该是一种按场景打开的精度增强,而不是默认万能药。
最终:记忆如何进入 LLM 上下文
召回不是终点。召回出来的 memories 最终要进入 LLM 的上下文。
一个常见结构是:
系统指令:
你是一个有长期记忆的助手。以下是和当前用户相关的历史记忆。
用户记忆:
- 用户不喜欢惊悚片。
- 用户偏好科幻电影。
- 用户下个月计划去东京。
- 用户不吃贝类。
当前用户输入:
今晚有什么推荐?这一步看起来简单,但也有几个问题:
召回多少条?
按什么顺序放?
是否区分事实、偏好、计划和历史事件?
是否告诉模型这些记忆可能过时?
是否允许模型基于记忆主动提问确认?记忆注入的质量会直接影响回答质量。召回太少,模型缺上下文;召回太多,模型会被噪音干扰。
所以长期记忆的目标不是“召回尽可能多”,而是“召回刚好够用”。
五、用一张总图理解 Mem0
把写入和召回放在一起,Mem0 的整体链路可以画成这样:
这张图里最重要的是:Mem0 不是单一检索器,而是一条闭环。
对话产生记忆
记忆影响未来对话
未来对话继续产生新记忆这就是 Agent 长期记忆的基本循环。
六、我对 Mem0 的初步判断
我现在对 Mem0 的理解是:它不是一个“记忆数据库”,而是一个记忆排序系统。
它真正解决的是:
在大量、分散、跨时间、跨实体、可能过时的记忆里,
为当前 query 找出最应该进入上下文的几条。它的优点是工程化程度很高,几乎把生产环境里会遇到的问题都拆成了对应模块:
多用户隔离 → Entity-Scoped Memory
语义召回 → Vector Search
关键词命中 → BM25
实体相关 → Graph Memory / Entity Linking
时间变化 → Temporal Reasoning
旧记忆污染 → Memory Decay
业务重要性 → Criteria Retrieval
高精度排序 → Rerank它的局限也很清楚:
第一,Graph Memory 更像实体增强检索,不是完整知识图谱。
第二,ADD-only 会让 memory 增长,后续必须依赖排序、衰减和清理策略。
第三,官方 benchmark 很有参考价值,但真正上线前仍然要在自己的业务数据上评估。
第四,隐私、同意、可见性、错误记忆纠正,这些治理问题不是接入 Mem0 就自动解决,应用层仍然要认真设计。
所以我对它的定位是:
Mem0 很适合作为学习 Agent Memory 工程化的第一个样本。它展示了现代长期记忆系统应该有哪些模块,但它不是所有记忆问题的最终答案。
七、以后拆其他记忆系统,可以沿用这套问题
这篇是系列第一篇。后面不管研究 Zep、Letta、LangGraph 还是 Cognee,我都会尽量用同一套问题拆:
1. 它怎么写入记忆?
原始对话、摘要、事实抽取,还是结构化事件?
2. 它怎么存储记忆?
向量库、全文索引、图数据库、SQL、对象存储?
3. 它怎么划分记忆边界?
user、agent、session、app、organization?
4. 它怎么召回?
向量、BM25、图遍历、实体匹配、时间推理、工具调用?
5. 它怎么排序?
score fusion、rerank、decay、recency、业务规则?
6. 它怎么处理变化?
update、delete、ADD-only、时间版本、事实失效?
7. 它怎么把记忆交给模型?
自动注入、工具调用、上下文块、prompt 模板?
8. 它有什么治理能力?
可见、可删、可审计、可纠错、权限隔离?如果用这套框架看 Mem0,可以得到一句总结:
Mem0 的核心是:写入时把对话蒸馏成事实,存储时建立语义和实体索引,召回时融合语义、关键词、实体、时间、衰减和业务信号,再把最相关的记忆注入上下文。
这也是我理解 Agent Memory 的第一块拼图。