2026年5月28日 周四晚上19:30,报名腾讯会议了解“如何转型成为前线部署工程师(FDE)”(限30人)
免费POC, 零成本试错
FDE知识库

PDE知识库

学习大模型的前沿技术与行业落地应用


我要投稿

每个RAG工程师都应该了解的Ranking技术

发布日期:2026-05-22 06:05:18 浏览次数: 1510
作者:AI算法之道

微信搜一搜,关注“AI算法之道”

推荐语

RAG系统的成败,往往取决于重排序技术。掌握核心排序算法,才能让AI应用真正精准高效。

核心内容:
1. Ranking技术为何是RAG成功的关键
2. Pointwise、Pairwise、Listwise三大排序范式
3. LambdaMART等核心算法的工作原理与应用价值

杨芳贤
53AI创始人/腾讯云(TVP)最具价值专家
点击蓝字
关注我们










01


引言



在做RAG日常应用中,很多人都不谈论Ranking技术——事实上重排序技术直接决定了你的 AI 应用成功还是失败。
GoogleNetflix、带网页搜索的ChatGPT。它们有什么共同点?——一个Ranking算法决定了你先看到什么。
LTR(Learning to rank)在日常开发调试为什么 RAG 流水线对某些查询返回垃圾结果时,反复出现在我们面前。算法本身不难找到。但几乎所有构建 AI 应用的人似乎都不了解底层的Ranking技术。
你的RAG 流水线和你选择的排序器一样好。 给 LLM 喂不相关的上下文,再多的提示词工程也救不了你。RAG 中的"R"(检索)其实是一个穿着检索外衣的排序问题。
本文涵盖基础知识:为什么Ranking不同于分类、LambdaMART 实际上是如何工作的,以及这一切对 RAG 意味着什么。





02

为什么是Ranking?


标准机器学习对每个实例预测一个单一数值。例如垃圾邮件或非垃圾邮件,猫或狗,价格估算等。而Ranking则不同。
给定一个查询和一组文档,产生一个最优排序,让最相关的条目排在最前面。
关键在于:绝对分数无关紧要,只有相对顺序才重要。
一个模型对两个文档给出 0.7 和 0.5 的相关性分数,与另一个给出 0.001 和 0.0005 的模型产生完全相同的排序。然而标准的回归指标会严重惩罚第二个模型。
考虑两个模型对同一查询的一个相关文档和一个不相关文档进行打分:
  • 模型 A:相关文档 0.1,不相关文档 0.2——分数本身的误差小,但顺序错了
  • 模型 B:相关文档 0.7,不相关文档 0.5——绝对误差更大,但排序正确
模型 B 胜出。用户看不到分数,他们看到的是排序后的次序。你不能简单地去最小化均方误差,因为更低的回归误差并不能保证更好的排序。
LTR 需要专门设计的损失函数,来优化我们真正关心的东西:排序次序本身的质量。






03

三大范式


该领域最终形成了三种方法。它们在简洁性、计算成本和理论完备性之间各有取舍。
  • Pointwise单点法:最直接的路径
单点法将排序视为回归问题。对每个文档独立打分,然后按分数排序,完成
不需要专门的损失函数或架构。如果你已经有了一个可用的分类流程,那你就得到了一个排序器。
问题在于,独立地对文档打分忽略了比较。没有任何机制能保证对于同一查询,相关文档的分数一定高于不相关文档。它优化的是错误的目标,然后寄希望于排序结果能凑合着用。
有时候确实凑合。这种程度足以用于原型开发,但当排序质量真正重要时,它并不可靠。
  • Pairwise配对法:直接比较文档
配对法将Ranking重新定义为在文档对上的二元分类。对于某个查询下的文档 A 和 B,预测哪个应该排在更前面。训练数据被转换成配对形式:(查询, 文档A, 文档B, 标签),其中标签指示 A > B 还是 B > A
微软研究院在 2005 年提出的开创性算法 RankNet,对这些配对比较应用交叉熵损失,训练神经网络以最小化排序错误的配对。关键的技术优势在于:配对比较比独立打分更接近真正的排序目标。
代价是计算量。对于每个查询有个文档,需要处理 O(n²) 个文档对。一个有 100 个候选文档的查询会产生近 5000 个训练对。将其扩展到数百万个查询,存储就变成了一个实际问题。
此外,配对法也没有考虑完整的列表结构。一个模型可能正确排序了位置 1–2 的文档,却在位置 5–6 上出现严重错误。这两者对配对损失的贡献是相等的,但对用户而言,前者远比后者重要——用户很少会滚动浏览前几个结果之后的内容
  • Listwise列表法:直接优化我们真正衡量的指标
列表级方法直接对整个排序列表进行优化。ListNet 基于 Plackett-Luce模型对所有可能的排列序列进行概率分布建模,并通过最小化预测分布与真实分布之间的 KL 散度来训练。AdaRank 则借助 Boosting 算法直接优化 NDCG 等信息检索指标。
这些方法在理论上更具优势,因为它们直接优化我们实际评估的指标。但它们面临一个根本性障碍:NDCG 等指标属于不可微的阶跃函数。当文档得分相互超越时,其排名位置会发生离散的跳变,导致无法为标准的反向传播算法计算梯度。
那么,人们究竟是如何实际优化 NDCG 的呢?





04

Lambda Gradients

技术的突破来自 LambdaRank(2006年)及其梯度提升变体LambdaMART2010年)。这一技巧简单得出乎意料。
我们不再从损失函数推导梯度(因为对于不可微的评估指标,这根本做不到),而是直接将梯度定义为推动文档向其正确排序位置移动的“力”。
可以把它想象成物理学。跳过能量函数,直接测量力。我们知道文档应该朝哪个方向移动(即朝向它们的正确位置),并且能计算出如果它们移动了,排序指标会提升多少。这就足够了。
文档对的 lambda 梯度将 RankNet 的逐对pairwise梯度与实际指标变化量结合了起来:
λᵢⱼ = σ(sⱼ — sᵢ) × |ΔNDCG|
其中 |ΔNDCG|表示如果文档 i 和 j 交换位置,NDCG 会变化多少。如果提升某文档的位置能显著改善 NDCG,它就会获得更大的梯度幅值;而已经接近正确位置的文档,其梯度则较小。
这种方法通过在排序完成后计算梯度,巧妙地绕过了指标的不可微性。即使指标本身相对于分数不可微,指标的变化量依然是可计算的。
LambdaMART 将这些 lambda 梯度与梯度提升决策树GBDT相结合,构建出一个集成模型:其中每棵树都在拟合前一棵树留下的残差梯度。该算法赢得了 2010 年雅虎学习排序Learning to Rank挑战赛第一赛道Track 1的冠军,并且至今仍是各大搜索引擎在生产环境中的核心主力。
目前它已集成在 XGBoostrank:ndcg 目标函数)、LightGBMlambdarank)和 CatBoostYetiRank)中。以下是实际应用示例:
from lightgbm import LGBMRankerranker = LGBMRanker(objective="lambdarank", metric="ndcg")ranker.fit(    X_train, y_train,    group=query_doc_counts,  # [10158= 3 queries with 10158 docs    eval_set=[(X_val, y_val)],    eval_group=[val_query_counts],    eval_at=[510]  # NDCG@5, NDCG@10)
group参数至关重要。它告诉排序模型哪些文档属于同一个查询,从而启用列表感知(list-aware)优化。缺少它,算法就会退化回逐点(pointwise)方法。





05

衡量指标

在深入之前,我们需要一套统一的术语来衡量排序质量。不同的指标捕捉了"好"这一概念的不同方面。
  • NDCG:黄金标准
NDCG(归一化折损累积增益,Normalized Discounted Cumulative Gain处理的是带有分级相关性和位置依赖权重的场景。并非所有相关文档都具有同等的相关性。有些是完全匹配,有些只是略有用途。NDCG 能够捕捉到这种细微差别。
其公式对位置施加对数折损:
DCG@k = Σᵢ (2^relevanceᵢ — 1) / log₂(1 + i)
位置 1 的文档获得全部积分。位置 2 的文档被折损 log₂(3) ≈ 1.58。到了位置 10,折损因子为 log₂(11) ≈ 3.46。这反映了用户的真实行为:他们对顶部结果的关注度远高于后面。
通过除以理想排序(即完美排序下的 NDCG 值)进行归一化,得到 [0, 1] 之间的分数。NDCG@10 为 0.85 意味着:你在前 10 个结果中达到了最佳可能排序的 85%。
NDCG 主导了学术研究,因为它能处理多级相关性,并且会惩罚排在较后位置的相关文档。如果你只能跟踪一个指标,那就选 NDCG
  • MRR:第一个好结果在哪?
MRR(平均倒数排名)回答一个更简单的问题:平均而言,第一个相关结果出现在多靠后的位置?
MRR = (1/|Q|) × Σ(1/rankᵢ)
如果第一个相关结果在位置1,该查询贡献1.0。位置2贡献0.5。位置10贡献 0.1。
这对于“手气不错”场景(用户只想要一个正确答案)至关重要。这也直接关系到 RAG 系统为生成而选择上下文的过程。如果你的 RAG 流程只取 top-1 结果,MRR 告诉你这个结果实际相关的频率有多高。
  • MAP:精确率-召回率的平衡
MAP平均准确率均值)针对二元相关性,计算所有召回水平上的平均准确率,然后在所有查询上取平均。本质上就是精确率-召回率曲线下的面积。它比 NDCG 更容易解释,但代价是丢失了分级相关性
  • Precision@k 与 Recall@k
Precision@k和 Recall@k只是统计 top-k 结果中的相关条目数量。Precision@10= 0.3 意味着你前 10 个结果中有 3 个是相关的。不过,它们没有位置加权。
对于 RAG 应用,当你为重排序阶段检索候选文档时,Recall@k 非常重要。如果你的第一阶段检索完全漏掉了相关文档,那么后续无论多强的重排序模型都无力回天。





06
从BM25到BERT


传统的学习排序(LTR)模型消费的是特征向量,而非原始文本。在神经方法出现之前,特征工程是竞争的主战场。团队会在 TF-IDF 分数、BM25 变体、文档长度归一化以及链接分析信号的组合上无休止地迭代。
LETOR 基准数据集标准化了 46 个特征,涵盖在文档不同区域(标题、正文、锚文本)计算出的词频,以及 PageRank 等其他信号。构建一个排序器,就意味着构建一个特征流水线。
神经模型通过直接从文本中学习特征,彻底改变了这一局面。
  • DSSM:第一个基于神经网络的排序器
微软于 2013 年提出的 DSSM (深度结构化语义模型)开创了神经网络排序的先
河。它通过多层感知机将查询和文档映射到一个共享的语义空间,然后计算余弦相似度。
其核心理念是捕捉语义匹配。"最适合初学者的编程语言" 应该能匹配到关于 "易学的编码语言" 的文档,即使两者之间没有词语重叠。
这种方法部分有效。但忽略精确词项信号也带来了问题:当查询包含特定产品编号、专业术语或专有名词时,关键信息就会丢失。模型学会了理解"含义",却忘记了"词语"本身。
  • BERT 时代到来
Transformer 革命于 2019 年 1 月到来。Nogueira  Cho  BERT 应用于段落重排序,在 MS MARCO 上实现了 27% 的相对 MRR@10 提升——这是该基准测试历史上最大的一次单次跃升。此后,所有顶级的提交结果都基于 BERT 或其变体。
关键突破在于交叉注意力机制(cross-attention)BERT 将查询和文档作为整体联合处理,使得每个查询词元(token)都能关注到文档中的所有词元,反之亦然。这能够捕捉独立编码器无法建模的细粒度交互:
  • 某个特定查询词是否出现在文档的特定位置
  • 文档中的论点是否支持或反驳查询的前提
  • 文本语气是否与用户意图匹配
但这种强大能力也带来了代价——而这一代价,恰恰定义了现代检索系统的架构范式。




07
Cross-Encoders Vs BI-Encoders


这一架构区分对于构建生产级系统至关重要。如果选错,你构建的系统要么慢到无法实用,要么准度低到毫无价值。
  • 交叉编码器Cross-Encoders:极致准确,难以扩展
交叉编码器将查询和文档拼接成单个输入:
[CLS] query tokens [SEP] document tokens [SEP]
完整的Transformer 中交叉注意力能够捕捉细粒度的交互。最终使用 [CLS] 词元的表示输入到一个分类器中,产生相关性分数。
交叉编码器能达到最高的精度,但也几乎无法扩展。
对于 个候选文档,每个查询需要对这 n 个文档分别执行完整的 Transformer 前向传播。你不能预先计算文档表示,因为表示本身依赖于查询。在 GPU 上,BERT 推理每个文档大约耗时 5–20 毫秒。对于一个包含 100 万个文档的语料库,这意味着每个查询需要 5,000–20,000 秒——完全不可行。
  • 双编码器Bi-Encoders:极致扩展,牺牲细节
双编码器通过独立的编码器分别处理查询和文档,生成独立的嵌入向量,再通过点积或余弦相似度计算相关性。
文档嵌入可以离线预计算并索引到向量数据库中。查询时只需一次编码器前向传播,再对整个语料库执行高效的近似最近邻ANN搜索。面对数百万文档实现亚 100 毫秒延迟已成为常规操作。
代价是:缺乏交叉注意力意味着会丢失查询与文档之间的细粒度交互。模型必须在看到查询之前,就将所有文档信息压缩进一个固定长度的向量中——部分信息不可避免地会丢失。
  • 关键数据对比
正是这一根本权衡,使得现代检索系统普遍采用两阶段架构:先用双编码器快速召回候选集,再用交叉编码器精细重排序,兼顾效率与精度。






08
两阶段检索


目前已成为生产系统主流、并广泛落地的解决方案是:两阶段检索。
Two-stage retrieval balances speed and accuracy: fast first-stage recall followed by precise cross-encoder re-ranking.
  • 第一阶段:快速召回(Fast Recall)
使用双编码器(Bi-Encoder) BM25(或两者结合),从可能高达数百万的文本块中快速召回 top-50 到 top-100 的候选结果。
此阶段优先保证召回率(Recall),而非精确率(Precision)。如果在此阶段漏掉了相关文档,将是致命错误——下游任何组件都无法挽回这一损失。
  • 第二阶段:精准重排序(Accurate Re-ranking)
对候选集应用计算成本高但精度强的交叉编码器(Cross-Encoder),将其重排序并筛选出最终进入大语言模型(LLM)上下文的 top-3 到 top-10 结果。
此阶段优先保证精确率:你已有 100 个候选,现在要选出真正最重要的那 5 个。
数学上完全可行:
假设语料库包含 4000 万个文本块,若直接对每个块应用 BERT 推理,单次查询将耗时超过 50 小时。而向量搜索可在 100 毫秒内 完成同等规模的候选召回;再对 100 个候选执行交叉编码器重排序,仅增加 100–200 毫秒延迟。总延迟控制在 500 毫秒以内——这正是生产环境可接受的量级。
对 RAG 而言,这一架构更是不可妥协。关于"中间迷失"(Lost in the Middle)现象的研究表明:随着上下文长度增加,大语言模型对信息的召回能力会下降——埋在长上下文中间的内容常常被忽略。你无法通过简单"塞入更多文档"来弥补这一缺陷;关键在于塞入正确的文档。
而重排序(Re-ranking),正是帮你找到这些正确文档的核心手段。






09


混合检索


生产系统中一个一致的发现:将 BM25 与稠密检索(Dense Retrieval)结合,效果优于单独使用任一方法

  • BM25 擅长捕捉精确关键词匹配:产品编号、专业术语、专有名词,或任何嵌入模型在向量空间中可能无法良好表示的内容。
    例如搜索 "error code 0x80070005",BM25 能精准定位该字符串;而稠密检索?可能会返回"权限错误"这类语义相近但实际无用的结果。
  • 稠密检索则能处理词汇不匹配问题。例如查询 "如何修复运行缓慢的笔记本电脑?",即使文档中没有"缓慢""笔记本电脑"等字词,也能匹配到关于"电脑性能优化"或"Windows 启动项管理"的内容。

倒数排名融合(Reciprocal Rank Fusion, RRF)能有效合并两类结果:

score(d) = Σ 1/(k + rank(d, retriever))

其中 k 通常设为 60。被两种检索器都排在前面的文档会跃升至顶部;仅被一种检索器发现的文档也会贡献分数,但权重较低。

一个健壮的 RAG 流水线通常如下:

  • 混合检索BM25 召回 top-50 + 稠密检索召回 top-50

  • 合并去重:通过 RRF 融合 → 约 75 个唯一候选

  • 重排序:交叉编码器筛选出 top-10

  • 生成:LLM 接收优化后的上下文

这并非过早优化,而是已被验证有效的基线架构






10
生产级重排序


当你准备在流水线中加入重排序时,主要有三条路径:

  • Cohere Rerank:托管式强大能力

Cohere 的 Rerank 3.5 提供托管 API,价格约为 每 1000 次搜索 2 美元(一次搜索 = 1 个查询 + 最多 100 个文档)。支持 100+ 语言,能处理 JSON 和表格,基准测试表现优异。

import cohereco = cohere.Client('your-api-key')results = co.rerank(    query="What causes memory leaks in Node.js?",    documents=retrieved_chunks,    model="rerank-v3.5",    top_n=5)

无需管理 GPU,多语言支持扎实。缺点:按查询付费,费用会累积。

  • BGE 重排序器:开源、生产就绪

BGEBAAI 通用嵌入)提供 Apache 2.0 许可的重排序器,你可以自行托管。bge-reranker-v2-m3 支持多语言查询。bge-reranker-v2-gemma 以 20 亿参数骨干网络将精度推得更高。

from FlagEmbedding import FlagRerankerreranker = FlagReranker('BAAI/bge-reranker-v2-m3', use_fp16=True)scores = reranker.compute_score([    [query, doc] for doc in candidate_documents])

自托管消除了 API 成本,但需要 GPU 推理基础设施。对于高流量应用,自托管在经济上更优。对于原型和中等规模,托管 API 在简洁性上胜出。

  • MS-MARCO MiniLM:轻量级起点

sentence-transformers 提供了在 MS-MARCO 上训练的交叉编码器,运行速度足以用于原型开发。cross-encoder/ms-marco-MiniLM-L-6-v2 只有 2200 万参数,精度合理。在投入更大的模型之前,用它来验证重排序是否有帮助,足够了

from sentence_transformers import CrossEncodermodel = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')scores = model.predict([    [query, doc] for doc in candidate_documents])

从这里开始。当需要生产级精度时,再迁移到 BGE 或 Cohere









11
模型微调


现成的重排序器针对通用网页搜索进行优化。医疗、法律、金融和技术领域有其特定的相关性标准、术语和文档结构,通用模型会遗漏这些。

微调可以弥合这一差距,但瓶颈在于训练数据。

  • 合成数据生成

你很可能没有成千上万的带标注的查询-文档对。但你确实有文档。LLM 可以填补这个空白。

流程如下:

  • 对每个文档片段,提示 LLM 生成该片段能够回答的合理查询。

  • 使用另一个 LLM(或同一个)对查询-文档相关性进行评分(例如按等级打分)。

  • 从其他片段中采样负例。

  • 在(查询,正文档,负文档)三元组上训练。

这不是完美的数据,但是领域特定的数据。在合成数据上微调的模型,在领域基准上始终优于通用模型。

  • 困难负例挖掘

有效微调的秘诀:困难负例。

随机负例太简单了。如果你训练一个医疗搜索重排序器,负例中包含关于烹饪食谱的文档,模型学不到任何有用的东西。它已经知道医疗查询不匹配烹饪内容。

困难负例是那些“几乎匹配但实际不匹配”的文档。使用你当前的检索器为训练查询找到 top-k 候选,过滤掉真正相关的文档,剩下的高相似度但不相关的文档就成为困难负例

# Pseudo-code for hard negative miningfor query, positive_doc in training_data:    candidates = retriever.search(query, top_k=20)    hard_negatives = [        doc for doc in candidates         if doc != positive_doc and not is_relevant(query, doc)    ]

针对困难负例训练的模型学会的是做出精细的区分,而不是明显的区分。这正是生产环境排序所需要的。







12
LLM技术革命


LLM 再次改变了游戏规则。

  • RankGPT行之有效的零样本排序

RankGPT证明GPT-4 可以通过指令生成排列来进行零样本排序。给定一个查询和候选文档LLM 输出一个重新排序后的列表。滑动窗口策略可以处理超过上下文长度的文档。

结果如何?使用零样本提示的 GPT-4  TRECBEIR和多语言基准上超越了有监督系统。不需要训练数据。这项成果获得了 EMNLP 2023 杰出论文奖。

问题在于:GPT-4 推理非常昂贵。对于高流量应用,你需要蒸馏。

  • 蒸馏:以可部署的成本获得LLM的智能

RankVicuna(70 亿参数)使用 GPT-3.5 从 RankGPT 中蒸馏而来,以极低的成本实现了相当的排序性能RankZephyr Mistral 微调而来,在保持可部署于通用硬件的同时,实现了最先进的段落排序。

模式是:使用昂贵的 LLM 生成训练信号,然后训练较小的模型来复制其行为。你只在训练时支付一次 LLM 的成本,而不是在推理时。

  • RankRAG统一的排序与生成

来自 NeurIPS 2024  RankRAG 更进一步:对单个 LLM 进行指令微调,使其同时执行排序和生成。在训练中加入少量排序数据,能显著提升检索和生成的质量

Llama3-RankRAG 在知识密集型基准上显著优于 GPT-4。不是因为它是一个更好的语言模型,而是因为它更擅长识别哪些上下文是重要的。

这正是该领域的发展方向。“检索”和“生成”组件之间的界限正在模糊。同时理解排序和生成的模型,优于将两者分开处理的系统。






13
框架集成


主流 RAG 框架现已将重排序作为一等公民支持:

  • LangChain
from langchain.retrievers import ContextualCompressionRetrieverfrom langchain.retrievers.document_compressors import CrossEncoderRerankerfrom langchain_community.cross_encoders import HuggingFaceCrossEncodermodel = HuggingFaceCrossEncoder(model_name="BAAI/bge-reranker-base")compressor = CrossEncoderReranker(model=model, top_n=5)compression_retriever = ContextualCompressionRetriever(    base_compressor=compressor,    base_retriever=vector_store.as_retriever(search_kwargs={"k"20}))# 现在查询会自动检索 20 个、重排序、返回 top-5docs = compression_retriever.get_relevant_documents("your query")
  • LlamaIndex:

from llama_index.core.postprocessor import SentenceTransformerRerankreranker = SentenceTransformerRerank(    model="cross-encoder/ms-marco-MiniLM-L-6-v2",    top_n=5)query_engine = index.as_query_engine(    similarity_top_k=20,    node_postprocessors=[reranker])# 检索 20 个节点,重排序至 5 个,传递给 LLMresponse = query_engine.query("your query")

集成方式非常直接。性能提升通常相当显著。对于结构良好的 RAG 应用,预计答案质量会提高 10%–30%。






14
框架集成


    强大 LLM 的出现并没有削弱学习排序(LTR)的重要性,反而放大了它。


    RAG 系统本质上就是排序问题,只是附加了生成。检索到的上下文的质量,决定了生成答案的质量。LLM 对于大规模语料库的第一阶段检索来说太慢、太昂贵。理解 NDCGlambda 梯度、交叉编码器与双编码器的取舍,为你构建、调试和改进现代 AI 应用提供了概念基础。


    与 RLHF 的联系非常深远:偏好学习背后的 Bradley-Terry 模型正是一个排序模型。直接偏好优化(DPO)及相关的对齐技术,从概念上就是应用于 LLM 输出的列表式 LTR。理解排序的基本原理,能为理解 LLM 对齐机制提供直觉。


    该领域正朝着统一系统收敛。像 BGE-M3 这样的模型同时提供了稠密、稀疏和延迟交互检索。像 RankRAG 这样的框架将排序和生成结合在单个模型中。蒸馏流水线将 LLM 的排序能力迁移到可高效部署的小模型上。


    但基本原理没有改变。你正在学习一个函数,该函数根据文档与查询的相关性对其排序,由位置加权的指标进行评估,并通过能够处理排序列表独特结构的损失函数进行优化。


    掌握这些概念,你就拥有了构建真正有效的搜索、推荐和 RAG 系统的工具。









    添加个人微信,进专属粉丝群!





    53AI,企业落地大模型首选服务商

    产品:场景落地咨询+大模型应用平台+行业解决方案

    承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业

    联系我们

    售前咨询
    186 6662 7370
    预约演示
    185 8882 0121

    微信扫码

    添加专属顾问

    回到顶部

    加载中...

    扫码咨询