README.md 10.8 KB

Reranker 模块

请求示例docs/QUICKSTART.md §3.5。扩展规范见 docs/DEVELOPER_GUIDE.md §7。部署与调优实战见 reranker/DEPLOYMENT_AND_TUNING.mdggml-org/Qwen3-Reranker-0.6B-Q8_0-GGUF 的专项接入与调优结论见 reranker/GGUF_0_6B_INSTALL_AND_TUNING.md


Reranker 服务提供统一的 /rerank API,支持可插拔后端(BGE、Jina Reranker v3、Qwen3-vLLM、Qwen3-Transformers、Qwen3-GGUF、DashScope 云重排)。调用方通过 HTTP 访问,不关心具体后端。

当前结论

在当前项目的线上形态里,首选后端是 qwen3_vllm_score次选后端是 qwen3_vllm

原因不是“LLM.score() 理论上更高级”,而是这轮优化后,qwen3_vllm_score 在当前硬件和依赖栈上形成了一套更干净、更稳定、也更快的组合:

  • 模型:Qwen/Qwen3-Reranker-0.6B
  • GPU:Tesla T4 16GB
  • CUDA:12.8
  • PyTorch:2.10.0+cu128
  • vLLM-score 环境:vllm==0.18.0
  • attention:由 vLLM 运行时自动选择后端实现;在已验证的 T4 栈上日志可见 FLASHINFER

后端总览

后端 当前定位 结论
qwen3_vllm_score 主推荐 走 vLLM LLM.score()pooling / classify 路径:对每条 (query, doc) 直接产出相关分,不经 causal LM 的整步 generate。相对 qwen3_vllmgenerate(max_tokens=1) + yes/no 的 logprob 推导),省去每对样本上大词表 softmax / 采样约束那一层的常规开销,语义与 cross-encoder 式 rerank 更一致;在当前栈与 T4 上延迟表现最好
qwen3_vllm 次推荐 稳定、成熟、好排障,是很好的 fallback 和对照组
jina_reranker_v3 新增本地方案 按官方推荐使用 AutoModel(..., trust_remote_code=True) + model.rerank(query, docs),更接近 Jina 原生 listwise rerank 用法
qwen3_transformers 兼容方案
qwen3_transformers_packed 特定场景方案 T可能实现还有问题,没调好
qwen3_gguf / qwen3_gguf_06b 低显存 / 功能兜底 更适合资源受限场景,不适合作为当前主在线方案
dashscope_rerank 云服务方案 运维简单,但依赖外部服务和网络

目录与入口

  • reranker/server.py:FastAPI 服务,启动时按配置加载一个后端
  • reranker/backends/:后端实现与工厂
    • backends/__init__.pyget_rerank_backend(name, config)
    • backends/jina_reranker_v3.py:Jina 官方 model.rerank(...) 接法
    • backends/qwen3_vllm_score.py:当前最优的本地 GPU reranker
    • backends/qwen3_vllm.py:次优的本地 GPU reranker
    • backends/qwen3_transformers.py:Transformers 基线实现
    • backends/qwen3_transformers_packed.py:packed 推理实现
    • backends/qwen3_gguf.py:GGUF + llama.cpp 后端
    • backends/dashscope_rerank.py:DashScope 云端重排后端
  • scripts/setup_reranker_venv.sh:按后端创建独立 venv
  • scripts/start_reranker.sh:启动 reranker 服务
  • scripts/smoke_qwen3_vllm_score_backend.pyqwen3_vllm_score 本地 smoke
  • scripts/benchmark_reranker_random_titles.py:随机标题压测脚本
  • scripts/run_reranker_vllm_instruction_benchmark.sh:历史矩阵脚本

环境基线

当前验证环境:

  • GPU:Tesla T4 16GB
  • Driver / CUDA:570.158.01 / 12.8
  • Python:3.12.3
  • torch2.10.0+cu128
  • transformers4.51+
  • qwen3_vllm_score 环境:vllm==0.18.0
  • qwen3_vllm 环境:vllm>=0.8.5

独立 venv 约定:

  • qwen3_vllm -> .venv-reranker
  • qwen3_vllm_score -> .venv-reranker-score
  • jina_reranker_v3 -> .venv-reranker-jina
  • qwen3_transformers -> .venv-reranker-transformers
  • qwen3_transformers_packed -> .venv-reranker-transformers-packed
  • qwen3_gguf -> .venv-reranker-gguf
  • qwen3_gguf_06b -> .venv-reranker-gguf-06b
  • bge -> .venv-reranker
  • dashscope_rerank -> .venv-reranker-dashscope

  • 不同后端的 CUDA / vLLM / llama.cpp 依赖耦合很深,混装后更难定位性能和兼容性问题

  • qwen3_vllm_score 和 qwen3_vllm 分了两个环境,是因为qwen3_vllm_score使用了vllm 0.18,但是后面经过测试两者性能相同。所以其实可以共用一个环境。不过没有动力合并回去。

安装与部署

1. 创建后端环境

qwen3_vllm_score

./scripts/setup_reranker_venv.sh qwen3_vllm_score

qwen3_vllm

./scripts/setup_reranker_venv.sh qwen3_vllm

jina_reranker_v3

./scripts/setup_reranker_venv.sh jina_reranker_v3

2. 基础检查

nvidia-smi
./.venv-reranker-score/bin/python -c "import torch, vllm; print(torch.cuda.is_available(), torch.cuda.get_device_name(0), vllm.__version__)"
./.venv-reranker/bin/python -c "import torch, vllm; print(torch.cuda.is_available(), torch.cuda.get_device_name(0), vllm.__version__)"

3. 启动服务

./scripts/start_reranker.sh

4. Smoke

PYTHONPATH=. ./.venv-reranker-score/bin/python scripts/smoke_qwen3_vllm_score_backend.py --gpu-memory-utilization 0.2

jina_reranker_v3

该后端参考 Jina 官方模型卡接入,使用:

from transformers import AutoModel

model = AutoModel.from_pretrained(
    "jinaai/jina-reranker-v3",
    dtype="auto",
    trust_remote_code=True,
)
results = model.rerank(query, documents)

服务内实现补了几件工程化工作:

  • 统一适配 /rerank 协议,返回与输入 docs 对齐的 scores
  • 对空文档与重复文档做预处理,避免重复推理
  • 支持 top_n hint,并保留原始输入顺序输出
  • 保留 cache_dir / device / dtype / batch_size 等配置项

推荐配置:

services:
  rerank:
    backends:
      jina_reranker_v3:
        model_name: "jinaai/jina-reranker-v3"
        device: null
        dtype: "float16"
        batch_size: 64
        max_doc_length: 160
        max_query_length: 64
        sort_by_doc_length: true
        cache_dir: "./model_cache"
        trust_remote_code: true

T4 实测建议:

  • dtype 优先使用 float16;在当前机器上 auto 会加载成 bfloat16,明显更慢
  • 在线短文本商品重排建议从 batch_size: 64 起步;它比更大的 listwise block 更快,但会牺牲一部分“完整 listwise”排序一致性
  • 若你更看重接近完整 listwise 的排序结果,可提高到 batch_size: 125,代价是延迟明显上升
  • max_doc_length: 160max_query_length: 64 更适合当前商品标题 / 短 query 场景

当前最优方案:qwen3_vllm_score

关键实现点

qwen3_vllm_score.py 里值得关注的地方:

  • runner / convert 保持 auto:走 pooling / classifyLLM.score() 的推荐接法(vLLM 0.17+)
  • hf_overrides:把原始 Qwen3 reranker 权重按官方要求映射到 Qwen3ForSequenceClassification
  • LLM(...) 仅使用本后端所需的模型与并行等参数;attention 后端由 vLLM 内部按运行环境选用
  • deduplicate_with_positions(...):先去重,再回填原始顺序
  • sort_by_doc_length:减少 padding 浪费
  • infer_batch_size:控制服务层分批
  • enable_prefix_caching:(作用每检验过)
  • self._infer_lock:避免当前进程模型下并发调用破坏 vLLM engine 稳定性

Attention 与算力路径(现状)

  • vLLM 根据 GPU 算力架构当前 wheel 中的实现(如随发行版提供的 flashinfer 等)自动选用 attention 路径。
  • Tesla T4(sm_75 + vLLM 0.18.x 的已验证环境中,服务日志中可见选用 FLASHINFER

attention后端对比

后端 计算能力要求 特点 适用场景
FLASH_ATTN (FA2/FA3/FA4) ≥ 8.0 (Ampere+) 最高性能,手写 CUDA 内核 A100/H100 等高端卡
FLASHINFER 7.x-9.x (JIT) 灵活定制,支持多种变体 需要特殊 attention mask
TRITON_ATTN 任意 纯 Triton,跨平台,零依赖 旧 GPU / AMD / fallback
XFORMERS 任意 替代方案,灵活性高 兼容性优先

推荐配置

当前项目统一使用 standard,README 也按这个基线描述:

services:
  rerank:
    backend: "qwen3_vllm_score"
    backends:
      qwen3_vllm_score:
        model_name: "Qwen/Qwen3-Reranker-0.6B"
        use_original_qwen3_hf_overrides: true
        engine: "vllm"
        max_model_len: 256
        tensor_parallel_size: 1
        gpu_memory_utilization: 0.20
        dtype: "float16"
        enable_prefix_caching: true
        enforce_eager: false
        infer_batch_size: 100
        sort_by_doc_length: true
        instruction_format: standard
        instruction: "Rank products by query with category & style match prioritized"

关键实现点

  • AutoTokenizer.apply_chat_template(...)
  • SamplingParams(max_tokens=1, allowed_token_ids=[yes, no])
  • generate(...) 后从最后一步 logprobs 计算 yes/no 概率
  • 同样具备去重、按长度排序、分批推理、前缀缓存、单进程锁等优化

推荐配置

services:
  rerank:
    backends:
      qwen3_vllm:
        model_name: "Qwen/Qwen3-Reranker-0.6B"
        engine: "vllm"
        max_model_len: 256
        tensor_parallel_size: 1
        gpu_memory_utilization: 0.20
        dtype: "float16"
        enable_prefix_caching: true
        enforce_eager: false
        infer_batch_size: 100
        sort_by_doc_length: true
        instruction_format: standard
        instruction: "Rank products by query with category & style match prioritized"

benchmark 建议流程

推荐流程:

  1. 确认目标 backend 已切换到正确配置
  2. ./scripts/start_reranker.sh
  3. curl http://127.0.0.1:6007/health
  4. 跑 benchmark 脚本
  5. 保存 JSON 和 Markdown 结果
  6. 记录当时的 GPU 占用情况和 nvidia-smi

常见问题

1. 为什么第一次启动很慢

  • 模型加载
  • torch.compile
  • CUDA graph capture
  • flashinfer / triton JIT

3. qwen3_vllm_score 的 attention 要在哪里调

由 vLLM 在运行时按 GPU 与版本自动选择;与延迟和稳定性更直接相关、且建议在仓库里动的,是 max_model_leninfer_batch_sizegpu_memory_utilization、去重、排序分批、prefix cache 等。

代码阅读建议

  1. reranker/backends/qwen3_vllm_score.py
  2. reranker/backends/qwen3_vllm.py
  3. scripts/start_reranker.sh
  4. scripts/setup_reranker_venv.sh
  5. config/config.yaml 里的 services.rerank.backends.*

性能测试、对比

ll tests/reranker_performance/
curl1.sh
curl1_simple.sh
rerank_performance_compare.sh