国产 Rerank 模型盘点:RAG 精排阶段选型与接入指南
你大概率遇到过这种情况:RAG 应用在自测的时候答得挺准,一上线用户反馈就变成”这答非所问是怎么回事”。排查半天发现问题不在 LLM,也不在 Embedding 模型选得不好,而是召回回来的 Top-10 里,真正相关的那条排在了第 7 位——LLM 拿到的上下文里,噪声比信号还多,生成质量自然打折扣。这就是 Rerank 要解决的问题:把召回结果里”看着像相关但其实不是”的文档摘出去,把真正该排前面的顶上来。
Embedding 检索和 Rerank 精排走的是两条完全不同的技术路线,搞清楚区别对选型很关键:Embedding 是”双塔模型”(bi-encoder),query 和文档各自独立编码成向量,之后做余弦相似度比对——好处是文档向量可以离线算好存进向量库,检索时只需要算一次 query 向量再做近似最近邻搜索,速度是毫秒级的;代价是 query 和文档在编码阶段互不感知,语义关联判断得比较粗。Rerank 用的是”交叉编码器”(cross-encoder),把 query 和每条候选文档拼接成一个序列一起丢进模型做联合编码,模型能看到两者之间逐词的交互关系,判断相关性自然更准,但计算量也跟着候选数量线性增长,没法像向量检索那样提前离线算好,只能在线实时跑。
为什么 RAG 需要 Rerank
| 阶段 | 技术 | 特点 |
|---|---|---|
| 粗召回 | 向量检索(Embedding + 余弦相似度) | 速度快,但语义匹配精度有限 |
| 精排 | Rerank 交叉编码器 | 精度高,但延迟略高,不适合全库扫描 |
| 生成 | LLM(Chat API) | 只处理精排后的 Top-N,节省 context window |
典型 RAG 流程:召回 Top-100 → Rerank → 取 Top-5 → 送入 LLM。
这里有个容易被忽略的细节:召回阶段的 Top-K 应该设多大,很大程度上取决于你打算送给 Rerank 多少候选。K 设得太小(比如 Top-10),相当于还没进 Rerank 就已经把可能相关的文档漏掉了,Rerank 精度再高也无力回天;K 设得太大(比如 Top-500),Rerank 的延迟和费用会线性上涨,而且大部分模型的候选数上限本身就有限制(后面表里能看到智谱是 64、百川是 32),超过上限要么报错要么被截断。实操里比较常见的搭配是召回 Top-50100,Rerank 精排后取 Top-35 送 LLM,这个比例在大多数知识库场景下能兼顾精度和延迟。
国产 Rerank 模型速查
| 厂商 | 模型名 | 支持语言 | 最大候选数 | 价格定性 |
|---|---|---|---|---|
| 智谱 | reranker | 中英文 | 64 | 极低 |
| 百川 | Baichuan-Reranker | 中英文 | 32 | 低 |
| 通义千问 | 内嵌于 RAG 套件 | 中英文 | 视套件而定 | 按 token 计费 |
| Cohere(国内镜像) | rerank-multilingual-v3.0 | 多语言 | 1000 | 中等 |
截至 2026-06,以官方为准;Rerank 独立 API 仍相对小众,部分厂商通过 RAG 平台集成提供,请以控制台实际可用为准。
表里”最大候选数”这一列很容易被新手忽略,但它直接决定了你的召回策略要不要做拆分。比如百川限制 32 条候选,如果你的召回 Top-K 设成了 50,直接整批传进去大概率会报参数错误或者被静默截断(不同厂商处理方式不同,务必自己实测一次,别假设它会帮你自动截)。稳妥的做法是在调用前用 documents[:32] 这种方式在客户端先做截断,或者干脆把召回 Top-K 直接设成不超过模型上限,省得线上偶发报错还得回头查半天。
接入示例:智谱 Reranker
智谱 Reranker API 采用自有接口格式(非 OpenAI 兼容),需直接调用 HTTP:
import requests
url = "https://open.bigmodel.cn/api/paas/v4/reranker"
headers = {
"Authorization": "Bearer sk-xxxxxxxx",
"Content-Type": "application/json",
}
payload = {
"model": "reranker",
"query": "如何优化 RAG 的检索精度?",
"documents": [
"向量检索是 RAG 的第一步,通过余弦相似度召回候选文档。",
"Rerank 模型对召回结果进行精排,显著提升相关性。",
"今天天气很好,适合出门运动。",
],
"top_n": 2, # 返回排名最高的 2 条
"return_documents": True,
}
resp = requests.post(url, json=payload, headers=headers)
results = resp.json()["results"]
for r in results:
print(f"相关性分数: {r['relevance_score']:.4f} | {r['document']['text'][:40]}")
这段代码几个细节值得展开讲讲。top_n 是”你要几条结果”,不是”候选池大小”——候选池就是 documents 列表本身,top_n=2 的意思是从这 3 条候选里挑出分数最高的 2 条返回,如果你把它设得比候选数还大,接口通常会直接把全部候选按分数排完返回,不会报错,但也没有实际精排效果,白花一次调用。return_documents=True 这个参数建议保留:不设的话响应里只有 index 和 relevance_score,你还得自己拿 index 回原始列表里对应文档,多一步容易在并发场景下因为顺序错乱对错行;设了 True 虽然多传一点数据量,但排查问题时能直接看到文本内容,调试成本低很多。
实际接入时你大概率会踩到下面这几个坑,提前知道能少走弯路:
- 401 Unauthorized:十有八九是
Authorization头少写了Bearer前缀,或者 key 是从别的产品线(比如 Chat 模型)复制过来的,Rerank 用的是独立的 API Key 体系,两者不通用。 - 429 Too Many Requests:说明触发了限流,智谱这类接口通常有 QPS 和并发数双重限制。别在收到 429 后立刻重试,先做指数退避(比如 1s、2s、4s 递增),否则重试请求会叠加在原有流量上,越限流越重试,形成雪崩。
- 超时(timeout):候选文档数量多、单条文档过长时,Rerank 的计算量会明显上涨。
requests.post默认不设超时会一直等,线上环境务必显式传timeout=10(按你的候选规模调),配合捕获requests.exceptions.Timeout做降级(比如降级为直接用向量检索的排序结果,保证服务不整体挂掉)。 - 文档过长被截断:交叉编码器有输入长度上限(通常和底层模型的 context window 相关),过长的文档会被模型自动截断,可能导致真正相关的内容恰好在被截掉的那一段。如果你的知识库文档本身很长,建议先做分段(chunk),别指望 Rerank 帮你处理整篇长文。
生产环境里更推荐用带重试和超时控制的封装,而不是裸调用:
import time
import requests
def rerank_with_retry(query, documents, top_n=5, max_retries=3, timeout=10):
url = "https://open.bigmodel.cn/api/paas/v4/reranker"
headers = {"Authorization": "Bearer sk-xxxxxxxx", "Content-Type": "application/json"}
payload = {
"model": "reranker",
"query": query,
"documents": documents[:64], # 客户端先按上限截断,避免超限报错
"top_n": min(top_n, len(documents)),
"return_documents": True,
}
for attempt in range(max_retries):
try:
resp = requests.post(url, json=payload, headers=headers, timeout=timeout)
if resp.status_code == 429:
time.sleep(2 ** attempt) # 指数退避:1s、2s、4s
continue
resp.raise_for_status()
return resp.json()["results"]
except requests.exceptions.Timeout:
if attempt == max_retries - 1:
return None # 超过重试次数,交给上层做降级处理
time.sleep(2 ** attempt)
return None
这个封装比裸调用多做了三件事:候选数客户端截断(避免踩 32/64 的上限)、429 指数退避(避免限流雪崩)、超时兜底返回 None(让上层能明确判断”精排失败,走降级逻辑”而不是异常直接抛出中断整个流程)。如果你的业务是高并发场景,还需要考虑用异步客户端(比如 httpx.AsyncClient 或 aiohttp)替换同步 requests,把多路检索请求的 Rerank 调用并发发出去,减少整体响应时间——单条 Rerank 调用通常在几十到两百毫秒,并发 10 路和串行 10 路的耗时差距是数量级的。
与 Embedding 纯向量检索的效果对比
| 指标 | 纯向量检索 | 向量 + Rerank |
|---|---|---|
| 检索精度(MRR@10) | 基线 | +15%~30%(视数据集) |
| 延迟 | 低(毫秒级) | 略高(增加 50~200ms) |
| LLM 输入 token | 多(Top-100 全送) | 少(Top-5 精选) |
| 综合成本 | Embedding 费用 | Embedding + Rerank,但 LLM token 大幅减少 |
结论:对于知识库问答、企业文档检索等精度要求高的场景,增加 Rerank 后总体成本往往更低(LLM token 节省抵消 Rerank 费用)。
MRR@10 这个指标简单解释一下:它衡量的是”正确答案排在第几位”,具体算法是取每次查询里第一条相关文档排名的倒数(排第 1 位得 1 分,排第 2 位得 0.5 分,排第 10 位得 0.1 分,第 10 位以外算 0 分),再对所有查询取平均。所以 MRR 提升的本质,不是”检索到了更多相关文档”,而是”相关文档排到了更靠前的位置”——这正好对应 LLM 只吃 Top-N 的现实:哪怕召回阶段把正确答案捞回来了,如果它排在第 8 位而你的 Top-N 只取 5,LLM 照样看不到,等于白召回。这也是为什么很多团队加了 Rerank 之后感觉”答案质量肉眼可见变好”,但看 Embedding 模型本身的召回率指标却没什么变化——两者衡量的根本不是一回事。
要不要上 Rerank,这里给个简单的判断依据:如果你的知识库文档之间语义区分度很高(比如产品手册、条款类文本,关键词重叠少),纯向量检索的精度往往已经够用,加 Rerank 的边际收益有限;如果文档之间高度相似只是细节不同(比如多个版本的政策文件、相似产品的参数对比),纯向量检索很容易把语义相近但答案不同的文档搞混,这时候 Rerank 带来的精度提升会非常明显,值得上。
选型建议
- 中文知识库首选:智谱
reranker,中文效果经过专项优化,价格极低; - 中英混合文档:百川
Baichuan-Reranker,双语场景表现稳定; - 已用通义 RAG 套件:直接使用内置精排,无需额外接入;
- 不想自建精排:考虑使用 LlamaIndex / LangChain 的本地 Cross-Encoder(
cross-encoder/ms-marco-MiniLM),零 API 成本,适合数据敏感场景。
如果你还在纠结用 API 还是本地部署 Cross-Encoder,可以按下面这个表快速判断:
| 维度 | 云端 Rerank API | 本地 Cross-Encoder |
|---|---|---|
| 接入成本 | 低,几行代码接入 | 中,需要自己起服务、管显存 |
| 单次调用延迟 | 依赖网络,通常 50~200ms | 本地推理,GPU 上更快但受限于并发排队 |
| 数据合规 | 文档内容出境/出司需评估 | 数据不出内网,敏感场景更放心 |
| 长期成本 | 按调用量计费,量大会累积 | 一次性硬件/维护成本,量越大越划算 |
| 效果上限 | 跟随厂商模型迭代 | 取决于你选的开源模型,一般略逊专项优化的商用模型 |
简单说:早期验证阶段、调用量不大,直接用 API 最省事;数据敏感或调用量已经上规模,本地部署的性价比会反超。
常见问题
Rerank 分数代表什么? 通常是 0~1 之间的相关性概率分数,分数越高表示文档与查询越相关。不同模型的分数范围和校准方式不同,跨模型比较需谨慎。
Rerank 需要微调吗? 通用文档检索场景一般无需微调;垂直领域(法律、医疗、金融)如果效果不理想,可用领域数据做 Fine-tuning 或换用支持自定义的模型。
能用 Rerank 替代 Embedding 做全量检索吗? 不推荐。Rerank 是交叉编码器,需要将 query 与每条候选文档拼接后推理,计算量随文档数线性增长。全量文档(数万条以上)直接 Rerank 延迟不可接受,应配合 Embedding 粗召回使用。
Rerank 会不会把召回阶段本来排前面的相关文档挤下去? 理论上会,这是正常现象,也是接入 Rerank 的意义所在——向量检索的排序本来就不完全准,Rerank 是用更精细的模型重新判断相关性。如果你发现精排后的结果和向量检索差异很大且直觉上更合理,说明 Rerank 在起作用;如果差异很大但看着更不合理,先检查 query 和文档的语言/领域是否匹配模型的训练分布(比如把英文 query 丢给中文专项优化的模型,效果可能不升反降)。
多路召回(比如同时用向量检索 + 关键词检索)要怎么接 Rerank?
把各路召回的结果去重合并后,作为统一的 documents 列表整体传给 Rerank 一次调用即可,不需要对每一路分别精排再合并——分别精排的分数不在同一个尺度上,没法直接比较排序。合并去重(按文档 ID 或内容哈希)之后统一精排,才能得到一致可比的相关性分数。
相关阅读:国产大模型 API 全景指南 · 国产 Embedding 模型盘点 · 接入 Rerank API 实战
分类导航:国产模型专题
实用工具:价格对比表