RAG学习之-Rerank 技术详解:从入门到面试

Rerank 技术详解:从入门到面试

一站式掌握 RAG 中的重排序技术 ------ 从 12 岁能懂的故事,到面试官想听的答案


目录

  1. 核心概念:什么是 Rerank\](#一核心概念什么是 rerank)

  2. 为什么需要 Rerank\](#三为什么需要 rerank)

  3. 代码实现:两阶段检索
  4. 面试回答模板
  5. 知识总结

一、核心概念:什么是 Rerank

1.1 12 岁就能听懂的故事 🍎

问题: 你让两个人帮你挑苹果,有什么区别?

第一个人:快手阿姨(检索)

  • 30 秒抓了 10 个苹果给你
  • 方法:看颜色(红的拿)、看大小(大的拿)、看位置(手边的拿)
  • 结果:快是快,但有些苹果看着红其实有伤

第二个人:品果大师(Rerank)

  • 接过这 10 个苹果,开始仔细检查
  • 方法:摸一摸(软硬)、闻一闻(香味)、掂一掂(水分)、看一看(斑点)
  • 结果:告诉你"这 10 个里真正最好吃的 3 个是这几个"
快手阿姨(检索) 品果大师(Rerank)
速度 30 秒 10 个 🚀 5 分钟 1 个 🐢
准确度 看外表 ⭐⭐⭐ 看内在 ⭐⭐⭐⭐⭐
能大批量吗 可以 太慢,只能挑少量

核心思想:

Rerank = 先快速找一堆候选答案,再花时间仔细排序,把最好的放在最前面

1.2 生活中的例子

场景 检索 Rerank
淘宝买东西 搜索"运动鞋"出来 1000 件 按销量/好评重新排序,展示前 20 个
抖音推荐 先找一批相关视频 根据你的喜好重新排序
高考志愿 把所有大学列出来 按分数/专业/地点排序,选前几个

1.3 概念定位

复制代码
Rerank(重排序技术)
    │
    └── 通常用 Cross-Encoder(模型架构)来实现
问题 答案
Rerank 是什么? 一种重排序技术思想
Rerank 用什么模型? Cross-Encoder
Bi-Encoder 用于什么? 第一阶段检索(召回)

二、技术原理:Bi-Encoder vs Cross-Encoder

2.1 本质定义

Bi-Encoder 和 Cross-Encoder 是基于 Transformer Encoder 的两种应用架构

它们不是 Transformer 原生的设计,而是后人基于 Transformer 的用法总结

2.2 结构对比

Bi-Encoder(双编码器)
复制代码
输入 A → 编码器 E → 向量 a ↘
                        相似度计算 → 得分
输入 B → 编码器 E → 向量 b ↗

特点:两个输入独立编码,无法交互
Cross-Encoder(交叉编码器)
复制代码
输入 A + 输入 B → 编码器 E → Self-Attention 交互 → 分数

特点:两个输入一起编码,充分交互

2.3 Self-Attention 交互差异

Bi-Encoder(无交互)
复制代码
句子 A: [我] [喜欢] [苹果]     句子 B: [苹果] [公司] [发布] [手机]
         │     │      │                   │      │      │      │
         └─────┴──────┘                   └──────┴──────┴──────┘
           Self-Attention                    Self-Attention
           (只在 A 内部)                    (只在 B 内部)

❌ A 的"苹果"看不到 B 的"苹果"
Cross-Encoder(充分交互)
复制代码
输入:[我] [喜欢] [苹果] [苹果] [公司] [发布] [手机]
       │     │      │      │      │      │      │
       └─────┴──────┴──────┴──────┴──────┴──────┘
                    全局 Self-Attention
                  
✅ A 的"苹果"能看到 B 的"苹果",判断是不是同一个意思

2.4 形象比喻

Bi-Encoder Cross-Encoder
比喻 相亲看照片 相亲真人见面
做法 分别给问题和文档拍照,然后对比照片 把问题和文档放在一起仔细读
速度 快 ✅ 慢 ❌
准确度 一般 高 ✅
预计算 可以 不可以

2.5 代码对比

Bi-Encoder
python 复制代码
from sentence_transformers import SentenceTransformer

model = SentenceTransformer('all-MiniLM-L6-v2')

# 分别编码
embedding_a = model.encode("问题")
embedding_b = model.encode("文档")

# 计算相似度
score = cosine_similarity(embedding_a, embedding_b)

特征encode() 单独调用,向量事后计算相似度

Cross-Encoder
python 复制代码
from sentence_transformers import CrossEncoder

model = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')

# 一起输入
score = model.predict([["问题", "文档"]])

特征predict() 输入是成对的,直接输出分数

2.6 对比总结表

特性 Bi-Encoder Cross-Encoder
输入方式 问题、文档分开编码 问题 + 文档拼在一起编码
输出 两个向量 一个相似度分数
预计算 ✅ 可以提前算文档向量 ❌ 不能预计算
检索速度 🚀 快(毫秒级) 🐢 慢(秒级)
准确度 ⭐⭐⭐ 一般 ⭐⭐⭐⭐⭐ 很高
适用场景 大规模检索 精排序 Rerank
计算复杂度 O(n) O(n²)

三、为什么需要 Rerank

3.1 核心问题:向量检索有先天缺陷

缺陷 1:向量检索是"粗匹配"
复制代码
用户问:"Python 怎么读取文件?"

向量检索返回:
├── ✅ "Python 文件操作方法大全"  ← 很相关
├── ❌ "Python 入门教程"          ← 标题有 Python,但内容不相关
├── ❌ "如何管理你的文件"         ← 有"文件",但讲的是整理文件
└── ✅ "Python open() 函数详解"   ← 很相关,但排在第 8 位

问题 :向量检索只看"整体相似度",不懂真正的相关性

缺陷 2:词汇不匹配
复制代码
文档里写:"使用 open() 函数打开文件"
用户问:"Python 怎么读取文件?"

→ 没有共同关键词!向量相似度可能很低

但如果有一个模型能理解语义

  • "open()" = "读取文件"
  • 它就知道这是高度相关的
缺陷 3:长文本吃亏
复制代码
文档 A:整篇都在讲"Python 文件操作"(1000 字)
文档 B:第一段讲"Python 文件操作",后面 90% 讲别的(2000 字)

向量检索可能觉得 B 更相似,因为总内容更多
但 A 才是真正相关的!

3.2 实际数据对比(BEIR 基准)

方法 Recall@10 MRR NDCG@5
向量检索(Bi-Encoder) 0.45 0.40 0.50
+ Rerank(Cross-Encoder) 0.65 0.58 0.68
提升 +44% +45% +36%

3.3 两阶段检索架构

复制代码
Stage 1: 向量检索(快)
├── 从 10 万文档中快速筛选 20 个候选
├── 耗时:10-20ms
└── 成本低

Stage 2: Rerank(慢但精)
├── 仔细判断 20 个候选的相关性
├── 耗时:50-200ms(20 个文档)
└── 成本较高

最终:给你看 Top-5 最相关的

3.4 适用场景

✅ 适合用 Rerank 的场景
场景 原因
专业领域问答(医疗、法律) 需要高精度,不能出错
代码检索 变量名不同但功能相同的代码需要被找到
长文档检索 避免"整体相似但内容不相关"
多语言检索 不同语言表达相同意思
歧义查询 "苹果"是水果还是公司?
❌ 可以不用 Rerank 的场景
场景 原因
简单事实查询 "珠穆朗玛峰多高"直接检索就够了
延迟敏感 Rerank 增加 100-500ms 延迟
预算有限 Rerank 增加计算成本

四、常用 Rerank 模型选型

4.1 模型清单总览

模型 发布者 语言 特点 适用场景
BGE-Reranker-base 智源 中英 中文最强,平衡速度和精度 中文知识库、生产环境
BGE-Reranker-large 智源 中英 精度最高,稍慢 专业领域、质量优先
Cohere Rerank Cohere 多语 API 服务,免部署 不想自己部署
Jina Reranker Jina 多语 支持长文本 长文档检索
ms-marco-MiniLM Microsoft 英文 轻量快速 快速原型、英文场景
bge-reranker-v2 智源 中英 最新版,支持混合检索 复杂检索场景

4.2 模型选择指南

场景 推荐模型
中文知识库 BGE-Reranker-base
英文场景 ms-marco-MiniLM 或 BGE
长文档(>1000 字) Jina Reranker
延迟敏感 ms-marco-MiniLM
质量优先 BGE-Reranker-large
不想部署 Cohere Rerank
资源有限(CPU) bge-reranker-v2-minilm

一句话记忆:

"中文用 BGE,英文用 Marco,长文本用 Jina,不想部署用 Cohere。"

4.3 性能对比(中文场景)

模型 Recall@10 MRR 延迟 (20 文档) 模型大小
BGE-Reranker-large 0.68 0.61 250ms 1.3GB
BGE-Reranker-base 0.65 0.58 150ms 440MB
ms-marco-MiniLM 0.58 0.52 80ms 80MB
Cohere Rerank 0.64 0.57 300ms(API) -
无 Rerank(基线) 0.45 0.40 - -

五、代码实现:两阶段检索

5.1 完整实现

python 复制代码
from sentence_transformers import SentenceTransformer, CrossEncoder
import numpy as np

class TwoStageRetriever:
    """两阶段检索器:检索 + 重排序"""
  
    def __init__(
        self,
        embed_model_name: str = 'all-MiniLM-L6-v2',
        rerank_model_name: str = 'BAAI/bge-reranker-base',
        top_k_retrieve: int = 20,
        top_k_rerank: int = 5
    ):
        # Stage 1: Bi-Encoder 用于快速检索
        self.embedder = SentenceTransformer(embed_model_name)
      
        # Stage 2: Cross-Encoder 用于精排序
        self.reranker = CrossEncoder(rerank_model_name)
      
        self.top_k_retrieve = top_k_retrieve
        self.top_k_rerank = top_k_rerank
        self.documents = []
        self.doc_embeddings = None
  
    def index(self, documents: list[str]):
        """索引文档"""
        self.documents = documents
        # 预先计算所有文档的向量
        self.doc_embeddings = self.embedder.encode(documents)
        # 归一化
        self.doc_embeddings = self.doc_embeddings / np.linalg.norm(
            self.doc_embeddings, axis=1, keepdims=True
        )
  
    def retrieve(self, query: str) -> list[tuple[str, float]]:
        """两阶段检索"""
        # === Stage 1: 向量检索(快)===
        query_embedding = self.embedder.encode([query])
        query_embedding = query_embedding / np.linalg.norm(query_embedding)
      
        # 计算余弦相似度
        similarities = np.dot(self.doc_embeddings, query_embedding.T).flatten()
      
        # 取 Top-20 候选
        candidate_indices = np.argsort(similarities)[::-1][:self.top_k_retrieve]
        candidate_docs = [self.documents[i] for i in candidate_indices]
      
        # === Stage 2: Rerank(慢但精)===
        pairs = [[query, doc] for doc in candidate_docs]
        rerank_scores = self.reranker.predict(pairs)
      
        # 重新排序
        ranked_results = sorted(
            zip(candidate_docs, rerank_scores),
            key=lambda x: x[1], reverse=True
        )
      
        # 返回 Top-5
        return ranked_results[:self.top_k_rerank]


# 使用示例
if __name__ == "__main__":
    retriever = TwoStageRetriever()
  
    docs = [
        "Python 中 open() 函数用于打开文件",
        "Python 入门教程:第一个 Hello World 程序",
        "如何管理电脑上的文件和文件夹",
        "Python 文件操作:read() write() close() 方法详解",
    ]
    retriever.index(docs)
  
    query = "Python 怎么读取文件?"
    results = retriever.retrieve(query)
  
    print(f"查询:{query}\n")
    for i, (doc, score) in enumerate(results, 1):
        print(f"[{i}] (得分:{score:.4f}) {doc}")

5.2 关键代码解析

python 复制代码
# Stage 1: Bi-Encoder 检索
query_embedding = self.embedder.encode([query])  # 编码查询
similarities = np.dot(self.doc_embeddings, query_embedding.T)  # 矩阵乘法算相似度
candidate_indices = np.argsort(similarities)[::-1][:20]  # 取 Top-20

# Stage 2: Cross-Encoder Rerank
pairs = [[query, doc] for doc in candidate_docs]  # 构建 (查询,文档) 对
rerank_scores = self.reranker.predict(pairs)  # Cross-Encoder 打分
ranked_results = sorted(zip(candidate_docs, rerank_scores), key=lambda x: x[1], reverse=True)

六、面试回答模板

6.1 30 秒简短版

"Rerank 的核心思想是:先广撒网,再精挑选。

第一阶段用向量检索快速召回 Top-20 候选文档,

第二阶段用 Cross-Encoder Rerank 精排序,最终返回 Top-5 给 LLM。

用少量的时间代价,换取检索质量的大幅提升。"

6.2 2 分钟完整版

第一步:说问题

"我发现纯向量检索有几个问题:

  1. 只看向量相似度,不懂真正的相关性
  2. 词汇不匹配时效果差(用户说'读文件',文档写'open()')
  3. 长文档容易吃亏"
第二步:说方案

"我引入了 Rerank 机制,采用两阶段架构:

Stage 1 检索:用 Bi-Encoder 从 10 万文档中快速召回 Top-20,耗时 10-20ms。

Stage 2 Rerank:用 Cross-Encoder 对这 20 个文档逐一打分,重新排序后取 Top-5,耗时 100-200ms。

Cross-Encoder 能把问题和文档拼在一起编码,通过 Self-Attention 捕捉细粒度语义交互,所以更精准。"

第三步:说结果

"效果提升很明显:

  • Recall@10 从 0.45 提升到 0.65(+44%)
  • MRR 从 0.40 提升到 0.58(+45%)
  • 延迟增加约 100-200ms,在可接受范围内"

6.3 被追问技术细节

问题 参考回答
Bi-Encoder 和 Cross-Encoder 有什么区别? "Bi-Encoder 分别编码,快但粗糙;Cross-Encoder 拼接编码,慢但精准。比喻:相亲看照片 vs 真人见面。"
为什么不只用 Rerank? "Cross-Encoder 不能预计算,10 万文档要算 5000 秒。所以先用 Bi-Encoder 快筛 20 个,再 Rerank 这 20 个,兼顾速度和精度。"
用的什么 Rerank 模型? "BGE-Reranker-base,中文场景效果最好,速度和精度平衡。"
Rerank 增加多少延迟? "每个文档约 5-10ms,20 个文档约 100-200ms。相比 LLM 生成的 1-2 秒,可以接受。"

6.4 加分项:说出 Trade-off

"Rerank 不是银弹,需要权衡:

  • 延迟敏感场景(实时对话)→ 可以不用 Rerank
  • 质量优先场景(专业问答)→ Rerank 是必须的
  • 我的项目是知识库问答,对准确率要求高,所以选择了 Rerank"

6.5 杀手锏:说出踩过的坑

"我一开始直接用 Cross-Encoder 对所有文档排序,结果延迟爆炸(5 秒+)。

后来改成两阶段:

  1. 向量检索从 10 万 → 20
  2. Rerank 从 20 → 5

延迟降到 200ms,效果还更好了。

这个教训让我理解到:好的架构不是堆模型,而是让每个模型在自己擅长的位置发挥作用。"

6.6 万能模板(背下来)

复制代码
核心思想:先粗筛,再精排

为什么:又快又准难兼得

怎么做:Bi-Encoder 快筛 20 个 → Cross-Encoder 精排 5 个

效果:Recall@10 提升 44%,延迟增加 100-200ms

比喻:快手阿姨抓苹果 → 品果大师选最好的

6.7 面试关键词清单

关键词 含义
Bi-Encoder 双编码器,向量检索用的
Cross-Encoder 交叉编码器,Rerank 用的
两阶段检索 Recall + Rerank
Recall@K 召回率指标
MRR / NDCG 排序质量指标
Self-Attention Cross-Encoder 的核心机制
预计算 Bi-Encoder 可以提前算文档向量
Trade-off 速度 vs 精度的权衡

七、知识总结

7.1 核心要点

知识点 核心内容
Rerank 是什么 先粗筛,再精排
为什么需要 向量检索有缺陷,需要更精准排序
用什么模型 Cross-Encoder
Bi-Encoder 用途 第一阶段快速检索
效果提升 Recall@10 提升 40%+
延迟代价 100-200ms
常用模型 BGE-Reranker-base(中文首选)

7.2 记忆口诀

Bi 检索,Cross 重排
先粗筛,再精排
中文就用 BGE,不想部署 Cohere
两阶段是标准做法,用时间换精度

7.3 一句话金句

"Rerank 就是用时间换精度,先广撒网再精挑选,是工业界提升检索效果的标准做法。"


文档整理日期:2026-04-14
基于 RAG 学习项目整理

相关推荐
AI工具指南2 小时前
2026年AI PPT工具横评:内容准确性、生成速度与排版质量实测
人工智能·powerpoint
东离与糖宝2 小时前
模块化基础:包、模块、导入导出设计思想
人工智能
kishu_iOS&AI2 小时前
机器学习 —— 总结
人工智能·python·机器学习·线性回归
Lab_AI2 小时前
电子实验记录本ELN企业案例:创腾科技iLabPower ELN助力浙邦制药创新转型,降本增效!
人工智能
爱凤的小光2 小时前
ROS1/ROS2中TF坐标变换---个人学习篇
学习
才兄说2 小时前
机器人二次开发高复杂度巡检?绕行率低于10%
人工智能·机器人
报错小能手2 小时前
ios开发方向——swift并发进阶核心 Task、Actor、await 详解
开发语言·学习·ios·swift
阿洛学长2 小时前
AI编码工具重塑开发流程——GitHub Copilot实战应用与效率提升指南
人工智能·github·copilot
cczixun2 小时前
GPT-6(Spud)全球发布:AGI 最后一公里,重新定义 AI 生产力边界
人工智能·gpt·agi