混合检索与重排:提升召回与排序质量

混合检索与重排:从"能找到"到"排得准"

RAG 系统的检索质量通常决定最终回答上限。单纯依赖向量检索,在 demo 中经常表现不错,但进入真实业务后会遇到很多问题:精确词召回不稳、结构化条件无法严格满足、重复 chunk 过多、Top K 噪声大、真正相关文档排在后面。

混合检索和重排的目标,就是把召回率和排序质量分开优化:先尽量把可能相关的候选找回来,再用更精细的模型或规则重新排序。

1. 为什么单路检索不够

向量检索擅长语义匹配,但不擅长所有检索问题。

它适合:

  • 同义表达。
  • 口语化问题。
  • 语义相近但字面不同的资料。
  • 开放式知识问答。

它不擅长:

  • 精确编号。
  • 人名、地名、代码。
  • 日期和数值范围。
  • 强布尔条件。
  • 术语必须命中的场景。

例如用户问"找 5 年以上经验且会 Go 的候选人",其中"5 年以上"应由结构化过滤保证,"Go"可能需要关键词召回,"候选人相关经验"则适合语义召回。单一路径很难同时做好。

2. 混合检索的基本结构

混合检索通常由多路召回组成:

text 复制代码
用户问题
  -> 参数抽取
  -> 结构化过滤
  -> 稠密向量召回
  -> 稀疏向量召回
  -> 全文检索召回
  -> 合并去重
  -> 重排
  -> 返回结果

这里的关键思想是:不同召回器解决不同问题。

  • 稠密向量负责语义相似。
  • 稀疏向量负责词项匹配。
  • 全文检索负责关键词、短语和字段。
  • 结构化过滤负责硬条件。

这比"所有问题都向量化"更符合业务现实。

3. 稠密和稀疏信号如何融合

稠密向量和稀疏向量的分数来源不同,不能随意直接相加。常见融合方式包括:

  • 加权融合:给不同通道设置权重。
  • RRF:根据排名而不是原始分数融合。
  • 规则优先:硬条件过滤后再做语义排序。
  • 分阶段处理:先召回候选,再交给重排模型。

加权融合简单直观,但权重需要评估。语义问题多的场景可以提高稠密权重;精确词、术语多的场景可以提高稀疏或全文权重。

不要把权重当成永久真理。它应该基于测试集、业务反馈和线上日志调整。

4. 元数据过滤是业务检索的稳定器

很多条件不应交给模型猜。例如:

  • 年龄小于 35。
  • 工作经验大于 5 年。
  • 城市为北京。
  • 日期在某个范围内。
  • 文档类型为合同。

这类条件适合在检索阶段用 metadata filter 或数据库过滤表达式执行。这样能保证硬条件严格生效。

参数抽取在这里非常重要。它负责把自然语言变成结构化条件:

json 复制代码
{
  "age_max": 35,
  "experience_min": 5,
  "city": "北京"
}

之后程序再构造过滤表达式,而不是让模型自己判断哪些文档符合条件。

5. 重排模型解决排序问题

召回阶段为了不漏掉,通常会取更多候选。但候选多了以后,噪声也会增加。重排模型的作用是对 (query, document) 进行更细致的相关性判断。

典型流程:

text 复制代码
多路召回 Top 30
  -> 构造 query-document pair
  -> CrossEncoder 打分
  -> 按 rerank_score 排序
  -> 返回 Top 3 或 Top 5

与向量检索不同,CrossEncoder 通常会同时看问题和文档内容,相关性判断更精细,但计算成本也更高。因此它适合处理召回后的候选集合,而不适合直接对全库文档打分。

6. 召回数量与最终返回数量要分离

一个常见错误是用户要 3 条结果,系统就只召回 3 条。这样没有给重排留下空间。

更合理的方式是:

text 复制代码
召回数量 = 最终数量的若干倍
最终数量 = 用户真正需要展示的数量

例如最终返回 3 条,可以先召回 15 或 30 条,再重排筛选。具体倍数取决于数据规模、延迟要求和召回质量。

如果召回数量太少,重排没有意义;如果太多,重排成本会上升。调参时要同时看准确率和响应时间。

7. 合并去重决定上下文质量

多路召回一定会产生重复。重复可能发生在:

  • 同一 chunk 被多个通道命中。
  • 同一文档的多个相邻 chunk 被命中。
  • 父子块同时被命中。
  • 内容相似的重复文档被命中。

去重粒度要根据业务目标决定:

  • 如果回答基于片段,可按 chunk ID 去重。
  • 如果推荐的是文档,可按 doc ID 去重。
  • 如果要展示来源,可保留最高分片段并关联原文档。

不去重会导致上下文重复,模型窗口浪费,回答也可能啰嗦或偏向某一来源。

8. 混合检索的评估方法

混合检索调优不能只看最终回答。建议建立一组查询样例,并标注期望命中文档。观察:

  • Recall@K:正确文档是否进入前 K。
  • MRR:第一个正确结果排在多靠前。
  • nDCG:排序整体质量。
  • 重排前后排名变化。
  • 无关文档比例。
  • 平均检索耗时。

如果没有标注集,也可以先人工抽样构建几十条高频问题。哪怕样本不大,也比凭感觉调权重可靠。

9. 常见工程风险

混合检索常见风险包括:

  • 多通道分数不可比却被直接相加。
  • metadata 类型不稳定,过滤表达式失效。
  • 文档切分太碎,重排看不到完整语义。
  • 重排输入过长,延迟明显增加。
  • 召回结果没有来源信息,无法回溯。
  • 只优化准确率,忽略响应时间。
  • 过滤过早导致正确文档被排除。

这些问题需要通过日志和评估定位。每次检索最好记录:原始 query、改写 query、过滤条件、各通道召回数量、合并后数量、重排分数和最终返回结果。

10. 过滤、召回和重排的顺序

混合检索中,一个关键设计问题是:过滤应该发生在召回前,还是召回后?

如果过滤条件非常明确,例如权限范围、城市、日期、文档类型,通常应在召回前执行。这样可以减少候选范围,提高效率,也避免把用户无权访问的数据带入后续上下文。

如果过滤条件来自模型抽取且不够可靠,可以采用更谨慎的方式:先宽召回,再在合并阶段过滤或二次校验。这样能避免因为参数抽取错误过早排除正确文档。

重排一般发生在候选集合形成之后。它不应该替代权限过滤,也不应该承担硬条件判断。重排负责相关性排序,硬约束仍应由程序逻辑保证。

11. 上线后的调参策略

混合检索上线后,不建议频繁凭感觉改权重。更稳的方式是建立查询样例池:

  • 高频真实问题。
  • 失败问题。
  • 边界问题。
  • 业务重点问题。
  • 容易混淆的相似问题。

每次修改切分、权重、Top K、重排模型或过滤逻辑,都在样例池上回归。这样可以避免"修好了一个问题,破坏了另一批问题"。

12. 小结

混合检索的核心不是堆组件,而是分工:

text 复制代码
结构化过滤保证硬条件,稠密向量保证语义召回,稀疏/全文检索保证关键词命中,重排模型保证最终排序。

当系统从 demo 走向业务,检索质量的优化会越来越像搜索系统工程。只有把召回、过滤、去重、排序和评估拆开看,RAG 才能稳定提升。

相关推荐
羑悻的小杀马特1 小时前
AI判不了设备异常?缺的不是算法,是这层数据底座
数据库·人工智能·ai
网安墨雨1 小时前
MySQL数据库 SQL语句详解
自动化测试·软件测试·数据库·python·sql·mysql
柠檬味的Cat1 小时前
GEO优化系统哪家技术强
人工智能·python
W658034191 小时前
腾讯混元Hy3深度解析:295B参数只激活21B,推理效率怎么做到提升40%的
ai·gpu算力·国产替代
Ai拆代码的曹操1 小时前
RocketMQ 消息堆积排查实战:从 20 个消费者线程卡死到 rebalance 死亡螺旋
后端·rocketmq
跨境小陈1 小时前
2026 年如何使用 Python 抓取 Reddit 数据
开发语言·网络·python
吃饱了得干活2 小时前
@Transactional 又失效了?把这 8 个坑全填了!
java·后端·spring
颜进强2 小时前
从零搭建私人 RAG 知识库:让项目决策真正“可检索、可追溯”
前端·后端·ai编程
殿方雪之下2 小时前
OpenAI 兼容 API 接入实战:统一 Base URL 与用量控制
python