混合记忆向量图与KV
Mem0(Chhikara等人,2025)将记忆视为三个并行存储——向量用于语义相似性,KV用于快速事实查找,图用于实体关系推理。一个评分层在检索时融合三者。这是2026年外部记忆的生产标准。
混合记忆:向量 + 图 + KV(Mem0)
Mem0(Chhikara等人,2025)将记忆视为三个并行存储——向量用于语义相似性,KV用于快速事实查找,图用于实体关系推理。一个评分层在检索时融合三者。这是2026年外部记忆的生产标准。
类型: 构建 语言: Python (stdlib) 前置条件: Phase 14 · 07 (MemGPT), Phase 14 · 08 (Letta块) 时间: ~75分钟
学习目标
- 解释为什么单一存储(仅向量、仅图、仅KV)对Agent记忆不够。
- 说出Mem0的三个并行存储以及各自优化的目标。
- 描述Mem0的融合评分——相关性、重要性、时效性——以及为什么它是加权和而非层级。
- 在stdlib中实现玩具三存储记忆,带
add()写入所有三个和search()融合结果。
问题所在
单一存储对三类查询中的一类是错误的:
- 语义相似性 — “我们上周讨论了什么关于Agent漂移的?” 向量胜出;KV和图遗漏。
- 事实查找 — “用户的电话号码是什么?” KV胜出;向量浪费,图过度。
- 关系推理 — “哪些客户共享同一计费实体?” 图胜出;向量和KV无法回答。
生产Agent在一个会话中发出所有三类查询。单存储记忆总是对其中两类是错误的。Mem0的贡献是在单一add/search面后连接所有三个,并用评分函数融合它们。
核心概念
三个并行存储
Mem0(arXiv:2504.19413,2025年4月)在add(text, user_id, metadata)上:
- 从文本中提取候选事实(LLM驱动的步骤)。
- 将每个事实写入向量存储(嵌入)用于语义搜索。
- 将每个事实写入KV存储,键为(user_id, fact_type, entity)用于O(1)查找。
- 将每个事实写入图存储(Mem0g)作为类型化边用于关系查询。
在search(query, user_id)上:
- 向量存储按嵌入余弦返回top-k。
- KV存储按查询派生的(user_id, type, entity)键返回直接命中。
- 图存储返回从查询实体可达的子图。
- 评分层融合三者。
融合评分
score = w_relevance * relevance(q, record)
+ w_importance * importance(record)
+ w_recency * recency(record)
- 相关性 — 向量余弦、KV精确匹配、图路径权重。
- 重要性 — 写入时标记或学习(某些事实更重要:姓名、ID、策略)。
- 时效性 — 自上次写入或读取以来的指数衰减。
权重按产品调整。聊天Agent更高的w_recency;合规Agent更高的w_importance;检索Agent更高的w_relevance。
Mem0g和时间推理
Mem0g添加了冲突检测器。当新事实与现有边矛盾时,现有边被标记为无效但不删除。时间查询(“用户3月份的城市是什么?“)遍历时间有效子图。
这是Letta失效模式泛化的合规级行为。
基准数据
Mem0论文报告(2025):
- LoCoMo(长篇对话记忆):91.6
- LongMemEval(长时间范围情景记忆):93.4
- BEAM 1M(1M token记忆基准):64.1
比较基线(全上下文128k LLM、扁平向量存储、扁平KV)都落后10+分。仅凭基准不能证明选择——运营形态才能——但数字表明融合设计不是四舍五入误差。
范围分类
Mem0按范围拆分记忆:
- 用户记忆 — 跨会话持久化,以
user_id为键。 - 会话记忆 — 在一个线程内持久化。
- Agent记忆 — 每Agent实例状态。
每次写入选择一个范围。检索可以跨范围查询,带每范围权重。不加思考地混合范围是产生”助手把Bob的项目告诉了Alice”事件的方式。
这个模式哪里会出错
- 嵌入漂移。 在前一百次查询上看起来正确的向量结果随语料库增长而退化。添加定期重新嵌入最常用的N条记录。
- KV Schema蔓延。
(user_id, type, entity)看起来简单,直到每个团队添加自己的type。每季度审计类型集。 - 图爆炸。 一个嘈杂的提取器每条消息添加50条边。限制每次
add调用的图写入;丢弃低置信度边。
构建它
code/main.py在stdlib中实现三存储模式:
VectorStore— 朴素token重叠相似性作为嵌入替代。KVStore— 以(user_id, fact_type, entity)为键的字典。GraphStore— 类型化边(subject, relation, object, valid)。Mem0— 顶层门面,带add()、search()、融合评分和范围感知检索。- 一个多用户、多会话对话的工作跟踪。
运行:
python3 code/main.py
输出显示三条独立的召回路径加上融合的top-k。翻转main()顶部的评分权重,观察排名变化。
使用它
- Mem0(Apache 2.0) — 生产就绪。用Postgres + Qdrant + Neo4j自托管,或使用托管云。
- Letta — 三层core/recall/archival;自带向量和图后端。
- Zep — 带时间KG和事实提取的商业替代品。
- 自定义构建 — 当你需要精确控制提取器(合规)或融合权重(时效性主导的语音Agent)时。
发布它
outputs/skill-hybrid-memory.md生成带融合评分器、范围分类和时间失效连接的三存储记忆脚手架。
练习
- 用真实嵌入模型(sentence-transformers、Ollama、OpenAI embeddings)替换玩具向量相似性。在合成长对话上测量recall@10。排名在1000次写入后会漂移吗?
- 添加时间查询:
search(query, as_of=timestamp)。只返回该时间或之前有效的记录。哪个存储需要最多工作? - 实现冲突检测器:如果传入事实与图边矛盾,使旧边失效并记录两者。在”用户住在柏林” -> “用户住在里斯本”上测试。
- 将融合评分器移植为包含
user_feedback维度(对检索记录的点赞)。你如何防止博弈(Agent只返回它已经喜欢的记录)? - 阅读Mem0文档(
docs.mem0.ai)。将玩具移植为mem0客户端调用。在相同的20个测试查询上比较检索质量。
关键术语
| 术语 | 人们常说的 | 实际含义 |
|---|---|---|
| 混合记忆 | ”向量加图加KV” | 三个存储并行写入,检索时融合 |
| 事实提取 | ”记忆摄入” | 将文本分解为(entity, relation, fact)元组的LLM步骤 |
| 融合评分 | ”相关性排名” | 相关性、重要性、时效性的加权和 |
| 范围 | ”记忆命名空间” | user / session / agent — 决定谁看到什么 |
| Mem0g | ”记忆图” | 带时间有效性的类型化边用于关系查询 |
| 时间失效 | ”软删除” | 标记矛盾边为无效;永不删除 |
| 嵌入漂移 | ”检索腐烂” | 向量质量随语料库增长退化;定期重新嵌入 |
延伸阅读
- Chhikara等人, Mem0 (arXiv:2504.19413) — 原始论文
- Mem0文档 — 生产API、SDK、托管云
- Packer等人, MemGPT (arXiv:2310.08560) — 虚拟上下文前身
- Letta, Memory Blocks博客 — 三层兄弟设计