什么是 reranker?
重排序器(reranker)是一个模型:它接收一个查询和一组候选文档,并根据每个文档与查询的真实相关性重新排序。它几乎总是作为第二阶段运行:先由某种快速方法召回一大批候选,再由 reranker 仔细地对这批候选的头部重新打分。
为什么排序顺序是个问题
现代搜索与 检索增强生成(RAG)通常都从一个向量数据库开始。你先对文档做一次嵌入,在请求时对查询做嵌入,再用余弦相似度取出最近邻。这很快,也能扩展到数百万文档 —— 但它给出的排序只是大致正确。
原因是结构性的。为了保持快速,检索器会独立地对查询和每个文档做嵌入,两段文本没有机会相互作用。一段只是与查询共享词汇的文本,得分可能和真正回答了问题的文本一样高。于是正确的文档常常确实在前 50 名里 —— 只是不在第 1、2、3 名,而当你只把少数几段送进 LLM 时,恰恰需要它排在最前面。
检索擅长 recall(召回)(“答案是否在候选名单里?”),但在 precision(精度)上表现平平(“答案是否就排在最前?”)。重排序正是用来修复精度的。
两阶段检索范式
reranker 之所以存在,是因为速度与准确性之间的取舍。比较查询与文档的准确做法,是把它们一起送进模型 —— 但对语料库里的每一个文档都这么做会慢到不可行。于是我们把工作拆开:
Stage 1 — Retrieve (fast, approximate)
vector search / BM25 over the whole corpus → top 50–100 candidates
Stage 2 — Rerank (slow per item, but only on the shortlist)
cross-encoder scores each (query, candidate) pair → reorder → keep top 3–10
检索器以很低的成本撒一张大网;reranker 只对幸存下来的少数候选施加一个昂贵而准确的模型。你以极小的代价,获得了在所有文档上都跑大模型才能得到的大部分质量。
rerank 模型如何为相关性打分
大多数 reranker 是 cross-encoder。查询和候选文档被拼接成单一输入,送入一个 transformer,输出一个数字:相关性分数。由于查询的每个 token 都能注意(attend)到文档的每个 token,模型能判断相似度分数无法判断的东西 —— 否定、具体性,以及这段文本是真正回答了问题,还是仅仅提到了话题。
你对每个候选跑一次,然后按分数排序。输出通常会(通过 sigmoid)转成 0–1 的数值,便于设阈值或展示。
关键对比:bi-encoder 分别嵌入查询和文档再比较向量 —— 快,但粗糙。cross-encoder 把两者一起读入并对这一对打分 —— 单条慢,但准确得多。reranker 就是你施加在一个短名单上的 cross-encoder。
什么时候该(以及不该)做重排序
以下情况,重排序很值得:
- 你把检索到的上下文喂给 LLM,并希望最相关的段落排在最前(经典 RAG)。
- 你的 top-k 看起来“大体正确但顺序不对”,或者正确答案在前 50 名里却不在前 5 名。
- 你能接受多花约几十毫秒的延迟,换取答案质量的明显提升。
- 你想给 LLM 送更少的段落(更便宜的 prompt),又不想漏掉那段好的。
以下情况,它用处不大:
- 在你的领域里,检索器返回的排序已经近乎完美。
- 你对延迟极度敏感,无法再加一次模型调用。
- 你的候选集合非常小(只有 3 条可重排,几乎没什么可调整的)。
亲自上手试试
建立直觉最快的方式,就是亲眼看 reranker 工作。我们的浏览器内 Demo 会加载一个真实的 cross-encoder,对你粘贴的段落按你的查询打分 —— 全程在你的设备上,无需 API 密钥、零成本。放进几段跑题的文字,看它们沉下去。