单一模态检索在边缘情形下会失效:稠密向量会遗漏稀有词元和 ID;纯词法检索则会遗漏释义和语义相似性。混合检索融合互补的信号——稠密语义、稀疏词法、结构化元数据、时间新鲜度——以生成稳定且高精度的候选集。本文详细介绍其架构、归一化、分数融合、故障处理与评估。
动机
故障场景:
- 稠密模型遗漏专有名词 / SKU 代码。
- 价格变更查询因缺少时间加权而拉取到陈旧快照。
- 在纯稀疏系统中,冗长的自然语言问题对停用词过度加权。
- 在语义宽泛的页面(营销空话)上出现向量误报,缺乏词法锚定。
混合检索通过捕获正交的证据维度来缓解这些问题。
组件分层
推荐流程:
- 查询嵌入 → ANN 搜索 (k_vec)
- 词法搜索 (BM25 / SPLADE / Elasticsearch) (k_lex)
- 合并 → 分数归一化(按来源缩放)
- 元数据过滤步骤 (locale、access_tier、page_type)
- 多样性与新鲜度调整
- 可选的交叉/单塔重排器
- 最终截断 (top K)
保留融合前的原始分数以供审计。
查询归一化
步骤:
- Unicode 归一化 NFKC
- 转小写(如需用于答案格式化,可保留大小写快照)
- 分词并保留停用词(语义嵌入可利用上下文)
- 同义词 / 别名扩展:为内部产品代号映射追加备用词元(不插入模型提示词;仅用于稀疏检索)。
- 数字与版本提取:捕获 X.Y.Z 模式以进行定向词法评分。
元数据与属性过滤器
在初始候选合并之后应用的过滤器可将召回损失降到最低。常见字段:locale、access_tier、page_type、product_area、updated_bucket。在分数融合之前强制执行安全过滤器(tenant / tier),以防止泄漏影响重排。提供调试模式,返回 filtered_out 集合以供检查。
重排策略
在前 N 个(10–20)结果上使用轻量级交叉编码器(蒸馏模型)。如果延迟 > 预算,则降级:跳过重排,或在提高词法权重的同时减少候选数量。跟踪 re_rank_delta = MRR_post - MRR_pre 以证明成本的合理性。在较短的 TTL 内为相同的合并集缓存重排结果。
新鲜度与时间信号
计算 freshness_weight = exp(-lambda * age_days),其中 lambda 按内容类型调整(价格类更高,稳定的 API 类更低)。组合:final_score = w_sem * sem_score + w_lex * lex_score + w_fresh * freshness_weight + w_meta * meta_priors。先对每个分量进行归一化(z-score 或 min-max),以避免某一分量占主导。
故障模式
| 故障 | 原因 | 缓解措施 |
|---|---|---|
| 流行度偏差 | 词法 tf-idf 过度加权 | 限制词频贡献的上限 |
| 结果陈旧 | 新鲜度权重调校不当 | 使用评估集重新校准 lambda |
| Locale 泄漏 | 过滤器应用过晚 | 将安全过滤器前移 |
| 语义漂移 | 嵌入模型升级 | 双索引并在上线前进行 A/B 比较 |
| 过度融合噪声 | 合并规模无上限 | 限制合并、按多样性剪枝 |
评估框架
实验:
- 消融:(仅向量、仅词法、无重排的混合、完整)测量 Recall@k、MRR。
- 融合权重调优:使用验证黄金集对权重进行网格搜索。
- 延迟预算:跟踪每种配置的平均检索延迟 + P95。
- 漂移:监控头部查询与长尾查询召回率的每周相对变化。
维护带有配置哈希的评估清单。
优化循环
循环:
- 记录检索轨迹 (query、candidates、scores、source_tag)。
- 识别误命中(下游忠实度低或引用数低)→ 归类根本原因(缺失词法候选、语义误报、内容陈旧)。
- 调整权重 / 阈值;运行离线套件。
- 在功能开关后以灰度方式发布新的融合权重。
- 在统计显著改善时予以推广。
关键要点
- 混合检索是一套可调节的旋钮系统——要持续不懈地进行检测。
- 尽早应用安全与访问过滤器;避免泄漏到评分中。
- 重排必须通过可衡量的 MRR / Recall 提升来证明延迟的合理性。
- 时间衰减可防止过时但高权威性的页面占据主导。
- 像对待代码一样对待融合变更:进行版本管理、评估、向前或向后回滚。