记忆架构 v4 召回质量 Eval 报告(首轮)

测试日期:2026-08-26 · 测试对象:mem0(Qdrant)+ memory-inject v4 多路召回 + 14 天半衰期时间衰减 数据源:mem0 真实记忆库 ~/.mem0(100 条,2026-08-11 ~ 2026-08-26) 复现:~/dev/memory-eval/(cases.json + run_eval.py + results.json)

TL;DR

一、为什么测(背景)

记忆架构 8-26 升级到 v4:召回侧改为多路召回(Lane A 当前用户消息 + Lane B 最近 recap 主题)+ 注入分层<recalled-memory> 块紧跟 <rules> 之后)+ 14 天半衰期时间衰减effective = score × 0.5^(days/14))。

之前(8-19)跑过 pi-search benchmark(237 cases,测的是 SQLite FTS5 全文检索工具),但从未对记忆架构本身做过 eval。v4 上线后需要基线数据,验证"多路召回 + 衰减"这套设计到底行不行。

二、方法

2.1 Ground truth 来源

从 mem0 真实记忆库取 27 条有明确唯一答案的事实/偏好/事件作为 target,query 用用户口吻重写:

2.2 分类构成(27 cases)

类别 条数 考察点
real 12 真实提问场景(最贴近使用)
fact 9 身份/事实/决策类记忆
preference 2 用户偏好类
paraphrase 2 同义描述(不出现专名)
negative 2 无关提问(防幻觉召回)

2.3 评估口径

三、结果

3.1 总体

口径 hit@1 hit@3 hit@5 平均延迟
raw(原始分) 44.4% 81.5% 88.9% 2.44s
eff(衰减后重排) 33.3% 77.8% 85.2%

3.2 分类型明细(raw)

类别 条数 hit@1 hit@3 hit@5
real 12 58.3% 91.7% 100%
fact 9 44.4% 66.7% 77.8%
preference 2 0% 100% 100%
paraphrase 2 50% 100% 100%
negative 2 0%(无幻觉) 0%(无幻觉)

3.3 分类型明细(eff,衰减后)

类别 条数 hit@1 hit@3 hit@5
real 12 50.0% 83.3% 91.7%
fact 9 33.3% 55.6% 55.6%
preference 2 0% 100% 100%
paraphrase 2 50% 100% 100%

四、失败模式分析(4 个 miss@3,全部命中)

4.1 同主题重复写入 → 召回互相稀释(real 类)

query:记忆框架的失败模式是不是要重点记住,target 61853aab(score 0.55)排第 5 名外

top5 里 4 条全是 PersonaMem 失败模式同主题记忆(a440df82 0.59 / 407198eb 0.56 / b40ff791 0.56 / 53dd55ca 0.56),把目标挤出去。

根因:8-26 同一天反复写入 5 条几乎一样的记忆("Mem0 失败模式要记住"被 autosediment 在不同轮次反复沉淀)。mem0 写入侧无相似度去重——同主题多轮写入本该合并,结果各占一条,召回时互相稀释。

4.2 身份类事实被时间衰减误伤(fact 类,2 条)

query:我是什么学校的,target 5d4f0347(墨尔本大学,8-14 记,12 天前,raw score 0.29)

原始分本来就低(0.29),衰减后 0.16 → 排第 5 名外。

query:我现在在哪个公司实习,target f8c0f3e1(Tezign,8-25 记,1 天前,raw 0.47)—— 未进 top5,被 1 天前的 4 条面试记忆(MemOS/石墨/fAIshion)淹没

根因14 天半衰期对"偏好/近期事件"合理,对"身份事实"是错的。学校、当前公司这类长期稳定事实不该随天数降温——它们是最该被记住的东西。衰减公式没有区分记忆类型。

4.3 口语化语义召回弱(fact 类)

query:我九月初要去哪上班,target 31f88a72(MaxInsights 入职,8-26 记,score 0.60)—— 完全没进 top5

而直接搜 MaxInsights 入职 时 31f88a72 排第 2(0.60)。"上班/入职/去哪"这些口语化表达与英文记忆文本("join maxinsights around early September")embedding 匹配弱

根因:embedding 对中英混合 + 口语化的语义桥接不足。这正是 PersonaMem-v3 指出的"需要的信息没被检索到"失败模式在真实系统里的复现——而且 8-26 刚把这条失败模式写进记忆,同一天自己就踩了。

4.4 旧记忆的合理降温(非缺陷,设计使然)

我九月初要去哪上班 raw 没命中但 eff 也没命中——因为 12 天前的 MaxInsights 早期探索条目(de8fb764,0.61)被衰减到 0.34 排后,而 8-26 的入职条目(31f88a72,0.60)又因口语化没召回。这是 4.3 的叠加效应,不是衰减的问题——衰减本身在 real 类只把 hit@3 从 91.7% 微降到 83.3%,代价可控。

五、结论与修复建议

✅ v4 设计验证

⚠️ 三个待修点(按优先级)

  1. 记忆类型区分衰减 —— 身份/事实类(学校、公司、邮箱、账号)豁免衰减或半衰期 ×10;偏好/事件类维持 14 天。实现:mem0 写入时打 type 标签(fact / preference / event),召回时按类型套不同半衰期。改动在 memory-inject v4 的 effectiveScore 函数
  2. 写入侧相似度去重 —— autosediment 写入前先对同 user 最近 N 条记忆做相似度检查(embedding 距离),>0.85 则合并/跳过,防止同主题多轮写入互相稀释。改动在 mem0-autosediment
  3. 口语化语义召回增强 —— query 扩展(LLM 把"上班"→"join/work/入职"再向量化)、或中英双语记忆存储。这条和 08-31 规划要做的"场景适配"合并,不是独立项

📊 与 pi-search benchmark(8-19)对比

口径 pi-search(FTS) mem0 v4(语义)
real hit@3 77.8% 91.7%
real hit@5 88.9% 100%
延迟 51ms / 1.22s(expand) 2.44s

语义召回在真实提问场景全面胜出(hit@3 +14 个点),但延迟高 2 个数量级(mem0 search 每次 ~2.4s,含 embedding + LLM 重写)。对 before_agent_start 注入场景 2.4s 可接受(启动时跑一次);但对交互式即时检索不可接受——这支持了"memory 做注入、session search 做即时检索"的分工。

六、复现

cd ~/dev/memory-eval
python3 run_eval.py   # 27 case × search,输出 results.json + 汇总
# 产物:cases.json(27 case 定义+ground truth)、run_eval.py(runner)、results.json(结果)
# 新增 case:往 cases.json 的 cases 里加 {query, target, cat, note},target 填 mem0 记忆 id 前缀(前 8 位)
# 注意:target 必须先在 mem0 里确认存在(~/bin/mem0-cli.py search "<专名>" 验证)

报告生成:memory-eval v1 · 2026-08-26 · 由 mem0 召回质量首轮评测产出