# Reranker 模块

**请求示例**见 `docs/QUICKSTART.md` §3.5。扩展规范见 `docs/DEVELOPER_GUIDE.md` §7。部署与调优实战见 `reranker/DEPLOYMENT_AND_TUNING.md`。`ggml-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_vllm`**（`generate(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__.py`：`get_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 服务
- `benchmarks/reranker/smoke_qwen3_vllm_score_backend.py`：`qwen3_vllm_score` 本地 smoke
- `benchmarks/reranker/benchmark_reranker_random_titles.py`：随机标题压测脚本
- `benchmarks/reranker/run_reranker_vllm_instruction_benchmark.sh`：历史矩阵脚本

## 环境基线

当前验证环境：

- GPU：`Tesla T4 16GB`
- Driver / CUDA：`570.158.01 / 12.8`
- Python：`3.12.3`
- `torch`：`2.10.0+cu128`
- `transformers`：`4.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`：

```bash
./scripts/setup_reranker_venv.sh qwen3_vllm_score
```

`qwen3_vllm`：

```bash
./scripts/setup_reranker_venv.sh qwen3_vllm
```

`jina_reranker_v3`：

```bash
./scripts/setup_reranker_venv.sh jina_reranker_v3
```

### 2. 基础检查

```bash
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. 启动服务

```bash
./scripts/start_reranker.sh
```


### 4. Smoke

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

## `jina_reranker_v3`

该后端参考 Jina 官方模型卡接入，使用：

```python
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` 等配置项

推荐配置：

```yaml
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: 160`、`max_query_length: 64` 更适合当前商品标题 / 短 query 场景

## 当前最优方案：`qwen3_vllm_score`


### 关键实现点

`qwen3_vllm_score.py` 里值得关注的地方：

- `runner` / `convert` 保持 **auto**：走 **pooling / classify** 与 **`LLM.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 也按这个基线描述：

```yaml
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 概率
- 同样具备去重、按长度排序、分批推理、前缀缓存、单进程锁等优化

### 推荐配置

```yaml
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_len`**、**`infer_batch_size`**、**`gpu_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.*`

## 性能测试、对比
```bash
ll tests/reranker_performance/
curl1.sh
curl1_simple.sh
rerank_performance_compare.sh
```
