跳到主要内容

重排序与精排

问题

什么是 Reranker?为什么需要在检索后做重排序?

答案

Reranker 是在初步检索之后,对候选文档进行精细排序的模型。它解决了 Embedding 检索"召回多但排序不精"的问题。

一、为什么需要重排序

阶段模型类型特点
检索(召回)Bi-Encoderquery 和 doc 分别编码,快速(毫秒级)
重排序(精排)Cross-Encoderquery 和 doc 联合编码,精确(但慢)

Bi-Encoder vs Cross-Encoder

  • Bi-Encoder:query 和 doc 独立编码,可以预计算 doc 向量,速度快但交互信息少
  • Cross-Encoder:query 和 doc 一起输入,充分交互,精度高但需要逐对计算

二、主流 Reranker 模型

模型来源特点
bge-reranker-v2-m3BAAI多语言,效果好
jina-reranker-v2Jina AI长文本支持好
Cohere RerankCohere云 API,易用
ms-marco-MiniLM-L-6-v2Cross-Encoder轻量,英文

三、代码示例

from sentence_transformers import CrossEncoder

# 加载 Reranker 模型
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3", max_length=512)

query = "如何配置 Nginx 反向代理"
candidates = [
"Nginx 反向代理配置需要在 server 块中使用 proxy_pass...",
"Apache 的反向代理使用 ProxyPass 指令...",
"Nginx 的 location 块可以配置不同路径的代理规则...",
"Docker 容器网络配置...",
]

# 计算 query 与每个候选的相关性分数
pairs = [[query, doc] for doc in candidates]
scores = reranker.predict(pairs)

# 按分数降序排列
ranked = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)
for doc, score in ranked:
print(f"[{score:.4f}] {doc[:50]}...")

LangChain 集成

from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank

# 第一阶段:向量检索 Top-20
base_retriever = vectorstore.as_retriever(search_kwargs={"k": 20})

# 第二阶段:Reranker 精排到 Top-5
reranker = CohereRerank(model="rerank-v3.5", top_n=5)
retriever = ContextualCompressionRetriever(
base_compressor=reranker,
base_retriever=base_retriever
)

docs = retriever.invoke("如何配置 Nginx 反向代理")
# 返回精排后的 Top-5 文档

四、使用建议

建议说明
检索 20,精排 5检索阶段多召回,Reranker 筛选出最相关的
只在候选较多时使用Top-K < 5 时,Reranker 开销大于收益
注意延迟Cross-Encoder 逐对计算,20 条约增加 50-200ms
可以用 LLM 替代让 LLM 判断文档相关性,效果好但成本高

常见面试问题

Q1: Reranker 会显著增加延迟吗?

答案

  • 轻量模型(MiniLM-L-6):20 条文档约 20-50ms
  • 大模型(bge-reranker-v2-m3):20 条约 100-200ms
  • 对比 LLM 生成的延迟(1-5s),Reranker 增加的延迟通常可接受
  • 优化方式:batch 处理、GPU 推理、限制候选数量

Q2: 不用 Reranker,有替代方案吗?

答案

  1. LLM-as-Judge:让 LLM 对每个文档打分(效果好,但成本高)
  2. 多路召回 + RRF:用混合检索的排名融合代替精排
  3. Embedding 微调:提升初始召回质量,减少对 Reranker 的依赖

相关链接