Memory Backend Audit — 大白话版
完整版见 audit_memory_backends.md。这份只讲做决定要知道的事。
一句话结论
Mem0 / MemOS / Graphiti 都能用。OpenRouter 都通过,没有 deal-breaker。
GAME.md 锁定的三个评估对象都跑得起来。剩下的全是工程细节,不影响选型。
三个意外发现
-
Zep 死了。 Zep 社区版 2025 年 4 月 deprecated。我们说的”Zep”实际是 Graphiti(
pip install graphiti-core),是 Zep 团队留下来的 OSS 引擎。GAME.md 引用 [34, 36] 已经覆盖到,但写文章时要把 Graphiti 放前面。 -
MemOS 居然有个
pref_mem类型,叫PreferenceTextMemory,自带explicit_preference/implicit_preference两类。听起来跟我们 IPaS 完美匹配——其实没用。它的分类轴是”明说 vs 没明说”,跟我们的 4-context(work/personal × internal/external)正交。要适配反而要打。 -
MemOS 的
search()签名压根不接受 metadata filter。 这是 C5 gap 最干净的源码证据。GAME.md 的 H1 假设(“三个框架 CS 都低”)直接被这一行签名背书——它根本没这个能力。
三个 backend,一句话定位
- Mem0:vector + 可选 graph。
pip install mem0ai,Qdrant 默认本地。最轻、API 最齐。Reset 有坑(graph 模式下reset()不清图谱 #3040),所以 v1 别开 graph 模式。 - MemOS:tree + memcube。Server 模式要 Neo4j+Qdrant+Redis,太重;用 in-process MOS 就行。Snapshot 最强——
MemCube.dump(dir)/load(dir)/init_from_dir(dir)是真原语。 - Graphiti:temporal KG。
pip install graphiti-core。group_id是 first-class 参数,context 隔离最干净(把group_id设成{user}_{context}就完了)。但没有delete_group/reset——重置只能 drop 整个数据库。用 Kuzu 后端(文件式,rm -rf即重置)能解决。
五个约束逐项谁赢
| 谁最强 | 备注 | |
|---|---|---|
| C1 OpenRouter | 平 | 三个都源码层确认 base_url 可改 |
| C2 用户隔离 | 平 | Graphiti group_id 概念最干净;MemOS 物理分目录最强 |
| C3 Reset/Snapshot | MemOS | 唯一有 dump/load 原语 |
| C4 Trace 可观测 | Graphiti | 唯一内置 tracer slot(OTel 风) |
| C5 Context 检索 | Graphiti(但都不行) | group_ids filter 是 native;但仍是硬分区,不是软条件——这正是 benchmark 要暴露的 gap |
共同的坑(都得处理)
- Embeddings 也走 OpenRouter,不用改代码。 OpenRouter 现在有
POST /api/v1/embeddings(OpenAI 兼容)。Mem0 / MemOS / Graphiti 三个 backend 的 embedder 源码都接受base_url参数。只要把 embedder 的 base_url 指到https://openrouter.ai/api/v1,model id 用openai/text-embedding-3-small这种provider/model形式即可。本地 HF embedder 当备选。 - Trace observability 都要自己 wrap(除 Graphiti 之外)。AMemGym 的 write/read/utilization 三段诊断对接,需要在
add/search路径上自己挂 logger。 - Reproducibility:三个都在写入路径调 LLM,温度调低 + OpenRouter 上 pin 模型版本。或者预抽事实自己喂
infer=False(Mem0 直接支持)。
实施建议(v1)
- Mem0:版本要 ≥ #3928 修复后的 release;关 graph 模式;Qdrant 本地;snapshot 用目录拷贝。
- MemOS:用 in-process MOS;
MemCube.dump/load做 checkpoint;先不上 server 模式。 - Graphiti:用 Kuzu 后端(不要 Neo4j);reset 直接
rm -rf db_dir;async API 注意 harness 适配。
已知失败模式(写论文时直接引用)
- OP-Bench(arxiv 2601.13722)测过 Mem0 和 MemOS:所有 memory 方法 OP 分数比 BASE(无 memory)下降 26–61%,MemOS 比 RAG 还差。原因是 “memory hijacking”——检索出来的记忆在 attention 上压过了用户当前 query。
- AMemGym(arxiv 2603.01966)测过 Mem0-G:write failure 是主要瓶颈——信息在写入抽取阶段就丢了,不是检索阶段丢的。所以我们的 trace 重点应该挂在 extractor 的输入输出。
这两条直接进 H1 / H2 的讨论,不用自己再证。