为什么检索"够了"还不够?

RAG系统的召回阶段(向量检索+BM25)追求查全率,返回Top-50甚至Top-100个候选;但LLM上下文有限,塞进去的噪声越多,回答越差。Rerank(重排序)就是第二道精排关卡:用交叉编码器(Cross-Encoder)把"查询-文档"成对打分,只留Top-5喂给LLM。实测在多数业务数据集上,双阶段检索比单阶段向量检索的命中率提升20%-30%。

一、Rerank的核心原理:交叉编码器 vs 双编码器

类型代表模型原理速度精度
双编码器bge-m3, text-embedding查询和文档各自编码,算向量余弦快(可离线)
交叉编码器bge-reranker-v2-m3查询+文档拼接一起过Transformer慢(需在线)

交叉编码器能看到查询与文档每个token的交互,所以精度高;但无法预计算向量,只能在线对候选逐条打分。因此正确的架构是:粗召回用双编码器,精排用交叉编码器

二、最小实现:用FlagEmbedding跑通Rerank

from FlagEmbedding import FlagReranker

reranker = FlagReranker('BAAI/bge-reranker-v2-m3', use_fp16=True)

query = "Agent如何做记忆管理"
candidates = [
    "基于向量的长期记忆存储方案",
    "如何给猫咪洗澡",
    "对话摘要与滑动窗口的短期记忆实现",
]

scores = reranker.compute_score([[query, c] for c in candidates])
print(scores)  # [0.72, 0.05, 0.65] 噪声文档得分显著更低

# 取Top-K
top_k = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)[:2]

三、生产级Rerank服务:缓存+批量+超时

Rerank是在线推理,必须考虑性能,三个要点:

import time
from functools import lru_cache

@lru_cache(maxsize=2048)
def score_pair(query: str, doc: str) -> float:
    return reranker.compute_score([[query, doc]])[0]

def rerank(query: str, docs: list, top_k: int = 5) -> list:
    start = time.time()
    scored = []
    for d in docs:
        # 批量计算,单条超时保护
        try:
            scored.append((d, score_pair(query, d)))
        except Exception:
            scored.append((d, 0.0))  # 打分失败降级为原始顺序
    scored.sort(key=lambda x: x[1], reverse=True)
    print(f"rerank {len(docs)} docs cost {time.time()-start:.2f}s")
    return [d for d, s in scored[:top_k]]

四、效果评估:别拍脑袋说"变好了"

用离线数据集做A/B对比,指标用Recall@KMRR

def recall_at_k(ground_truth, ranked_docs, k=5):
    top = set(ranked_docs[:k])
    return len(set(ground_truth) & top) / len(set(ground_truth))

# 对比:仅向量检索 vs 向量+Rerank
# 典型结果:Recall@5 从 0.61 -> 0.82,MRR 从 0.42 -> 0.67

五、避坑指南

  • **候选集别太小**:Rerank至少喂20条候选,只喂5条等于没召回
  • 2. 别对全库Rerank:交叉编码器在线推理慢,必须配合粗召回

    3. 阈值过滤:得分低于0.3的文档直接丢弃,防止低质内容混入

    4. 监控打分分布:如果分数普遍偏高,说明查询与语料分布漂移,需要重训或换模型

    总结:Rerank是RAG链路里性价比最高的一环——不用换Embedding模型、不用改向量库,只加一层精排就能显著提升答案质量。先把粗召回做扎实,再上Rerank,效果立竿见影。