跳到正文
RadarAI· OpenRouter:Announcements(RSS)·· 2 小时前AI 评分65

OpenRouter 实测 RAG 重排序:274 题基准中 precision@1 从 81% 提升到 97%

AI 导读

OpenRouter 发布 RAG 重排序教程,在 274 题合成基准上,google/gemini-embedding-2 向量检索的 precision@1 为 81.0%,加入 voyageai/rerank-3-lite 对 top 30 重排序后提升到 97.1%,成本约 $0.10/千次查询。

正文 · AI 翻译

OpenRouter:Announcements·2026-11-13 08:00· 2 小时前AI 评分67

RAG 中的重排序:如何用重排序器修复糟糕的检索

AI 导读

OpenRouter 发布 RAG 重排序教程,在 274 题合成基准上,向量检索用 google/gemini-embedding-2 的 precision@1 为 81.0%,加入 voyageai/rerank-3-lite 对 top 30 重排序后提升到 97.1%,成本约 $0.10/千次查询。

正文 · 原文

当 RAG(检索增强生成)应用明明文档里有正确信息却给出错误答案时,问题往往出在检索环节。向量搜索很擅长找到主题正确的片段,但常常被“近似命中”误导,比如用户问的是 Growth 套餐,却检索出了 Enterprise 套餐的存储桶上限。RAG 中的重排序可以解决这个问题:它取向量搜索的前 30 个候选片段,送入专门的 cross-encoder 模型,让模型直接针对问题对每个片段重新打分。

在 274 题的基准测试中,使用 google/gemini-embedding-2 的标准向量搜索有 81% 的概率把完全正确的片段排在首位。加入 voyageai/rerank-3-lite 对前 30 个候选重排序后,这一比例提升到 97%,成本约为每 1,000 次查询 $0.10。请注意,这是在小型合成数据集上测试的结果,实际收益取决于你的文档,但下面的流程可以帮助你测量自己的基线。

TL;DR
Retrieve about 30 candidates, rerank them, and send the top 3 to the LLM.
voyageai/rerank-3-lite and voyageai/rerank-3 were the most accurate dedicated rerank models and the cheapest of all 11 rerankers, at $0.10 and $0.26 per 1,000 queries.
An LLM reranker (openai/gpt-6-luna) put the right chunk first for 99.6% of questions, but each call took 4.0 seconds against 1.3 for a rerank model.
The cheap voyageai/voyage-4-lite plus voyageai/rerank-3-lite reached 96.7% precision@1, against 81.0% for the more expensive google/gemini-embedding-2 alone.
Set input_type on embedding calls. Leaving it out costs 7 to 12 points of precision@1.
cohere/rerank-v3.5 reads only the first 4,096 tokens (4K) of a document and gives no error.

为什么 RAG 会检索到错误的片段?

标准向量搜索之所以吃力,是因为嵌入模型在见到用户问题之前,就已经把整个片段压缩成了单个向量。如果一个 130 词的片段在解释存储桶上限,具体的套餐名称只占整段中的一两个词。结果,Starter、Growth、Scale 和 Enterprise 套餐的向量在向量空间中彼此紧挨着,检索器很容易把错误的套餐排在第一。

为了在不依赖主观评分的情况下测试检索准确率,我们为一家名为 Fernbank 的虚构存储服务构建了一个受控数据集。语料库包含 274 个片段,涵盖文档、错误码、SDK 指南、变更日志条目和噪声内容,其中包括未回复的论坛帖子和支持工单,专门用来诱骗简单的关键词匹配和向量匹配。我们用 anthropic/claude-sonnet-5.5 根据一组固定事实生成每个片段,并用脚本进行校验。另一个模型 openai/gpt-6.1-sol 负责编写问题。由于每个问题都对应一个正确片段,我们可以在无需主观判断的情况下对检索打分。

在完整测试集中,问题是“在 Growth 套餐下,我可以在单个 Fernbank 账户中创建多少个存储桶?”。google/gemini-embedding-2 把 Starter、Enterprise 和 Scale 套餐的片段分别排在第 1、2、3 位。一个未回复的论坛帖子排第四,而真正的 Growth 套餐答案排在第五。如果你的 RAG 流水线只把前三个候选发送给 LLM,模型根本看不到正确的文档。

重排序器通过 cross-encoder 架构解决这个问题。它不会孤立地评估文档,而是将用户的问题与每个候选片段一起处理。在数千个文档上运行 cross-encoder 对实时查询来说太慢,因此向量搜索充当快速检索器,先把范围缩小到候选列表,再由重排序器排序。

如何为你的 RAG 流水线添加重排序器

你不需要替换现有的嵌入搜索。把它保留为第一检索阶段,增加它返回的候选数量,并在将最终结果传给 LLM 之前添加一次重排序调用。

RAG pipeline with a reranker: question, vector search for the top 30 chunks, rerank model, top 3 chunks, LLM answer

用嵌入检索 30 个文本块,对它们重排序,然后将前 3 个发送给 LLM。

以下 Python 示例使用我们的嵌入和重排序 API。它使用余弦相似度检索候选文本块,用 voyageai/rerank-3-lite 对它们重排序,并返回排名最高的三个结果。

你需要一个 OPENROUTER_API_KEY 环境变量,以及安装 numpy 和 requests。

Python

import os
 
import numpy as np
import requests
 
API = "https://openrouter.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}"}
 
def embed(texts, input_type, model="google/gemini-embedding-2"):
    r = requests.post(f"{API}/embeddings", headers=HEADERS, timeout=120,
                      json={"model": model, "input": texts,
                            "input_type": input_type})
    r.raise_for_status()
    data = sorted(r.json()["data"], key=lambda d: d["index"])
    v = np.array([d["embedding"] for d in data])
    return v / np.linalg.norm(v, axis=1, keepdims=True)
 
def retrieve(question, chunks, chunk_vectors, n=30):
    sims = chunk_vectors @ embed([question], "search_query")[0]
    return [(sims[i], chunks[i]) for i in np.argsort(-sims)[:n]]
 
def rerank(question, candidates, top_n=3, model="voyageai/rerank-3-lite"):
    r = requests.post(f"{API}/rerank", headers=HEADERS, timeout=120,
                      json={"model": model, "query": question,
                            "documents": candidates, "top_n": top_n})
    r.raise_for_status()
    data = r.json()
    ranked = [(res["relevance_score"], candidates[res["index"]])
              for res in data["results"]]
    return ranked, data.get("usage", {}).get("cost")
 
# Your knowledge base, already split into chunks
chunks = [
    "Starter plan limits: an account on the Starter plan can create up to "
    "10 buckets.",
    "Scale plan limits: accounts on the Scale plan can hold up to "
    "2,500 buckets.",
    "Enterprise plan limits: Enterprise accounts can create up to "
    "40,000 buckets.",
    "Growth plan limits: an account on the Growth plan can hold up to "
    "150 buckets.",
    "Q: What's the bucket cap on the Growth plan? Reply: I think it "
    "changed recently, check the docs.",
    "Growth plan object size: a single object on the Growth plan can be "
    "up to 50 GB.",
]
chunk_vectors = embed(chunks, "search_document")
 
question = ("How many buckets can I create in a single account "
            "on the Growth plan?")
retrieved = retrieve(question, chunks, chunk_vectors)
print("Vector search:")
for sim, text in retrieved:
    print(f"  {sim:.3f} {text[:60]}")
 
ranked, cost = rerank(question, [text for _, text in retrieved])
print(f"Reranked (${cost:.7f}):")
for score, text in ranked:
    print(f"  {score:.3f} {text[:60]}")

输出

Vector search:
  0.832 Growth plan limits: an account on the Growth plan can hold u
  0.758 Starter plan limits: an account on the Starter plan can crea
  0.741 Scale plan limits: accounts on the Scale plan can hold up to
  0.737 Enterprise plan limits: Enterprise accounts can create up to
  0.717 Growth plan object size: a single object on the Growth plan
  0.695 Q: What's the bucket cap on the Growth plan? Reply: I think
Reranked ($0.0000038):
  0.922 Growth plan limits: an account on the Growth plan can hold u
  0.793 Q: What's the bucket cap on the Growth plan? Reply: I think
  0.727 Starter plan limits: an account on the Starter plan can crea

对于这些简短的单句文本块,向量搜索已经将正确的 Growth 套餐限制排在第一位。余弦相似度分数范围从 0.695 到 0.832,因此有几个候选相对接近。重排序后,正确的文本块获得 0.922 的相关性分数。未回答的论坛帖子以 0.793 的分数升至第二位,排在 Starter 套餐条目之前。

第二个结果说明了一个重要的局限性:相关性并不等同于正确性。论坛帖子提出了同样的问题,因此重排序器认为它相关,尽管它并没有回答问题。在这个简化示例中,重排序器没有修正第一个结果,因为它已经是正确的。在完整的基准测试中,使用 130 词的文本块,向量搜索对 19% 的问题将错误的文本块排在第一位,包括 Growth 套餐问题,而使用 voyageai/rerank-3-lite 重排序修复了其中大部分问题。

实际教训是向 LLM 发送几个强有力的候选,而不是依赖单一结果。你还应考虑过滤掉未回答的讨论以及其他提及问题但未解决该问题的内容。

代码中还有两个细节值得正确处理:

  • 首先,input_type 参数告诉嵌入模型它是在编码搜索查询还是文档。一些模型对这些输入的处理方式不同,因此省略该参数可能会损害检索效果。在我们的测试中,省略它使 Gemini 的 precision@1 从 81.0% 降至 74.1%,使 voyageai/voyage-4-lite 的从 64.6% 降至 52.9%。请参阅 embeddings API 参考,它将其作为字符串接收,并记录了 search_query 和 search_document 作为其值。

  • 其次,top_n 控制重排序器返回多少结果,而不是它评估多少结果。模型仍然会对你发送的每个候选进行评分,因此候选数量会影响成本和延迟。

如何知道重排序是否有帮助?

重排序器可以改善结果排序,但不一定能改善用户收到的答案。要确定是否值得添加,请在更改前后测量检索准确率,然后评估最终答案。

1. 从 precision@1 开始:即第一个检索到的文本块包含正确答案的问题百分比。你不需要巨大的评估集就可以开始。来自应用程序日志的 50 个真实问题,每个都标注了其正确的答案文本块,可以为你提供初始基线。从生产流量构建黄金评估数据集的指南解释了如何构建一个。

2. 不要只依赖 recall@5:它衡量的是正确片段是否出现在前五名中的任意位置,而不考虑其具体位置。在我们的测试中,Gemini 的 recall@5 达到 98.2%,但 precision@1 仅为 81.0%。正确的信息通常就在结果中的某个位置,但并不总是在最前面。

我们还测试了这对最终答案的影响。我们使用 anthropic/claude-haiku-5.5,基于每种检索配置返回的片段来回答全部 274 个问题,然后将回答与已知事实进行对比。

发送给 LLM 的片段回答正确上下文中包含正确片段
voyage-4-lite 前 5,无重排93.1%93.1%
gemini-embedding-2 前 5,无重排97.1%98.2%
gemini-embedding-2 前 3,无重排95.6%96.0%
gemini-embedding-2 前 30,重排至 399.3%100%
voyage-4-lite 前 30,重排至 399.3%99.6%

我们 2026 年 10 月 8 日的运行包含 274 个问题。重排使用了 voyageai/rerank-3-lite。

结果表明,重排帮助 LLM 在使用更少片段的情况下正确回答了更多问题。大多数错误回答都源于信息缺失。在正确片段未进入前三名的案例中,有十分之九模型表示所提供的段落不包含答案。换句话说,应用程序告诉用户它不知道某些事情,而它自己的文档其实能够回答。

重排通过改进到达模型的片段解决了这个问题。它还让我们可以只发送三个片段而不是五个,将 LLM 回答成本从每 1,000 个问题 $0.22 降至 $0.16。重排调用增加了 $0.10,因此在我们的设置中,重排每 1,000 个问题净增加 $0.04 的成本。

重排是否能为你省钱取决于你的模型、文档大小和查询量,因此请衡量整个流水线(从检索到最终答案)的成本和准确率。

哪个重排模型最适合 RAG?

我们使用 google/gemini-embedding-2 为 274 个问题各检索相同的 30 个候选片段,对比了 11 个重排器。这为我们比较它们的准确率、延迟和成本提供了一致的基础。

在我们测试的专用重排模型中,Voyage 重排器在准确率和价格之间提供了最佳组合。

重排器Precision@1中位秒数(我们的设置)每 1,000 次查询的 $ 成本
无(仅嵌入)81.0%不适用不适用
voyageai/rerank-397.8%1.27$0.26
voyageai/rerank-3-lite97.1%1.26$0.10
voyageai/rerank-2.5-lite96.7%1.50$0.10
voyageai/rerank-2.596.4%1.30$0.26
cohere/rerank-4-pro95.3%1.54$2.50
qwen/qwen3-reranker-8b92.3%1.51$1.49
cohere/rerank-4-fast92.0%1.25$2.00
cohere/rerank-v3.590.5%1.47$1.00
openai/gpt-6-luna(LLM)99.6%4.01$0.70
anthropic/claude-haiku-5.5(LLM)98.9%4.44$0.87
google/gemini-3.8-flash(LLM)100%3.25$4.14

我们于 2026 年 10 月 8 日运行。成本为每次响应的使用成本,与 GET /api/v1/generation 一致。每个中位时间中约有 0.9 秒来自我们测试机器的网络开销。

在此数据集上,voyageai/rerank-3 有 97.8% 的时间将正确片段排在第一位,而 Lite 版本达到 97.1%。这一差异在我们 274 个问题的测试中仅相当于两个问题,因此不足以证明更昂贵的模型始终更好。建议先从 voyageai/rerank-3-lite 开始,并在你自己的评估集上将其与 voyageai/rerank-3 进行比较。两者使用相同的 /rerank 端点,因此切换模型只需更改模型标识符。

价格差异在很大程度上反映了各提供商如何收费,具体列在我们的重排序模型页面上。Voyage 和 Qwen 按 token 计费(每百万 token 0.02 至 0.20 美元),而 Cohere 按每次搜索最多 100 个文档收取 0.001 至 0.0025 美元,与文档长度无关。由于我们的 30 个候选文档包含约 5,000 个 Voyage token,Voyage 模型的价格尤其便宜。在这些短片段上,Cohere 的重排序器成本约为 Voyage 各选项的 4 到 25 倍,具体取决于所比较的模型。在我们的测试中,向 Cohere 发送 101 个文档还触发了第二次搜索计费。

对于涉及特定错误代码(如 FB-2411)的问题,重排序带来的差异尤为明显。仅靠嵌入搜索时,使用 voyageai/voyage-4-lite 只有 25% 的情况下能把正确条目排在第一位,使用 google/gemini-embedding-2 时为 53.6%。全部 11 个重排序器在该子集上都达到了 100%。由于错误代码条目往往讨论相似的错误,它们的嵌入可能看起来很相似。交叉编码器可以将问题中的确切代码与每个候选中的代码进行比较,从而区分出正确的条目。

如果你想知道开发者最常使用哪些模型,我们的重排序模型排名提供了另一个有用的参考。截至 2026 年 10 月 20 日,voyageai/rerank-2.5 以截至 10 月 18 日当周的 468 万次请求领先,并在我们的测试中得分 96.4%。使用热度值得考虑,但它不应取代针对你自己的文档测试模型。模型性能、价格和提供商延迟都可能发生变化。重排序模型集合列出了可用的选项及其当前详情。

你应该对多少个文档进行重排序?

先从对大约 30 个候选文档进行重排序开始,然后根据你的评估结果调整数量。

为了解候选数量如何影响性能,我们测试了 voyageai/rerank-3-lite 在由 voyageai/voyage-4-lite 检索到的不同数量候选文档下的表现:

重排序的候选数量候选中的正确片段重排序后的 Precision@1每 1,000 次查询的费用
1097.1%94.5%$0.035
2098.9%96.4%$0.070
3099.6%96.7%$0.104
50100%97.1%$0.174
100100%97.1%$0.348

我们于 2026 年 10 月 8 日进行的运行使用了 274 个问题,第一阶段使用 voyageai/voyage-4-lite。

将候选数量从 10 增加到 30,使 precision@1 从 94.5% 提升到 96.7%。再增加到 50 使 precision 达到 97.1%,仅多修正了一个问题,同时使重排序成本增加约三分之二。从 50 增加到 100 个候选并未提升 precision。

重排序有其局限,因为只有当第一检索阶段将相关片段纳入候选集时,它才能将其提升。如果向量搜索完全遗漏了答案,任何重排序器都无法将其找回。

对于更大的知识库,请使用你的评估集来找到这样一个点:继续检索更多候选不再能显著提高正确片段可用的题目比例。这比假设 30 对每个应用都是最优的,是选择候选数量的更好方法。

LLM 可以用作重排序器吗?

在我们的基准测试中,基于 LLM 的重排序器最为准确,尽管它们返回结果所需的时间更长。我们没有将每个候选文档送入专门的重排序模型,而是将问题和全部 30 个带编号的片段交给一个聊天模型,然后要求它按顺序返回最相关片段的 ID。我们使用了严格的结构化输出 schema来确保响应符合预期格式。

这两种方法在一个关键方面有所不同。专用重排器会针对问题对每个候选文档单独评分。LLM 则可以同时阅读所有候选文档并进行比较,当多个文档包含相似信息时,这一点很有帮助。

在我们的测试中,openai/gpt-6-luna 在每 1,000 次查询 0.70 美元的成本下实现了 99.6% 的 precision@1,处于 LLM 成本区间的低端,而 google/gemini-3.8-flash 的成本则高达 4.14 美元。这比专用重排器的准确率更高,但在我们的设置中,每次调用大约需要四秒,而专用模型约为 1.3 秒。

在用户等待答案的交互式应用中,这多出的时间很重要。LLM 重排可能更适合批处理,或那些检索正确信息尤为重要、且可以接受额外延迟的应用。

请记住,我们的基准测试使用的是干净、由模型生成的文本。真实的知识库存在格式不一致、文档不完整以及其他复杂情况,因此我们不能假设 LLM 重排器在更混乱的真实世界数据上也能保持同样的优势。

有了混合搜索或更好的嵌入模型,还需要重排器吗?

混合搜索和更好的嵌入模型都能改善检索,但我们的基准测试表明,两者的效果都不如添加重排器。混合搜索将向量相似度与基于关键词的检索相结合,通常使用 BM25。我们用倒数排名融合(RRF)合并结果,它会将两个排名融合在一起。

在我们的测试集上,混合搜索将 voyageai/voyage-4-lite 的 precision@1 从 64.6% 提升到 69.3%。然而,使用 google/gemini-embedding-2 时,precision@1 从 81.0% 下降到 78.8%,尽管 recall@5 有所改善。能力更强的嵌入模型胜过了更便宜的替代方案。Gemini 实现了 81.0% 的 precision@1,而 Voyage 4 Lite 为 64.6%。但 Gemini 的嵌入价格为每百万 token 0.20 美元,而 Voyage 4 Lite 为 0.02 美元。将更便宜的嵌入模型与 voyageai/rerank-3-lite 结合使用,达到了 96.7% 的 precision@1。

混合搜索和更好的嵌入仍然有用,因为它们承担不同的职责。混合搜索可以帮助检索向量搜索遗漏的候选文档,而更强的嵌入模型可以改善初始排名。重排器则通过将每个候选文档直接与问题进行比较,增加了另一层。

为了获得最佳结果,请分别并组合评估这些选项。你可以使用我们的嵌入模型比较来帮助为第一检索阶段选择嵌入模型。

什么会破坏重排?

当文档超过模型的上下文限制时,重排可能会静默失败。例如,cohere/rerank-v3.5 有4,096 token 的上下文限制,因此它可能永远看不到文档中包含答案的那部分。

我们用两个 11,000 token 的文档进行了测试,它们仅在最后一句上有所不同。其中一个包含答案,但两者获得了相同的相关性分数:0.2703。模型实际上错过了区分它们的细节。相比之下,voyageai/rerank-3-lite 给这两个文档的评分分别为 0.7812 和 0.3242,正确地将包含答案的文档排在更高位置。Cohere 4 模型、voyageai/rerank-3 和 qwen/qwen3-reranker-8b 也将正确的文档排在更高位置。检查你的重排器的上下文限制,并让分块舒适地保持在限制之内。

另一个问题是模型兼容性,因为 /rerank 端点只接受 rerank 模型。向它发送聊天模型 openai/gpt-6-luna 会返回 400 Model openai/gpt-6-luna does not exist,这与模型标识符拼写错误时得到的错误相同。在发起请求之前,请确认该模型出现在重排序模型集合中。

后续步骤

常见问题

RAG 中的重排序是什么?

RAG 中的重排序是第二个检索步骤,其中重排序模型会针对问题对向量搜索返回的每个分块进行评分并重新排序,使最相关的少数几个分块进入 LLM。重排序模型会同时读取问题和分块,这使它能够捕捉到近似错误,例如为错误的套餐给出了正确的限额。在我们 274 个问题的测试中,它将正确分块排在首位的比例从 81% 提高到 97%。

用于 RAG 的最佳重排序模型有哪些?

在我们 2026 年 10 月的测试中,voyageai/rerank-3 和 voyageai/rerank-3-lite 是最准确的专用重排序模型,也是最便宜的重排序器,在 274 个问题中分别有 97.8% 和 97.1% 的情况下将正确分块排在首位。LLM 重排序器得分更高,但每次调用大约需要 4 秒。

我应该对多少文档进行重排序?

对大约 30 个候选进行重排序,对于更大的知识库,增加数量,直到正确分块可靠地出现。在我们的测试中,从 30 增加到 50 使 precision@1 从 96.7% 提高到 97.1%(在噪声范围内仅多答对一个问题),并使重排序成本增加了三分之二。

参考文献

来源:OpenRouter:Announcements · openrouter.ai

来源:RadarAI · aihot.news