Skip to content

04. 混合检索、重排与评测

版本:v1.1

最后更新:2026-07-09

适用对象:已经搭过向量检索,但开始遇到编号搜不准、top-k 质量不稳、候选池里有正确结果却最终答案仍然错、以及不知道该怎么做离线评测与线上复盘的团队

很多团队做到第二阶段时都会发现:

  • 纯向量检索不是每类 query 都够用
  • top-k 里明明有正确证据,答案还是错
  • 编号、产品名、报错码这种词法强信号经常掉
  • 大家都在说 rerank,但不知道该放在哪层
  • 效果变好还是变坏,最后只能靠“主观感觉”

这篇专题主要回答四个问题:

  1. 为什么企业检索通常要做 hybrid,而不是只做 pure vector。
  2. rerank 在哪一层最有价值。
  3. 候选池、重排、证据组装和最终答案之间是什么关系。
  4. 怎样把这套链路变成可评测、可回放的系统。

1. Pure Vector 为什么经常不够

向量检索的强项是:

  • 概念相近
  • 语义变体
  • 同义表达

但企业知识里还有另一类强信号:

  • 编号
  • 报错码
  • 合同号
  • API 名
  • 角色名
  • 产品型号
  • 时间和版本

这类内容如果只做纯语义,常会出现:

  • 找到语义接近但字面不对的内容

OpenAI 当前 File search 文档明确说明它结合:

  • semantic search
  • keyword search

Azure AI Search 当前 Hybrid search overview 也明确把 hybrid 定义成:

  • 同一个请求里并行跑全文检索和向量检索
  • 再用 RRF 融合

所以现实的结论是:

  • 生产检索更像“多信号融合”,不是“纯向量决胜”

2. Hybrid Search 到底在补什么

2.1 dense 信号负责语义近似

适合处理:

  • 同义问法
  • 口语化问题
  • 概念归纳型 query

2.2 sparse / lexical 信号负责字面精确

适合处理:

  • 专有名词
  • 编号
  • 错误码
  • 精确字段词

2.3 filter 负责范围正确

适合处理:

  • tenant
  • acl
  • doc_type
  • version
  • effective window

2.4 rerank 负责最终顺序更稳

适合处理:

  • 候选都大致相关,但顺序不稳
  • 需要更强 query-doc 对齐
  • 候选池较大,需要更精细排序

3. RRF 和 rerank 不要混为一谈

Azure AI Search 当前文档里,RRF 是结果融合机制,作用是:

  • 把全文和向量两路结果融合成一个统一排序

它解决的是:

  • 多路召回怎么合并

而 rerank 解决的是:

  • 已经有候选池后,怎样更精确地按 query 重新排序

两者可以一起存在:

  1. 先做 lexical + vector 双路召回。
  2. 用 RRF 合并初始候选池。
  3. 再用 semantic reranker 或 cross-encoder 进一步排序。

4. 为什么候选池是第一等证据

很多团队只看最终答案,忽略候选池。

但排查时最关键的问题往往是:

  • 正确文档到底有没有进 top-k

如果没进 top-k,更像:

  • 检索问题
  • filter 问题
  • 索引问题

如果已经进了 top-k,但最终答案仍然错,更像:

  • rerank 问题
  • 上下文装配问题
  • 生成阶段消费问题

所以一个成熟的系统至少要保留:

  • raw query
  • rewritten query
  • filter
  • lexical 候选池
  • vector 候选池
  • 融合后候选池
  • rerank 前后顺序

5. Query Rewrite 应该放在哪里看

很多问题其实不是检索库“不认识”,而是 query 表达不稳定。

常见情况包括:

  • 用户问得太口语
  • 缩写没有展开
  • 业务术语有别名
  • 多轮上下文里真正查询意图没被抽出来

这时更值得保留的不是最终答案,而是:

  • 原始 query
  • 改写后的 query
  • 改写理由或改写策略版本

因为它能帮你分清:

  • 问题是在 query rewrite
  • 还是在真正的检索层

6. Rerank 最适合在哪些场景上

rerank 通常在下面几类场景特别有价值:

6.1 候选池里经常有正确项,但不是第一名

这说明召回不一定差,排序更可能是瓶颈。

6.2 语义很像但答案边界差异很大

例如:

  • 相似制度,但适用对象不同
  • 相似 API,但版本不同
  • 相似排障文档,但产品线不同

6.3 候选池需要结合更多字段判断

比如:

  • 标题
  • 正文
  • 章节路径
  • 时间新鲜度
  • 来源权威级

这类场景下,单一向量分数往往不够。

7. Weaviate / Azure / OpenAI / Pinecone / Qdrant / Milvus 给出的组合启发

7.1 OpenAI 的启发

OpenAI File search 当前文档明确使用:

  • keyword + semantic

它说明一件事:

  • 托管式工具也没有把企业检索简化成“纯向量就够了”

7.2 Azure 的启发

Azure AI Search 当前文档把:

  • hybrid search
  • RRF
  • semantic ranker

放成同一条推荐路径,这其实就是完整检索规划的公开版本。

7.3 Weaviate 的启发

Weaviate 当前文档不仅强调 hybrid,也强调多种搜索模式与向量配置,提醒我们:

  • 同一个知识对象可以有多种召回信号

更值得注意的是,Weaviate 当前 hybrid 文档明确把:

  • fusion 方法
  • 相对权重
  • 返回 score / explainScore

都当成第一等配置对象。

这说明 Weaviate 的心智不是:

  • “hybrid 开一下就行”

而是:

  • hybrid = 多信号并行召回 + 可解释融合 + 可调权重

7.4 Pinecone 的启发

2026-07-09 可访问的 Pinecone Hybrid searchRerank results 官方文档来看,Pinecone 给出的工程启发非常实用:

  • hybrid 不只是一种部署形态
  • 可以做单索引 dense+sparse
  • 也可以做 dense / sparse 分离后再 merge
  • rerank 既可以作用在单路结果上,也可以作用在 merge 后结果上

这带来两个很重要的现实判断:

  1. 如果你更关心工程简单度,可以先从单索引 hybrid 开始。
  2. 如果你更关心不同信号单独调优、单独扩容、单独实验,可以走双索引或多索引组合。

也就是说,Pinecone 给出的不是“唯一标准架构”,而是:

  • 先决定你的操作面要不要拆,再决定 hybrid 形态

这对企业团队很重要,因为很多系统真正难的不是“把 dense 和 sparse 拼在一起”,而是:

  • dense 和 sparse 是否要独立回放
  • 是否要分别打实验开关
  • 是否要分别设缓存和成本预算

7.5 Qdrant 的启发

Qdrant 当前 Hybrid Queries 官方文档把 hybrid 讲得更像一套多阶段检索语言,而不只是一个布尔开关。文档里明确强调:

  • 可以先做 prefetch
  • 再做融合
  • 融合可选 RRFDBSF
  • 还可以在融合后再叠 Formula Query 做额外打分

这意味着在 Qdrant 的心智里:

  • hybrid 不只是 dense + sparse 并跑
  • 它更像“先构造候选,再决定如何融合,再决定如何加业务打分”

这个思路非常值得借鉴,因为很多团队的问题并不是:

  • 有没有 hybrid

而是:

  • 能不能把“相关性信号”和“业务排序信号”分层

例如:

  • 相关性先由 dense / sparse 召回解决
  • 新鲜度、热度、来源级别、地理距离等再由公式层加权

这样系统会比“把所有东西都塞进同一个最终分数”更容易解释、调试和评测。

7.6 Milvus 的启发

Milvus 当前 RerankingHybrid Search with MilvusMulti-Vector Search 官方文档给出的信号也很清楚:

  • hybrid search 可以来自多个 AnnSearchRequest
  • 最终会对多路结果再做 rerank
  • 内建就支持 RRFRankerWeightedRanker

这个设计的工程含义是:

  • 在 Milvus 视角里,hybrid 从一开始就不是“只有一条向量路”
  • 它允许你把多个表示空间一起拉进候选池

比如同一文档对象,你完全可能同时有:

  • dense text embedding
  • sparse embedding
  • title embedding
  • body embedding

而最终问题会变成:

  • 哪些表示空间先召回
  • 哪些表示空间只参与重排
  • 多路结果最终用 RRF 还是加权融合

这比“只看一个 embedding 字段”更接近真实企业检索。

7.7 这些官方文档放在一起看,真正共同在强调什么

把 OpenAI、Azure、Weaviate、Pinecone、Qdrant、Milvus 这些当前正式文档放在一起看,会出现一个非常稳定的共同结论:

  • 生产检索不是 single score,而是 staged ranking

也就是:

  1. 先召回足够好的候选池。
  2. 再融合多路召回结果。
  3. 再按语义或业务信号重排。
  4. 最后才进入上下文组装和答案生成。

如果你还把检索系统想成:

  • “向量库吐一个 top-k,后面直接回答”

那很容易在复杂企业知识里吃亏。

8. 什么时候先不要上 rerank

如果你现在的问题是这些,先别把 rerank 当万能药:

  • 正确文档根本没进候选池
  • filter 经常把正确结果过滤掉
  • chunk 设计严重不合理
  • 租户和版本经常串
  • query rewrite 质量很差

这些问题没先解决,rerank 只会把错误排得更漂亮。

9. 一个更稳的检索流水线

建议把检索流水线明确拆成下面几层:

  1. query normalization
  2. query rewrite / expansion
  3. lexical retrieval
  4. vector retrieval
  5. filter enforcement
  6. candidate fusion
  7. rerank
  8. context assembly
  9. citation rendering

这样做的价值是:

  • 每一层都能单独评测
  • 故障能定位到具体环节

9.1 候选池深度不要靠拍脑袋,至少要单独实验 top_n -> rerank_n -> context_n

很多团队只配置一个 top_k=10,然后既拿它当召回深度,也拿它当 rerank 输入深度,还拿它当最终上下文长度。

这通常会把三件事混在一起:

  • 召回是否足够宽
  • 重排是否有发挥空间
  • 最终上下文是否足够干净

更稳的做法通常是把三个数拆开:

  • retrieve_n
  • rerank_n
  • context_n

一个很常见的更稳模式是:

  1. 先拉更宽的候选池,例如 retrieve_n = 30~100
  2. 再对较窄集合做重排,例如 rerank_n = 10~30
  3. 最后只送更干净的证据给生成层,例如 context_n = 4~8

为什么这一步很重要?

因为很多“rerank 没效果”的问题,其实不是 rerank 模型不行,而是:

  • 候选池太浅,正确项根本没机会进来

而很多“答案仍然胡”的问题,也不一定是生成模型不行,而是:

  • 最终送给模型的上下文太脏、太长、太互相冲突

9.2 filter -> retrieve -> fuse -> rerank -> assemble 的先后顺序最好固定

很多系统一开始会把这些步骤写得很松散:

  • 有时先 filter
  • 有时先 rerank
  • 有时 query rewrite 之后直接过 semantic ranker

这会让复盘越来越难,因为你根本不知道:

  • 某次结果差,到底是哪个阶段动了手

更稳的生产心智通常是:

  1. 先确定 query scope
  2. 再执行过滤和权限边界
  3. 然后做多路召回
  4. 然后做融合
  5. 然后做重排
  6. 最后做 context assembly

这样每一层的责任会清楚很多:

  • filter 保证范围正确
  • retrieve 保证候选覆盖
  • fuse 保证多信号整合
  • rerank 保证最终顺序
  • assemble 保证证据可消费

10. 评测别只看最终答案

更稳的检索评测至少要分三层:

10.1 召回层

  • Recall@k
  • Hit@k
  • 候选池是否包含正确父文档

10.2 排序层

  • top1 命中率
  • rerank 胜率
  • RRF 融合后相对提升

10.3 业务层

  • 最终答案引用正确率
  • 是否引用了错误版本或错误租户
  • 用户是否需要追问才能拿到正确答案

10.4 分数解释也应该进评测,不然很难调权重

如果你已经上了 hybrid 和 rerank,却没有保留分数拆解,后面常见的尴尬是:

  • 效果变好了,但不知道哪一路贡献的
  • 效果变差了,但不知道是 dense、sparse 还是 rerank 出的问题

更稳的做法通常是把这些都当成评测字段:

  • dense score
  • sparse / lexical score
  • fused score
  • rerank score
  • 最终选入上下文的序号

像 Weaviate 当前文档明确支持返回 score / explainScore,Azure AI Search 当前文档也把 @search.score 和 reranker 分层当成不同阶段的结果。它们都在提醒我们:

  • 调 hybrid 不是只盯“最终第 1 名”
  • 还要看各层分数怎么变化

否则你很难回答:

  • 是 lexical 权重太低
  • 还是 RRF 融合后顺序就已经歪了
  • 还是 reranker 把本来正确的顺序又改坏了

11. Query 类型一定要分桶

不要只看平均分。

至少建议按下面几类 query 分桶:

  • 编号/错误码型
  • 制度/流程型
  • FAQ/问答型
  • 长描述问题型
  • 跨文档综合型
  • 时效敏感型

因为不同桶的最佳策略常常不同:

  • 编号类更依赖 lexical
  • 问答类可能更依赖 dense
  • 综合型往往更依赖 rerank 与证据装配

12. 一个最小离线评测集应该包含什么

建议至少包含:

  • query
  • gold parent document
  • gold chunk 或 gold passage
  • query type
  • tenant / acl scope
  • version expectation
  • 是否需要关键词精确命中

如果没有 tenant / acl / version 这些字段,你就很难验证:

  • 检索是否在正确范围内做对了

12.1 评测集最好强制包含“容易出错的坏样本”

很多团队的离线评测集只放:

  • 常见问法
  • 成功案例
  • 业务最熟悉的 query

这样做出来的分数通常会虚高。

更稳的最小评测集应该故意包含这些“难例”:

  • 编号差一个字符就完全不同的 query
  • 同产品不同版本的 query
  • 同制度不同角色的 query
  • 同义问法跨度很大的 query
  • 需要 freshness 判断的 query
  • 需要严格 tenant / acl 边界的 query

因为真正会把系统打崩的,经常不是平均 query,而是:

  • 边界 query
  • 高风险 query
  • 很像但不能答错的 query

所以检索评测集更像:

  • 能力覆盖集 + 失败暴露集

而不只是:

  • 演示效果集

13. 线上最值得保留的复盘证据

为了让 hybrid 和 rerank 可运营,建议至少保留:

  • raw query
  • normalized query
  • rewritten query
  • vector top-k
  • lexical top-k
  • fused top-k
  • rerank scores
  • final selected context
  • final citations
  • answer version / model version

这部分和 RAG失败复盘专题 可以直接联动。

13.1 最好把“为什么选中它”也留痕,而不只是“选中了什么”

很多线上系统保留了:

  • 最终用了哪些 chunk

但没有保留:

  • 为什么这些 chunk 会被选进来

这会让复盘非常被动,因为你只能看到结果,看不到过程。

更稳的线上证据通常还应包含:

  • dense / sparse 命中来源
  • 融合前排名
  • 融合后排名
  • rerank 前后位置变化
  • 是否命中过滤条件
  • 是否被 freshness / authority / business rule 加权

如果是支持解释字段的平台,最好把解释对象也保留,例如:

  • Weaviate 的 explainScore
  • Azure 的不同阶段 score

这样你才能在事故里真正回答:

  • 是召回把它拉进来的
  • 是融合把它抬上来的
  • 还是 rerank / 业务规则把它推成第一名的

13.2 Query rewrite 版本、embedding 版本和 reranker 版本也要进复盘对象

很多系统只记录:

  • 模型版本
  • 向量库索引版本

但检索质量真正经常波动的地方还包括:

  • query rewrite prompt/version
  • embedding model/version
  • reranker model/version
  • analyzer / tokenizer 配置版本
  • hybrid fusion 参数版本

如果这些版本不留痕,后面你很难判断:

  • 是语义表示变了
  • 是 rewrite 变了
  • 还是排序链路变了

所以一条完整复盘记录最好既能回答:

  • 这次搜到了什么

也能回答:

  • 这次是用哪套检索策略搜出来的

14. 常见症状到治理动作

14.1 编号总搜不准

优先动作:

  • 增强 lexical
  • 检查 tokenizer / analyzer
  • 提高 hybrid 权重中的 sparse 信号

14.2 top-k 里有正确项,但最终答案错

优先动作:

  • 引入或加强 rerank
  • 优化 context assembly
  • 缩小无关候选干扰

14.3 新文档不容易压过老文档

优先动作:

  • 引入 freshness 字段
  • rerank 中加入时效权重
  • 检查 version / status 过滤

14.4 同义问法表现差异太大

优先动作:

  • 做 query rewrite
  • 建立 query type 分桶
  • 检查 embedding 是否适配场景

15. 最常见的反模式

  • 只开 pure vector,不做 lexical 和 filter 协同。
  • 只看最终答案,不保存候选池。
  • 没有 query 分桶,就直接比较平均效果。
  • rerank 上线后只看单次 Demo 体感,不看离线和线上指标。
  • 所有效果问题都怪模型,不拆检索链路。
  • top_krerank_ncontext_n 混成一个参数。
  • 只保留最终 chunk,不保留融合与重排过程。
  • 没有版本留痕,导致 query rewrite、embedding、reranker 变更无法复盘。

16. 推荐上线顺序

  1. 先建立 pure vector baseline。
  2. 再加 metadata filter 和权限边界。
  3. 再补 lexical 或全文检索。
  4. 再做 hybrid 融合。
  5. 最后引入 rerank,并把评测分层。

这个顺序的好处是:

  • 每一步都更容易看清贡献来源

17. 推荐搭配阅读

18. 重点官方资料

以下资源已按 2026-07-09 复核到当前正式入口;其中少数站点对脚本探测会返回 403,但浏览器入口仍可正常访问: