重排与路由
先说结论
重排序(Reranking)是对初步检索结果进行精排以提升相关性,查询路由(Query Routing)是根据查询特征动态选择最佳检索策略,二者共同提升 RAG 系统的检索质量和系统灵活性。
QUESTION 面试高频:为什么需要重排序?向量检索不够吗? 向量检索使用 Bi-Encoder(查询和文档分别编码再计算相似度),速度快但精度有限——它只看了各自的独立表示,缺少"交叉注意力"。重排序使用 Cross-Encoder(查询和文档拼接后一起过 Transformer),能捕捉 query-doc 之间的细粒度交互,精度大幅提升。代价是速度慢,所以只对 Top-K(通常 20-50 个)结果重排。
重排序(Reranking)
Bi-Encoder vs Cross-Encoder
| 维度 | Bi-Encoder | Cross-Encoder |
|---|---|---|
| 输入 | query 和 doc 分别编码 | query + doc 拼接后一起编码 |
| 速度 | 快(向量预计算) | 慢(每对都要过 Transformer) |
| 精度 | 中等 | 高 |
| 适用阶段 | 粗检索(召回 Top-K) | 精排(对 Top-K 重排) |
| 典型模型 | BGE, DPR, OpenAI Embedding | bge-reranker, Cohere Rerank, ColBERT |
Cross-Encoder 工作原理
输入:[CLS] query [SEP] document [SEP]
↓
Transformer Encoder
↓
[CLS] token 输出 → Linear → 相关性得分
Cross-Encoder 让 query 和 doc 的每个 token 都能互相"看到",通过自注意力机制捕捉细粒度的语义交互。
主流重排模型对比
| 模型 | 特点 | 适用场景 |
|---|---|---|
| bge-reranker-v2-m3 | BAAI 开源,多语言,效果好 | 通用场景首选 |
| Cohere Rerank | API 调用,效果顶级 | 不想自建重排服务 |
| ColBERT | 延迟交互模型,速度/精度折中 | 需要快速重排 |
| LLM 重排 | 用 GPT-4/Claude 做重排 | 追求极致精度 |
| FlashRank | 轻量级,速度快 | 低延迟场景 |
| Jina Reranker | 开源,支持长文档 | 长文档场景 |
ColBERT:延迟交互模型
ColBERT 是介于 Bi-Encoder 和 Cross-Encoder 之间的方案:
每个 query token 与所有 doc token 做内积取最大值,再求和。精度接近 Cross-Encoder,但可以利用预计算加速。
QUESTION 面试高频:重排多少个文档合适? 经验值:先检索 Top-20
50,重排后取 Top-35。重排的文档数量直接影响延迟和成本。Cross-Encoder 对每个 (query, doc) 对都要过一遍 Transformer,50 个文档意味着 50 次前向传播。实践中通常 Top-20 重排就够了,Top-50 收益递减但延迟翻倍。
重排序的工程实践
# 典型的重排管线
results = vector_search(query, top_k=50) # 粗检索
reranked = cross_encoder.rerank(query, results, top_n=5) # 精排
context = "\n".join([doc.text for doc in reranked]) # 拼接上下文
response = llm.generate(query, context) # 生成回答
查询路由(Query Routing)
QUESTION 面试高频:什么是查询路由?为什么需要它?
查询路由是根据用户查询的特征,动态选择最佳的检索策略或数据源。当一个 RAG 系统有多个数据源或多种检索策略时,路由是不可或缺的。
路由场景
| 场景 | 说明 | 示例 |
|---|---|---|
| 数据源路由 | 不同知识库有不同内容 | 产品文档 vs 内部 Wiki vs 代码库 |
| 检索策略路由 | 不同查询适合不同检索方式 | 关键词查询 → BM25,语义查询 → Dense |
| 模型路由 | 不同复杂度用不同模型 | 简单问题 → 小模型,复杂问题 → 大模型 |
| 工具路由 | 判断是否需要调用外部工具 | 实时数据 → 搜索 API,历史数据 → 向量库 |
路由实现方式
| 方式 | 原理 | 优缺点 |
|---|---|---|
| LLM 路由 | 用 LLM 根据查询判断路由目标 | 灵活但增加延迟和成本 |
| 语义分类 | 用嵌入相似度选择最相关数据源 | 快速但不够灵活 |
| 关键词规则 | 基于关键词匹配路由 | 简单但覆盖不全 |
| 多路召回 + 合并 | 所有数据源都检索,合并结果 | 最全但计算开销大 |
LLM 路由示例
ROUTE_PROMPT = """
根据用户查询,选择最合适的数据源:
- product_docs: 产品文档、使用指南、API文档
- internal_wiki: 公司内部知识、流程规范
- code_repo: 代码相关、技术实现细节
- web_search: 实时信息、最新新闻
用户查询:{query}
选择的数据源:
"""
自适应检索策略
| 查询特征 | 推荐策略 |
|---|---|
| 关键词精确匹配(产品号、人名) | BM25 稀疏检索 |
| 语义模糊查询 | Dense Retrieval |
| 简单事实性问题 | 单次检索 + 小模型 |
| 复杂推理问题 | 多步检索 + 大模型 |
| 实时性问题 | Web Search API |
| 全局总结性问题 | GraphRAG |
设计时真正要权衡什么
| 取舍 | 说明 |
|---|---|
| 重排模型大小 vs 延迟 | 大模型精度高但慢,小模型快但精度有限 |
| 路由精度 vs 延迟 | LLM 路由灵活但增加一轮 LLM 调用 |
| 单一策略 vs 多策略路由 | 单一策略简单,多策略效果好但复杂 |
| 重排数量 vs 成本 | Top-20 重排是性价比甜蜜点 |
如果要对外讲,可以怎么概括
"重排序和路由是 RAG 检索优化的两个关键环节。重排序方面,Cross-Encoder 是精度最高的方案——它让 query 和 document 一起过 Transformer,捕捉细粒度的语义交互,精度远超 Bi-Encoder 的向量检索。工程实践上,我通常先检索 Top-2050,再用 Cross-Encoder 重排取 Top-35,这是性价比最高的配置。路由方面,当系统有多个数据源或策略时,用 LLM 做查询路由可以大幅提升检索效率——不是所有查询都需要走最重的路径。核心原则是粗检索用快速模型,精排用高精度模型,分层设计控制成本。"
最后记几条
- Cross-Encoder 精度远超 Bi-Encoder——代价是速度,所以只对 Top-K 重排
- Top-20 重排 → Top-5 送入 LLM 是性价比最优配置
- ColBERT 是速度和精度的折中——延迟交互模型
- 查询路由让系统自适应——不同查询走不同路径
- 分层检索是工程最佳实践——粗筛快速、精排高质量
参考资料
- Nogueira, R. et al. "Passage Re-ranking with BERT" (2019)
- Khattab, O. et al. "ColBERT: Efficient and Effective Passage Search via Contextualized Late Interaction" (SIGIR 2020)
- Cohere Rerank: https://cohere.com/rerank
- BAAI bge-reranker: https://huggingface.co/BAAI/bge-reranker-v2-m3