记忆系统的多信号混合检索
记忆系统的多信号混合检索
学习目标
读完本章后,你将能够:
- 理解语义搜索、BM25 和实体提升三种检索信号的特点与互补性
- 设计查询长度自适应的 BM25 归一化策略
- 实现多信号融合评分公式
- 评估混合检索相比纯向量检索的改进
核心概念
为什么需要混合检索
纯向量检索(语义搜索)的优势是理解语义相似性——“编程偏好”可以匹配到”喜欢 Python”。但它有两个局限:
- 精确词匹配不足:当查询包含特定专有名词(如 “Poppy”、“Osteria Francescana”)时,向量检索可能返回语义相似但不包含该词的记录
- 关键词权重不敏感:向量检索对查询中每个词的权重分配是隐式的,无法显式强调关键实体
BM25 关键词匹配和实体提升正好弥补这两个短板:
三信号融合评分
混合检索的评分公式为:
combined = (semantic_score + bm25_score + entity_boost) / max_possible其中 max_possible 根据活跃信号动态调整:
| 活跃信号 | max_possible | 说明 |
|---|---|---|
| 仅语义 | 1.0 | 只有语义信号 |
| 语义 + BM25 | 2.0 | 两种信号等权 |
| 语义 + BM25 + 实体 | 2.5 | 实体权重为 0.5 |
| 语义 + 实体(无 BM25) | 1.5 | 向量存储不支持关键词搜索 |
关键设计:阈值(threshold)在融合前应用于语义分数——语义分数低于阈值的候选即使 BM25/实体分数高也会被排除。这保证了语义相关性是基础门槛。
BM25 归一化
BM25 原始分数是无界的(通常 0-20+),需要归一化到 [0, 1] 才能与语义分数融合。Mem0 使用逻辑 Sigmoid 归一化:
normalized = 1 / (1 + exp(-steepness * (raw_score - midpoint)))查询长度自适应参数:
| 查询词数 | midpoint | steepness | 原因 |
|---|---|---|---|
| ≤ 3 | 5.0 | 0.7 | 短查询 BM25 分数低,中点下调 |
| 4-6 | 7.0 | 0.6 | 中等查询 |
| 7-9 | 9.0 | 0.5 | 较长查询 |
| 10-15 | 10.0 | 0.5 | 长查询 |
| > 15 | 12.0 | 0.5 | 超长查询,分数更高 |
直觉:长查询更容易匹配到更多词,BM25 原始分数天然更高,所以需要更高的 midpoint 来保持归一化的一致性。
实体提升(Entity Boosting)
实体提升流程:
- 从查询中提取实体(使用 NLP 模型如 spaCy)
- 在 Entity Store 中搜索匹配实体(相似度 ≥ 0.5)
- 对每个匹配实体,获取其关联的记忆 ID 列表
- 计算提升权重:
boost = similarity × ENTITY_BOOST_WEIGHT × memory_count_weightENTITY_BOOST_WEIGHT = 0.5(最大提升幅度)memory_count_weight = 1 / (1 + 0.001 × (num_linked - 1)²)(spread-attenuation 衰减)
Spread-Attenuation 衰减:一个实体关联的记忆越多,单条记忆获得的提升越小。这防止了”大众实体”(如常见人名)过度影响所有关联记忆。
检索管道的 over-fetch 策略
混合检索的一个关键设计:语义搜索的 internal_limit = max(top_k × 4, 60)。原因:
- 语义搜索召回的候选集会经过阈值过滤和 BM25/实体加分后重排
- 如果只检索
top_k条,经过重排后可能不足top_k条 - 过度检索确保最终返回的结果数量充足
设计优势与代价
优势
- 精确词 + 语义双覆盖:既有语义理解,又有精确匹配
- 实体感知:查询中的人名、地名等实体获得额外权重
- 自适应评分:根据可用信号动态调整
max_possible - 可扩展:新增检索信号只需加入评分公式
代价
- 多次存储查询:需要同时查询向量存储和 Entity Store
- 参数调优:BM25 sigmoid 参数、entity boost 权重需要经验调优
- 依赖 Lemmatization:BM25 搜索依赖词形还原,需要额外 NLP 处理
陷阱与对策
| 陷阱 | 对策 |
|---|---|
| BM25 压制语义信号 | 设置合理的 max_possible 分母,BM25 最多贡献 1.0 |
| 实体提升过度放大常见实体 | Spread-attenuation 衰减,关联记忆越多权重越小 |
| 短查询 BM25 分数过低 | 查询长度自适应的 midpoint/steepness 参数 |
| Entity Store 未初始化时查询失败 | Entity Store 延迟初始化,实体提升失败时优雅降级 |