想象你是一家大型婚恋平台的金牌红娘,手里握着几十万份相亲档案。客户只给你一句话:“帮我找一个喜欢户外、在北京工作的程序员。” 你不可能把几十万人都请来面谈——那得聊到明年。于是你分三步走:先让前台保安凭关键词把档案快速翻一遍,筛出几千份沾边的;再让红娘助理按“职业、城市、爱好”逐条核对,挑出几十个像样的;最后你亲自约见这几十人,深聊三观、性格、未来规划,从中选出最匹配的三五个推荐给客户。体育馆里的层层筛人,就是搜索系统里的“召回、粗排、精排”三段式流水线。 RAG(检索增强生成)系统面对的文档库同样可能达到百万量级。如果每个用户问题都让最聪明的模型把所有文档读一遍,算力成本高到离谱,用户也等不起。于是工程上把“找答案”拆成三个接力棒:召回用最快的方式从百万文档中拉出几百个候选;粗排用轻量模型把候选缩到几十个;精排让大模型在这几十个里仔细比较,最终输出最相关的几个片段给大语言模型生成回答。每往下一层,模型更聪明、更慢,但候选数量急剧变少,整体开销被压到可接受范围。

岗位关联

三段式排序是 RAG 系统落地的核心工程范式。掌握它,你就能在“效果”与“成本”之间做出专业权衡,设计出支撑百万级文档库的高性能检索管线。

目录
  1. 可视化演示
  2. 三段式总览
  3. 召回阶段
  4. 粗排阶段
  5. 精排阶段
  6. 模型选型
  7. 性能评估
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

动态演示召回粗排精排的核心机制,通过基础/核心/应用/扩展四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

召回粗排精排:三段式排 三段式排序流水线的整体架构与设 召回阶段:向量检索的候选快速拉 核心机制可视化 召回粗排精排整体架构与关键组件

三段式总览

婚恋平台的三步筛选,本质是一个“倒金字塔”漏斗:越往前走,人事越多、动作越快;越往后走,人事越少、判断越精细。RAG 排序流水线完全复刻了这个结构——召回、粗排、精排分别对应保安初筛、红娘助理核对、金牌红娘面谈,三者各司其职,缺一环都会失衡。如果直接用最精细的模型处理百万文档,就像让金牌红娘一人约见几十万人,既不现实也没必要。

三段式设计的第一层逻辑是目标拆分。召回环节只求“别漏掉对的”,粗排追求“在低成本下把明显不相关的剔掉”,精排则要“在最后几十个里排出最准的顺序”。每一级有独立的优化目标,使用不同复杂度的模型,让整体流水线同时满足“快”和“准”两个看似矛盾的要求。

从工程角度看,三段式本质是用“模型复杂度递增 × 候选数量递减”换整体延迟的数学平衡。假设每层耗时固定,总耗时几乎由最后一级的候选数量决定:

就像相亲大会,保安扫一眼几万人只要几小时,红娘助理核对接下来的几百人花一天,金牌红娘面谈最后几十人却要花一周——但整体进度由最慢的环节决定,所以必须让“最慢的环节面对最少的人”。

总耗时=延迟召回+N召回×延迟粗排+N粗排×延迟精排\text{总耗时}= \text{延迟}_{\text{召回}} + N_{\text{召回}} \times \text{延迟}_{\text{粗排}} + N_{\text{粗排}} \times \text{延迟}_{\text{精排}}
这个公式说明:精排虽然最慢,但只要候选数量从百万缩到几十,它的总耗时就受控;粗排耗时中等,却要处理几百条候选,是延迟的大头。
  1. 总耗时整条排序流水线从收到查询到给出最终候选的端到端时间。
    总耗时=延迟召回+N召回×延迟粗排+N粗排×延迟精排\text{总耗时}= \text{延迟}_{\text{召回}} + N_{\text{召回}} \times \text{延迟}_{\text{粗排}} + N_{\text{粗排}} \times \text{延迟}_{\text{精排}}
  2. 召回项召回通常只需一次向量检索,延迟几乎固定,与候选数量无关。
    延迟召回≈常数\text{延迟}_{\text{召回}} \approx \text{常数}
  3. 粗排项粗排要对 N\_召回 个候选逐一打分,所以是“数量 × 单条耗时”。
    N召回×延迟粗排N_{\text{召回}} \times \text{延迟}_{\text{粗排}}
  4. 精排项精排只处理 N\_粗排 个候选,尽管单条最慢,总耗时依然可控。
    N粗排×延迟精排N_{\text{粗排}} \times \text{延迟}_{\text{精排}}

召回阶段

保安怎么从几万人里快速捞出“可能喜欢户外”的档案?他不可能逐字读完整简历,而是扫关键词、看标签,先把范围缩到几百人。RAG 的召回阶段也一样:面对百万级文档库,它用向量检索把 query 和 document 都编码成向量,在向量空间里找“语义距离最近”的一批文档。

向量检索的核心是相似度计算。每个文档被映射成一个固定维度的向量,查询也被映射成向量,然后计算两者之间的余弦相似度:

召回结果的候选集规模通常设定在 100~1000 条之间。为了更稳,工程上还常把向量检索和传统的 BM25 关键词检索混合起来:BM25 擅长精确匹配专有名词,向量检索擅长语义泛化,两者取并集再统一打分。就像保安既看档案上的“户外”标签,也听客户说“喜欢爬山”这种近义词——一个抓字面,一个抓意思,搭配使用才不容易漏人。召回阶段的唯一 KPI 是召回率:真正的相关文档必须尽可能出现在候选池里,否则后面再精细也无力回天。

score(q,d)=q⋅d∥q∥∥d∥\text{score}(q,d)=\frac{\mathbf{q}\cdot\mathbf{d}}{\lVert\mathbf{q}\rVert \lVert\mathbf{d}\rVert}
余弦相似度衡量两个向量的“方向是否一致”,值越大表示语义越接近,取值范围在 -1 到 1 之间。
  1. 向量点积把查询向量和文档向量的每一维相乘后累加,得到一个标量。
    q⋅d=∑i=1nqi×di\mathbf{q}\cdot\mathbf{d}=\sum_{i=1}^{n} q_i \times d_i
  2. 向量模长分别计算两个向量的长度,用于归一化。
    ∥q∥=∑i=1nqi2,∥d∥=∑i=1ndi2\lVert\mathbf{q}\rVert = \sqrt{\sum_{i=1}^{n} q_i^{2}}, \quad \lVert\mathbf{d}\rVert = \sqrt{\sum_{i=1}^{n} d_i^{2}}
  3. 余弦相似度点积除以两个模长的乘积,消除向量长度的影响,只保留方向信息。
    q⋅d∥q∥∥d∥\frac{\mathbf{q}\cdot\mathbf{d}}{\lVert\mathbf{q}\rVert \lVert\mathbf{d}\rVert}

粗排阶段

红娘助理拿到几百份档案后,会把“北京、程序员、户外”逐条对照,快速打个分,淘汰掉明显不合适的。粗排阶段干的正是这件事:用轻量级的 Cross-Encoder 模型对每个候选文档做相关性判断。相比召回阶段的双塔结构,Cross-Encoder 最大的不同是把 query 和 document 拼在一起送进模型,让两者在自注意力层充分交互,因此判断更准,但代价是没法预先计算文档向量,速度慢许多。

粗排模型的输入是拼接后的文本序列,输出是一个相关性分数:

粗排阶段还会把召回阶段的向量相似度分数与 CE 分数做加权融合,防止单一模型误判。例如总分数 = 0.3 × 向量分 + 0.7 × CE 分。融合后按分数排序,只保留前 50~100 条进入精排。这一步的价值在于:它用可接受的算力成本,把精排模型从面对几百条候选变成面对几十条候选,正如红娘助理先把明显不合适的人划掉,金牌红娘才不用浪费口舌。

sCE=CrossEncoder([q;d])s_{\text{CE}}=\text{CrossEncoder}([q; d])
这里的 [q; d] 表示把查询文本和文档文本拼接成一个序列。Cross-Encoder 通过深层交互捕捉 query 与 doc 之间的细粒度匹配信号。
  1. 拼接序列用分隔符把 query 和 doc 拼接成一个输入序列,让模型能看到两者的完整上下文。
    [q;d]=concat(q,[SEP],d)[q; d] = \text{concat}(q, \text{[SEP]}, d)
  2. 交叉编码Transformer 的每一层都让 query 的 token 与 doc 的 token 互相 attend,捕捉“北京”和“程序员”之间的关联。
    CrossEncoder([q;d])∈Rh\text{CrossEncoder}([q; d]) \in \mathbb{R}^{h}
  3. 打分输出把最后一层输出经过线性层压缩成一个标量分数。
    sCE=w⊤Enc([q;d])+bs_{\text{CE}} = \mathbf{w}^{\top} \text{Enc}([q; d]) + b

精排阶段

到了金牌红娘这里,候选人已经从几十万人缩到了几十人。她不再看标签,而是坐下来逐一深聊,甚至让几位候选人同时出现,观察他们在交流中的细微差别,最终排出最匹配的前三名。RAG 的精排阶段同理,它用大语言模型(LLM)对这几十个候选做深度排序。LLM 拥有强大的语义理解能力,能捕捉同义词、隐含意图、段落级关联,甚至能理解“喜欢户外”背后的“周末徒步、露营”等衍生场景。

精排有两种主流实现方式。第一种是打分式:让 LLM 对整个候选列表生成一个排序序列;第二种是列表式生成:直接把候选文档的 ID 列表交给 LLM,让它输出重新排序后的 ID 序列。后者可以建模“候选之间的相对关系”,而不是孤立地对每条打分:

精排阶段还要处理上下文窗口限制。LLM 无法一次性读完 50 条长文档,常见做法是分段滑窗处理:把候选切成小组,先在组内排序,再把每组冠军拉进来做最终排序,类似先分区预选、再全国决赛。精排输出的通常是最相关的 1~5 个片段,这些片段最终拼接进 Prompt,交给生成模型回答用户问题。就像金牌红娘最终只向客户推荐三个人,而不是把几十人的详细报告全甩过去。

P(o∣q,D)=∏i=1nexp⁡(s(doi))∑j=inexp⁡(s(doj))P(o \mid q, D)=\prod_{i=1}^{n} \frac{\exp(s(d_{o_i}))}{\sum_{j=i}^{n} \exp(s(d_{o_j}))}
这个公式描述了一个列表排序概率:LLM 依序选择每个位置的文档,每次都在剩余候选中选分数最高者,越靠前的位置权重越大。
  1. 候选集合精排阶段待排序的候选文档集合 D。
    D={d1,d2,…,dn}D=\{d_1, d_2, \dots, d_n\}
  2. 排序序列概率把输出序列 o 的概率拆成每一步选中文档的条件概率连乘。
    P(o∣q,D)=∏i=1nexp⁡(s(doi))∑j=inexp⁡(s(doj))P(o \mid q, D)=\prod_{i=1}^{n} \frac{\exp(s(d_{o_i}))}{\sum_{j=i}^{n} \exp(s(d_{o_j}))}
  3. 分数指数化将相关性分数 s 取指数,保证概率非负且相对大小被放大。
    exp⁡(s(doi))\exp(s(d_{o_i}))
  4. 归一化分母每一步只在“剩余候选”中做 Softmax,因此前面选错的文档会直接影响后续排列概率。
    ∑j=inexp⁡(s(doj))\sum_{j=i}^{n} \exp(s(d_{o_j}))

模型选型

三种角色对应三类模型,各有绝活也各有软肋。双塔模型(如 Sentence-BERT)把 query 和 doc 分别编码成独立向量,可以离线把百万文档向量全部算好,在线查询时只算 query 的向量,再去做近邻搜索,快如闪电,但双方没有深层交互,精度有限——它适合当保安。Cross-Encoder 把 query 和 doc 拼在一起编码,交互充分、精度更高,但每个候选都要实时算一次,适合当红娘助理。LLM 最聪明,能理解复杂意图和长文本结构,但速度最慢、成本最高,只能用来当金牌红娘。

选型本质是算一笔“性价比账”:每多花一分算力,究竟换来了多少精度提升。可以用下面的公式来指导决策:

实际工程中,模型选型还要看文档库规模、业务时延要求、GPU 预算。百万级文档库通常坚定走“双塔召回 + CE 粗排 + LLM 精排”三段式;如果文档量只有几千,完全可以用 CE 直接一步到位,省去精排的昂贵开销。选型没有银弹,关键是让每一级模型的复杂度与它处理的候选数量匹配——保安不需要博士学位,金牌红娘也不该去门口查证件。

性价比=NDCG新模型−NDCG旧模型延迟新模型−延迟旧模型\text{性价比}=\frac{\text{NDCG}_{\text{新模型}}-\text{NDCG}_{\text{旧模型}}}{\text{延迟}_{\text{新模型}}-\text{延迟}_{\text{旧模型}}}
分子是排序质量的提升幅度,分母是延迟的增加幅度。如果分子增长远小于分母增长,说明换模型不划算。
  1. 效果增益新模型相比旧模型在 NDCG 指标上的提升,NDCG 是衡量排序质量的经典指标。
    NDCG新模型−NDCG旧模型\text{NDCG}_{\text{新模型}}-\text{NDCG}_{\text{旧模型}}
  2. 成本代价新模型带来的额外延迟开销,通常以毫秒计。
    延迟新模型−延迟旧模型\text{延迟}_{\text{新模型}}-\text{延迟}_{\text{旧模型}}
  3. 性价比比值两者相除得到“每增加 1 毫秒延迟换来的排序增益”,用于横向对比模型升级方案。
    Δ效果Δ成本\frac{\Delta \text{效果}}{\Delta \text{成本}}

性能评估

怎么知道你的三段式流水线干得好不好?就像婚恋平台要同时考核“是否漏掉了优质客户”“推荐名单里第一名是否真的匹配”“整体排序是否稳定”,RAG 排序系统也有三大类评估指标,分别对应不同阶段的优化目标。

Recall@K 最常用于召回阶段,衡量“真实相关文档出现在前 K 个候选中的比例”。MRR(Mean Reciprocal Rank) 关注第一个正确答案出现的位置:如果第一个相关文档排在首位,RR 就是 1;排在第二位,RR 就是 1/2。NDCG 则是更全面的排序质量指标,它按位置折扣累积相关度,既奖励“相关文档排前面”,也容忍“不相关文档被排到很后面”。NDCG 的计算公式为:

除了离线指标,线上工程还必须盯住 p99 时延和吞吐量。一次查询若召回耗时 30ms、粗排 80ms、精排 500ms,总时延可能接近 1 秒,对在线系统已偏慢。优化手段包括:粗排用更小的模型、精排候选限制在 10 条以内、对请求做批处理、用缓存复用相似查询的召回结果。评估不是一次性动作,而是流水线持续迭代的指南针——哪一级指标掉队,就优先优化哪一级,正如婚恋平台每周复盘:保安漏人了?红娘助理标准太松?还是金牌红娘偏好跑偏?对症下药才能让漏斗始终高效。

NDCG@K=DCG@KIDCG@K,DCG@K=∑i=1K2reli−1log⁡2(i+1)\text{NDCG@K}=\frac{\text{DCG@K}}{\text{IDCG@K}}, \quad \text{DCG@K}=\sum_{i=1}^{K}\frac{2^{\text{rel}_i}-1}{\log_2(i+1)}
其中 rel_i 表示第 i 个位置的相关性等级(0 表示不相关,1~3 表示相关程度递增)。IDCG 是理想情况下能达到的最大 DCG,用来做归一化。
  1. DCG 计算每个位置的相关性增益按位置的对数做折扣,排得越靠后,折扣越大。
    DCG@K=∑i=1K2reli−1log⁡2(i+1)\text{DCG@K}=\sum_{i=1}^{K}\frac{2^{\text{rel}_i}-1}{\log_2(i+1)}
  2. 相关性指数用 2 的 rel 次方减 1,让高相关文档的增益远大于低相关文档。
    2reli−12^{\text{rel}_i}-1
  3. 位置折扣除以 log2(i+1),排名第二的文档增益只保留约 63%,排名越靠后衰减越狠。
    log⁡2(i+1)\log_2(i+1)
  4. IDCG 归一化DCG 除以理想 DCG,得到 0 到 1 之间的分数,方便跨查询比较。
    NDCG@K=DCG@KIDCG@K\text{NDCG@K}=\frac{\text{DCG@K}}{\text{IDCG@K}}

AI 应用场景

企业知识库智能问答

阶段:RAG 检索排序流水线搭建

解决的问题:企业文档库动辄几十万甚至上百万篇 PDF、Wiki、工单记录。传统关键词搜索只能做字面匹配,用户用口语提问“报销流程大概多久”时,文档里写的是“费用审批周期为三个工作日”,关键词检索几乎找不到。AI 三段式排序先用向量召回拉出候选,再用粗排过滤明显不相关的旧版本文档,最后用 LLM 精排把真正描述审批周期的段落排到最前面,让问答系统给出可靠答案。

具体案例:某互联网公司搭建内部知识库助手,文档总量约 80 万篇。原始方案只用向量检索,Top1 准确率仅 42%;接入 CE 粗排后升至 61%;再引入 LLM 精排后 Top1 达到 78%。查询耗时从 2 秒压到 1.2 秒,用户满意度显著提升。

电商商品搜索排序

阶段:召回与粗排环节的工程落地

解决的问题:电商平台的商品库以亿计,用户搜索“男士运动鞋”时,系统先通过类目、品牌、文本向量召回数万商品,再用轻量排序模型按销量、库存、点击率粗排到几百个,最后把个性化偏好交给精排模型。如果没有多阶段漏斗,直接对所有商品跑复杂排序模型,算力成本会让系统直接崩溃。

具体案例:某电商平台搜索团队用“双塔召回 + 轻量 DNN 粗排 + 大模型精排”重构搜索链路,召回阶段用向量相似度快速定位相关商品,粗排阶段融合销量与文本相关性,精排阶段引入用户历史行为序列建模。结果搜索转化率提升 12%,单次搜索平均响应时间维持在 50ms 以内。

学术文献检索工具

阶段:精排阶段的深度排序优化

解决的问题:科研人员经常面对“想找某篇论文但只记得模糊想法”的困境。传统检索按标题关键词匹配,效果很差。三段式排序可以先用向量召回从千万级论文库中拉出 200 篇,粗排用 Cross-Encoder 评估标题与摘要相关性,精排则让 LLM 通读摘要、比对方法部分,输出最相关的 3 篇论文并附理由。

具体案例:某科研工具团队为论文检索加入 LLM 精排后,用户点击 Top1 论文的比例从 31% 提升到 64%,“找不到想要的文献”类投诉下降 70%。由于精排只处理 20 篇候选,单次请求额外耗时不到 1 秒。

Python 演示

python56 行
import random  class ThreeStageRetriever:    """三段式排序流水线的极简模拟:召回 -> 粗排 -> 精排"""     def __init__(self, docs):        self._docs = docs        self._k_recall = 100        self._k_coarse = 20        self._k_final = 3     @staticmethod    def _query_terms(query):        return set(query.lower().split())     def _lexical_score(self, query, doc):        q = self._query_terms(query)        d = set(doc.lower().split())        return len(q & d)     def _recall(self, query):        scored = [(i, self._lexical_score(query, d))                  for i, d in enumerate(self._docs)]        scored.sort(key=lambda x: -x[1])        return [i for i, _ in scored[:self._k_recall]]     def _coarse_score(self, query, doc):        base = self._lexical_score(query, doc)        return base + random.random() * 0.5     def _fine_score(self, query, doc):        exact = 1.0 if query.lower() in doc.lower() else 0.0        return self._coarse_score(query, doc) + exact * 2.0     def search(self, query):        recalled = self._recall(query)        coarse = sorted(recalled,                        key=lambda i: -self._coarse_score(query, self._docs[i]))        coarse = coarse[:self._k_coarse]        final = sorted(coarse,                       key=lambda i: -self._fine_score(query, self._docs[i]))        return final[:self._k_final]  if __name__ == "__main__":    random.seed(42)    docs = [        "retrieval augmented generation is a popular ai topic number " + str(i)        for i in range(1, 201)    ]    pipe = ThreeStageRetriever(docs)    result = pipe.search("retrieval generation ai")    print("final top3 docs:")    for idx in result:        print("-", docs[idx])
目的:用 200 条假文档演示召回、粗排、精排三段流水线的数据流:每级过滤掉大量候选,最终输出 Top3。
  1. self._k_recall = 100召回阶段保留 100 个候选,模拟向量检索的规模控制。
  2. self._lexical_score(query, doc)用关键词重叠数模拟向量相似度,衡量 query 与 doc 的相关性。
  3. scored.sort(key=lambda x: -x[1])按分数降序排列,取出前 100 个作为候选集。
  4. self._k_coarse = 20粗排阶段只保留 20 个候选,模拟轻量 Cross-Encoder 的缩圈效果。
  5. base + random.random() * 0.5模拟粗排模型的排序噪声,让结果不完全依赖关键词。
  6. exact = 1.0 if query.lower() in doc.lower() else 0.0模拟 LLM 精排对精确匹配的强偏好。
  7. coarse[:self._k_coarse]粗排排序后截断候选,对应真实流水线中的 TopN 截断操作。
  8. pipe.search(query)串联三段流程,返回最终 Top3 文档索引,等价于生产系统中的 RAG 精排结果。

常见误区

误区既然精排模型那么准,为什么不干脆让精排模型去处理全部百万文档?只要模型够强,召回再做过滤纯属多此一举。

正解召回阶段的核心约束是“快”和“全”。用最强模型处理百万文档,单次查询时延会从几十毫秒飙到几分钟,系统直接不可用。三段式的本质是让模型复杂度与候选数量错位匹配:最强的模型只处理最少的候选。就像金牌红娘不可能一个人面谈几十万人,她只专注服务最后那几十个精英候选人。

为何常见:初学者容易被“模型越强效果越好”吸引,忽略了工业系统的时延和成本约束,把离线评测的逻辑误搬到在线服务上。

误区粗排反正要被精排再排一遍,用最简单的打分规则糊弄过去就行,不如把精力全砸在精排上。

正解粗排是漏斗中最关键的“守门员”。如果粗排阶段把真正相关的文档截断掉了,精排模型再强也看不到它——这就像红娘助理把最合适的候选人提前淘汰,金牌红娘压根没机会见到人。粗排的质量直接决定精排的上限,必须配置足够有区分度的轻量模型,并仔细做分数融合。

为何常见:粗排的中间结果不直接呈现给用户,导致人们低估它的价值,忽略了“截断即不可逆”的漏斗本质。

误区大模型这么聪明,无论什么场景,用 LLM 做精排都能碾压小模型。

正解LLM 的优势在开放域语义理解,但在垂直领域(如法律条文、医疗指南)中,经过微调的 Cross-Encoder 往往更稳定、更快。LLM 还有上下文窗口限制,候选文档一长就放不下,而且输出可能存在随机性,直接排序结论可能抖动。选型要看业务场景:候选少、要求高、预算足时用 LLM;候选多、时延敏感时用 CE。

为何常见:宣传中“大模型最强”的刻板印象根深蒂固,让人们忽略了成本、稳定性和场景适配这些工程现实。

误区召回、粗排、精排都是排序模型,用同一个指标(比如 NDCG)一起调优就好,不需要区分。

正解三个阶段的目标完全不同。召回阶段优化 Recall@K,只关心“相关文档有没有被捞进来”;粗排阶段优化 Recall@K 与精排前截断质量,追求“用最少算力过滤最多噪声”;精排阶段才优化 MRR、NDCG 这类“顺序是否正确”的指标。用错指标会导致整条流水线失衡——比如召回阶段死磕 NDCG,反而可能把候选池缩得太小,漏掉长尾相关文档。

为何常见:排序任务在形式上相似,让初学者误以为目标也一致,忽略了流水线中不同环节的角色分工。

面试题

Q1. 在 RAG 三段式排序中,召回阶段的首要优化目标是什么?

单选题 · easy

  • A.最大化精排模型效果
  • B.提高检索召回率← 正确答案
  • C.最小化计算成本
  • D.提升排序稳定性

答案:B。召回阶段负责把相关文档尽可能多地捞进候选池,因此首要指标是召回率(Recall)。若召回漏掉相关文档,后续粗排和精排再强也无济于事。A 是精排目标,C 是系统约束而非召回核心目标,D 是排序稳定性问题,均非召回核心。

Q2. 召回阶段常将向量检索与 BM25 混合使用,主要目的是什么?

单选题 · mid

  • A.让模型参数量更小
  • B.同时捕捉语义相似与字面匹配← 正确答案
  • C.减少候选文档数量
  • D.替代精排阶段

答案:B。向量检索擅长捕捉语义相近但字面不同的表达,BM25 擅长精确匹配专有名词、编号等。两者混合取并集,可以兼顾“意合”与“形合”,减少漏召回。A 与模型参数量无关,C 反而可能增加候选数量,D 是错误职责定位。

Q3. 关于 Cross-Encoder 粗排模型,下列说法正确的有哪些?

多选题 · mid

  • A.将查询和文档拼接后编码← 正确答案
  • B.可以离线预计算文档向量
  • C.比双塔模型交互更充分← 正确答案
  • D.比大模型精排速度更快← 正确答案

答案:ACD。Cross-Encoder 把 query 和 doc 拼接后送入模型(A 对),因此交互充分(C 对),但代价是无法离线缓存 doc 向量(B 错)。它的模型规模通常远小于 LLM,速度更快(D 对)。B 正是双塔模型的优势,与 Cross-Encoder 相反。

Q4. 精排阶段一般只处理多少个候选文档?

单选题 · easy

  • A.1~5 个
  • B.5~50 个← 正确答案
  • C.100~1000 个
  • D.全部文档

答案:B。精排使用大模型,单条处理成本极高,因此候选数量必须严格控制。工业实践通常让粗排输出 50~100 条,精排在此基础上再缩到 5~50 条。A 是最终输出给生成模型的片段数,C 是召回候选规模,D 完全违背漏斗原则。

Q5. 精排阶段应对 LLM 上下文窗口限制的常见手段有哪些?

多选题 · hard

  • A.截断候选文档的开头部分
  • B.分组滑窗内部排序← 正确答案
  • C.逐组冠军汇总再排序← 正确答案
  • D.增加模型最大 token 数

答案:BC。工程上常把候选分成小组,每组在窗口内排序,再让各组冠军进入下一轮(B、C 对)。A 直接截断开头可能丢掉关键信息,D 增加窗口会显著提高算力成本,并非拿来即用的常规手段。

Q6. 双塔模型为什么适合召回阶段?

单选题 · mid

  • A.查询和文档交互充分
  • B.支持离线预计算文档向量← 正确答案
  • C.模型参数规模最大
  • D.不需要训练即可使用

答案:B。双塔模型分别编码 query 和 doc,文档向量可以离线算好存进向量数据库,在线查询只需计算 query 向量并做近邻搜索,速度极快。A 是 Cross-Encoder 的优势,C 与实际不符,D 任何排序模型都需要训练。

Q7. MRR 指标主要衡量排序系统的什么能力?

单选题 · mid

  • A.第一个相关结果出现的位置← 正确答案
  • B.所有相关结果是否都被召回
  • C.排序结果的整体相关性分布
  • D.系统响应耗时是否稳定

答案:A。MRR 是“第一个正确结果排在首位得 1 分,排在第二位得 1/2”的倒数平均,它关注第一个正确答案的位置,常用于问答与搜索场景。B 是召回率,C 是 NDCG 关注的,D 是工程时延指标。

Q8. 关于 NDCG 指标,下列说法正确的是哪些?

多选题 · hard

  • A.对排在后面的相关性增益做对数折扣← 正确答案
  • B.需要用理想排序的 DCG 做归一化← 正确答案
  • C.完全不考虑相关文档的位置
  • D.更适合单一正确答案场景

答案:AB。NDCG 用 log2(i+1) 对位置做折扣(A 对),并用 IDCG 归一化使不同查询可比(B 对)。它专门依赖位置信息(C 错),且面向多级相关性标注、可容纳多个相关结果,而非单一正确答案(D 错,单一答案更常用 MRR)。

Q9. 某 RAG 系统精排耗时占总时延的 80%,在保证精排质量的前提下最合理的优化手段是?

单选题 · extreme

  • A.更换更大的精排模型
  • B.把粗排候选从 100 压缩到 30← 正确答案
  • C.完全去掉召回阶段
  • D.将精排模型替换为双塔模型

答案:B。精排耗时与候选数量线性相关,减少进入精排的候选数量能直接压缩最大头的时延。粗排更严格地把候选从 100 缩到 30,精排只需处理 30 条,质量损失可接受。A 会放大耗时,C 破坏流水线结构,D 用双塔做精排会损失精度,违背“保证质量”前提。

Q10. 三段式排序流水线的核心设计思想是什么?

单选题 · easy

  • A.所有阶段使用同一个最强模型
  • B.模型复杂度随候选数量递减而递增← 正确答案
  • C.阶段越多,系统越慢
  • D.召回阶段保证排序精度

答案:B。漏斗原则是“每往下一层,候选数量变少,模型复杂度上升”。召回用最快模型处理海量候选,精排用最强模型处理极少数候选,从而在整体时延可控的前提下逼近最优效果。A 会让系统崩溃,C 是表象而非目的,D 混淆召回与精排的目标。