ReMe vs Mem0 源码对比:两种 AI 记忆管理方案的架构差异
AI记忆管理框架对比:ReMe与Mem0 ReMe和Mem0是当前开源的两种典型AI记忆管理框架,定位和设计哲学存在显著差异。ReMe由AgentScope团队开发,专注于Agent的上下文管理,将记忆视为对话压缩的副产品,采用Markdown文件存储,通过FileWatcher异步更新向量索引。Mem0由Y Combinator孵化,定位为AI应用的个性化记忆层,采用显式调用方式管理结构化记忆,
导读:ReMe 和 Mem0 是当前开源社区中两个代表性的 AI 记忆管理框架。ReMe 由 AgentScope 团队开发,聚焦于 Agent 的上下文管理和文件化工作记忆;Mem0(“mem-zero”)由 Y Combinator S24 孵化,定位为 AI 应用的"记忆层",主打用户画像和个性化交互。本文从源码层面对比两者的架构设计,帮助开发者理解它们的定位差异,以便在自己的 Agent 应用中做出合适的技术选型。
一、定位与设计哲学
在深入源码之前,先明确两者的定位差异——这是理解后续所有架构差异的根源。
| 维度 | ReMe | Mem0 |
|---|---|---|
| 一句话定位 | Agent 的上下文管理 + 工作记忆框架 | AI 应用的个性化记忆层 |
| 核心问题 | “对话太长,上下文溢出了怎么办?” | “如何记住用户的偏好和事实?” |
| 记忆来源 | 对话流中自动提取(压缩副产品) | 开发者显式调用 memory.add() |
| 记忆粒度 | 文件级(Markdown 文档) | 事实级(一条条独立的 fact) |
| 架构风格 | 框架型(继承、Hook、可选子系统) | 服务型(API 调用、托管平台) |
| 开源协议 | Apache 2.0 | Apache 2.0 |
| 背景 | AgentScope 团队 | Y Combinator S24 |
ReMe 的哲学:记忆是上下文管理的副产品——对话太长需要压缩,压缩产生的摘要顺便持久化为记忆。记忆的生命周期与对话的生命周期紧密耦合。
Mem0 的哲学:记忆是独立于对话的一等公民——每次交互后主动提取事实,存入独立的记忆库,下次交互前检索出来注入上下文。记忆的生命周期独立于任何具体对话。
二、记忆的写入流程
Mem0:Extract → Search → Decide → Store
Mem0 的记忆写入是一个两阶段 LLM 调用的流程:
# 开发者显式调用
memory.add(messages, user_id="user_123")
内部流程:
第一次 LLM 调用:事实提取
输入:对话消息
输出:{"facts": ["Name is John", "Is a Software engineer"]}
↓
对每个 fact 做向量检索,找到相关的已有记忆
↓
第二次 LLM 调用:记忆决策
输入:新 facts + 已有记忆
输出:对每条记忆执行 ADD / UPDATE / DELETE / NONE
↓
执行操作:写入向量数据库 + 记录变更历史到 SQLite
核心源码(Memory._add_to_vector_store()):
# 第一阶段:LLM 提取事实
system_prompt, user_prompt = get_fact_retrieval_messages(parsed_messages)
response = self.llm.generate_response(
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
],
response_format={"type": "json_object"},
)
new_retrieved_facts = json.loads(response)["facts"]
# 对每个新 fact,检索已有记忆
for new_mem in new_retrieved_facts:
messages_embeddings = self.embedding_model.embed(new_mem, "add")
existing_memories = self.vector_store.search(
query=new_mem, vectors=messages_embeddings, limit=5, filters=search_filters,
)
# 第二阶段:LLM 决定 ADD/UPDATE/DELETE/NONE
function_calling_prompt = get_update_memory_messages(
retrieved_old_memory, new_retrieved_facts
)
response = self.llm.generate_response(
messages=[{"role": "user", "content": function_calling_prompt}],
response_format={"type": "json_object"},
)
# 解析 response,执行 ADD/UPDATE/DELETE 操作
ReMe:Compress → Summarize → Write File
ReMe 的记忆写入是上下文压缩的副产品:
上下文 token 超限
↓
FbCompactor:压缩上下文(生成摘要替代原始消息)
↓ ↓
_compressed_summary(滚动更新) FbSummarizer:异步持久化
↓
LLM 按 prompt 指令写入 memory/YYYY-MM-DD.md
↓
FileWatcher 检测变化 → 更新向量索引
核心特点:
- 记忆写入是被动触发的(token 超限时)
- 写入目标是 Markdown 文件(非结构化)
- 向量索引由 FileWatcher 异步更新
关键差异
| 维度 | Mem0 | ReMe |
|---|---|---|
| 触发方式 | 开发者显式调用 memory.add() |
上下文溢出时自动触发 |
| LLM 调用次数 | 2 次(提取 + 决策) | 1 次(压缩/持久化共用) |
| 写入目标 | 向量数据库(结构化 payload) | Markdown 文件 → FileWatcher → 向量索引 |
| 记忆格式 | 独立的 fact 字符串 | 按日期组织的文档段落 |
| 去重策略 | LLM 判断 ADD/UPDATE/DELETE | 依赖 FbSummarizer prompt 中的"智能合并"指令 |
三、记忆的存储结构
Mem0:向量数据库 + SQLite 变更历史
Mem0 的每条记忆存储为向量数据库中的一条记录:
# 向量数据库中的一条记忆
{
"id": "uuid-xxx",
"vector": [0.1, 0.2, ...], # Embedding 向量
"payload": {
"data": "Name is John", # 记忆内容(一条 fact)
"user_id": "user_123", # 所属用户
"agent_id": None, # 或所属 Agent
"hash": "abc123", # 内容哈希(用于去重)
"created_at": "2025-02-12T...",
"updated_at": "2025-02-12T...",
}
}
同时在 SQLite 中维护变更历史:
CREATE TABLE history (
id TEXT PRIMARY KEY,
memory_id TEXT, -- 关联到向量数据库的 ID
old_memory TEXT, -- 修改前的内容
new_memory TEXT, -- 修改后的内容
event TEXT, -- ADD / UPDATE / DELETE
created_at DATETIME,
updated_at DATETIME,
is_deleted INTEGER,
actor_id TEXT, -- 来源标识
role TEXT
);
这意味着 Mem0 可以追踪每条记忆的完整变更历史——什么时候加的、改过几次、每次改了什么。
ReMe:Markdown 文件 + 向量索引
ReMe 的记忆存储在纯 Markdown 文件中:
working_dir/
MEMORY.md ← 长期记忆(用户/Agent 手动维护)
memory/
2025-02-12.md ← 每日日志(自动 + 手动)
2025-02-13.md
向量索引由 FileWatcher 自动维护——文件一改,自动切 chunk、embedding、写入向量数据库。
关键差异
| 维度 | Mem0 | ReMe |
|---|---|---|
| 存储介质 | 向量数据库(Qdrant/Chroma/Pinecone 等 25+ 种) | Markdown 文件 + 可配置向量存储 |
| 记忆单元 | 一条 fact = 向量数据库一条记录 | 一个文件 = 多个 chunk = 多条向量记录 |
| 变更追踪 | SQLite 完整变更历史 | 无(文件被覆盖就丢失旧版本) |
| 人可读性 | 需要通过 API 查看 | 直接打开 Markdown 文件 |
| 可编辑性 | 需通过 memory.update() API |
直接编辑文件,FileWatcher 自动同步 |
四、记忆的检索方式
Mem0:向量检索 + 可选 Reranker + 知识图谱
results = memory.search(query="项目语言", user_id="user_123", limit=5)
内部流程:
查询 → Embedding → 向量数据库检索(带 metadata 过滤)
↓
可选:Reranker 重排序
↓
可选:知识图谱实体检索(Neo4j/Kuzu)
↓
合并返回结果
Mem0 的检索特点:
- 支持
user_id、agent_id、run_id三维度的 metadata 过滤 - 支持 Reranker(Cohere、Jina 等)对结果重排序
- 支持 知识图谱(Neo4j、Kuzu、Memgraph)做实体关系检索
- 支持丰富的过滤操作符(
eq、ne、in、gt、contains、AND/OR/NOT)
ReMe:向量 + BM25 混合检索
results = memory_search(query="项目语言", max_results=5, min_score=0.1)
内部流程:
查询 → 向量语义搜索(权重 0.7)
→ BM25 全文检索(权重 0.3)
↓
按 chunk 去重 + 加权融合 + 排序截断
↓
返回 top-N 结果
ReMe 的检索特点:
- 向量 + BM25 混合检索是核心差异——BM25 对精确 token 命中效果极好(如函数名、错误码)
- 无 Reranker,但通过加权融合实现类似效果
- 无知识图谱,纯文本检索
关键差异
| 维度 | Mem0 | ReMe |
|---|---|---|
| 检索方式 | 纯向量 + 可选 Reranker | 向量 + BM25 混合 |
| 知识图谱 | 支持(Neo4j/Kuzu/Memgraph) | 不支持 |
| 过滤能力 | 丰富(多操作符、逻辑组合) | 基础(按文件路径/来源) |
| 精确匹配 | 依赖向量语义相似度 | BM25 擅长精确 token 匹配 |
| 多用户隔离 | 原生支持(user_id/agent_id/run_id) | 通过文件目录隔离 |
五、记忆的去重与更新
Mem0:LLM 驱动的四操作决策
Mem0 的去重是其架构中最精巧的部分。每次 add() 时:
- LLM 提取新 facts
- 对每个 fact 做向量检索,找到相关的已有记忆
- 将新 facts + 已有记忆一起发给 LLM,让 LLM 判断每条应该 ADD / UPDATE / DELETE / NONE
已有记忆:["I really like cheese pizza", "User likes to play cricket"]
新 facts:["Loves chicken pizza", "Loves to play cricket with friends"]
↓ LLM 决策
结果:
"cheese pizza" → UPDATE 为 "Loves cheese and chicken pizza"
"play cricket" → UPDATE 为 "Loves to play cricket with friends"
这种方式的优势是语义级去重——LLM 能理解"cheese pizza"和"chicken pizza"应该合并而非新增。
ReMe:Prompt 指令驱动的文件合并
ReMe 的 FbSummarizer 通过 prompt 指令实现去重:
工作流程:
1. 先 read memory/YYYY-MM-DD.md
2. 智能合并新信息与现有内容:
- 避免重复已记录的信息
- 在相关时丰富现有条目的新细节
- 在适用时保持时间顺序
3. 写入更新后的内容
去重的质量完全依赖 LLM 对 prompt 的遵循程度,没有 Mem0 那样的结构化检索 + 决策流程。
ReMe(ReMe 类):Draft-Retrieve-Deduplicate
ReMe 的 ReMe 类(CoPaw 未使用的长期记忆子系统)有更精细的去重机制:
- Draft:LLM 生成候选记忆
- Retrieve:在向量数据库中检索相似记忆
- Deduplicate:LLM 判断是否重复,决定合并或丢弃
这与 Mem0 的流程非常相似,但 ReMe 的 ReMeFb 子系统(更常用)没有这套机制。
六、记忆的层级与分类
Mem0:三维度记忆空间
Mem0 通过 user_id、agent_id、run_id 三个维度组织记忆:
# 用户级记忆(跨 session 持久)
memory.add("I prefer Python", user_id="user_123")
# Agent 级记忆(Agent 自身的学习)
memory.add(messages, agent_id="agent_456")
# 运行级记忆(单次 run 内有效)
memory.add("Current task is data cleaning", run_id="run_789")
# Procedural 记忆(Agent 的行为模式)
memory.add(messages, agent_id="agent_456", memory_type="procedural_memory")
此外,Mem0 支持知识图谱存储实体关系:
User --[likes]--> Python
User --[works_at]--> Google
Python --[is_a]--> Programming Language
ReMe:两套独立子系统
ReMe 项目
|
|-- ReMe 类(向量化长期记忆)
| |-- PersonalSummarizer 个人记忆
| |-- ProceduralSummarizer 程序性记忆
| |-- ToolSummarizer 工具记忆
|
|-- ReMeFb 类(文件化工作记忆)
|-- MEMORY.md 长期事实
|-- memory/*.md 每日日志
ReMe 的 ReMe 类支持四种记忆类型(personal / procedural / tool / task),由 DelegateTask 自动路由。但实践中更常用的 ReMeFb 类不区分类型,统一按文件组织。
七、上下文管理能力
这是两者最根本的差异所在。
Mem0:不管理上下文
Mem0 不参与上下文窗口的管理。它只负责"记住"和"想起",至于上下文 token 超限的问题需要开发者自行处理:
# Mem0 的典型用法——开发者自己管理上下文
def chat_with_memories(message, user_id):
# 1. 检索记忆
relevant_memories = memory.search(query=message, user_id=user_id, limit=3)
# 2. 手动注入上下文
system_prompt = f"User Memories:\n{memories_str}"
# 3. 调用 LLM(上下文管理完全由开发者负责)
response = openai_client.chat.completions.create(...)
# 4. 保存新记忆
memory.add(messages, user_id=user_id)
ReMe:上下文管理是核心
ReMe 的核心能力就是上下文管理——自动检测 token 超限、自动压缩、自动持久化:
每次 LLM 推理前(pre_reasoning Hook)
↓
FbContextChecker 检测 token 是否超限
↓ 超限
FbCompactor 压缩上下文
↓ 同时
FbSummarizer 异步写入 memory/*.md
关键差异
| 维度 | Mem0 | ReMe |
|---|---|---|
| 上下文压缩 | ❌ 不支持 | ✅ 核心能力 |
| 自动触发 | ❌ 需手动调用 add/search | ✅ Hook 自动触发 |
| 与 Agent 耦合度 | 低(独立服务) | 高(继承/Hook 集成) |
八、LLM 与 Embedding 管理
Mem0:自管理所有模型
Mem0 内置了完整的 LLM 和 Embedding 管理:
- LLM:OpenAI、Anthropic、Gemini、DeepSeek、Groq、Ollama、vLLM 等 18 种
- Embedding:OpenAI、Azure、Gemini、HuggingFace、Ollama、FastEmbed 等 14 种
- Reranker:Cohere、Jina 等
config = MemoryConfig(
llm=LlmConfig(provider="openai", config={"model": "gpt-4o-mini"}),
embedder=EmbedderConfig(provider="openai"),
vector_store=VectorStoreConfig(provider="qdrant"),
)
memory = Memory(config=config)
ReMe:支持外部 LLM 委托
ReMe 同样内置 LLM 管理,但其架构允许外部委托——如 CoPaw 通过 return_prompt=True 绕过 ReMe 的 LLM,只使用其 Embedding。这种灵活性是 Mem0 不具备的。
九、向量存储生态
| 后端 | Mem0 | ReMe |
|---|---|---|
| Qdrant | ✅ | ✅ |
| ChromaDB | ✅ | ✅ |
| Elasticsearch | ✅ | ✅ |
| FAISS | ✅ | ❌ |
| Pinecone | ✅ | ❌ |
| Milvus | ✅ | ❌ |
| pgvector | ✅ | ❌ |
| MongoDB Atlas | ✅ | ❌ |
| Redis | ✅ | ❌ |
| Weaviate | ✅ | ❌ |
| Supabase | ✅ | ❌ |
| SQLite(本地) | ❌ | ✅ |
| JSONL(本地) | ❌ | ✅ |
Mem0 在向量存储生态上占据明显优势(25+ 种后端),这与其"服务化"定位一致——适合部署在各种云环境。ReMe 的后端较少但包含轻量级本地选项(JSONL、SQLite),更适合桌面/边缘场景。
十、集成方式与侵入性
Mem0:零侵入的 API 调用
from mem0 import Memory
memory = Memory()
# 完全解耦——在任何框架中都能用
memory.add("User prefers dark mode", user_id="user_123")
results = memory.search("UI preferences", user_id="user_123")
Mem0 与应用完全解耦,通过 API 调用即可集成,不需要修改现有的 Agent 架构。
ReMe:深度集成的框架模式
from reme import ReMeFb
class MemoryManager(ReMeFb):
# 继承 ReMeFb 获得全部能力
def __init__(self, ...):
super().__init__(
llm_api_key="", # 可选:绕过 ReMe 的 LLM
embedding_api_key=key, # 委托 Embedding 给 ReMe
...
)
# 通过 Hook 集成
agent.register_hook("pre_reasoning", MemoryCompactionHook(...))
ReMe 的集成需要继承和 Hook 注入,侵入性更强但功能更深入。
十一、适用场景对比
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 多用户 SaaS 产品 | Mem0 | 原生多用户隔离,丰富的云存储后端 |
| 单用户 AI 助理 | ReMe (ReMeFb) | 自动上下文管理,文件化记忆透明可控 |
| 客服/销售 Agent | Mem0 | 用户画像积累,跨 session 个性化 |
| 开发者 Copilot | ReMe (ReMeFb) | 长对话压缩是刚需,代码记忆需要 BM25 精确匹配 |
| 需要知识图谱 | Mem0 | 原生 Neo4j/Kuzu 支持 |
| 桌面/边缘部署 | ReMe | JSONL/SQLite 本地存储,无需云服务 |
| 已有 Agent 框架 | Mem0 | API 调用零侵入,不改架构 |
| 从零搭建 Agent | ReMe | 框架级集成更深入,上下文管理自动化 |
十二、总结
ReMe 和 Mem0 解决的是 AI 记忆管理的不同侧面:
上下文管理 用户画像
(对话压缩) (事实提取)
↑ ↑
| |
ReMe Mem0
| |
↓ ↓
文件化工作记忆 结构化向量记忆
(Markdown + FileWatcher) (向量数据库 + 变更历史)
- ReMe 更像一个操作系统级的内存管理器——自动检测、自动压缩、自动持久化,深度嵌入 Agent 的运行时
- Mem0 更像一个独立的记忆数据库服务——提供 CRUD API,让任何应用都能快速接入记忆能力
两者并非互斥。一个理想的 Agent 系统完全可以同时使用 ReMe 管理上下文(防止 token 溢出),用 Mem0 管理用户画像(跨 session 个性化)——它们工作在记忆管理的不同层级,天然互补。
相关链接:
- ReMe GitHub:https://github.com/agentscope-ai/ReMe
- Mem0 GitHub:https://github.com/mem0ai/mem0
- Mem0 官网说明:https://mem0.ai/research
更多推荐




所有评论(0)