跳到主要内容

Mem0 项目快速入门实战

Mem0 项目快速入门实战

Agent 记忆系统公开课(上集)· Part 2 · 自动管家派代表项目

§2a Mem0:LLM 当后台管家自动整理记忆

§1d 把三派并排放在一张表里时,自动管家派对应的设计哲学是「LLM 在后台抽取事实做 CRUD」、写入方式是「异步抽取 + LLM 自动判 ADD/UPDATE/DELETE/NOOP」。本节把这两行的代表项目 Mem0 —— 完整展开先说清它是什么、谁在用、论文怎么定义;再讲它内部的两阶段流水线机制;最后用上一节 §1d 的「周末项目」例子把机制走一遍。部署细节和真实生产坑放在 §2b 跑通 hello world 之后再讲,避免在概念阶段就被陷阱劝退。

Mem0 三视角速览:流程 · 实例 · 优劣势

在深入项目背景和机制细节之前,先用 三张图 + 三段文字 把 Mem0 是什么、跑起来是什么样、好坏在哪里——一次性看完。看完这一段,再往下读项目背景 / 主页矩阵 / 机制详解会更顺。

视角 1:用人话讲,Mem0 在干什么

想象你在做一个 AI 学习助教 SaaS。用户 alice 第一次跟 AI 说:"我想做博客,对 Python 熟,喜欢简单部署"。 Mem0 在背后偷偷做的事 是:

  1. AI 助教把 alice 说的话变成几条"笔记"存进自己的记忆库 ——比如"alice 会 Python"、"alice 喜欢简单部署"、"alice 在做博客项目"。这一步靠一次 LLM 调用完成,AI 自己判断哪些信息值得记

  2. 这些笔记都带 alice 的名字(标签) ——后续 bob、carol 跟同一个 AI 助教说的话不会混进 alice 的笔记里

  3. 第二天 alice 回来问"我之前想做什么项目" ——AI 助教 自动从 alice 的笔记里翻出 "想做博客"那条相关的笔记,把这条笔记 作为背景塞进 prompt ,主 AI 看到背景就能答对

下图把这套数据流完整画出来——左边是 写入路径 (用户聊天 → 笔记 → 入库),中间是 笔记库 (默认用 Qdrant 向量数据库 + 每条笔记带归属标签),右边是 读取路径 (用户新问题 → 自动翻笔记 → 拼回 prompt → 主 AI 答复):

人话 vs 工程名词的对照 (看完图之后想看技术细节时用):

人话内部叫什么工具调用
AI把话变成笔记Extraction Phase(抽
取阶段)
第1次LLM调用
决定这条笔记是新增
还是改旧的
Update Phase(决策
阶段)
第2次LLM调用,输出
ADD/UPDATE/DELETE/NOOP
笔记入库写入向量数据库m.add(messages, user_id="alice")
翻笔记找相关的向量检索+标签过滤m.search(query, filters)
把笔记塞进prompt业务代码自己拼不是Mem0自动做的

和 Letta 的本质差异 ——Mem0 翻出来的笔记 不会自动塞进 prompt ,业务代码自己决定塞几条、放哪里;Letta 的工作笔记区是 直接在 prompt 里 LLM 都看得到 (§3a 已讲)。这是两条不同的设计哲学。

视角 2:换一组实际数据,这流程跑出来什么

用 §1d 周末项目 alice 的真实对话走一遍——周六 09:00 alice 说"我想做博客,对 Python 熟,喜欢简单部署",周六 15:00 改 Flask,周日 10:00 回来问"我之前在调什么 RAG"。下图按时间线展示对话经过 Mem0 处理后 实际产出的 fact 内容、score 数值、调用次数、延迟

读图重点(这些数字会在 §2b / §2c 实操中被反复印证):

指标实际数值含义
单次add耗时4-6秒含2次LLM call + 1次embedding
抽出fact条数1-4条不等LLM决定,非确定性(V3 prompt挑剔)
fact文本格式英文short-form中文输入也翻译成英文
单次search耗
≈1.4s(论文p95)远低于full-context 17.1s
返回fact条数
limit(默认10)
业务方可调
limit/
threshold
指标实际数值含义
prompt占用≈200 tokens

limit=5
对比业内标准25k全量历史塞prompt小约
99%

视角 3:什么场景适合用 Mem0,什么场景容易翻车

不讲优劣势卡片, 只讲场景

这些场景非常适合用 Mem0 —— 它能解决你的核心问题

  • 客服 SaaS 想给用户做个性化 —— alice 第二次咨询时 AI 能"认识她",记得她的偏好、之前问过的问题。Mem0 把"跨 session 记住用户"这件事变成两个 API 调用

  • 多用户 chatbot 平台 (Character.AI / Replika / 极客时间答疑助手类)—— 单 Agent 实例服务上千用户,每个用户独立记忆。Mem0 的 user_id 隔离 + 向量库就是为这种场景设计的

  • 个人 AI 助手 / 长期陪伴 Agent —— 跨周、跨月维持用户长期偏好(饮食 / 工作风格 / 兴趣)。 Mem0 的 ADD-only 风格在"只记不删"的场景反而是优势

  • 多 Agent 协作系统 —— CrewAI / AutoGen 都内置 Mem0 集成。多个 Agent 共享同一用户的偏好层,而各自的工作状态用 agent_id 隔离

  • 想快速给现有 chatbot 接长期记忆 —— pip install mem0ai + m.add / m.search 两个 API 就跑起来,所有派别里 工程改造最少

这些场景用 Mem0 容易翻车 —— 应该选别的派

  • 强一致性 / 可审计场景 (金融交易、合规审计、法律咨询)—— Mem0 默认 ADD-only 会让"alice 跳槽前后的公司"都留在库里,主 LLM 在矛盾事实间猜,答错就是事故。 这种场景选 Letta(OS 派)或 GBrain(文档派)

  • 要求每条记忆可追溯(何时写、为什么写、谁写的) —— Mem0 的 m.add() 是黑盒:LLM 抽 fact 你看不见过程,没法 git blame、没法回滚。 这种场景选 GBrain ——所有改动走 git,可 diff、 可 revert

  • 个人知识管理 / Markdown 笔记沉淀 —— 用户想直接读写自己的笔记,Mem0 把笔记锁在向量库里看不见、改不了。 这种场景选 GBrain ——markdown 文件就是真相源,可以用 Obsidian / VSCode 直接打开

  • 长任务 stateful runtime (agent 跨 session 自动维持工作状态、自动 page in/out)—— Mem0 的笔记需要业务代码主动 m.search 拉回来;Letta 的 working context 直接在 prompt 里。 这种场景选 Letta

  • 生产直接照用默认配置 —— 这不是翻车场景,是 翻车原因 :97.8% junk 真实坑(issue #4573)会咬人。Mem0 上生产 必须自己写 custom_fact_extraction_prompt + 治理脚本 ,否则 32 天后记忆库 98% 是垃圾

下图把这两组场景并排放在一起,作为选型时的速查:

一句话总结: Mem0 的强项是"快速给 SaaS Agent 接长期记忆",弱项是"任何要可读、可审计、 可解释的场景" 。三派可以并存(§1d 已说),关键是 用对地方 而不是「用最强的」。

—— —— 下面把这三张速览里提到的事实展开项目背景、主页矩阵、机制流水线、生产坑逐一深入。

项目背景

Mem0 由 Taranjeet Singh 和 Deshraj Yadav 在 2024 年 YC W24 创立,定位是 "AI Agent 的通用记忆层" ——目标是把"记住用户偏好、跨 session 持久化、自适应个性化"这套能力从每个 Agent 项目里抽出来,做成可独立部署的 SaaS / OSS 双形态服务。

发展轨迹(截至 2026-05):

时间点里程碑
2024
Q1
YC W24加入,初版OSS发布
2025-
04
Mem0论文(arXiv 2504.19413) 首发,提出"抽取+决策"两阶段流水线+ LOCOMO
benchmark实测
2025-
10
3.9M Kindred Ventures领投+ Series A $20M Basis Set
Ventures领投,参与方含Y Combinator、Peak XV Partners、GitHub Fund)
累计融资公布(
2025-
12
GitHub Stars突破50k,月度API调用达1.86亿次(创始团队对外披露)
2026-
02
OSS主线升级到2.0系列,引入
ADDITIVE_EXTRACTION_PROMPT,对1.x是breaking
change
2026-
04
推出"单次扫描分层抽取+多信号检索"算法,进一步压缩token与延迟

论文是它和其他记忆框架的最大差异 ——绝大多数同期项目(包括很多自动管家派同行)只有 README 没有 paper。Mem0 论文用 LOCOMO 数据集(10 个长对话 × 约 600 轮 × 约 26K tokens 每对话)跑过一组实测对照:

方法p95响应延
存储 token
J指标(与人类标注对齐
度)
Full-context(整段历史塞进
prompt)
17.117s26,031baseline
Mem01.440s~7,000更高

p95 延迟降低 91%、存储 token 减少 73%,同时检索质量反而更高——这是 Mem0 给"用一次额外 LLM 调用做抽取,换上下文体积大幅压缩"这个 trade-off 的官方答案。

企业落地情况 (2025-2026 年公开案例):

  • 客服 / 个人助手 SaaS :50k+ 开发者集成(来自 Mem0 官方公告),主要用于"记住用户偏好、跨次会话延续"场景

  • 多 Agent 系统 :CrewAI 把 Mem0 作为默认记忆后端之一,AutoGen 与 AG2 提供官方集成示例

  • 垂直领域 :医疗、金融、教育平台的 AI 助手(SOC 2 Type II + HIPAA 合规打开了这些行业的采购可能)

项目主页矩阵

记忆框架选型时第一件事是确认信息源齐全可信——下面 4 个官方页面就是 Mem0 的"完整入口",建议学员先把这四个标签页打开备用。

官网(mem0.ai) ——最新功能、Pricing、Mem0 Cloud 入口、企业咨询通道。

GitHub(github.com/mem0ai/mem0) ——OSS 源码、issue 与社区讨论、Release Notes、贡献者列表。所有 watch-out 都能在这里反查——比如 §1c 提到的 issue #4573 那份 97.8% junk 审计。

官方文档(docs.mem0.ai) ——Platform Overview、API Reference、Migration Guide、Integration 列表。所有版本差异(如 1.x → 2.0 的 filters 写法变更)都以这里为准。

学术论文(arXiv 2504.19413) ——"Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory",Chhikara 等 2025-04 首发,定义了抽取 + 决策两阶段流水线和 LOCOMO 测评方法。本节后面讲机制时直接引用论文术语。

项目情况

把上面 4 个主页背后的关键事实压缩到一张表,作为后续选型对照用:

项目名Mem0(
github.com/mem0ai/mem0)
当前版本2.0.2(OSS主线,截至2026-05公开课录制周)
GitHub
Stars
55.6k(截至2026-05公开课录制周)
许可Apache-2.0
团队Mem0 Inc.(YC W24校友,Taranjeet Singh / Deshraj Yadav创立)
学术血统Mem0论文,
arXiv 2504.19413(Chhikara等,2025-04首发)
融资3.9M由Kindred Ventures领投+ Series A $20M由Basis Set
Ventures领投,2025-10公布)
部署形态OSS自托管(
pip install mem0ai)/ Mem0 Cloud SaaS(
app.mem0.ai)
客户端Python SDK(
mem0)/ TypeScript SDK / REST API
默认栈Qdrant(向量库)+ OpenAI gpt-5-mini(抽取与决策LLM)+ text-embedding-3-
small(embedding,1536维)+ SQLite(历史)
合规SOC 2 Type II + HIPAA

| 主流集成 | CrewAI、AutoGen、AG2、LangChain、LlamaIndex |

注:截至 2026-05 OSS 主线版本是 2.0.2;2.0 系列相对 1.x 是 breaking change(最显眼的是 search API 从 search(user_id=...) 改成 search(filters={"user_id": ...},

version="v2") ),网上很多 Mem0 教程写于 1.x 时代,照搬会拿到空结果。后续 §2b 会把这个 差异显式说清。

抽取 + 决策两阶段流水线

理解 Mem0 的核心是看清它 每次 m.add(messages, user_id="zhang") 内部做了什么 ——这不是简 单的"把消息存进数据库",而是 2 次 LLM 调用 + 1 次 embedding 的完整流水线。下面用 §1d 的「周末 —— 项目」例子走一遍 学员对那个场景已经熟悉,正好用来印证机制。

回顾场景:周六 09:00 学员说"我想做博客,对 Python 熟,喜欢简单部署",AI 推荐 FastAPI;周六 15:00 学员改主意 "FastAPI 太复杂,改 Flask"。下面看 Mem0 怎么处理。

阶段 1:Extraction Phase(抽取)

调一次 LLM,把当前消息对 + 对话摘要 + 最近若干条上下文(默认窗口 m=10)提炼成 显著事实集合

周六 09:00 消息对:
user: "我想做博客,对 Python 熟,喜欢简单部署"
assistant: "推荐 FastAPI,部署简单"
→ LLM 抽取(一次调用):
fact_1: "User is making a personal blog"
fact_2: "User is familiar with Python"
fact_3: "User prefers simple deployment"

Mem0 默认的抽取 prompt 在 V3(2.0 系列)改名为 ADDITIVE_EXTRACTION_PROMPT ,源码在 mem0.configs.prompts 。它默认把对话事实 翻译为英文 short-form 后存储

use_input_language 默认 False)——这也解释了为什么上面的 fact 是英文。这是 §2b 演示 中"中文输入 → 英文 fact"现象的源头。

阶段 2:Update Phase(决策)

对每条抽出的 fact,从向量库查 语义相似度最高的若干条已有记忆 (默认 top 10),让 LLM 再调一次 决 定四种操作之一:

操作触发条件周末项目场景示例
ADD新fact在已有记忆
没有语义等价
周六09:00三条fact全部ADD(库里之前没东西)
UPDATE新fact增强 /细化
了某条已有记忆
假设已存"User prefers Python",新fact "User is familiar
with Python for 5 years"应触发UPDATE(细化)
DELETE新fact与某条已有
记忆直接矛盾
周六15:00 "改Flask"理论上应DELETE旧"decided
FastAPI"——但2.0默认ADD-only不做这个判断
NOOP已存在或与对话无
第二次说"我用Python"——LLM判定与库内重复

关键设计取舍 :Mem0 2.0 的 ADDITIVE_EXTRACTION_PROMPT 把默认决策收敛到 ADD-only —— 源码第一句就是 "Your sole operation is ADD" 。1.x 时代有自动 UPDATE / DELETE 决策 (FACT_RETRIEVAL_PROMPT + DEFAULT_UPDATE_MEMORY_PROMPT 两步),2.0 把它拿掉, 理由是"召回率优先于一致性"。后果是矛盾事实会并存——这就是 §1d 那张周末项目"自动管家派 60-75% 准确率"表中"主 LLM 在矛盾 fact 间猜"的源头。完整的 UPDATE / DELETE 决策依赖业务 侧自己用 update_memory_template 配合 m.add() 的可选参数触发,并不在默认管线里,§2c 会用真实数据印证。

隐藏成本

每次 m.add() 至少触发 两次 LLM 调用 (抽取 + 决策),加一次 embedding 调用。一段 5 轮对话的 add 通常耗时 4-6 秒(用 deepseek-chat 实测)。批量加载 100 条对话约等于 200+ 次 LLM 调用——成 本与时间需要纳入预算, 这是用 LLM 当后台管家的代价 。Mem0 提供 AsyncMemory 类用于异步化,调 用方式与 Memory 一致。

阶段 3:Retrieval Phase(检索)

写入流水线讲完, 读取流水线对应 ——每次 m.search() 内部做什么、能带多少 fact 进 prompt、业务 侧怎么用召回结果。

继续周末项目场景:alice 周日 10:00 重新打开对话问"我之前在调什么 RAG 问题?"——业务侧怎么用 Mem0 答这个问题?

# 一次完整的 search 调用
hits=m.search(
""
query=我之前在调什么 RAG 问题,
filters={"user_id": "alice"}, # 拉 alice 的 fact,不是全用户
version="v2", # 必填,2.0 API 铁律
limit=10, # 默认 10 条,可改
threshold=None, # 默认无门槛
)
# Mem0 内部三步:
# 1) query embedding :用配置的 embedder 把 query 编成向量(一次 embedding 调用)
# 2) 向量检索:在向量库(默认 Qdrant)按 cosine similarity 检索 top-limit 条
fact
# 3) metadata filter :按 filters 过滤——只返回 user_id=alice 的条目
#
# 返回结构:
hits["results"]
# [
# {"memory": "User uses LangChain for long-doc RAG", "score": 0.91, "id":
"..."},
# {"memory": "User struggles with chunking strategy", "score": 0.87, "id":
"..."},
# {"memory": "User prefers Cursor over VSCode", "score": 0.42, "id":
"..."},
# ... 共 N 条(≤ limit)
# ]

召回结果怎么进 LLM prompt —— Mem0 不接管 prompt 构造, 业务侧自己拼

# 业务侧拿到 hits 后自己拼 system prompt
"
context="\n".join(f"- {h['memory']}forhinhits["results"][:5])
system=f"""你是 SaaS 学习助教。已知该用户的事实:
{context}

请基于这些事实回答用户问题。 """

resp=client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": system},
{"role": "user", "content": "我之前在调什么 RAG 问题?"},
],
)

这是与 Letta 的关键差异——Mem0 的检索是 主动拉 (业务侧自己 m.search() 、自己拼 prompt),Letta 是 被动看 (working context 自动在 prompt 里)。所以 Mem0 把"什么时候召 回、召回几条、塞到 prompt 哪个位置"这些决策全交给业务方,灵活度高、但也意味着这些决策 业务方要自己设计好。

带几条进 prompt?三个参数生产侧实际会调

参数默认值调整动机
limit10想要更多/更少fact进prompt。
limit=20 召回更全但prompt
占用翻倍;
limit=3 极简但容易漏掉关键fact
thresholdNone
(不过
滤)

threshold=0.5 只保留相似度 ≥0.5的fact,过滤低相关性噪
——score < 0.5的fact通常是被强行召回的不同主题,进
prompt反而干扰LLM
filtersNone
user_id / agent_id / run_id 隔离命名空间,按
categories 按业务类别筛选(§2c步骤5详谈)

生产侧调优经验limit=5 + threshold=0.5 是最常用组合——既控成本又保质量。低于 threshold 的 fact 不进 prompt 反而提升回答质量。

关于 limit 的 token 估算:每条 Mem0 fact 平均约 30-50 tokens(V3 prompt 默认抽英文 shortform)。 limit=5 ≈ 200 tokens 进 prompt, limit=20 ≈ 800 tokens。相比 §2c 步骤 1 算 的"业内标准 25k tokens 全量历史塞 prompt",Mem0 召回方案的 prompt 体积 小一个量级 —— 这是 Mem0 论文 91% 延迟降幅的来源。

架构示意

把抽取 / 决策两阶段流水线和默认存储栈整合在一张图上:

图中第 4 列的存储后端是 Mem0 OSS 默认配置——Qdrant 走 local mode 持久化在 ~/.mem0/ , SQLite 存历史变更,text-embedding-3-small 提供 1536 维向量。这三件套都是可替换的:换 Pinecone / Chroma / Milvus 改 vector_store.provider ,换 Anthropic / DeepSeek / Qwen 改 llm.provider ,换 Cohere / Qwen embedding 改 embedder.provider 。完整的可替换矩 阵在 §2d 速查给出。

本节涉及的核心概念

概念一句话定义
自动管家派用LLM当后台管家把对话异步提炼成结构化事实并做CRUD
的Agent记忆设计范式
Mem0自动管家派的代表项目,2024年YC W24校友Taranjeet
Singh / Deshraj Yadav创立
Extraction PhaseMem0流水线第一阶段,调一次LLM把对话提炼成显著事
实集合
Update PhaseMem0流水线第二阶段,对每条新fact与已有记忆比对后决
策ADD / UPDATE / DELETE / NOOP
ADDITIVE_EXTRACTION_PROMPTMem0 V3(2.0系列)默认抽取prompt,源码在
mem0.configs.prompts,默认ADD-only且翻译为英文
LOCOMO benchmarkMem0论文使用的长对话记忆基准,10个对话×约600轮
×约26K tokens每对话
Mem0 CloudMem0提供的SaaS形态(
app.mem0.ai),SOC 2 Type II
+ HIPAA合规

抽象的机制讲到这里。下面 §2b 把这一切跑起来——一条 pip install 、一段 config、一行 add() —— 验证完概念再回头看默认配置下会撞上哪些真实生产坑。

§2b 实操:装机、配 LLM、跑通 hello mem0

Mem0 的入门路径在三派代表项目里最短:一条 pip install 、一段 OpenAI 风格的 config、一行 add() 。本节按学员开发机的真实流程跑一遍,验证 deepseek-chat 通过 OpenAI 协议接入 Mem0、并 看到 Mem0 把中文对话自动抽取成英文事实存储的关键现象。后续 §2c 的客服 Agent 案例直接复用本节 产出的环境与数据。

前置条件

项目要求检查命令
Python3.10–3.12(本节用3.11)python3 --
version
包管理器pip
uv(推荐
uv,安装快5–10倍)
pip --version
uv --version
DeepSeek
API Key

platform.deepseek.com 注册后申请(首次访问
见下方截图)
写入下文config
OpenAI API
Key
仅用于embedding(
text-embedding-3-small
1536维),不用OpenAI的chat
写入下文config
网络DeepSeek国内可直连;OpenAI embedding需经代
见下方「Mac代理注
意」

Mac 代理注意 :若开了系统代理(如 http_proxy=http://127.0.0.1:10080 ),需要确保 NO_PROXY 包含 localhost,127.0.0.1 ,否则后续连本机 Qdrant 的请求会被代理误拦。下文示 例代码已显式设置。

关于演示用模型 :本节固定用 deepseek-chat + text-embedding-3-smalldeepseek-chat 是 DeepSeek 提供的别名, 截至 2026-05 实际指向 DeepSeek V4-Flash 的 non-thinking 模式 (同期 deepseek-reasoner 指向 thinking 模式)。DeepSeek 官方公告这两个别名将在 202607-24 deprecated ,届时迁移到显式名(如 deepseek-v4-flash )。本节代码是"当下能跑"的 写法,2026-07 之后要按当时官方 Models & Pricing 页面 替换 model 字符串。

想换 OpenAI / Anthropic / Qwen 等其他 OpenAI 协议兼容的模型,只需改 config 里的 modelopenai_base_urlapi_key 三个字段,其余流程不变。

步骤 1:装包

工作目录里建一个独立 venv,然后装 mem0ai 。本节用 uv ,命令也给出 pip 的等价写法。

# 推荐:uv(快)
uv venv --python3.11 .venv
VIRTUAL_ENV=$PWD/.venv uv pip install mem0ai
# 或:pip
python3.11 -m venv .venv
.venv/bin/pip install mem0ai

装包尾部输出(截取依赖列表的尾段):

成功标志:装机过程不报红,最终列出 qdrant-clientpydanticsqlalchemytqdm 等依赖。 Mem0 默认用 Qdrant 作为本地向量库(持久化在 ~/.mem0/ ),无需单独装 Qdrant 服务。

关于 spaCy / fastembed 的提示:后续运行时会看到 Failed to load spaCy lemma modelfastembed not installed — BM25 keyword search disabled 两条 warning。这两个是可选 依赖(spaCy 做 NLP 词形还原、fastembed 做 BM25 关键词检索),不装也不影响向量检索。需 要这两项再 pip install mem0ai[nlp] fastembed

步骤 2:验证版本与 import

装完直接 import 一下,确认 Mem0 2.0 系列版本到位。

.venv/bin/python -c'import mem0; print("mem0 version:", mem0.__version__)'

关键提醒(API breaking change) :本节所有代码都基于 Mem0 2.0 写。Mem0 1.x 与 2.0 的 search API 不兼容——1.x 写 m.search(query, user_id="alice") ,2.0 必须写

m.search(query, filters={"user_id": "alice"}, version="v2") 。网上很多 Mem0 教程是 1.x 的,复制粘贴会拿到空结果但不报错。看到 pip show mem0ai 显示 2.0.x 后,请按本节代码而非搜来的旧文章操作。

步骤 3:配 LLM 与 embedding,单独探活

mem0 的网络后端先各跑一遍,把鉴权 / 网络 / 模型名三类问题前置筛掉。下面这段代码做三件事: 导入 Mem0、用 DeepSeek API 跑一句对话、用 OpenAI API 取一次 embedding。

# demo_step1_install_check.py
importos
# Mac 系统代理对 OpenAI 必须开(DeepSeek 走代理也能通),但本机服务要 NO_PROXY
os.environ["HTTPS_PROXY"] ="http://127.0.0.1:10080"
os.environ["HTTP_PROXY"] ="http://127.0.0.1:10080"
os.environ["NO_PROXY"] ="localhost,127.0.0.1,::1"
importmem0
"
print(f"mem0 version: {mem0.__version__})
fromopenaiimportOpenAI
# DeepSeek (OpenAI 协议)
ds=OpenAI(api_key="sk-deepseek-...", base_url="https://api.deepseek.com/v1")
r=ds.chat.completions.create(
model="deepseek-chat",
""
messages=[{"role": "user", "content": 回答一个字:好}],
max_tokens=8,
)
print(f"deepseek-chat ok: {r.choices[0].message.content}")
# OpenAI Embedding
oa=OpenAI(api_key="sk-proj-...")
e=oa.embeddings.create(model="text-embedding-3-small", input="hello")
print(f"text-embedding-3-small ok: {len(e.data[0].embedding)} dim")

执行:

.venv/bin/python demo_step1_install_check.py

成功标志:三行连续 ok 输出。任何一行卡住或抛异常,先按下表对症排查:

现象原因解决
httpx.ConnectTimeout:
timed out
embeddings.create 这一步
OpenAI API
国内直连超时
把系统代理开起来,并
os.environ["HTTPS_PROXY"]=... 同步
给Python
502 Bad Gateway 后续连本
机服务时
代理把
localhost
流量也劫走了
严格设置
NO_PROXY=localhost,127.0.0.1
401 Authentication Fails
from DeepSeek
API Key错或
没有余额
platform.deepseek.com→API Keys与额
度页面确认
404 model not foundfrom
DeepSeek
DeepSeek模
型名拼错或别
名已下线
当下用
deepseek-chat(指向V4-
Flash);2026-07-24后官方会下掉这个别
名,看
Models & Pricing 替换

步骤 4:跑通 hello mem0——5 轮对话喂入,看 Mem0 自动抽取

下面这段代码把"客服 Agent 与 Alice 的 5 轮对话"作为一次 m.add() 输入,由 Mem0 自动抽取事实。 这是后续 §2c 案例的最小骨架。

# demo_step3_hello_mem0.py
importos
os.environ["HTTPS_PROXY"] ="http://127.0.0.1:10080"
os.environ["HTTP_PROXY"] ="http://127.0.0.1:10080"
os.environ["NO_PROXY"] ="localhost,127.0.0.1,::1"
OPENAI_KEY="sk-proj-..."
DEEPSEEK_KEY="sk-..."
os.environ["OPENAI_API_KEY"] =OPENAI_KEY# mem0 的 embedder 默认从这里取
frommem0importMemory
m=Memory.from_config({
"llm": {"provider": "openai", "config": {
"model": "deepseek-chat",
"openai_base_url": "https://api.deepseek.com/v1",
"api_key": DEEPSEEK_KEY,
"temperature": 0.0,
}},
"embedder": {"provider": "openai", "config": {
"model": "text-embedding-3-small",
"api_key": OPENAI_KEY,
}},
})
dialog= [
{"role": "user", "content": "你好,我叫 Alice Wang,2021 年加入阿里通义实验
室,做 RAG 优化方向。"},
{"role": "assistant", "content": "你好 Alice!请问今天我能帮你解决什么问题?"},
{"role": "user", "content": "我习惯用 Cursor 写代码,比 VSCode 顺手。最近在调
一个 LangChain RAG,长文档检索效果不好。"},
{"role": "assistant", "content": "对长文档 RAG,建议尝试 hierarchical chunking +
"
parent document retrieval。},
{"role": "user", "content": "好的,下周我会试。另外我对 Multi-Agent 系统很感兴
趣,有入门资料推荐吗?"},
]
# add 触发 Mem0 内部两步:① LLM 抽取事实② LLM 决策 ADD/UPDATE/DELETE/NONE
res=m.add(dialog, user_id="alice")
forevinres["results"]:
print(f"[{ev['event']}] {ev['memory']}")
# search 用 2.0 的 filters 写法 + version='v2'
"
hits=m.search("Alice 喜欢用什么编辑器?,
filters={"user_id": "alice"}, version="v2")
forhinhits["results"][:3]:
print(f"score={h['score']:.3f}{h['memory']}")

执行(先清空 ~/.mem0 保证干净起点):

rm-rf ~/.mem0
.venv/bin/python demo_step3_hello_mem0.py

输出值得逐条看:

  1. 抽出的 fact 全部是英文 short-form ——输入是中文对话,Mem0 在内部把事实翻译为英文后存储 (如 "Alice Wang prefers using Cursor for coding over VSCode")。这是 Mem0 抽取式记忆派的典型行为,§2c 会作为高光对照演示。

Warning

关于抽取条数的非确定性 :Mem0 V3 的抽取流水线是 LLM 驱动的, 同一段对话每次跑出来的 fact 数量并不稳定 ——本截图实测产出 3 条,但学员实际复跑可能拿到 1-4 条不等(取决于 LLM 当时对"哪些信息值得存"的判断)。这并非配置错误,是抽取式记忆派的固有特性。看到条数与截图不一致不必紧张,下一步 m.search() 能查到 alice 名字 + Python 偏好即合格。

  1. search 用中文 query 仍能命中英文 fact —— text-embedding-3-small 是多语种 embedding, 中英在向量空间相邻。学员不用提前自己翻译。

  2. filters={"user_id":"alice"} + version="v2" 是 Mem0 2.0 的 search 写法,1.x 的 search(user_id=...) 在 2.0 不会报错而是被静默忽略,调试时会以为索引坏了——这是 Mem0

2.0 升级时最容易踩的坑。

本节产出与后续衔接

至此 2b 跑通的"成果"有四样:

产出后续在哪里用
.venv 里装好的mem0ai 2.0.x§2c全程复用
~/.mem0/ 里alice的3条英文fact§2c多用户演示对比基准
验证过的deepseek + openai embedding双API通路§2c完整案例继续走这套配置

Watch-out:跑通之后必须知道的真实生产坑

§2a 末段提过"部署细节和真实生产坑放在 §2b 跑通 hello world 之后再讲"——现在到了讲它们的位置。 下面 5 件事不是 Mem0 实现 bug,是 "让 LLM 在后台自动判什么该记"这条路线的工程代价 。在把 §2b 这套环境推到生产之前必须看一遍。

1. 默认 prompt 抽一切——97.8% junk 的真实生产坑(架构性代价)

§1c 局限 4 提过的那份审计:跑 32 天后入库 10134 条记忆, 逐条人工评估发现仅 38 条原样可用—— 97.8% 是垃圾 。垃圾来源不是抽取错了,而是 默认 prompt 把"什么值得记"完全交给 LLM ——心跳 / cron 日志 / NO_REPLY 标记 / 系统配置全被存。更隐蔽的是 反馈环 :召回的记忆又被喂回抽取阶段,同一条 "User uses she/her pronouns" 反复重抽多次。

呼应步骤 4 跑 hello world 时看到的"ADD 接连冒出"——刚跑出来很爽,但在生产环境会 失控 。这是 Mem0 不能直接 ship 生产的核心原因。生产侧两条缓解路径:

  • Custom PromptMemory.from_config({"custom_fact_extraction_prompt": "..."}) 替换默认 prompt,明确告诉 LLM 只抽与你业务相关的几类事实

  • Conditional Persistence :在 m.add() 之前用一个轻量分类器过滤,决定是否进入抽取——社区 fork 已有相关实现,issue #4573 评论区也有官方对该问题的迁移指引

2. V3 ADDITIVE_EXTRACTION_PROMPT 比 1.x 更挑剔——单条裸字符串频繁 NOOP

Mem0 2.0.2 的 V3 默认 prompt 比 1.x / 早期 2.0 都更挑剔——单条裸字符串 m.add(" 我用 Python 5 年了 ", user_id="alice") 在 deepseek 上常返回 {"results": []} (NOOP)。 稳妥做法是 messages 数组 + 多轮上下文 + 信息密度高的内容 。这个设计趋势是 Mem0 团队主动收紧"什么算值得记的事实"——同样数据下 gpt-4o-mini 抽取也比早期版本保守。

3. 2.0 是 breaking change——search API 静默 fallback

步骤 2 已经强调过的坑: m.search(query, user_id="alice") (1.x 写法)在 2.0 不会报错——它会被 静默忽略 ,返回全用户混合结果。正确写法是 m.search(query, filters={"user_id":

"alice"}, version="v2") 。网上 2024 年的 Mem0 教程绝大多数是 1.x 的,复制粘贴会以为索引坏 了——实际是 silent fallback。

4. 默认 model 在 OpenAI 协议兼容场景可能失效

Mem0 2.0 OSS 不显式配置时默认 LLM 是 OpenAI gpt-5-mini。在两类场景会出问题:

OpenAI key 余额不足或被限流 ——抽取阶段直接抛 401 / 429,整个 add 失败

  • 走 DeepSeek / Qwen 等 OpenAI 协议兼容 endpoint ——某些模型不支持 GPT-5 系列特有的 max_completion_tokens 参数,会抛参数不支持错

显式指定 LLM provider 是必做项 ——步骤 3 的 Memory.from_config({...}) 配置可以直接复用。

5. m.add() 同步阻塞 4-6 秒——批量加载要预算时间

每次 m.add() 至少触发两次 LLM 调用 + 一次 embedding 调用。5 轮对话约 4-6 秒(deepseek-chat 实测)。批量加载 100 条对话 ≈ 200+ 次 LLM 调用—— 成本与时间不能忽略 。生产环境用 AsyncMemory 异步化(调用方式与 Memory 完全一致)是必备做法。

默认存储位置

默认在 ~/.mem0/ (Qdrant local mode)。演示完想清空重来直接 rm -rf ~/.mem0 即可。生产环境 换远程 Qdrant / Postgres + pgvector 的写法见 §2d。

—— §2c 案例:技术学习 SaaS AI 助教 单 Agent 实例服务 多用户

§2b 跑通了 Mem0 单用户最小骨架。本节把它放到一个真实的 SaaS 产品架构里—— 一个 AI 学习助教平 台,单 Mem0 实例服务多个独立用户 ——并演示 Mem0 在产品级落地时 真正发挥差异化价值的三个核 心功能 (不是 add/search 那种基础):

  1. 四范围记忆模型user_id / agent_id / run_id / app_id )—— 单实例多 scope 隔离,SaaS 产品架构基石

  2. Custom Categories + 按类别筛选检索 —— 让 fact 按业务维度归档,避免噪声干扰精准推荐

  3. get_all + metadata 时间过滤 + delete 治理 —— 生产运营时的批量管理与遗忘策略

这三个功能合起来覆盖了"产品架构 / 检索精准度 / 生产治理"的完整链路,是把 Mem0 真正用起来的"三 件套"——比 add/search 深得多。

真实场景:SaaS 产品架构挑战

设想你在做一个面向技术工程师的 AI 学习助教 SaaS(类似极客时间的内置答疑助手、Coursera Coach、ChatGPT 的 Custom GPT)。 产品架构核心特征

维度说明
Agent实
一个核心Agent模板("友好的技术学习助教"),服务整个平台所有学员
维度说明
用户规模1000+注册用户,每人独立的学习路径+卡点+工具偏好
典型交互学员发起会话 →Agent答疑/推荐/校对 → 关掉、第二天再来
架构约束不可能为每个用户起一个Agent进程(成本爆炸);也不可能把所有用户对话塞同一
context(context window几小时就撑爆+跨用户串台)
真正的需
单Agent实例+多用户独立持久记忆+跨session个性化

这个产品架构在 SaaS 行业是普遍模式——Character.AI、Replika、Notion AI、Cursor 的 Personal Memories 都是同一类。本节用这个真实场景把 Mem0 的三个核心功能演示透。

演示数据集:3 用户 × 50 条 × 5 主题 = 150 条预生成对话

本节用预生成的数据集 experiments/data-gen/output/mem0/conversations.jsonl 。这份数据规 —— 模虽小但 设计有讲究 拆开看:

数据集字段与规模

{"user_id": "alice", "content": "我在用LangChain做RAG,但长文档总是丢上下文,怎么优
化?"}
{"user_id": "bob", "content": "周末写博客时总想引用论文,但看论文效率低,有没有速读工具推
荐?"}
{"user_id": "carol", "content": "我想让 Agent 能自动对比新旧合同版本的差异,类似
"
diff。}

每条 jsonl 包含 user_idcontent 两个字段(精简模式,便于 Mem0 直接喂入)。规模 3 用户 × 50 条 = 150 条

三个用户角色(真实背景)

user_id角色背景数据特征
alice阿里通义实验室基础架构组高级Python
工程师,5年Python经验,RAG优化
方向
覆盖RAG优化/ FastAPI性能/ Qwen-VL
集成/ Multi-Agent学习/ P7晋升/工具
偏好
bob腾讯反欺诈团队Python工程师,4年
Go后端经验,转向LLM应用方向
覆盖反欺诈实时性/ LLM推理延迟/ Go
工具栈/学习路径/周末博客/引用论文
carolAI法律科技公司CTO(曾任腾讯产品经
理+字节技术负责人,清华本+斯坦福
硕)
覆盖合规要求/合同diff工具/国内云部
署/ Node.js + React栈/团队管理/商务
对接

主题分布(覆盖广度)

每个 user 的 50 条对话 横跨 5 大主题 ——这是设计上有意为之的:单一主题(如只覆盖"技术问题")无 法演示 Custom Categories 按类别归档的价值。

主题类别内容样例
技术问题RAG / FastAPI / Qwen-VL / LangChain / Vector DB
工作场景团队协作/系统设计/性能调优/上线流程
工具偏好编辑器(Cursor / VSCode / Vim)/ LLM框架/部署平台
学习与成长学习路径/课程推荐/论文阅读/技能图谱
个人偏好周末活动/沟通风格/时间管理/长期目标

检查数据集就绪

head -3 experiments/data-gen/output/mem0/conversations.jsonl
wc-l experiments/data-gen/output/mem0/conversations.jsonl
python3 -c'
import json
from collections import Counter
d = [json.loads(l) for l in open("experiments/data-
gen/output/mem0/conversations.jsonl")]
print("by user:", Counter(x["user_id"] for x in d))
'

成功标志:3 行 sample 都是 {"user_id": ..., "content": ...} 格式, wc -l 报 150,三个 user 各 50 条。

步骤 1:业内标准做法 + 它在哪三种场景撞墙

讲 Mem0 价值之前先把业内已有的方案讲清楚—— 不上 Mem0 的话,SaaS 多用户场景的标准做法是给 每个用户分配独立的 conversation session ,每次 API 调用拼装该用户的对话历史。这种做法 根本不会 出现跨用户串台 ——因为 user A 的 session 和 user B 的 session 在数据层就完全隔离了。

业内标准做法:Per-user Session + 数据库存对话历史

OpenAI 官方推荐的 Responses API 是这条思路的官方实现;Redis、PostgreSQL、MongoDB 也广泛 用作 conversation history 后端(Azure Redis 官方教程)。一个最小可工作的实现:

# 业内标准做法(不上 Mem0):每个用户独立 session
importjson, redis
fromopenaiimportOpenAI
client=OpenAI(api_key=DEEPSEEK_KEY, base_url="https://api.deepseek.com/v1")
r=redis.Redis()
""
SYSTEM_PROMPT=你是 SaaS 平台的 AI 学习助教,回答用户的技术问题。
defchat(user_id: str, message: str) ->str:
# 1. 从 Redis 拿该用户的对话历史
"
history_key=f"conv:{user_id}
history=json.loads(r.get(history_key) or"[]")
# 2. 加入当前消息
history.append({"role": "user", "content": message})
# 3. 调 LLM,把该用户的全量历史塞 prompt
resp=client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "system", "content": SYSTEM_PROMPT}, *history],
)
answer=resp.choices[0].message.content
# 4. assistant 回复也写回 Redis
history.append({"role": "assistant", "content": answer})
r.set(history_key, json.dumps(history))
returnanswer
# alice 和 bob 的 session 在 Redis 里物理隔离(不同 key),LLM prompt 里也只看到当前用户
的对话
chat("alice", "我喜欢用 Claude Code")
chat("bob", "你之前提过我喜欢什么编辑器?") # bob 的 prompt 里没有 alice 的偏好

这个方案在 用户对话量小、单 session 时长短 时完全够用——大量生产 SaaS 都跑在这上面,不需要任 何记忆框架。

但当业务规模和时长上去之后,这条标准做法会在 三种场景 撞墙——下面三个痛点是 Mem0 在标准做法 之上真正解决的问题, 不是用 Mem0 替代 session,而是叠加在 session 之上

痛点 1:单用户长对话累积 → context 爆炸 + 成本飙升

alice 在你的 SaaS 助教上活跃 30 天,累积 200+ 轮对话(≈ 25k tokens)。每次她发新消息:

  • API 调用塞 25k tokens 历史 + 几百 tokens 新消息 → 每次调用都在为"重传历史"付费

  • 假设每天 5 轮对话 × 30 天 × 1000 用户: 全平台 ~75% 的 token 成本花在重传历史上

  • 单次首 token 延迟随 attention 矩阵规模 O(n²) 增长——25k tokens 的 prompt 比 1k tokens 慢一 个数量级

业内常见对应做法: 滑动窗口 (只留最近 20 轮)+ 手动摘要 前面对话(Context Window Management Strategies)。但滑动窗口会丢早期重要 fact(如"alice 是阿里通义的 Python 工程师"),手动摘要的质 量决定记忆质量——做不好就是 alice 第 50 轮被问"你叫什么名字"。

痛点 2:长 context 下 context rot → 召回准确率下降

即使学员愿意为长 context 付钱, LLM 在长 context 里的召回精度本身就在下降 ——这是 Anthropic 2026 官方研究的 context rot 现象(§1b 已展开)。在 SaaS 助教场景:

alice 周一聊:
  • " 我在阿里通义实验室做 Python 工程师,调 long-doc RAG 用 LangChain"

  • " 我特别喜欢 Cursor ,因为 LSP 集成最好 " ... 累积到 50 轮 ...

alice 周五新会话直接问:
"我之前提过我喜欢什么编辑器?"
业内标准做法:把周一到周四全部 50 轮历史拼成 messages 数组传 LLM
后果:context rot——25k tokens 中召回特定 fact 的准确率约 70-80%(Claude Opus 4.6 在 1M
token 实测 MRCR v2 准确率 76%)
学员体验:每 5 个学员就有 1 个被回答"你之前没提过"——明明历史里有

痛点 3:多端 / 多 Agent 状态同步 → 标准 session 表达不出层次

业内标准 session 是 一份扁平的 conversation history ——它表达不出"哪些是用户长期偏好(跨端共 享)、哪些是当前 Agent 的 working state(不跨 Agent)、哪些是本次会话临时状态(结束即丢)"这 种层次。

具体场景:

alice 在 web 端用「助教 Agent」聊 RAG(应该跨端共享 alice 的 Python 偏好 + 助教 working
state)
  • ↓ 切到 mobile 端,用「推荐 Agent 」找 Multi-Agent 课程
业内做法:所有内容都在一份 alice 的 conversation history 里
后果:
  • alice 在 web 端 " 调 LangChain" 的卡点污染 mobile 端的「推荐 Agent 」 prompt → 错误推荐 LangChain 入门课

  • 如果想隔离 Agent ,必须自己额外建一层 agent_id → conv_id 映射,工程量翻倍

  • 跨 Agent 共享 alice 的 喜欢 Python + 简单部署 偏好,又要自己再建一层 user_preferences 表

Mem0 的真正位置

Mem0 不是替代 per-user session(那个继续用 Redis / Postgres),而是 叠加在标准 session 之上 的"结构化长期记忆层"

角色业内标准做法Mem0在其上叠加什么
短期对话历史(当前
会话/最近N轮)
Redis + conversation_id不替代——继续用session
长期用户事实(偏好/
身份/长期目标)
❌ 没有——只能让LLM在长
context中自己找
✅Mem0抽取成结构化fact,按
query智能召回top-k(5-10条)
多 Agent /多端层次❌ 扁平conversation history✅ 四范围记忆模型(user_id /
agent_id / run_id / app_id)
类别归档与精准检索❌ 无✅Custom Categories
批量治理 /衰减清理❌ 手动写脚本✅get_all + metadata时间过滤+
delete

真正的演进路径

方案 0:什么都不做,每次 API 调用都重传全量历史 ← 业内门槛最低
方案 1:滑动窗口 + 手动摘要 ← 业内中级方案
方案 2:RAG over conversation history(向量化历史 + 召回) ← 业内进阶方案
方案 3:用 Mem0 等专门记忆框架 ← 本节要演示的

下面三个步骤把方案 0/1/2 解决不了的问题用 Mem0 跑一遍—— 注意演示的 alice / bob / carol 三人对 话是为了把"长期 fact 抽取 + 多用户 + 多 Agent 隔离"等场景压缩在公开课时长内可演示 ,不是用三个 用户 demo Mem0 解决"用户隔离"(用户隔离 Redis 已经做了)。

—— 步骤 2:基础 用 m.add() 把对话抽成结构化长期 fact

针对步骤 1 的 痛点 1+2 (长对话 context 爆炸 + context rot),Mem0 的核心动作是: 让对话经过抽取 阶段沉淀为结构化长期 fact ——之后 LLM 不再看原始对话历史,只看 Mem0 召回的几条相关 fact。下 面给三个用户各喂入 6 条"自我介绍 + 工作场景 + 偏好"对话,让 Mem0 真做一次抽取,看看长 context 是怎么被压缩成 fact 库的。

注: user_id 在这里的作用是"给 fact 打用户归属标签"——后续 m.search() 时按 user_id 拉回该用户的 fact 库,与步骤 1 的 Redis session 隔离机制是 两个维度(前者管"长期 fact 归属"、后者管「短期对话历史归属」)。两者叠加使用——不是替代关系。

# demo_2c_resolution.py 的核心
PROFILES= {
"alice": [
"我是华中科技大学本科毕业,2021 年校招进的阿里。",
"我在通义实验室基础架构组,做高级 Python 工程师。",
"我特别喜欢用 Claude Code 来做架构思考,比 Cursor 顺手。",
"我不喜欢过度抽象的框架,黑盒系统让我头疼。",
"我正在负责一个内部知识 Agent,给销售团队用,要支持多轮对话。",
"我今年想晋升 P7,需要拿出一个完整的 Multi-Agent 项目。",
],
"bob": [
"我是 Bob Chen,腾讯反欺诈团队的 Python 工程师,今年 31 岁。",
"我后端用 Go 写了四年多,调优经验挺多,但大模型这块完全新手上路。",
"反欺诈需要实时,LLM 推理延迟不能超过 200ms。",
# ... 6 条
],
"carol": [
"我本科清华,硕士斯坦福 CS,回国后做过腾讯产品经理和字节技术负责人。",
# ... 6 条
],
}
foruid, itemsinPROFILES.items():
msgs= []
fortxt, replyinzip(items, ASSIST_REPLIES[uid]):
msgs.append({"role": "user", "content": txt})
msgs.append({"role": "assistant", "content": reply})
res=m.add(msgs, user_id=uid) # ← 关键:user_id 把三人完全隔离
facts= [evforevinres["results"] ifev["event"] =="ADD"]

关键操作 :必须 rm -rf ~/.mem0 /private/tmp/qdrant 后再跑。Mem0 默认把元数据放在 ~/.mem0 ,但 qdrant 向量库默认存在 /tmp/qdrant ——只清前者会让旧 fact 残留并污染新加 载的 existing memories,三个用户里只有第一个能正常 ADD,后两个会被 LLM 误判"已存在"。

运行结果(21 条 fact 全部完成中→英自动翻译):

值得逐项看的几个点:

  1. alice 的 7 条 fact 把 6 条对话拆成更细的事实。最后一条对话「想晋升 P7 + Multi-Agent 项目」被 拆成"P7 目标"和"需要交付一个 Multi-Agent 项目"两条 fact。这是 Mem0 V3 的"信息原子化"特性 ——一句话里多个独立维度会被拆成多条 fact。

  2. bob 的 7 条 fact 中,"31 岁 + Python 工程师 + 腾讯反欺诈"被合并成一条信息密集的 fact。同一 句话里 强相关 的属性会被打包, 弱相关 的会被分拆——分合标准由 LLM 在抽取时即时判断。

  3. carol 的 7 条 fact 全部以 "Carol" 开头(不是 "User"),因为她在第一条就给出了名字。bob 同样 给了名字但只有第一条用 "Bob Chen",后续都用 "User"——这种命名一致性的小不稳定,是 Mem0 默认 prompt 在 deepseek 上的常见现象,不会影响检索。

  4. 全部 21 条 fact 都是英文 ——这是 Mem0 默认 prompt(V3 ADDITIVE_EXTRACTION_PROMPT) 的下游效果,源码里的 use_input_language 默认 False。需要中文 fact 的话要手动构造 custom prompt 或换用 mem0.configs.prompts 里的旧版 USER_MEMORY_EXTRACTION_PROMPT

—— 步骤 3:基础验证 用 m.search() 按用户拉 top-k 相关 fact

步骤 2 已经把对话沉淀进 fact 库。下面验证关键的读取行为—— 给同一句 query,Mem0 在每个用户的 fact 库里独立做语义检索,只返回该用户的相关 fact 。这一步对应步骤 1 痛点 2 的解法: 主 LLM 的 prompt 不再塞全量对话历史,只塞 top-k 召回的相关 fact

# demo_2c_search_isolation.py
""
QUERY=工作中遇到的关键技术挑战是什么?
foruidin ("alice", "bob", "carol"):
hits=m.search(QUERY, filters={"user_id": uid}, version="v2")
forhinhits["results"][:3]:
print(f" score={h['score']:.3f}{h['memory'][:90]}")

每个用户都拿到与 query 相关的 top-3 fact,且 只来自自己的 fact 库

user_idtop-3 fact主题
alice阿里通义实验室高级Python工程师/销售团队知识Agent
bob转AI团队主导反欺诈系统LLM化重构/ Go四年后端经验
carolNode.js + React技术栈/腾讯字节经历/国内合规要求

到这里步骤 1 痛点 1+2 的核心闭环已经跑通—— 对话经过抽取沉淀为 fact、按 query 智能召回 top-k ——LLM 不再需要在 25k tokens 长 context 中自己找东西。alice 累积 200 轮对话后再来问问题,主 LLM 的 prompt 只需要 5-10 条相关 fact(约 500-1000 tokens),既省钱又避开了 context rot。

2.0 API 关键铁律 :必须写 m.search(query, filters={"user_id": uid}, version="v2") 。 Mem0 1.x 的 m.search(query, user_id=uid) 在 2.0 不会报错——它会返回 全用户的混合结 果 。这个 silent fallback 是 §2b 提过的、在升级 Mem0 版本时最容易踩的坑。

到这里基础"抽取 + 召回"闭环已经搞定,但步骤 1 的 痛点 3 (多 Agent / 多端层次表达不出)还没 解决—— user_id 只是 Mem0 四范围记忆模型的第一个维度。下面三个步骤展开 Mem0 在产品 —— 级 真正发挥差异化价值的三个核心功能 四范围记忆模型 / Custom Categories / 生产治理。

步骤 4:核心功能 ① — 四范围记忆模型(user_id / agent_id / run_id / app_id)

user_id 只是 Mem0 四范围记忆模型的第一个维度。SaaS 产品架构通常需要 更细颗粒 ——同一个用户在不同 Agent / 不同会话 / 不同 App 端的状态都应该独立隔离。Mem0 的四范围让单个实例同时承载这四个隔离维度。

四个 scope 的语义

Scope隔离粒度典型应用
user_id一个用户独立记忆跨session持久化的个人偏好(已在步骤
2-3演示)
agent_id同一用户下不同Agent的working
state隔离
SaaS平台多Agent服务(助教/推荐/校
对Agent)
Scope隔离粒度典型应用
run_id单次任务执行的短期记忆单次答疑会话的working memory,结束
后可丢弃
app_id应用级命名空间同一公司web端/ mobile端/桌面端隔离

生产场景下的组合用法

# 学员 alice 在 web 端用助教 Agent 发起一次答疑会话
m.add(messages,
user_id="alice",
agent_id="tutor",
run_id="session-2026-05-14-001",
app_id="learnsmart-web")
# 检索时按业务需求组合 scope
# 案例 A:学员个人偏好(跨 agent / 跨 run,长期个性化的核心数据)
""
m.search(学习偏好, filters={"user_id": "alice"}, version="v2")
# 案例 B:本次答疑会话的 working memory(短期,run 结束后可清理)
""
m.search(刚才问的问题, filters={
"user_id": "alice",
"run_id": "session-2026-05-14-001"
}, version="v2")
# 案例 C:alice 在助教 Agent 下的所有交互(排除推荐 / 校对 Agent 的污染)
""
m.search(助教对话历史, filters={
"user_id": "alice",
"agent_id": "tutor"
}, version="v2")

演示:用同一用户喂入两个 agent_id 看 working state 隔离

# alice 用助教 Agent 学习 long-doc RAG
m.add([
{"role": "user", "content": "我在调 LangChain 的 long-doc RAG,效果不好"},
{"role": "assistant", "content": "建议试试 hierarchical chunking..."},
], user_id="alice", agent_id="tutor")
# alice 同时用推荐 Agent 找 Multi-Agent 系统资源
m.add([
{"role": "user", "content": "推荐一些 Multi-Agent 系统的好课"},
{"role": "assistant", "content": "..."},
], user_id="alice", agent_id="recommender")
# 助教 Agent 下检索:拿到 long-doc RAG / hierarchical chunking 相关 fact
print(m.search("alice 在学什么",
filters={"user_id": "alice", "agent_id": "tutor"}, version="v2"))
# 推荐 Agent 下检索:拿到 Multi-Agent 相关 fact
print(m.search("alice 在学什么",
filters={"user_id": "alice", "agent_id": "recommender"},
version="v2"))
# 不限 agent 检索:跨 Agent 看 alice 的全部学习状态(适用于跨 Agent 协同)
print(m.search("alice 的学习全貌",
filters={"user_id": "alice"}, version="v2"))

为什么这是 SaaS 产品架构基石

不用 agent_id 的话,平台所有 Agent 共享 alice 的同一份 fact 库—— 推荐 Agent 会拿到 alice 在助教 Agent 里的"调试 LangChain"卡点 ,错误推荐"LangChain 入门课"——但 alice 此刻在推荐 Agent 下的 " 目标是"Multi-Agent 系统 。 agent_id 隔离让每个 Agent 的 working state 不互相污染, 同时 user_id 层的个人偏好依然跨 Agent 共享 ——这种"个人偏好共享 + 业务状态独立"的双层结构是 SaaS Agent 产品架构的关键。

run_id 用于亚秒级响应场景——一次答疑产生的临时 working memory("刚才咱们讨论到了哪一 步")在 run 结束时清理,避免污染长期记忆。 app_id 用于跨端隔离——web 端的对话和 mobile 端的 对话可以独立,也可以通过同 user_id 在跨 app 时共享个人档案。

步骤 5:核心功能 ② — Custom Categories + 按类别筛选检索

默认 Mem0 抽出的 fact 是 平铺的 ——alice 的 50 条对话被抽成 50+ 条 fact,它们在向量库里没有显式 分类。检索时只能按"语义相似度 + recency"召回,没法按业务维度精准筛选。

举个具体痛点:Agent 想给 alice 推荐学习资料时,它只想看 alice 的 学习历史 (已掌握什么 / 卡在哪 里),不想看 alice 的 周末活动偏好 —— 但默认 search 不区分这两类,会被无关 fact 干扰,推荐质量 打折。

Custom Categories 是 Mem0 给生产环境的工程化答案 —— 在 m.add() 时声明业务类别,检索时按 metadata 筛选。

# 1. 配置时声明自定义类别
config= {
"llm": {...},
"embedder": {...},
"custom_categories": [
{"name": "technical_stack", "description": "技术栈偏好(语言、框架、工
具)"},
{"name": "learning_history", "description": "学习历史(已掌握 / 卡在哪 /
学习路径)"},
{"name": "personal_preferences","description": "个人偏好(沟通风格、时间、长期
目标)"},
{"name": "work_context", "description": "工作场景(团队 / 项目 / 上线
流程)"},
],
}
m=Memory.from_config(config)
# 2. 喂入对话时让 LLM 同时归类
m.add([
{"role": "user", "content": "我特别喜欢 Cursor,因为 LSP 集成最好"},
{"role": "assistant", "content": "..."},
], user_id="alice")
# 抽出的 fact: "User prefers Cursor for LSP integration"
# 自动归类: categories=['technical_stack']
m.add([
{"role": "user", "content": "我今年想拿 P7,需要交付一个 Multi-Agent 项目"},
{"role": "assistant", "content": "..."},
], user_id="alice")
# 抽出的 fact: "User aims for P7 promotion and needs a Multi-Agent project"
# 自动归类: categories=['learning_history', 'personal_preferences']
# 3. 检索时按类别精准筛选
recommend_context=m.search(
"推荐学习资料",
filters={"user_id": "alice", "categories": ["learning_history"]},
version="v2"
)
# → 只召回学习历史相关 fact,不会被工具偏好 / 周末活动等无关内容干扰
style_context=m.search(
"用户沟通偏好",
filters={"user_id": "alice", "categories": ["personal_preferences"]},
version="v2"
)
# → 用于 Agent 调整回复风格
# 跨类别检索(业务交叉场景)
plan_context=m.search(
"学习规划",
filters={"user_id": "alice", "categories": ["learning_history",
"work_context"]},
version="v2"
)
# → 同时召回学习历史 + 工作背景,给 Agent 综合视角

对比:不用 categories 时的噪声

# 默认 search (不带 categories ) " " hits = m.search( 推荐学习资料 , filters={"user_id": "alice"}, version="v2") # top-5 结果里混入: # "User uses Cursor"technical_stack (不该出现) # "User watches funny videos on weekends"personal_preferences (不该出现) # "User wants P7 promotion"learning_history (该出现) # "User has 5 years Python experience"technical_stack (边缘相关) # "User joins Alibaba via 2021 campus recruitment"work_context (不该出现) # 主 LLM 拿到这堆混杂内容,推荐质量打折

为什么 categories 是生产必备

回到 §1c 局限 4 的 97.8% junk 问题——根因是默认 prompt 把"什么值得记"全交给 LLM。Custom Categories 是对这条局限的工程化抑制: 把"按业务维度分类"作为抽取阶段的硬约束 ,让 LLM 在抽 fact 时同时决定它属于哪个业务类别。生产环境通常用 4-8 个类别,覆盖 90% 业务场景——剩下的"未分类" fact 走默认通道,不影响主路径。

步骤 6:核心功能 ③ — get_all + metadata 时间过滤 + delete 治理(结合信息演化)

生产环境运营 Mem0 时绕不开两件事—— 已有 fact 的批量管理 (按时间窗 / 按 score / 按类别清理)+ 新旧矛盾事实的治理 (不会自动 DELETE 时怎么办)。这一步把这两件事串成一条完整治理链路演示。

6.1 信息演化场景:alice 跳槽

业务场景里用户的状态会变:alice 升 P7、跳槽、换工具栈。Mem0 怎么处理这些"和旧 fact 矛盾的新事实"?

# demo_2c_evolution.py
# 跳槽前 search
"
hits_before=m.search("Alice 现在在哪家公司?,
filters={"user_id": "alice"}, version="v2")
# 喂入新事实
m.add([
{"role": "user", "content": "其实我已经从阿里离职了,下个月入职 Anthropic 中国办公
室。"},
{"role": "assistant", "content": "恭喜!Anthropic 中国办公室是个新机会。"},
], user_id="alice")
# 跳槽后再 search 同一问题
"
hits_after=m.search("Alice 现在在哪家公司?,
filters={"user_id": "alice"}, version="v2")

观察结果:

  1. 喂入"我从阿里离职"→ Mem0 ADD 一条新 fact "User left Alibaba and will join Anthropic's China office in June 2026"

  2. 旧 fact "User works at Alibaba's Tongyi Lab" 仍然存在 ,没有被自动 DELETE。

  3. 跳槽后 search 同一问题,top-1 是新 fact(score 0.493),top-2 是旧 fact(score 0.414)—— 两条矛盾事实并存,按相关性排序。

这是 Mem0 2.0 V3 ADDITIVE_EXTRACTION_PROMPT 的设计取舍——只做 ADD,不做

UPDATE/DELETE 。源码里这个 prompt 的第一句就是 "Your sole operation is ADD" 。1.x 时代有自动 UPDATE/DELETE 决策(FACT_RETRIEVAL_PROMPT + DEFAULT_UPDATE_MEMORY_PROMPT 两步),2.0 把它拿掉换成 ADD-only 单步管线,理由是"召回率优先于一致性"。

代价是:业务方需要自己负责清理过期 fact。如果 Agent 系统对一致性敏感(比如要根据"用户当前公司"路由到不同合规分区),不能直接用 Mem0 的 search 结果——要自己加一层"按 created_at 取最新 + LLM 摘要去重"的后处理,或者周期性扫一遍 history 调 m.delete()

# 手动清旧 fact 的最小写法

old_alibaba=next(hforhinhits_after["results"]
if"Tongyi Lab"inh["memory"])
m.delete(memory_id=old_alibaba["id"])

6.2 批量治理:get_all + metadata 时间过滤

生产环境的治理不能靠人工逐条 delete——下面是 SaaS 平台运营时常用的批量治理脚本骨架:

# 1. 列出某用户的全部 fact(按 created_at 排序)
all_facts=m.get_all(filters={"user_id": "alice"}, version="v2")
print(f"alice 当前共{len(all_facts['results'])}条 fact")
forfinall_facts["results"]:
# 每条 fact 自带 metadata:id / memory / categories / score / created_at /
updated_at
print(f" [{f['created_at'][:10]}] {f['memory'][:80]}")
# 2. 按时间窗清理旧 fact(如:清理 90 天前的低价值 fact)
fromdatetimeimportdatetime, timedelta, timezone
cutoff=datetime.now(timezone.utc) -timedelta(days=90)
forfinall_facts["results"]:
created=datetime.fromisoformat(f["created_at"].replace("Z", "+00:00"))
ifcreated<cutoffandf.get("score", 1.0) <0.5:
# 90 天前 + 低重要性 → 清理
m.delete(memory_id=f["id"])
# 3. 按类别批量重新分类(Custom Categories 升级时常用)
# 例:把 'personal_preferences' 中关于"工具偏好"的 fact 重新归到 'technical_stack'
""
hits=m.search(工具偏好, filters={
"user_id": "alice",
"categories": ["personal_preferences"]
}, version="v2")
forhinhits["results"][:10]:
# 重新喂入,让 LLM 重新分类(带新的 categories 配置)
m.delete(memory_id=h["id"])
m.add([{"role": "user", "content": h["memory"]}],
user_id="alice") # 新配置下重抽 + 自动归类

6.3 治理对应 §1c 局限 4 遗忘策略

回到 §1c 局限 4 那条铁律—— 没有任何记忆系统完整解决遗忘问题 (MemoryAgentBench 实测 ≤ 7% 准确率)。Mem0 的治理方案不是自动遗忘,而是 给业务方完整的运营接口get_all / metadata 时间过滤 / delete / 重新分类)。生产侧通常配 cron 定期跑治理脚本,结合 §1c 介绍的 Generative Agents 三因子检索公式(recency × importance × relevance)做"按 score + 时间窗清理"——这就是把"自动遗忘"问题转化为"工程化治理"问题的标准范式。

步骤 7:把 Mem0 嵌进 SaaS 助教 Agent 的真实代码骨架

把前面 6 步拼起来——一个完整的"基于 Mem0 的 SaaS 助教 Agent"骨架。每次学员问问题:先用四范围 filter 拉本用户的相关 fact,拼进 system prompt,再让 LLM 回答;最后把这一轮对话写回 Mem0。

defserve_learner(user_id: str, question: str,
agent_id: str="tutor",
run_id: str=None) ->str:
# 1. 从 Mem0 拉本用户的相关历史 fact(四范围 filter 组合)
# user_id 必传 → 跨 session 个性化的核心
# agent_id 可选 → 隔离不同 Agent(助教 vs 推荐 vs 校对)的 working state
# categories 可选 → 按业务维度精准筛选(推荐用 learning_history,闲聊用
personal_preferences)
filters= {"user_id": user_id, "agent_id": agent_id}
if"推荐"inquestionor"学"inquestion:
filters["categories"] = ["learning_history", "technical_stack"]
hits=m.search(question, filters=filters, version="v2")
"
context="\n".join(f"- {h['memory']}forhinhits["results"][:5])
# 2. 构造 system prompt(只包含本用户、本 agent_id 下的相关 fact)
system=f"""你是 SaaS 平台的 AI 学习助教,正在服务用户{user_id}。
以下是关于该用户的已知事实:
{context}
请按这些事实个性化响应,不要混入其他用户的信息,不要泛泛回答。"""
# 3. 调 LLM 生成答复
resp=ds.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": system},
{"role": "user", "content": question},
],
temperature=0.0,
)
answer=resp.choices[0].message.content
# 4. 把这一轮对话写回 Mem0,作为后续记忆增量
# 带 run_id 让本次会话的临时 working memory 可被独立清理
m.add([
{"role": "user", "content": question},
{"role": "assistant", "content": answer},
], user_id=user_id, agent_id=agent_id, run_id=run_id)
returnanswer
# 用 Bob 身份在助教 Agent 下提问(呼应步骤 1 的串台案例)
""
print(serve_learner("bob", 你之前提过我喜欢用什么编辑器?, agent_id="tutor"))

真实运行结果:

观察这次的输出:

  1. Mem0 检索到的 4 条 fact 全部属于 Bob 自己 ——Tencent 反欺诈 Python 工程师、不喜欢 LangChain、4 年 Go 后端经验、LLM 新手。Alice 的 Cursor / Claude Code 偏好和 Carol 的 Node.js 技术栈完全没出现。

  2. Agent 回答基于这 4 条 fact 推断 Bob 用 Vim ——这是 LLM 基于"Go 工程师 + 反对重 Python 框架 + 性能调优偏好"做出的合理推断(Vim 在 Go 圈是常见选择)。Bob 的 fact 里其实没明确提过编辑器,但推断方向正确, 没有出现步骤 1 那种把 Alice 的 Claude Code 偏好张冠李戴 的串台。

回到步骤 1 的串台案例做对照:

维度步骤 1朴素方案步骤 5接入 Mem0
同一问题("Bob之前提过喜
欢什么编辑器")
Claude Code(Alice的偏好)Vim(基于Bob的Go +性
能偏好推断)
是否串台
上下文长度9条全用户历史4条Bob专属fact
可扩展性用户越多越糟(O(N) context增
长+ context rot)
与用户数无关(每次
search只取top-k)

一个生产侧的注意 :步骤 4 的 m.add() 会触发一次 LLM 抽取调用(≈3-5 秒)。如果客服 Agent —— 要求亚秒级响应,建议把这一步异步化 asyncio.create_task(m_async.add(...)) 后立刻返回 answer 给用户,让记忆写入在后台跑。Mem0 提供了 AsyncMemory 类,调用方式与 Memory 完全一致。

本节做了什么 / 没做什么 + 适用场景判断

本节产出汇总

演示了演示要点
朴素方案在SaaS架构下必然撞墙system prompt塞全用户上下文 → 串台+ context
rot
演示了演示要点
基础:
user_id 单维度隔离
同一Mem0实例下3用户独立fact库
核心功能 ① 四范围记忆模型user_id/
agent_id/
run_id/
app_id 组合,
SaaS产品架构基石
核心功能 ②Custom Categories +按类别
筛选
抽取阶段强制业务归类,检索精准化
核心功能 ③
get_all+ metadata时间过
滤+
delete 治理
生产运营接口,把"自动遗忘"转化为"工程化治理"
完整SaaS助教Agent集成骨架serve_learner 函数+四范围filter + categories
筛选

适用场景判断

Mem0 适合的场景 ——核心特征是"个人偏好 / 跨 session 个性化 / SaaS 多用户":

  • ✅ AI 学习助教 / Custom GPT / 个人 AI 助手(Character.AI 类)

  • ✅ 客服 SaaS(智能客服记住每个用户的偏好、历史问题)

  • ✅ 推荐系统(基于 user_id 下的长期兴趣画像生成推荐)

  • ✅ 多 Agent 协作(不同 Agent 共享个人偏好,独立 working state)

  • ✅ Anthropic Memory Tool / OpenAI Conversation memory 类需求的开源替代

Mem0 不太适合的场景 —— 用别的派别更好:

  • 强一致性的状态机系统 (如金融交易 / 合规审计)—— ADD-only 副作用 + 矛盾事实并存会出错;选 Letta 或 Zep(temporal-graph)

  • 知识管理 / 个人 brain repo (如 Obsidian 风格的笔记沉淀)—— 没有可读 markdown / 没有 git 可控;选 GBrain

  • stateful agent runtime (如长任务陪跑、可观测的 Memory Pressure 触发)—— 没有 working context 实时可见;选 Letta

  • 重型 multi-hop 关系推理 (如知识图谱构建)—— OSS 默认无 graph store;选 Cognee 或 Zep

  • 审计 / 合规要追溯每条 fact 的写入历史 —— m.add() 黑盒,过程不可追溯;选文档派

  • (GBrain / OpenClaw memory-wiki)

§2d 速查里会列出 Mem0 的所有"没展开"接口( m.update() / m.get_all() 完整参数 / 远程 Qdrant 切换 / Mem0 Cloud 接入 / Graph Memory Pro 特性),方便复用本节代码骨架时按需扩展。

§2d Mem0 速查

§2b / §2c 演示了 Mem0 三个核心 API( add / search / delete )和 user_id 隔离一个维度。本节把 Mem0 的其余能力——三级隔离、向量后端切换、Mem0 Cloud、主流集成——压缩成速查表,方便后续开发时按图索骥。

三级记忆隔离

Mem0 的 add / search / get_all / delete 都接收三个独立的 scope 字段,组合使用就是三级隔离:

scope字
作用典型业务场景
user_id隔离不同终端用户的记忆客服Agent服务多个客户、Copilot服务多个
开发者
agent_id隔离同一用户接入的多个Agent一个用户既用「邮件助手」又用「代码助
手」,两边的事实分库
run_id隔离同一(user_id, agent_id)的
多个session
长任务陪跑场景下,每个task跑一个独立
run,避免跨任务串台
# 示例:alice 同时使用「邮件助手」和「代码助手」两个 Agent
m.add(messages, user_id="alice", agent_id="email_assistant")
m.add(messages, user_id="alice", agent_id="code_assistant")
# search 时只看「代码助手」的事实,不会捞到邮件助手的内容
"
m.search("alice 的工具偏好, filters={"user_id": "alice", "agent_id":
"code_assistant"}, version="v2")
# 加 run_id 进一步隔离到当前 task
m.search("...", filters={"user_id": "alice", "agent_id": "code_assistant",
"run_id": "task_2026_q1_refactor"}, version="v2")

隔离粒度由调用方决定 ——Mem0 不强制要求三层都填。 add 时填了哪些字段, search 时就用相同字段过滤,规则保持对称即可。

完整 API 表

----- Start of picture text -----
API 作用关键参数
llm / embedder / vector_store
创建 Memory
Memory.from_config(config) / history_db_path /
实例
custom_instructions
写入新事实
m.add(messages, user_id,
(默认会触发 infer=False 跳过抽取直接存原文
agent_id?, run_id?, metadata?)
LLM 抽取)
m.search(query, filters, filters 接 user/agent/run 三 ID
向量检索
version="v2", limit=5) 任意组合
m.get_all(filters, 列出 scope 内
用于审计 / 周期清理
version="v2") 所有 fact
修改某条 fact
m.update(memory_id, data) 业务侧自己负责
的内容
----- End of picture text -----

API作用关键参数
m.delete(memory_id)删除某条fact配合
get_all 做批量清理
m.delete_all(filters)按scope批量
删除
用户注销/ GDPR数据擦除
m.history(memory_id)查某条fact的
修改历史
审计/调试
m.reset()清空整个
Memory实例
测试场景常用

向量后端切换

Mem0 默认用 Qdrant 本地模式(写到 /tmp/qdrant ),可换成下面任意后端,写法都是改 config["vector_store"]

后端provider字段适用
Qdrant Local(默认)qdrant(带path)单机开发/ Demo
Qdrant Cloud /远程qdrant(带
host/port/api_key)
生产,要持久化+多实
例共享
Postgres + pgvectorpgvector已有PG集群、想统一
存储栈
Pineconepinecone想要SaaS、不想自管
vector DB
Weaviate / Milvus / OpenSearch /
Redis / MongoDB
同名provider已有对应栈、按
namespace复用
Chroma / FAISSchroma/
faiss
离线场景/嵌入式

切换写法(以 Postgres + pgvector 为例):

config["vector_store"] = {
"provider": "pgvector",
"config": {
"host": "localhost", "port": 5432,
"user": "mem0", "password": "...", "database": "mem0_prod",
"collection_name": "mem0_alice",
"embedding_model_dims": 1536, # text-embedding-3-small 的维度
},
}

LLM 与 Embedding 切换

LLM 与 embedding 的切换原则一致——Mem0 把它们抽象成 provider + OpenAI 兼容 config:

provider字段实际后端备注
openaiOpenAI /任何OpenAI协议兼容(DeepSeek /
Qwen / Anthropic via Compat /自部署vLLM)
本课用法
anthropicAnthropic原生API不走OpenAI
compat
geminiGoogle Gemini原生API
together/
groq/
xai
/
litellm
各家原生SDK见mem0
docs
ollama本地Ollama完全离线场景
huggingfaceHF Transformers本地自部署小模型

国内常见组合 :LLM 用 deepseek-chat (通过 openai provider 配 base_url)+ embedding 用 text-embedding-v3 (Qwen DashScope,OpenAI 兼容模式)→ 全栈国内 API。本课用 OpenAI embedding 是因为它的多语种 1536 维做 demo 最稳,生产换 Qwen embedding 仅需改 config。

OSS 与 Mem0 Cloud 的差异

维度OSS(自托管)Mem0 Cloud(SaaS)
部署pip install mem0ai
即用

MemoryClient(api_key=...)
运维自己管vector DB /
Postgres /备份
全托管
鉴权无内置,自己加OAuth 2.0 / API key体系
DashboardWeb UI看/改fact,含审计日志
周期清理自己写cron内置auto-cleanup策略
Graph
Memory
2.0已移除仍提供(基于Neo4j)
合规看自己部署的环境SOC 2 Type I已认证、HIPAA-ready、SOC 2
Type II审计中
价格免费按fact数/ API调用计费
适合开发期/小规模/内网部
生产期/多租户SaaS /需合规凭证

从 OSS 切到 Cloud 的代码改动 :把 Memory.from_config(config) 换成

MemoryClient(api_key=os.environ["MEM0_API_KEY"]) ,其余 add / search / delete 调 用方式完全一致。

Graph Memory 的当前状态

§2a 提到的「Mem0^g 图增强」需要更正: Mem0 OSS 2.0 已移除 graph_store enable_graph 配置项 ,本地 Neo4j 集成不再支持。Graph Memory 现在仅在 Mem0 Cloud 提供。

如果业务确实需要 entity-relationship 级别的图查询("Alice 的下属管理的下属是谁"这种 traversal 题),当前两条路径:

  1. 切到 Mem0 Cloud,用其 graph 功能。

  2. 用 Mem0 OSS 存事实 + 自己另搭 Neo4j / KuzuDB 做 entity 关系层,两边按 memory_id 关联。

主流集成清单

Mem0 已经做了一批官方集成,开发时可以直接 pip install 接入而不用自己写 adapter:

集成对象包名说明
OpenAI Agents SDK内置把Mem0作为Agent的memory tool
LangChain /
LangGraph
langchain-mem0LangChain Memory interface的Mem0
实现
LlamaIndex内置chat memoryMem0Memory
Vercel AI SDK内置providerTS / JS项目
CrewAI内置memory
backend
多Agent协作
Pydantic AI内置结构化输出Agent
MCP servermem0-mcp给Claude Code /任何MCP客户端用

什么时候不该用 Mem0

把"什么时候用"反过来——以下场景 Mem0 不是首选:

场景更适合
主要需求是RAG(查静态知识库,不需要"记用
户偏好")
直接用向量库+ LangChain RetrievalQA
需要Agent自己掌控记忆何时page in / outLetta(OS派)
业务对一致性敏感、不能容忍"新旧fact共存"自己写fact层,或改用Letta的working
context block
主要数据载体是markdown /文档/代码GBrain(文档派),Mem0抽取后丢失原文结
单次会话足够,不需要跨session直接用LLM的context window

场景

全离线 / 不能调云端 LLM 抽取

Letta self-host + 本地 LLM,或 GBrain

更适合

官方文档与社区资源

资源URL用途
项目主页mem0.ai综合介绍、Cloud注册
官方文档docs.mem0.aiAPI ref、集成指南、迁移指
GitHub仓库mem0ai/mem0源码、Issue、Release
Notes
OSS V2→V3迁移docs.mem0.ai/migration/oss-v2-to-v31.x升2.0的breaking
change列表
安全合规mem0.ai/securitySOC 2 / HIPAA文档
Series A公告mem0.ai/series-a$24M融资详情、投资方背
论文arXiv 2504.19413Mem0 vs full-context p95
latency论证
State of AI Agent
Memory 2026
mem0.ai/blog/state-of-ai-agent-
memory-2026
Mem0团队对2026年记忆
赛道全景的判断

一句话场景推荐

业务是否上 Mem0备注
客服Agent的多用户偏好直接上user_id 隔离开箱即用
Copilot跨会话记开发者偏好直接上agent_id 区分不同Copilot
多Agent共享一个客户的"客户
档案"
上+自己加去重
默认ADD-only会累积冗余
Agent的long-task内部状态不上——用LettaMem0做不了working context
已有的markdown知识库要变
Agent记忆
不上——用
GBrain
Mem0抽取后会丢原文结构
需要审计每条记忆的修改历史OSS自己做/上
Cloud
OSS的
m.history() 够基础场景,复
杂审计需Cloud