Skip to content

Reranking:让答案证据排到前面 ​

精排(Reranking)对已经召回的候选重新排序。它接收用户问题和候选文本,计算候选与问题的相关程度,把更可能包含答案的材料排到前面。它通常位于初步召回之后、上下文选择之前,处理范围受已有候选集限制。

用户问“2026 年境内出差报销审批通过后,多久能收到钱”,检索返回了三条候选:

候选文本
A境内差旅结束后 30 个自然日内提交报销材料。
B境内差旅报销审批通过后 5 个工作日内支付。
C报销系统支持查询审批进度和支付状态。

A 与问题共享“境内差旅报销”和时间表达,C 也提到审批和支付。它们都相关,但只有 B 回答了从审批通过到支付的期限。精排要识别这种差别,让 B 优先进入回答模型的上下文。

召回通常保留较多候选以减少遗漏,生成模型的上下文却需要控制长度。精排后的顺序为下一步选择材料提供依据:

text
问题 ── 召回候选 ── 逐条计算问题与候选的相关性 ── 重排 ── 选择上下文 ── 生成回答

交叉编码器怎样判断相关性 ​

常见的 dense 检索使用双编码器(bi-encoder):问题和文档独立编码,文档向量可以提前算好并放入索引。在线只需编码问题,再检索相似向量。这种计算方式适合从大量文本中取候选,但每篇文档在读到具体问题之前就已压缩成向量。

交叉编码器(cross-encoder)把问题和一条候选共同输入模型:

text
输入:问题 + 文档标题 + 候选正文
输出:该候选对当前问题的相关性分数

在典型 Transformer 实现中,问题 token 和文档 token 可以在编码过程中相互关注。模型有机会结合“审批通过后”判断候选谈的是提交阶段还是支付阶段。它对每个问题—候选组合单独打分,同一条文档面对不同问题时会得到不同的分数。

代价是每个问题与候选组合都要重新推理。文档表示无法像双编码器那样完全复用。因此常见安排是先用便宜的检索方法缩小范围,再让 cross-encoder 处理有限候选。批处理可以提高吞吐,但一次批量推理 40 对文本,计算对象仍然是 40 个问题—文档对。

从候选列表到精排结果 ​

对开头的例子,交叉编码器分别处理 (问题, A)、(问题, B)、(问题, C) 三对输入,得到三个相关性分数。随后按照分数降序排列,并将结果映射回原候选 ID。对于支付期限这个问题,期望 B 排在最前;A 与 C 的先后对这道问题的主要证据选择影响较小。

这里的分数由模型对文本内容计算,与 RRF 累加检索名次不同。即使 A 在多路检索中排名靠前,精排仍然可以根据“提交报销材料”与“审批通过后支付”的差别,把 B 提到它前面。

进入下一步时,保留的是原始文本、ID 和精排得分。生成模型仍需阅读 B 才能回答“5 个工作日内支付”,精排本身不生成这个答案。候选 ID 应原样保留,后续引用才能指向原记录。

如果 B 从未进入候选集,精排就没有机会选中它。因此,发现最终上下文缺少 B 时,应先确认它是否被召回,再检查精排前后的名次。交叉编码器的排序也可能出错,尤其需要关注数字、否定和例外条件。

标题和正文怎样送入模型 ​

候选 B 如果只剩“通过后 5 个工作日内支付”,模型可能无法判断是哪一类审批。输入中应带上必要标题、章节路径和适用范围,例如“2026 年境内差旅制度 / 报销支付”。这些字段帮助解释正文,不应替代正文提供不存在的事实。

权限、生效范围等硬约束要在受控检索和过滤阶段执行。相关性模型可能认为 2025 年旧版制度更贴近问题用词;过滤阶段应先根据查询的年份和用户权限限定候选,精排再对这些候选排序。

精排模型的最大输入长度通常包含问题、标题、正文及特殊 token。一个很长的问题会压缩正文可用空间;候选的支付条款如果在尾部,简单取前若干 token 就可能将答案裁掉。

这时看到的现象是“B 明明含答案,模型却给低分”,但模型实际读到的 B 已经没有答案。诊断日志需要记录截断后的输入长度和截断策略,抽样查看模型真正收到的文本。

可以把候选切成若干有重叠的窗口,分别评分,再映射回原候选。若采用窗口最大分数,候选只要某一处相关就能保留,但包含很多窗口的长文也获得了更多命中机会,且局部高分无法证明全文满足问题全部条件。另一种做法是先定位命中段,再补回相邻语句和标题。无论采用哪种,都应保存文本位置,防止截断掉例外条件。

用大语言模型完成排序 ​

LLM 也可以执行精排。逐条评估属于 pointwise;每次比较两条属于 pairwise;同时排列一组候选属于 listwise。这些术语描述比较方式,与具体模型架构并不一一对应。

Pointwise 容易并行,但多次调用产生的分数可能缺少统一尺度。Pairwise 需要明确比较策略,全部两两比较会产生 N × (N - 1) / 2 对,模型还可能给出循环偏好。Listwise 可以直接输出一组 ID 的次序,但受上下文长度、候选位置和顺序影响,分组或滑动窗口排序也需要合并策略。

例如要求模型返回:

json
{"ranking": ["B", "A", "C"]}

解析端必须检查 ID 是否都来自输入、是否重复,以及是否符合“必须包含全部候选”或“只返回前若干条”的约定。证据正文中的指令应当被当作待阅读文本,不能允许它改变排序任务。格式校验失败或超时时,可以回退到原融合排序,并记录降级原因。

模型给出的解释适合辅助排错,不能当作证据引用。分数也未必是概率:某个 reranker 的 0.95 不等于答案有 95% 的正确率,跨模型沿用阈值尤其容易出错。

怎样判断精排是否值得保留 ​

先冻结召回候选,用同一批问题比较原排序与精排排序。这样才能区分收益来自排序变化,还是来自某次改动顺便扩大了候选集。单一主要证据可以观察 MRR,多级相关性可以观察 nDCG;多条证据共同支持答案的问题,还要检查必要条款是否都进入最终范围。

把上面的示例改成“最晚什么时候交,审批后多久支付”,A 和 B 就都不可少。只测第一名是否相关,会漏掉这类不完整答案。评测集中还应包含无答案问题,例如材料未提供的境外提交期限。即使精排必须返回第一名,也不能据此宣称知识库有答案。

质量之外,还要记录精排输入 token、候选数量、尾部延迟、超时比例。精排改善排序后,最终上下文仍可能塞入太多重复片段,相关处理见证据选择与压缩。完整的指标与测试集设计见 RAG 评测。

参考资料 ​

持续学习,持续实践。