2026年11月4日
6分钟阅读
Embed 5 与 Rerank 5 现已上线 OpenRouter通过单一 API 访问 Cohere 最先进的检索模型,统一计费,无需额外 SDK。

Embed 5 和 Rerank 5 现已在 OpenRouter 上线。下面介绍如何通过一个 API,用几十行 Python 代码将它们变成可用的 RAG 流水线。 单一 API.
这是 Cohere 迄今最强大的检索模型,在企业文档和复杂检索任务上均展现出领先性能。如果你已经在使用 OpenRouter,可以立即开始使用——沿用现有模型所用的同一 API 密钥和额度,无需任何额外设置。
RAG 会在 LLM 撰写答案之前先检索相关片段,从而让答案以你自己的数据为依据。嵌入搜索提供了一种快速有效的第一阶段近似。随后,重排序器会同时读取查询和每个候选片段,为已检索到的内容增加精确度。
Cohere 模型的两个特性塑造了这一设计:
- Embed 5 Pro 与 Fast 共享同一个嵌入空间。 使用
embed-5-pro建立索引以获得质量,然后使用embed-5-fast进行查询以降低延迟。 - Rerank 5 的分数经过校准。 分数在不同查询和领域之间含义一致,因此可以用同一个相关性阈值在弱上下文到达 LLM 之前将其过滤掉。
到最后,你将拥有一个简短的 Python 脚本,能够基于你的文档回答问题并给出带分数的引用。同样的方法几乎可以应用于任何检索用例,从企业搜索和客户支持到知识管理和文档发现。

设置
你需要 Python 3.10 或更高版本、一个 OpenRouter API 密钥, 以及 OpenRouter Python SDK,以及用于内存向量存储的 NumPy。
pip install openrouter numpy
export OPENROUTER_API_KEY="sk-or-..."import os
import numpy as np
from openrouter import OpenRouter
client = OpenRouter(api_key=os.environ["OPENROUTER_API_KEY"])
EMBED_INDEX_MODEL = "cohere/embed-5-pro" # indexing: highest quality
EMBED_QUERY_MODEL = "cohere/embed-5-fast" # queries: lowest latency
RERANK_MODEL = "cohere/rerank-5-pro" # or cohere/rerank-5-fast
CHAT_MODEL = "deepseek/deepseek-v4.1-flash-1017" # any chat model on OpenRouter
DIMS = 1024 # 256 | 512 | 768 | 1024 | 1536 | 2048Embed 5 返回六种尺寸的 Matryoshka 向量,默认 2048 维。我们 建议 采用 1,024 维 int8 向量作为质量与成本的最佳平衡点;OpenRouter 的 嵌入 API 返回浮点数,因此本文使用 1,024 维浮点数。
NumPy 存储让这个演示保持简单。在生产环境中,请将其替换为你偏好的向量数据库,例如 pgvector、Qdrant、Pinecone 或 Weaviate。
索引
索引会把每个文本块转换成一个向量,也就是一串数字,含义相近的内容在向量空间中彼此靠近。每个语料库只需运行一次,因此这是最值得使用最高质量模型的步骤。
把每个文档切分成块,用 Embed 5 Pro 以 search_document进行嵌入,并对向量做归一化,使点积等于余弦相似度。
示例语料库是一个虚构 API 的文档,其中故意设置了几处近似但不匹配的内容:
docs = [
{"title": "Rotating API keys",
"text": "To rotate a key without downtime, create a second key, deploy it to every service, "
"confirm traffic on the new key in the usage dashboard, then revoke the old key."},
{"title": "Creating API keys",
"text": "Create keys under Settings > API Keys. Each key can be scoped to read or write and to one project."},
{"title": "Revoking API keys",
"text": "Revoking a key takes effect immediately. Requests with a revoked key return 401 Unauthorized."},
{"title": "Webhook signing secrets",
"text": "Rotate your webhook signing secret from the Webhooks page. The old secret stays valid "
"for 24 hours so you can update your verifier."},
{"title": "Log rotation",
"text": "Request logs rotate daily and are kept for 30 days. Export them to S3 for longer retention."},
{"title": "Rate limits",
"text": "Each API key is limited to 600 requests per minute. Going over returns 429 Too Many Requests."},
]def chunk(doc, max_chars=1500):
"""Split on blank lines, packing paragraphs up to ~max_chars."""
out, buf = [], ""
for para in doc["text"].split("\n\n"):
if buf and len(buf) + len(para) > max_chars:
out.append({"title": doc["title"], "text": buf.strip()})
buf = ""
buf += para + "\n\n"
if buf.strip():
out.append({"title": doc["title"], "text": buf.strip()})
return out
def embed(texts, model, input_type, batch=96):
vecs = []
for i in range(0, len(texts), batch):
res = client.embeddings.generate(
model=model,
input=texts[i:i + batch], # one request per batch
input_type=input_type, # "search_document" | "search_query"
dimensions=DIMS,
)
vecs += [d.embedding for d in res.data]
v = np.array(vecs, dtype=np.float32)
return v / np.linalg.norm(v, axis=1, keepdims=True)
chunks = [c for d in docs for c in chunk(d)]
doc_vecs = embed([c["text"] for c in chunks], EMBED_INDEX_MODEL, "search_document")需要指出的三个关键细节:
input_type:告诉 Embed 5 某段文本位于搜索的哪一侧。OpenRouter 会将其传递给 Cohere。- 批处理: 每次请求发送多个块,从而减少往返次数并加快索引速度。这不会改变成本,因为嵌入按 token 计价。
- 块大小: 将整段内容打包,遵循 中的按段落策略, OpenRouter 的指南,而 1,500 个字符大约相当于 300–400 个英文 token。Embed 5 最多接受 128k token,但每个块也都会经过 Rerank 5,后者最多读取查询与块合计 32k token,并将超长内容拆分为多次处理。
检索
检索会找出向量与问题向量最接近的块。这充当两段内容之间语义相似性的表示。
使用 Embed 5 Fast 嵌入问题,作为 search_query,然后通过余弦相似度拉取一个包含 20 个块的宽泛候选集。
def retrieve(query, k=20):
q = embed([query], EMBED_QUERY_MODEL, "search_query")[0]
scores = doc_vecs @ q # cosine, since both sides are normalized
top = np.argsort(-scores)[:k]
return [(chunks[i], float(scores[i])) for i in top]用 Fast 查询由 Pro 构建的索引之所以可行,是因为这两个模型 共享同一嵌入空间,只要双方使用相同的 dimensions。这正是我们推荐的拆分方式:在 Cohere 的测试 中,覆盖 40 个数据集,在 Pro 索引上使用 Fast 查询保留了全 Pro 检索质量的 98.4%,而两侧都用 Fast 则为 96.6%。若使用其他任何模型系列,则必须在两侧使用同一模型。
在这个阶段,让我们广撒网:召回是检索器的职责,精度则交给 Rerank。OpenRouter 的指南建议用 10–20 个候选送入 top 3–5 的重排。
重排序
重排序通过同时读取问题和每个文本块,对候选列表重新打分。在整个索引上运行太慢,但比向量相似度更准确,因此只对排名靠前的候选运行。重排序不需要 Embed,也不需要任何嵌入模型。它可作为简单的第二阶段,与你现有的语义、关键词或混合搜索系统配合使用。
将查询和 20 个候选发送给 Rerank 5,保留前 5 个,并丢弃任何低于相关性阈值的项。
MIN_SCORE = 0.3
def rerank(query, candidates, top_n=5):
res = client.rerank.rerank(
model=RERANK_MODEL,
query=query,
documents=[c["text"] for c, _ in candidates],
top_n=top_n,
)
return [
(candidates[r.index][0], r.relevance_score)
for r in res.results # sorted by relevance, highest first
if r.relevance_score >= MIN_SCORE
]每个结果都带有该候选在你列表中的位置(index)和一个 relevance_score,依据 重排序响应架构.
什么 Rerank 5 在此步骤中增加:
- 校准后的分数。 分数在不同查询和领域之间保持一致,因此只需一个
MIN_SCORE即可决定哪些内容进入 LLM。 - 32k token 上下文。 长块会被整体评分。
- 半结构化数据。 当 JSON 记录和表格格式化为 YAML 字符串时,重排序效果良好。
- 无需重新建立索引即可升级。 重排序在查询时读取原始文本,因此切换模型只需改一行代码。
对于推理密集型查询以及长文档或特定领域文档,请使用 rerank-5-pro 。对于高并发搜索以及每个任务中需要多次搜索的智能体,请使用 rerank-5-fast 。需要注意一点: Rerank 5 仅支持文本,但可用于解析后的 PDF。
生成
生成阶段将最佳文本块作为编号来源交给 LLM,并要求它仅依据这些来源作答。这样可确保答案扎根于你的文档,并为读者提供可核查的引用。若没有任何内容达到阈值,则完全跳过 LLM 调用。
SYSTEM = (
"Answer using only the numbered sources. "
"Cite them inline like [1]. "
"If the sources don't contain the answer, say you don't know."
)
def answer(query):
hits = rerank(query, retrieve(query))
if not hits:
return "I couldn't find that in the docs."
sources = "\n\n".join(
f"[{i}] {c['title']}\n{c['text']}" for i, (c, _) in enumerate(hits, 1)
)
res = client.chat.send(
model=CHAT_MODEL,
messages=[
{"role": "system", "content": SYSTEM},
{"role": "user", "content": f"Sources:\n\n{sources}\n\nQuestion: {query}"},
],
)
return res.choices[0].message.content
print(answer("How do I rotate an API key without downtime?"))将每个文本块的标题连同其文本一起发送,可以让模型引用可读的内容;如果你的文档中有 URL,也一并加上。OpenRouter 的指南在这一步改用 Responses API。要遵循该指南,请调用 client.responses.send ,并将系统提示词作为 instructions ,并将来源和问题作为“ input,然后从消息项中读取答案,在 res.output 而非来自 choices.
结果
接下来我们将验证所实施的步骤是否改善了我们的响应。
当重排序能自信地选出正确的文本块,并剔除那些在嵌入搜索中排名紧随其后的近似候选时,它多出的这次调用就物有所值。
q = "How do I rotate an API key without downtime?"
cands = retrieve(q)
hits = rerank(q, cands)
print("Embedding only (top 3):")
for c, s in cands[:3]:
print(f" {s:.3f} {c['title']}")
print("After Rerank 5:")
for c, s in hits:
print(f" {s:.3f} {c['title']}")
| 排名 | 仅嵌入 5 | 嵌入 5 + 重排序 5 |
|---|---|---|
| 1 | 轮换 API 密钥 · 0.522 | 轮换 API 密钥 · 0.808 |
| 2 | Webhook 签名密钥 · 0.337 | 低于 0.3 的截断阈值 |
| 3 | 创建 API 密钥 · 0.316 | 低于 0.3 的截断阈值 |
总结
这条流水线中的所有环节都通过同一个 API 密钥和同一个客户端运行。Embed 5 Pro 负责构建索引,Embed 5 Fast 和 Rerank 5 负责处理每个问题,再由一个聊天模型撰写答案,无需分别管理多个 SDK、账户或账单。
这个单一接口也正是让流水线易于演进的原因。每个模型都只是一个字符串,因此尝试 rerank-5-fast ,或换用其他聊天模型,都只需改一行代码。先从示例语料开始,再换成你自己的文档,看看 Rerank 5 会把哪些内容排到最前。下一步可以尝试:混合搜索。在向量命中结果旁加入关键词(BM25)命中结果。Rerank 读取原始文本,因此可在一次调用中为两个列表打分。更小的索引。降到 512 或 256 维,或通过 Cohere 自己的 API 使用 int8 或二进制向量。图像和 PDF。Embed 5 可嵌入图像以及文本与图像混合的输入(如 PDF 页面),而 OpenRouter 的嵌入 rerank-5-pro,或换用其他聊天模型,都只需改一行代码。
先从示例语料开始,再换成你自己的文档,看看 Rerank 5 会把哪些内容排到最前。
接下来可以尝试的方向:
- 混合搜索。 在向量命中结果旁加入关键词(BM25)命中结果。Rerank 读取原始文本,因此可在一次调用中为两个列表打分。
- 更小的索引。 降到 512 或 256 维,或通过 Cohere 自己的 API 使用 int8 或二进制向量。
- 图像和 PDF。 Embed 5 可嵌入图像以及文本与图像混合的输入(如 PDF 页面),而 OpenRouter 的嵌入 API 接受
image_url内容部分。Rerank 5 仅支持文本,因此需基于其文本(如解析后的页面文本或说明文字)对这些结果重新排序,或对其跳过重排序。 - 评估。 标注一小组真实查询,比较启用和不启用重排序时前5个结果的命中率,并进行调优。
MIN_SCORE在同一集合上。 - 探索 Compass。Cohere 的企业搜索与检索平台将 Embed 和 Rerank 整合到单一解决方案中,让企业数据上的强大搜索和 AI 应用构建变得更加容易。现已向 云客户.


