图谱式明文记忆(下):检索召回、重排与推理
30 秒导读: 上一章讲了记忆怎么"写进"图谱(04)。这一章讲反向的一半: 一条用户 query 进来,系统怎么把散落在图里的相关记忆找回来、排好序、去掉重复,最后交给对话模型。 主角是一个叫
Searcher的类,它把检索拆成"解析 → 多路并行召回 → 多源融合 → 重排 → 排序裁剪"五步流水线。
本章只讲读取一侧。写入(抽取、组织、去重、冲突消解)见 03 和 04;
记忆的形态与容器见 01;上层内核 MOSCore 见 02。
1. 这是什么(零基础也能懂)
一句话定义: 检索管线 = 给定一句话,从记忆图谱里"捞出"最相关的一批记忆条目,排好序返回。
它解决什么问题。 记忆库越写越大,几千上万条记忆散落在图谱的节点里。对话时不可能把全部记忆塞进 上下文窗口——太贵、也会淹没重点。所以每轮对话前要做一次精准的召回:只取"和这次问题相关"的十几条。
一个直觉类比。 把它想成图书馆找书:
- 你只说一句"我上次说的那个项目截止日期"(query,模糊)。
- 图书馆员先听懂你要什么(任务解析:关键词=项目、截止日期)。
- 然后兵分几路同时找:按卡片目录找( 图谱结构)、按"意思相近"找(向量)、按字面词找(BM25/全文)。
- 各路把候选堆到一起,去掉重复,按相关度排好序,只把最上面几本递给你(重排 + 裁剪)。
用起来什么样。 上层调用极简——MOSCore.search("我周五的会议改到几点了?"),内部就跑完整条管线:
# 示意,非源码:一次检索的对外观感
results = mos.search(
query="我周五的会议改到几点了?",
top_k=10,
mode="fine", # fine=慢而准(用大模型解析),fast=快而糙
internet_search=False, # 是否允许联网补充
)
# results 是一批 TextualMemoryItem,已按相关度排好序
为什么要"多路"而不是只用向量? 因为单一召回各有盲区:向量擅长"意思相近"但对精确的专有名词 (人名、编号)不敏感;字面匹配(BM25/全文)擅长专名但抓不住语义;图谱结构召回擅长"同一主题/标签 的邻居"但依赖抽取时打好的标签。并行跑、再融合,才能既召得全又召得准。