RAG-03重排组装-Retrieval-Rerank-centric-RAG

本文属于 RAG 工程框架中的「3 重排与证据组装」环节,聚焦「Retrieval Rerank centric RAG」方法。可先阅读 RAG-00.方法概述 再进入本篇。

原理

围绕召回率与排序质量构建迭代闭环。

1
2
3
4
5
6
7
8
flowchart TD
Q[Query] --> Recall[多路召回]
Recall --> Cand[候选文档]
Cand --> RR[重排模型]
RR --> Top[Top-N 证据]
Top --> LLM[生成]
LLM --> Log[在线日志/标注]
Log --> Train[召回与重排再训练]

优缺。

  • 优点:对事实正确性提升最直接。
  • 缺点:需要标注与评估体系支撑。

性能/资源

  • 重排器带来额外推理成本。
  • 训练与标注是长期投入。

应用场景

  • 搜索问答、合规检索、专家助手。

统一合成数据示例

输入数据片段

1
2
3
4
5
6
7
8
{
"query": "差旅报销时限和上限",
"candidates": [
{"doc_id": "D01", "retrieval_score": 0.77, "text": "机票报销上限 2000 元,30 天内提交。"},
{"doc_id": "D09", "retrieval_score": 0.75, "text": "餐补标准 80 元/天。"},
{"doc_id": "D03", "retrieval_score": 0.71, "text": "报销需附原始发票。"}
]
}

中间结果(重排与组装)

1
2
3
4
5
6
7
{
"rerank_top": [
{"rank": 1, "doc_id": "D01", "rerank_score": 0.95},
{"rank": 2, "doc_id": "D03", "rerank_score": 0.62}
],
"assembled_context": ["D01:上限+时限", "D03:凭证要求"]
}

最终生成示例(含引用)

1
2
3
4
5
6
7
{
"answer": "机票报销上限 2000 元,需 30 天内提交,并附原始发票。",
"citations": [
{"doc_id": "D01", "evidence_span": "上限 2000 元,30 天内提交"},
{"doc_id": "D03", "evidence_span": "需附原始发票"}
]
}

原始发表与工程实现

  • 代表性原始发表:MonoBERT (2019), monoT5 (2020)。
  • 核心解决问题:解决候选排序精度不足。
  • 成熟实现工具:bge-reranker, Cohere Rerank。

详细原理拆解

  • 两阶段检索:高召回候选池 + CrossEncoder 精排,优化精度/吞吐平衡。
  • 典型实现可拆为:输入预处理 -> 方法核心计算 -> 候选/证据构建 -> 生成与引用。
  • 工程调优重点:质量(准确率/引用率)与成本(时延/token)的联合优化。
1
2
3
4
5
flowchart LR
In[输入 Query 与知识] --> Core[方法核心计算]
Core --> Rank[匹配/路由/排序]
Rank --> Build[证据组装]
Build --> Out[答案与引用]

工程落地扩展示例

伪代码

1
2
3
4
5
6
7
def two_stage_rag(query, bi_encoder, retriever, cross_encoder, llm, pool_k: int, top_n: int):
qv = bi_encoder.encode(query)
rough = retriever.topk(qv, k=pool_k) # 高召回、低精度
pairs = [(query, d.text) for d in rough]
scores = cross_encoder.predict(pairs) # query-doc 交互
best = sorted(zip(rough, scores), key=lambda x: -x[1])[:top_n]
return llm.generate(query, context=best)

参数示例

1
2
3
4
biencoder_top_k: 80
cross_encoder_top_n: 12
cross_encoder_batch: 16
precision_target: nDCG@10

常见失败案例

  • 失败模式 1:候选池 pool_k 太小,gold 段根本进不了 cross-encoder。
  • 失败模式 2:长文档整段拼进 cross-encoder,超长截断丢否定词。
  • 失败模式 3:重排与生成 引用粒度不一致(段级 vs 句级),用户难审计。

Demo 数据带入计算示例

1
2
粗排 D01 与 D09 分数接近(0.77 vs 0.75);重排后 D01(0.95) >> D09(0.41)——
因 D09「餐补」与问句「时限+上限」交互分低。体现 **Cross-encoder 的 query-doc 交互** 能纠正单塔相似度。
-------------本文结束感谢您的阅读-------------