如何自托管 reranker

生产实践 · 约 10 分钟阅读 ·

托管 rerank API 很方便,但自托管能带来零按次成本、数据完全可控,以及在自己 GPU/CPU 集群上的可预测延迟。本文从第一次 CrossEncoder 调用,到生产级微服务的实操路径。

何时值得自托管

若你需要多语言质量且运维要极简,Cohere RerankJina 等托管 API 的综合成本可能更低 —— 见按场景选型

选择模型

模型规模最适合
bge-reranker-base~278MCPU 友好的英文默认
bge-reranker-v2-m3~568MGPU 有限时的多语言选择
Qwen3-Reranker-4B~4B2026 开源 SOTA 首选(需 GPU)
mxbai-rerank-large-v1~435M经典 BEIR 强,Apache 2.0
jina-reranker-v3largeListwise 长上下文;或 v2 成对

原型阶段用 CPU 跑 bge-reranker-base。有 GPU 时在标注集上 A/B Qwen3-Reranker-4Bbge-v2-m3mxbai-large —— 不要假设榜单顺序会迁移。

sentence-transformers 快速上手

pip install sentence-transformers torch

from sentence_transformers import CrossEncoder

model = CrossEncoder("BAAI/bge-reranker-base", max_length=512)

query = "How do I add reranking to RAG?"
docs = [
    "Retrieve 50–100 candidates, rerank with a cross-encoder, keep top 5.",
    "London is the capital of the United Kingdom.",
]

pairs = [(query, d) for d in docs]
scores = model.predict(pairs)  # higher = more relevant
ranked = sorted(zip(scores, docs), reverse=True)

批量打分 —— 一次 predict() 处理 50 段远比 50 次单独前向快。单段长度建议不超过 512 token(模型默认),避免静默截断。

服务化方案

嵌入应用进程

在 FastAPI / Flask RAG 服务内加载模型。低 QPS 最简单;水平扩展副本即可。

独立 rerank 微服务

暴露 POST /rerank,请求体 { query, documents[] }。多个应用 Pod 共享一块 GPU。

# Minimal FastAPI sketch
from fastapi import FastAPI
from sentence_transformers import CrossEncoder

app = FastAPI()
model = CrossEncoder("BAAI/bge-reranker-base")

@app.post("/rerank")
def rerank(body: dict):
    q, docs = body["query"], body["documents"]
    scores = model.predict([(q, d) for d in docs])
    order = sorted(range(len(docs)), key=lambda i: -scores[i])
    return {"results": [{"index": i, "score": float(scores[i])} for i in order]}

ONNX 导出与 C++ 运行时见 Hugging Face 模型卡。仅浏览器实验可用我们的 在线 Demo(xsmall ONNX 构建)。

运维清单

部署前先原型验证

在浏览器 Demo 粘贴自己的查询与段落 —— 无需服务器。

打开 Demo →

继续阅读