mem0 学习页

mem0 是一个围绕“抽取式长期记忆”设计的 Memory / AsyncMemory 层,把近期消息、已有记忆、实体链接和历史审计串成一套可检索、可更新的记忆系统,而不是完整的对话运行时。

它最重要的特点是:长期记忆主体在向量库,SQLite 只是短窗上下文与审计辅助层;因此你不能把 history/messages 当成真正的 memory 本体。

源码事实Memory / Context 能力层
这页怎么读
  • 先看“这一轮模型看到了什么”,建立模型视角。
  • 再看 context 和 memory 两张图,抓主链。
  • 最后看源码锚点和证据页,确认细节。
01

这一轮模型到底看到了什么

这一段只讲模型真正可见的材料,不把所有底层状态都算进 context。

context 组成图

mem0 的上下文是为“抽取长期记忆”服务的,不是完整会话 runtime 的上下文窗口。

消息输入
先规范化消息和 metadata。
session_scope
确定当前隔离边界。
最近 10 条消息
形成短窗上下文。
最近 10 条 memories
用于去重和参考。
抽取 prompt
拼成 additive extraction prompt。
记忆写入
把候选 memory 写入长期层。
  • session_scope 作为隔离边界,决定这一轮抽取/写入能看见哪一组消息和记忆。
  • 最近 10 条消息会被拉出来,和新消息一起形成“抽取上下文”。
  • 最近 10 条已有 memories 会参与检索与去重,防止重复写入。
  • parse_messages / parse_vision_messages 会把消息扁平化成统一文本输入,视觉内容先转成描述。
  • generate_additive_extraction_prompt 会把 Summary、Last k Messages、Recently Extracted Memories、Existing Memories、New Messages、日期和自定义指令拼进去。
  • 只有 agent_id 而没有 user_id 时,会追加 AGENT_CONTEXT_SUFFIX,把抽取视角切到 agent 视角。
  • search 阶段看到的是混合检索输入:语义向量、关键词/BM25、实体命中和可选 rerank 结果。
02

context 是怎么拼起来的

先看组成块,再看顺序。这里最容易帮助普通读者分清“哪些东西会真的进模型”。

仓库定位

mem0 的核心是 Memory / AsyncMemory,围绕抽取式长期记忆工作,不是完整 chat runtime。

定位

上下文窗口

抽取时只看 session_scope 内最近 10 条消息,并结合最近 10 条已有 memories。

上下文

抽取输入

上下文会被拼成 additive extraction prompt,包含 Summary、Last k、Existing、New、日期和自定义指令。

输入

写入主链路

add() 会先抽取,再去重、embedding、写向量库,同时落 SQLite history/messages,并更新实体链接。

流程

存储分层

长期记忆主体在 vector store,SQLite 只负责 history/messages,entity store 单独保存实体到 memory 的关联。

存储
  1. 先校验 user_id / agent_id / run_id 和 memory_type,并把消息与 metadata 规范化。
  2. 按 session_scope 取最近 10 条消息,再检索 top 10 现有 memories 作为上下文。
  3. 组装 additive extraction prompt;如果是 agent-only 场景,再追加 agent 视角后缀。
  4. 调 LLM 做一次抽取,解析 JSON 结果,拿到候选 memories。
  5. 对候选结果做 hash 去重、embedding,并写入 vector store。
  6. 同步写 SQLite history/messages;再根据实体结果更新或插入 entity store 里的链接。
03

memory 是怎么形成、保存、再被取回的

不要把记忆想成一个抽象黑盒。这里直接按时间顺序讲“它什么时候生成、存哪、怎么再回来”。

memory 流程时间线

真正的长期记忆不是对话历史,而是抽取、去重、编码后写进向量库的结果。

规范化输入
把文本和视觉消息统一化。
上下文收集
取最近消息和已有 memory。
抽取 / 总结
让 LLM 产出候选记忆。
去重与 embedding
先判重再编码。
写入向量库
形成长期记忆主体。
history / entity linking
补齐审计与实体索引。
  1. 输入消息先被规范化,必要时先做视觉描述或文本扁平化。
  2. 进入抽取阶段后,系统会生成候选 memory,或者在 procedural_memory 分支里直接产出总结式记忆。
  3. 候选 memory 被去重、编码、写入向量库,成为长期记忆主体。
  4. 同步生成 history 记录,并把近期消息留在 SQLite 的 messages 窗口里。
  5. 搜索时,系统会综合语义、关键词、实体和 rerank 结果,返回可读记忆。
  6. 更新和删除会保留历史轨迹;reset() 则直接清掉历史表、消息表和向量存储。
04

存储分层图

很多误解都来自把 transcript、summary、文件、数据库和向量库混成一层看。

存储分层图

主记忆在向量库,entity store 是索引层,SQLite 是辅助层。

L1 向量库
主记忆本体。
L2 entity store
实体索引层。
L3 SQLite history
审计轨迹。
L4 SQLite messages
最近 10 条上下文。
L5 本地状态
MEM0_DIR/config.json/history.db。
  • vector store:长期记忆主体,保存 memory 本体、hash、时间戳、lemmatized text 和检索索引。
  • entity store:独立 collection,保存实体文本、类型和 linked_memory_ids。
  • SQLite history:记录 add / update / delete 的审计轨迹,不是长期记忆本体。
  • SQLite messages:只保留每个 session_scope 最近 10 条消息,作为抽取上下文。
  • local state:MEM0_DIR、config.json 和 history.db 组成本地状态根目录。
  • provider-backed storage:向量库后端由 factory 和 provider config 决定。
05

哪些东西最容易被误认为 memory

这部分是防误解,不是额外功能清单。

常见误解

把 history/messages 当成长期记忆本体,实际上它们只是辅助上下文和审计。

  • 在 search() 里没带 user_id / agent_id / run_id,会直接触发过滤校验失败。
  • 以为 AsyncMemory 是另一套逻辑,实际上只是同步逻辑的异步包装。
  • 以为 mem0 内置了完整 conversation compaction 主线,其实没有统一压缩流程。
  • 忽略 agent_id 单独出现时的 agent 视角后缀,导致抽取视角和预期不一致。

读完应记住的 3 件事

mem0 的核心价值是“把短期消息抽成可检索的长期记忆”,不是把对话全文一直塞进上下文。

  • 真正的长期记忆主体在向量库,SQLite 主要服务于历史和短窗上下文。
  • 理解 session_scope、抽取 prompt 和 entity linking,就基本理解了 mem0 的主设计。
06

关键源码位置

每个结论都要能往下追。这里列的都是站内证据入口,不是营销材料。

07

回到原始 docs 深挖

如果你想继续看原文、行号和分专题分析,可以直接跳到证据页。

证据页

站内会把这个 repo 对应的 docs 文件按行展开,方便核对路径和行号。

原始文档清单

你也可以直接从总览、仓库入口页和 5 篇专题页继续追。

  • 仓库入口页
  • 01-架构与范围
  • 02-context管理
  • 03-memory实现
  • 04-存储与状态
  • 05-调用链、压缩与边界