很多人做完 RAG 检索会发现:明明资料库里就有答案,模型却答偏了——因为向量召回只负责「捞回来」,不负责「排好队」。这篇面向刚上手 RAG 的开发者,把 rerank 的角色、放在链路哪一步、怎么接进去、怎么验证有没有用讲一遍,最后给一份能照着做的排查顺序。
很多人第一次搭 RAG 都遇到过这种尴尬:答案明明就躺在你的资料库里,模型却一本正经地答偏,或者干脆说没找到。翻一下检索日志才发现,正确的那段确实被捞回来了,只是排在候选列表很靠后的位置,最后被截断掉,压根没进模型的上下文。向量召回干的是「捞回来」的活,它不负责「排好队」。
rerank(重排)就是补上「排队」这一环的。它把查询和每条候选段落配成一对,一起过一遍模型,打出更贴近真实相关性的分数,再按分数重新排序。这篇面向刚上手 RAG 的人,把它的位置、选型、接入、验证和降级讲清楚,最后给一份照着做的排查顺序。
先搞清楚:为什么召回完了还要再排一次
向量召回靠的是向量距离,追求的是「像不像」,特点是快但粗。它会把语义相近但答非所问的段落一起捞回来,所以候选列表里混进噪声是常态,不是你的库有问题。rerank 相反,它只对少量候选做,愿意花更重的计算去精读每一对「查询 + 段落」。
一句话分工:召回负责「别漏」,rerank 负责「别错」。
判断自己要不要上,别靠感觉,看一个指标就行:把你现在最终喂给模型的上下文打印出来,看看真正相关的那段排在第几位。如果经常排到很后面甚至被截断,就是该上的信号;如果它本来就在前几位,那加了也是白加。
- 什么时候不需要 rerank
- 候选本来就很少(比如固定几段),或者你的场景是强关键词匹配、查询和文档用词高度一致,排序已经够准。
- 什么时候必须先修别的
- 正确段落压根没被召回,那属于召回问题,rerank 救不了它没拿到的东西。
rerank 站在链路的哪个位置
- 典型顺序:查询改写(可选)→ 向量或混合召回一批候选 → rerank 精排 → 截断到最终上下文 → 交给生成模型。
- rerank 永远在召回之后、生成之前,放在别的位置都别扭。
- 关键参数只有两个:召回阶段取多少条,要明显大于你最终要喂给模型的条数;精排后保留多少条,直接决定成本和延迟。
- 如果你已经做了混合检索(向量 + 关键词),rerank 更适合放在两路结果融合之后,用一个分数口径统一收口。
前一个参数决定效果上限,后一个决定你花多少钱。很多人调参时把两个一起改,结果出了问题根本不知道是哪一步变的。建议先锁定召回条数,只动保留数,单独观察变化。
rerank 模型怎么挑:几个判断维度
选型不用纠结榜单,抓住几个和你的数据直接相关的维度就够了。下面这张表可以当作对照清单,逐项去你手上的候选模型那里确认。
| 判断维度 | 要确认什么 | 不适用的情况 |
|---|---|---|
| 中文效果 | 用中文语料实测排序,别只看英文榜的表现 | 资料库以英文为主时可以放宽 |
| 长度上限 | 单条候选太长会被截断,要和你的分块长度对齐 | 分块本身就短,这条影响很小 |
| 部署形态 | 托管接口省事按量走,本地部署省调用费但吃显存 | 调用量极小的项目本地部署不划算 |
| 与召回是否同源 | 同系列有时分数更协调,但不是硬规则 | 两端都换了模型时,这个参考价值有限 |
部署形态对五个人以内的小团队尤其重要:先走接口把链路跑通,等调用量和延迟数据稳定了再考虑本地化,别一上来就为了省调用费折腾显卡。具体有哪些可选项、各自什么特点,去站内嵌入模型目录对照一遍。
接入落地:从零到能跑的分步动作
- 固定基线把召回 TopK、最终上下文条数、评测问题集全部记下来,改 rerank 的期间不要同时改检索参数,否则效果变化说不清是谁带来的。
- 准备评测集攒一批带标准答案的问题,每条标注「正确段落应该排进前几名」。这就是后面判断 rerank 有没有用的尺子,没有它你只能凭感觉。
- 接上调用输入是查询加候选段落列表,输出是每条的分数,按分数重排后截断。注意是批量传候选,不是循环里一条一条调。
- 对比前后同一批问题跑改动前后两版,看正确段落进入最终上下文的比例变化,而不是盯某一次回答好不好看。
- 打点观察把 rerank 调用单独埋点,记录耗时和失败次数,出问题时能一眼判断是它挂了还是召回本来就空。
延迟和成本:rerank 会带来什么代价
rerank 的开销和「候选条数 × 每条文本长度」大致成正比,所以最容易失控的地方,就是把召回条数一口气开到很大。候选越多越贵,而且是乘上去的,不是加一点。
- 分档试探:候选条数小步往上加,找到效果和延迟的平衡点再停,别一上来就拉满。
- 按场景分开对待:对延迟敏感的在线问答同步跑 rerank,离线批处理可以放宽条数追求效果。
- 别在循环里逐条调用,批量传候选能省掉大量往返开销。
- 只留一个候选时不要调 rerank,纯属浪费调用。
真实的单价和延迟基线不要拿别人的经验值直接套,你手上的资料库长度分布和别人完全不同。各家接口的当时报价去站内价格追踪页面核对,延迟数据到站内接口测速页面看实测记录。
rerank 没效果或挂了怎么办
| 症状 | 先怀疑什么 | 下一步动作 |
|---|---|---|
| 加了反而变差 | 候选里根本没有正确答案 | 回看召回结果,先修召回 |
| 延迟暴涨 | 候选条数或单条长度失控 | 砍候选条数,确认没在循环调用 |
| 服务超时或报错 | rerank 端异常 | 降级回退到召回原始顺序,别让问答整体失败 |
| 换模型或改分块后结论失效 | 评测基线过期 | 用同一批问题集重跑一遍 |
有一个原则要记牢:rerank 的超时和报错不应该让整个问答挂掉。降级路径应该是「回退到召回原始顺序」,用户拿到的可能是排序差一点的结果,但至少拿得到结果。这条降级逻辑要提前写好并测过,别等线上出事才临时加。
上线前的一张自查清单
- 问题集覆盖了你最关心的几类查询,而不是随手挑几条好答的。
- 召回条数、精排保留数、分块长度三个参数记录在案,方便随时回滚。
- 正确段落进入最终上下文的比例,改动前后都测过并有记录。
- rerank 调用单独监控,超时和错误有明确的降级路径。
- 资料库更新后有机制重跑评测,避免效果悄悄退化。
几个初学者最容易踩的坑
- 拿 rerank 的分数去和向量相似度做阈值比较——两套分数口径不同,混用等于乱设阈值。
- 把整篇长文档丢给 rerank 不分块,关键句被截断在窗口外,分数自然不准。
- 只调 rerank 不管分块:分块本身把一句话切碎时,再好的精排也救不回来。
- 把 rerank 当成召回的替代品,试图用它扫全库。
- 换了模型却不重跑评测,拿旧结论指导新配置。
这些坑里有三条指向同一个根源:链路是连着的,分块和召回的地基没打好,精排的效果上限就被锁死了。调 rerank 之前先确认前面两步是干净的。
下一步想知道各家中转站和官方接口的当时报价、模型对照和实测延迟,别用别人的经验值套自己的项目,去站内对照一遍再决定。→常见问题
rerank 和向量检索是一回事吗?
不是。向量检索负责从大量文档里快速捞出一批候选,速度快但精度有限;rerank 是在这批候选上再做一次更精细的相关性打分,只处理少量文本所以可以更准。两者是前后接力关系,不是替代关系。
小项目有必要上 rerank 吗?
看你的资料库规模和查询复杂度。如果资料只有几十条、问题类型单一,向量召回加混合检索可能就够了;如果经常出现答案明明在库里却排不到前面,那加 rerank 的收益会比较明显。先用评测数据判断,别凭感觉。
接入 rerank 要改多少现有代码?
通常只动检索这一段:在召回结果拿到之后、拼上下文之前插一步重排,输入输出都是数组,改动面不大。真正需要花时间的是准备评测问题集和调参数,而不是写调用代码。
rerank 会不会让响应变慢很多?
会加一段额外延迟,但因为它只处理少量候选,通常比重新做一次全库检索便宜。控制手段是限制候选条数和单条文本长度,并且做批量调用。具体能接受多少,先用接口测速量出自己的延迟基线再定。
换了模型或分块策略后,之前的调优结论还能用吗?
不能直接沿用。分块长度、召回条数、精排模型三者互相影响,任一改动都会改变最优参数组合。建议每次改动后重跑同一套问题集,看指标是涨还是跌,再决定保留哪一版。