在线AI教程 / AI上云
[Cohere] Embed 5 与 Rerank 5 现已上线 OpenRouter
2026 年 11 月 4 日 6 分钟阅读 Embed 5 与 Rerank 5 现已上线 OpenRouter 通过单一 API 接入 Cohere 最先进的检索模型,统一计费
2026 年 11 月 4 日
6 分钟阅读
Embed 5 与 Rerank 5 现已上线 OpenRouter
通过单一 API 接入 Cohere 最先进的检索模型,统一计费,无需额外的 SDK。

Embed 5 与 Rerank 5 现已在 OpenRouter 上线。下面说明如何通过单一 API,用几十行 Python 代码把它们搭成一条可用的 RAG 流水线。
这是 Cohere 迄今最强大的检索模型,在企业文档与复杂检索任务上提供领先的表现。如果你已经在使用 OpenRouter,就能马上开始——用的是与现有模型相同的 API key 和额度,不需要任何额外设置。
RAG 在 LLM 落笔之前先取回相关的 chunk,把它的回答扎根在你自己的数据里。嵌入搜索提供一个快速而有效的第一阶段近似;reranker 随后把 query 与每个候选放在一起读取,为已经检索到的内容补上精度。
Cohere 模型的两个特征塑造了这一设计:
Embed 5 Pro 与 Fast 共享同一个嵌入空间。 用 embed-5-pro 建索引换取质量,再用 embed-5-fast 做查询换取低延迟。 Rerank 5 的分数经过校准。 同一个分数在不同查询、不同领域里含义一致,因此一个相关性阈值就能在弱上下文抵达 LLM 之前把它筛掉。
读到最后,你会拿到一个简短的 Python 脚本,它能针对你的文档回答问题,并给出带分数的引用。同样的做法几乎可以用在任何检索用例上,从企业搜索、客户支持到知识管理与文档发现。
一条 RAG 流水线分成两半:一个离线作业,构建可搜索的索引;一条在线路径,每一次提问都要走它。弄清哪些调用只发生一次、哪些调用每个请求都发生,就能解释这条流水线大部分的成本与延迟。索引对每个语料库只运行一次。此后每个问题的开销是一次 Embed 5 Fast 调用、一次 Rerank 5 调用和一次 chat 调用,全部经由 OpenRouter 的 API。
设置
你需要 Python 3.10 或更新的版本、一个 OpenRouter API key、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 | 2048
Embed 5 返回 Matryoshka 向量,共有六档尺寸,默认为 2048。我们建议使用 1,024 维的 int8 向量,那是质量与成本之间的最佳平衡点;OpenRouter 的 embeddings API 返回的是浮点数,所以本文使用 1,024 维的浮点向量。
用 NumPy 做存储能让这个 demo 保持简单。上生产环境时,把它换成你自己的向量数据库,例如 pgvector、Qdrant、Pinecone 或 Weaviate。
建立索引
建索引把每一个 chunk 的文本变成一个向量——一串数字,语义相近的内容在其中彼此靠得很近。它对每个语料库只运行一次,因此是最能体现最高质量模型价值的环节。
把每篇文档切成若干 chunk,以 search_document 类型用 Embed 5 Pro 对它们做嵌入,并把向量归一化,让点积就等于余弦相似度。
示例语料库是一个虚构 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。 批量处理: 一次请求发送多个 chunk,减少往返、加快建索引。它不改变成本,因为嵌入按 token 计价。 chunk 大小: 把整段整段的段落打包进一个 chunk,遵循 OpenRouter 的指南里的按段落切分策略;1,500 个字符大约相当于 300–400 个英文 token。Embed 5 最多接受 128k token,但每个 chunk 还要经过 Rerank 5,而它一次读取的 query 与 chunk 合计上限是 32k token,更长的内容会被拆成多趟处理。
检索
检索找出那些向量与问题的向量靠得最近的 chunk,这充当两段内容之间语义相似度的表示。
用 Embed 5 Fast 以 search_query 类型对问题做嵌入,然后按余弦相似度拉出一个撒得较宽的候选集,取 20 个 chunk。
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 的重排。
重排
重排给候选短名单重新打分,做法是把问题和每个 chunk 放在一起读。它的速度慢到没法跑遍整个索引,但比向量相似度更准,所以只用在排名靠前的候选上。Rerank 并不要求有 Embed——也不要求任何嵌入模型。作为一个简单的第二阶段,它能直接配合你现有的语义搜索、关键词搜索或混合搜索系统工作。
把 query 和这 20 个候选发给 Rerank 5,保留 top 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 ]
按照 rerank 响应结构说明,每条结果都带着该候选在你列表中的位置(index)以及一个 relevance_score。
Rerank 5 在这一步带来的是:
经过校准的分数。 分数在各次查询和各领域之间保持一致,于是单个 MIN_SCORE 就能决定什么内容可以抵达 LLM。 32k token 上下文。 长 chunk 可以整篇打分。 半结构化数据。 JSON 记录和表格格式化成 YAML 字符串后,重排表现很好。 升级无需重建索引。 Rerank 在查询时读取原始文本,所以换模型只是一行改动。
推理密集的查询,以及篇幅长或领域专用的文档,用 rerank-5-pro。大批量的搜索,以及单个任务里要搜索许多次的 agents,用 rerank-5-fast。有一点要注意:Rerank 5 只处理文本,但对解析过的 pdf 可以工作。
生成
生成环节把最好的几个 chunk 作为编号的来源交给 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?"))
把每个 chunk 的标题连同它的正文一起发送,模型就能引用出可读的东西;如果你的文档里有 URL,也一并加上。OpenRouter 的指南在这一步改用 Responses API。要跟着它做,就调用 client.responses.send,把 system prompt 作为 instructions、把来源和问题作为 input,然后从 res.output 里的 message 条目读取回答,而不是从 choices 读取。
结果
这里我们要验证自己实现的这些步骤是否真的改善了回答。
当重排有把握地挑出正确的那个 chunk,并把嵌入搜索只排在它稍后位置的差一点相关的候选筛掉时,这次额外调用就物有所值。
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']}")
排名仅用 Embed 5Embed 5 + Rerank 5 1Rotating API keys · 0.522Rotating API keys · 0.808 2Webhook signing secrets · 0.337低于 0.3 阈值 3Creating API keys · 0.316低于 0.3 阈值
总结
这条流水线里的一切,都只经过一个 API key 和一个 client。Embed 5 Pro 建好索引,Embed 5 Fast 与 Rerank 5 处理每一次提问,最后由一个 chat 模型写出回答——不必再同时应付分开的 SDK、分开的账号和分开的账单。
正因为它只有这一个入口,这条流水线才容易演进。每个模型不过就是一个字符串,所以想用 rerank-5-fast 换掉 rerank-5-pro,或者换一个 chat 模型,都是一行改动。
先从示例语料库开始,换上你自己的文档,看看 Rerank 5 会把什么挪到最前面。
接下来可以往哪里走:
混合搜索。 在向量命中旁边加上关键词(BM25)命中。Rerank 读的是原始文本,所以一次调用就能给两份列表打分。 更小的索引。 降到 512 或 256 维,或者通过 Cohere 自己的 API 使用 int8 或二进制向量。 图片与 PDF。 Embed 5 能对图片,以及 PDF 页面这类文本与图片混合的输入做嵌入,OpenRouter 的 embeddings API 也接受 image_url 内容片段。Rerank 5 只处理文本,所以对这些结果要基于它们的文本去重排,例如解析出来的页面文字或图注,或者干脆对它们跳过重排。 评估。 给一小批真实查询打上标注,对比有无重排时前 5 名的命中率,并在同一批数据上调整 MIN_SCORE。 了解 Compass。Cohere 的企业搜索与检索平台把 Embed 和 Rerank 收进一个解决方案,让人更容易在整片企业数据上构建强大的搜索与 AI 应用。现已面向云客户开放。
有用链接
OpenRouter embeddings API OpenRouter Python SDK rerank Embed 5 发布公告博客 Rerank 5 发布公告博客 Embed 5 基准测试结果 Rerank 5 基准测试结果
延伸阅读
产品发布全球领先的开放模型,完全由你掌控2026 年 11 月 3 日4 分钟阅读
公司新闻Cohere 推进 40 亿加元投入,巩固加拿大的 AI 领先地位并大幅扩充本国员工队伍2026 年 10 月 30 日3 分钟阅读
企业 AI面向开发者的 AI在 AWS 上用 Cohere AI 构建金融研究助理2026 年 10 月 29 日17 分钟阅读