# https://github.com/lm-sys/RouteLLM 项目说明书

生成时间：2026-07-24 20:58:28 UTC

## 目录

- [项目概览与快速开始](#page-1)
- [系统架构与代码组织](#page-2)
- [路由器实现机制详解](#page-3)
- [Python SDK 与 Controller](#page-4)
- [OpenAI 兼容服务器部署](#page-5)
- [阈值校准与基准评估](#page-6)
- [模型训练与自定义嵌入](#page-7)
- [扩展、集成与故障排除](#page-8)

<a id='page-1'></a>

## 项目概览与快速开始

### 相关页面

相关主题：[系统架构与代码组织](#page-2), [Python SDK 与 Controller](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/lm-sys/RouteLLM/blob/main/README.md)
- [pyproject.toml](https://github.com/lm-sys/RouteLLM/blob/main/pyproject.toml)
</details>

# 项目概览与快速开始

## 项目定位与目标

RouteLLM 是一个用于在大语言模型（LLM）请求层面进行动态路由的开源框架。它基于 LMSYS 团队（lmsys/lab）的研究成果，通过训练好的路由器判断每条查询应由"强模型"还是"弱模型"作答，从而在保证响应质量的前提下显著降低推理成本。

框架的核心思路是：并非所有用户查询都需要调用顶级闭源大模型（例如 GPT-4o），许多简单问题可以由开源或低成本模型有效回答。RouteLLM 在调用入口处插入一个轻量级的路由器（router），将请求分流到合适的模型端点。路由器是模型无关的（model-agnostic），强/弱模型的具体选型由使用者根据预算与场景自行决定 资料来源：[README.md:1-80]()。

## 核心能力概览

- **多种训练好的路由器**：仓库内置矩阵分解（matrix factorization，简称 `mf`）与 BERT 等路由器权重，可在不重新训练的情况下开箱即用。社区多次询问是否能更换嵌入模型（例如 `intfloat/e5-small-v2`），表明路由器在推理时会读取预计算的查询嵌入 资料来源：[README.md:40-120]()。
- **两种使用方式**：
  - **方式 A（Python SDK）**：在 Python 代码中直接调用 Controller，将提示词交给路由器决策后再发送到大模型 资料来源：[README.md:80-120]()。
  - **方式 B（OpenAI 兼容服务）**：启动 `python -m routellm.openai_server` 暴露一个与 OpenAI API 兼容的端点，前端可继续沿用原有 SDK 调用 资料来源：[README.md:80-160]()。
- **可定制的强/弱模型配对**：用户可以自由指定强模型与弱模型的 provider。在 issue #27 的讨论中，有用户反馈当前 Controller 仅允许统一设置 `OPENAI_API_BASE`，对分别托管在不同端点的强/弱模型支持不足 资料来源：[README.md:80-120]()。
- **强/弱两端点灵活配**：通过对 `OPENAI_API_KEY`、`TOGETHER_API_KEY` 等环境变量的配置，可在 OpenAI、Together AI、Anthropic、Ollama 等多种 provider 之间自由搭配，例如 issue #76 中的用户就成功跑通了本地 Ollama 的双模型（Phi4 + Llama3 8B）组合 资料来源：[README.md:100-160]()。

## 安装与最小配置

`pyproject.toml` 中声明了项目的 Python 包元数据与依赖。安装方式推荐使用 `pip`，安装完成后需要从 HuggingFace Hub 拉取路由器权重与评测数据缓存。

最小运行所需的配置包括：

1. 设置所选 provider 的 API 密钥环境变量（OpenAI、Together 等）。
2. 选择合适的路由器权重（`mf` 或 `bert`），必要时指定嵌入模型路径。
3. 在 Python 中调用 `RouteLLM` Controller，或在终端启动 OpenAI 兼容服务。

社区在 issue #78 中报告"按 demo 跑不通"的情况，常见根因多与速率限制（rate limit）、鉴权错误（authorization error）以及 Ollama 远程连接配置相关，因此在快速开始阶段建议先用环境变量确认 provider 可用 资料来源：[README.md:120-200]()。

## 两种使用方式示意

| 维度 | 方式 A：Python SDK | 方式 B：OpenAI 兼容服务 |
| --- | --- | --- |
| 启动入口 | Python 中直接导入 `routellm` | `python -m routellm.openai_server --routers mf --weak-model ...` |
| 调用方式 | 显式调用客户端完成路由 + 推理 | 沿用 OpenAI 客户端，只需替换 `base_url` |
| 定制程度 | 高，便于嵌入自定义流水线 | 适合已有 OpenAI 兼容前端的应用 |
| 常见问题 | 路由器/嵌入模型配置 | `litellm.drop_params` 报错、Ollama 连接失败 (issue #63, #76) |

该框架的本质是"路由器 + Controller"，底层的模型调用实际由 `litellm` 完成，因此任何 `litellm` 支持的 provider 都可以作为强/弱模型候选，这也是 issue #63 中出现的 `litellm.drop_params` 异常的来源 资料来源：[README.md:80-200]()。

## 快速开始示例（基于官方文档骨架）

下面的伪代码片段对应方式 A 与方式 B 的最简流程，请以仓库 `README.md` 中随版本变化的实际代码为准 资料来源：[README.md:80-200]()：

```python
# 方式 A：Python SDK
from routellm.controller import Controller

client = Controller(
    routers=["mf"],                 # 指定路由器
    strong_model="gpt-4o",          # 强模型端点
    weak_model="ollama_chat/llama3",# 弱模型端点
)
response = client.chat.completions.create(
    model="router-mf-0.93",         # 路由阈值，可调
    messages=[{"role": "user", "content": "你好"}],
)
```

方式 B 在命令行启动后，客户端只需把 `base_url` 指向本服务即可，无需改动原有 OpenAI SDK 代码。

## 常见使用注意事项

- **嵌入模型需匹配**：自定义路由器嵌入（如 `intfloat/e5-small-v2`）时需保证权重维度与路由器期望一致，否则会出现 shape 不匹配错误（issue #84）。
- **训练脚本**：仓库并未公开所有路由器的训练脚本，社区多次请求开放 BERT 训练代码（issue #67、#82），目前训练主要依赖官方预发布产物。
- **多模型路由**：当前版本以一对强/弱模型为基本路由单元，若需要三路以上路由，需在 Controller 之上自行叠加逻辑（issue #23）。
- **LangChain 集成**：社区已在 issue #28 中讨论过，可通过 OpenAI 兼容服务或自定义 LLM Wrapper 与 LangChain 对接。

以上即为 RouteLLM 的项目概览与快速开始说明。后续页面将分别深入到路由器训练、Controller 配置以及评测数据等子模块。

---

<a id='page-2'></a>

## 系统架构与代码组织

### 相关页面

相关主题：[项目概览与快速开始](#page-1), [路由器实现机制详解](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [routellm/controller.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/controller.py)
- [routellm/routers/routers.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/routers.py)
- [routellm/__init__.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/__init__.py)
- [routellm/openai_server.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/openai_server.py)
- [routellm/model_openai.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/model_openai.py)
- [routellm/routers/matrix_factorization/train_matrix_factorization.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/matrix_factorization/train_matrix_factorization.py)
- [routellm/routers/bert/__init__.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/bert/__init__.py)
</details>

# 系统架构与代码组织

## 概述与设计目标

RouteLLM 是一个面向大语言模型推理的"路由器"框架，其核心思想是在两个或多个模型之间，根据查询难度自动选择"强模型"与"弱模型"，从而在成本与质量之间取得平衡。仓库代码按职责划分为四大模块：`controller`（控制器）、`routers`（路由策略）、`model`（模型包装层）以及对外暴露的 OpenAI 兼容服务层。`routellm/__init__.py` 负责汇总顶层公共 API（如 `OpenAIServer` 启动入口），对上层屏蔽内部模块细节。

资料来源：[routellm/__init__.py:1-30]()

## 整体架构与请求流转

系统的请求生命周期可以划分为"客户端接入 → 路由判别 → 目标模型推理 → 流式/非流式回包"四个阶段：

1. **客户端接入**：通过 `python -m routellm.openai_server` 启动与 OpenAI Chat Completions API 兼容的 HTTP 服务（参见 issue #76 中用户尝试串联两个 Ollama 模型的用法）。
2. **路由判别**：`routellm/openai_server.py` 接收请求后调用 `Controller` 的方法，让已加载的路由器（`routers/routers.py` 中的 `ROUTERS` 字典）针对 prompt 给出强弱模型选择。
3. **模型调用**：`routellm/controller.py` 中的 `Controller` 根据路由器结果，将请求转发到对应的 `OpenAIModel` 包装器。
4. **结果回传**：控制器统一处理流式响应并将 OpenAI 格式的响应回写给客户端。

```mermaid
flowchart LR
    Client[客户端] --> Server[openai_server.py]
    Server --> Ctl[Controller]
    Ctl -->|选择| RouterDict[routers/routers.py]
    RouterDict --> MF[matrix_factorization]
    RouterDict --> BERT[bert]
    RouterDict --> Random[random / similarity]
    MF --> Ctl
    BERT --> Ctl
    Random --> Ctl
    Ctl --> Strong[OpenAIModel 强模型]
    Ctl --> Weak[OpenAIModel 弱模型]
    Strong --> Client
    Weak --> Client
```

资料来源：[routellm/openai_server.py:1-80]()、[routellm/controller.py:1-60]()

## 控制器与路由器层

### Controller 的职责

`Controller` 是整个框架的中枢，承担三件事：

- **路由器加载**：根据配置（`--routers`、`--config`）从 `routellm/routers/routers.py` 的 `ROUTERS` 字典中按名称实例化对应路由器类，并支持多路由器加权组合。
- **强弱模型管理**：内部维护 `strong_model` 与 `weak_model` 两个 `OpenAIModel` 包装器实例，并允许它们指向不同的 `base_url`，这一设计直接回应了 issue #27 中"允许强弱模型使用不同 base URL"的需求。
- **请求编排**：提供 `chat_completion`、`stream` 等方法，把"路由决策 + 模型调用"封装为一次完整的 OpenAI 调用，调用方无需感知底层路由器。

资料来源：[routellm/controller.py:30-120]()、[routellm/routers/routers.py:1-50]()

### 路由器子模块

路由器层位于 `routellm/routers/`，每个子目录对应一种路由策略：

| 子模块 | 路由策略 | 关键文件 | 训练入口 |
|--------|----------|----------|----------|
| `matrix_factorization` | 基于人类偏好数据的矩阵分解打分 | `routers.py`、`train_matrix_factorization.py` | `train_matrix_factorization.py` |
| `bert` | 使用 BERT 分类器直接预测强弱 | `__init__.py` | 仓库未公开训练脚本（issue #67、#82） |
| `similarity_weighted` | 与"基准路由"相似度比较 | `__init__.py` | 复用预计算嵌入 |
| `random` | 随机路由，用作基线 | `__init__.py` | 无需训练 |

`ROUTERS` 字典（位于 `routellm/routers/routers.py`）通过字符串名称懒加载上述策略，运行时由 `Controller` 选择其一或组合使用。矩阵分解路由器在训练时载入 `.npy` 文件作为查询的固定嵌入向量，这是 issue #83 关注的核心问题：嵌入之所以不可训练，是因为它来源于外部句子编码器的预计算结果，以避免对 BERT 等大模型做端到端反向传播，从而降低训练成本并支持切换不同的嵌入模型（issue #84）。

资料来源：[routellm/routers/routers.py:20-90]()、[routellm/routers/matrix_factorization/train_matrix_factorization.py:50-80]()

## 模型包装、服务入口与扩展性

### 模型包装层

`routellm/model_openai.py` 提供与 `litellm` 兼容的 OpenAI 协议封装，统一处理鉴权、`base_url`、流式响应与 `drop_params` 等细节。当上游 litellm 版本不兼容时，会沿调用栈抛出异常（issue #63 中出现的 `litellm.drop_params` 报错即源于此层）。

资料来源：[routellm/model_openai.py:1-60]()

### 服务入口

`routellm/openai_server.py` 使用 FastAPI 暴露 `/v1/chat/completions` 接口，使任何 OpenAI SDK 客户端（包括 LangChain、LlamaIndex 与自定义脚本）都可以无侵入地接入 RouteLLM（issue #28 中讨论的 LangChain 集成正是基于这一层）。常见命令行参数包括：`--routers` 指定路由器，`--weak-model`/`--strong-model` 指定模型名，`--config` 指向路由器权重配置。issue #76 中的 Ollama 双模型场景也通过此入口串接。

资料来源：[routellm/openai_server.py:40-100]()

### 扩展点与社区诉求

整体上，RouteLLM 采用"控制器 + 策略 + 适配器"的清晰分层：

- **入口层**：`openai_server.py` 负责协议兼容；
- **编排层**：`controller.py` 负责路由器与模型调度；
- **策略层**：`routers/` 子目录承载可插拔的路由算法；
- **适配层**：`model_openai.py` 抹平不同上游模型的差异。

这种分层让新增路由算法（例如 issue #23 中所诉求的多模型路由）可以通过新增 `routers/*` 子模块并注册到 `ROUTERS` 字典即可接入，而无需改动 Controller 与 Server 层。BERT 路由器的训练代码（issue #67、#82）以及更多路由器实现，正是社区当前最关注的扩展方向。

资料来源：[routellm/controller.py:1-30]()、[routellm/routers/routers.py:1-20]()

---

<a id='page-3'></a>

## 路由器实现机制详解

### 相关页面

相关主题：[系统架构与代码组织](#page-2), [模型训练与自定义嵌入](#page-7)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [routellm/routers/matrix_factorization/model.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/matrix_factorization/model.py)
- [routellm/routers/matrix_factorization/train_matrix_factorization.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/matrix_factorization/train_matrix_factorization.py)
- [routellm/routers/similarity_weighted/utils.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/similarity_weighted/utils.py)
- [routellm/routers/similarity_weighted/generate_embeddings.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/similarity_weighted/generate_embeddings.py)
- [routellm/routers/causal_llm/model.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/causal_llm/model.py)
- [routellm/routers/causal_llm/llm_utils.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/causal_llm/llm_utils.py)
</details>

# 路由器实现机制详解

RouteLLM 的核心设计目标是根据用户查询动态选择"强模型"或"弱模型"，以在保证响应质量的同时降低调用成本。路由器（Router）模块负责接收查询并输出胜率（win rate），最终根据该胜率决定请求由哪一类模型处理。当前仓库内置三类路由器实现，分别采用矩阵分解、相似度加权以及因果语言模型三种判别范式。

## 整体架构与抽象

所有路由器均继承自 `routellm/routers/` 下的统一抽象，并暴露一致的 `calculate_strong_win_rate` 或同类入口方法以供上层 `Controller` 调用。`openai_server` 启动时通过 `--routers` 参数选择路由算法，并通过 YAML 配置文件载入对应模型的检查点与嵌入。社区在 Issue #76 中提及使用 `python -m routellm.openai_server --routers mf --config config.example.yml` 即对应此加载路径。资料来源：[routellm/routers/matrix_factorization/model.py:1-40]()

## 矩阵分解路由器（Matrix Factorization）

该路由器是 RouteLLM 论文中性能最具竞争力的实现，其核心思想是将"查询嵌入"与"模型嵌入"分别映射到低维空间，通过点积近似预测"强模型胜出"的概率。

- **模型定义**：`model.py` 中 `MatrixFactorization` 类包含一个可学习的 `model_embedding` 矩阵（行为待路由的候选模型，列为隐藏维度），以及一个固定不变的 `query_embedding` 张量。资料来源：[routellm/routers/matrix_factorization/model.py:10-60]()
- **预计算查询嵌入**：训练阶段不直接更新查询嵌入，而是从外部 `.npy` 文件载入已编码好的特征向量。这正好回应了社区 Issue #83 关于"`train_matrix_factorization.py:58-62` 中查询嵌入不可训练、`.npy` 文件是什么"的疑问——该文件由独立的嵌入脚本（基于 `gte-large` 等模型）预先生成，目的是降低训练时的 GPU 显存占用并保证跨实验的可复现性。资料来源：[routellm/routers/matrix_factorization/train_matrix_factorization.py:55-75]()
- **嵌入替换**：社区 Issue #84 询问能否替换为 `intfloat/e5-small-v2`。由于 `MatrixFactorization.__init__` 直接接收 `query_embedding` 张量，只要新嵌入维度与 `model_embedding` 一致即可热插拔，但需重新训练 `model_embedding` 以匹配新维度。资料来源：[routellm/routers/matrix_factorization/model.py:20-35]()
- **训练入口**：训练脚本构造二分类交叉熵损失，将人类偏好标签（GPT-4 vs 弱模型）的强弱胜率作为监督信号；仅更新 `model_embedding`，查询嵌入保持只读。资料来源：[routellm/routers/matrix_factorization/train_matrix_factorization.py:80-130]()

## 相似度加权路由器（Similarity Weighted）

该路由器不需要显式的训练阶段，更接近 KNN 风格的判别方式。

- **离线嵌入生成**：`generate_embeddings.py` 调用 `sentence_transformers` 将训练集中的查询编码为向量并保存到磁盘，作为后续路由阶段的参考库。资料来源：[routellm/routers/similarity_weighted/generate_embeddings.py:1-50]()
- **在线判别逻辑**：`utils.py` 中的 `calculate_win_rate` 将当前查询嵌入与参考库做余弦相似度计算，取最相似的若干条样本，根据其中"强模型胜出"的比例作为最终胜率。资料来源：[routellm/routers/similarity_weighted/utils.py:20-80]()
- **可解释性优势**：相对于矩阵分解，相似度加权法的路由决策完全可追溯到训练样本，便于排查路由偏差。资料来源：[routellm/routers/similarity_weighted/utils.py:60-90]()

## 因果语言模型路由器（Causal LLM）

该方案利用一个小参数量的指令微调 LLM 直接以"分类"形式输出路由决策。

- **模型包装**：`model.py` 中的 `CausalLLMRouter` 接受一个 HuggingFace `pipeline`，将聊天模板与系统提示注入后调用 `model.generate`，再将首个 token 解析为"strong/weak"。资料来源：[routellm/routers/causal_llm/model.py:15-70]()
- **提示工程**：`llm_utils.py` 维护提示模板与标签映射，确保不同基础模型（如 Llama-3、Qwen）下输出格式一致；同时包含批处理与 token 预算控制逻辑。资料来源：[routellm/routers/causal_llm/llm_utils.py:1-60]()

## 路由器对比与选型建议

| 路由器 | 是否需要训练 | 显存占用 | 推理延迟 | 适用场景 |
|---|---|---|---|---|
| matrix_factorization | 是 | 低 | 极低 | 生产环境首选 |
| similarity_weighted | 仅生成嵌入 | 中（取决于参考库大小） | 中 | 快速冷启动、可解释场景 |
| causal_llm | 是 | 高 | 较高（LLM 推理） | 复杂查询判别 |

社区 Issue #67 中用户多次询问 BERT 路由器训练代码——该实现并未开源在当前仓库中，如需使用需自行参考论文附录实现。资料来源：[routellm/routers/matrix_factorization/model.py:1-10]()

## 常见问题与注意事项

- **双模型限制**：当前三类路由器仅输出二元的"强/弱"路由，无法直接扩展到多模型选择，对应 Issue #23 中讨论的"按隐私、数学等维度细分路由"需求尚未实现。资料来源：[routellm/routers/matrix_factorization/model.py:40-45]()
- **服务端报错**：Issue #63 反映 `litellm.drop_params` 异常多发于不同模型供应商参数不一致的情况，建议在 `Controller` 配置中显式声明 `OPENAI_API_BASE` 以隔离强/弱模型后端。资料来源：[routellm/routers/similarity_weighted/utils.py:1-20]()
- **嵌入维度一致性**：替换嵌入模型时务必保持向量维度与 `model_embedding` 一致，否则会触发 `RuntimeError: shape mismatch`。资料来源：[routellm/routers/matrix_factorization/model.py:25-35]()

## 总结

RouteLLM 的路由器模块通过统一的"查询 → 胜率 → 模型选择"管线，将路由算法抽象为可替换组件。矩阵分解路由器在性能与效率之间提供了最佳平衡，是生产部署的默认推荐；相似度加权路由器适合需要快速迭代与可解释性的场景；因果语言模型路由器则面向更高难度的查询判别任务。理解三类路由器的输入、训练机制与部署约束，是合理选型与排障的关键。

---

<a id='page-4'></a>

## Python SDK 与 Controller

### 相关页面

相关主题：[项目概览与快速开始](#page-1), [OpenAI 兼容服务器部署](#page-5), [扩展、集成与故障排除](#page-8)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [routellm/controller.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/controller.py)
- [examples/python_sdk.md](https://github.com/lm-sys/RouteLLM/blob/main/examples/python_sdk.md)
- [examples/routing_to_local_models.md](https://github.com/lm-sys/RouteLLM/blob/main/examples/routing_to_local_models.md)
- [routellm/openai_server.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/openai_server.py)
- [routellm/model_collection.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/model_collection.py)
- [routellm/routers/matrix_factorization/router.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/matrix_factorization/router.py)
- [routellm/routers/bert/router.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/bert/router.py)
- [README.md](https://github.com/lm-sys/RouteLLM/blob/main/README.md)
</details>

# Python SDK 与 Controller

RouteLLM 提供两种调用方式：直接在 Python 进程中以 SDK 形式调用，或启动一个兼容 OpenAI 的本地 HTTP 服务。两种方式都通过 `Controller` 类来调度路由器与底层大模型。Controller 是 Python SDK 的核心入口，封装了路由决策、模型调用与配置加载等逻辑。

## Controller 的角色与初始化

`Controller` 是 SDK 的主要门面（facade）。它接收一组路由器（如 `mf`、`bert`、`random`、`sw_ranking`）、一个强弱模型对（`strong-model`、`weak-model`）以及一个可选的路由阈值。Controller 在构造时会按需惰性加载路由器，并缓存训练好的路由器权重。

```python
from routellm.controller import Controller

client = Controller(
    routers=["mf"],
    strong_model="gpt-4-1106-preview",
    weak_model="ollama_chat/llama3",
    config="config.example.yaml",
)
```

资料来源：[examples/python_sdk.md:1-15]() [routellm/controller.py:1-40]()

初始化参数说明：

| 参数 | 说明 |
| --- | --- |
| `routers` | 要启用的路由器列表，例如 `["mf", "bert"]` |
| `strong_model` | 强模型标识，遵循 litellm 命名规则 |
| `weak_model` | 弱模型标识 |
| `config` | 路由阈值与路由器权重的 YAML 配置文件 |
| `thresholds` | 可选，覆盖配置文件中默认路由阈值 |

## 路由决策与模型调用

Controller 暴露 `route`/`route_sync` 方法，用于在调用 LLM 前先决定目标模型。`route_sync` 接受 OpenAI Chat 风格的 `messages` 列表，由路由器输出每个查询被分派到强模型的概率；概率高于阈值则走强模型，否则走弱模型。

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:6060/v1", api_key="any")
resp = client.chat.completions.create(
    model="route-mf",
    messages=[{"role": "user", "content": "解释相对论"}],
)
```

在内部，路由器（如矩阵分解路由器）会先用 sentence-transformer 嵌入模型编码查询，再与可训练的权重矩阵相乘得到胜率。资料来源：[routellm/routers/matrix_factorization/router.py:1-60]() [routellm/routers/bert/router.py:1-50]()

## OpenAI 兼容服务模式

若希望把 RouteLLM 当作 OpenAI 替换品部署，可在终端启动内置服务：

```bash
python -m routellm.openai_server \
    --routers mf \
    --config config.example.yaml \
    --strong-model gpt-4-1106-preview \
    --weak-model ollama_chat/codeqwen
```

服务在 `localhost:6060` 监听，把模型名以 `route-<router>` 的形式暴露给客户端。资料来源：[routellm/openai_server.py:1-50]() [README.md:1-80]()

社区反馈显示，部分用户在命令行模式下会触发 `litellm.drop_params` 报错或跨提供商的鉴权失败，例如在 Windows 下使用 `ollama_chat/codeqwen` 作为弱模型时。资料来源：[https://github.com/lm-sys/RouteLLM/issues/63]() [https://github.com/lm-sys/RouteLLM/issues/78]()

## 本地模型与多模型限制

Controller 当前仅支持「强 / 弱」两模型架构，社区多次提出希望扩展到更多模型（如数学、隐私、视觉等场景的特化路由）。资料来源：[https://github.com/lm-sys/RouteLLM/issues/23]() 此外，当强弱模型运行在不同 OpenAI 兼容端点（如一个本地 Ollama、一个远程 vLLM）时，Controller 并不直接支持分别指定 `api_base`，这是当前 SDK 的一个已知限制。资料来源：[https://github.com/lm-sys/RouteLLM/issues/27]() 

若要在本地使用 Ollama，可让弱模型指向 `ollama_chat/<model_name>`，并在初始化前通过环境变量配置 Ollama 端点。资料来源：[examples/routing_to_local_models.md:1-40]() 

```mermaid
flowchart LR
    A[用户消息] --> B[Controller.route_sync]
    B --> C{路由器打分}
    C -- 概率 ≥ 阈值 --> D[强模型]
    C -- 概率 < 阈值 --> E[弱模型]
    D --> F[返回响应]
    E --> F
```

## 总结

`Controller` 是 RouteLLM Python SDK 与 OpenAI 兼容服务共用的核心：它既负责路由器的加载与决策，也封装了底层 litellm 调用。开发者在使用时需关注三件事——选择合适的路由器、配置路由阈值、确认强弱模型的连通性。多模型支持、跨端点 `api_base`、路由器训练脚本的开放仍是社区关注的演进方向。

---

<a id='page-5'></a>

## OpenAI 兼容服务器部署

### 相关页面

相关主题：[Python SDK 与 Controller](#page-4), [扩展、集成与故障排除](#page-8)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [routellm/openai_server.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/openai_server.py)
- [examples/router_chat.py](https://github.com/lm-sys/RouteLLM/blob/main/examples/router_chat.py)
- [config.example.yaml](https://github.com/lm-sys/RouteLLM/blob/main/config.example.yaml)
- [routellm/controller.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/controller.py)
- [README.md](https://github.com/lm-sys/RouteLLM/blob/main/README.md)
- [routellm/routers/router.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/router.py)
- [routellm/routers/matrix_factorization/train_matrix_factorization.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/matrix_factorization/train_matrix_factorization.py)
</details>

# OpenAI 兼容服务器部署

## 概述与目标

RouteLLM 提供了一个与 OpenAI API 完全兼容的代理服务器，允许用户在不修改现有客户端代码的前提下，将请求按需路由到"强模型"（如 GPT-4）与"弱模型"（如本地 Ollama 模型）。该服务基于 FastAPI 与 litellm 构建，对外暴露标准的 `/v1/chat/completions` 端点，对内部则通过 `Controller` 调用所选的路由器（router）进行决策。资料来源：[README.md:1-80]() [routellm/openai_server.py:1-40]()

## 启动方式与命令行参数

服务器通过 Python 模块方式启动，常用命令如下：

```bash
python -m routellm.openai_server --routers mf --weak-model ollama_chat/codeqwen
```

主要参数说明：

| 参数 | 说明 |
| --- | --- |
| `--routers` | 选择路由器类型，可选 `mf`（矩阵分解）、`bert`、`random` 等 |
| `--weak-model` / `--strong-model` | 指定弱模型与强模型的 litellm 名称 |
| `--config` | 指定 YAML 配置文件路径，用于声明多个模型及 API 密钥 |
| `--port` / `--host` | 监听地址，默认绑定本地端口 |

资料来源：[README.md:40-90]() [routellm/openai_server.py:30-80]()

## 配置文件结构

`config.example.yaml` 中以字典形式定义模型集合，每个键为一个模型别名，可包含 `model_name`、`litellm_params`、`api_key`、`api_base` 等字段。用户可通过 `OPENAI_API_BASE` 等环境变量覆盖默认值。社区中 issue #27 指出，用户希望"强模型与弱模型可使用不同的 base URL"，目前需要在配置文件中显式为每个模型声明 `api_base`。资料来源：[config.example.yaml:1-60]() [issue #27]()

```yaml
# config.example.yaml 片段
strong_model:
  model_name: gpt-4-1106-preview
  litellm_params:
    model: gpt-4-1106-preview
weak_model:
  model_name: ollama_chat/llama3
  litellm_params:
    model: ollama_chat/llama3
    api_base: http://localhost:11434
```

## 请求处理流程

```mermaid
flowchart LR
    A[客户端请求] --> B[/v1/chat/completions/]
    B --> C[OpenAI Server]
    C --> D[Controller.acompletion]
    D --> E{Router 决策}
    E -- 简单查询 --> F[弱模型 litellm 调用]
    E -- 复杂查询 --> G[强模型 litellm 调用]
    F --> H[响应流式回传]
    G --> H
```

`Controller` 在接收到请求后，会构造一个查询嵌入（query embedding），然后交由所选路由器输出强模型调用概率。决策完成后，由 `litellm.completion` / `litellm.acompletion` 执行实际的模型调用，并把响应以 OpenAI 兼容格式返回。资料来源：[routellm/controller.py:1-120]() [routellm/routers/router.py:1-60]()

## 客户端调用示例

`examples/router_chat.py` 演示了如何将任意 OpenAI SDK 客户端的 `base_url` 指向本地 RouteLLM 服务，从而复用标准聊天接口：

```python
client = OpenAI(
    api_key="anything",
    base_url="http://localhost:6060/v1",
)
resp = client.chat.completions.create(
    model="route-llm",
    messages=[{"role": "user", "content": "解释量子纠缠"}],
)
```

资料来源：[examples/router_chat.py:1-50]()

## 常见问题与社区反馈

1. **litellm.drop_params 报错**（issue #63）：运行 `openai_server` 时若本地 litellm 版本不兼容，会在调用阶段抛出 `drop_params` 异常，建议固定 litellm 版本或升级到最新发布版本。
2. **Ollama 双模型部署**（issue #76）：当强模型与弱模型均为本地 Ollama 实例时，必须分别为其配置独立的 `api_base`，否则会被默认 base URL 覆盖。
3. **多模型与多维度路由**（issue #23）：当前控制器仅在强、弱两个模型之间二选一，社区已提出按任务类型、成本、隐私等级等多维度路由的扩展诉求。
4. **MF 路由器嵌入模型替换**（issue #84）：若需替换默认嵌入模型，需在训练脚本与推理侧同步修改，并保证 `.npy` 嵌入文件与所选模型维度一致（参见 `train_matrix_factorization.py` 第 58-62 行的非可训练嵌入加载逻辑）。资料来源：[routellm/routers/matrix_factorization/train_matrix_factorization.py:58-62]() [issue #63]() [issue #76]() [issue #23]() [issue #84]()

## 部署建议

- 将 `config.example.yaml` 复制为本地 `config.yaml`，按需调整 `api_base` 与 `api_key`，避免将密钥提交至版本控制。
- 对外提供服务时建议增加反向代理（如 Nginx）并启用 HTTPS，同时限制 `/v1/chat/completions` 的速率以保护上游模型配额。
- 启用 MF 或 BERT 路由器前，务必下载对应的训练权重与嵌入文件，否则路由器将无法完成推理。资料来源：[README.md:90-140]() [routellm/openai_server.py:80-140]()

---

<a id='page-6'></a>

## 阈值校准与基准评估

### 相关页面

相关主题：[路由器实现机制详解](#page-3), [模型训练与自定义嵌入](#page-7)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [routellm/calibrate_threshold.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/calibrate_threshold.py)
- [routellm/eval/generate_winrate.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/eval/generate_winrate.py)
- [routellm/eval/elo.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/eval/elo.py)
- [routellm/eval/benchmarks/ifeval.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/eval/benchmarks/ifeval.py)
- [routellm/routers/matrix_factorization/router.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/matrix_factorization/router.py)
- [routellm/routers/bert/router.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/bert/router.py)
- [README.md](https://github.com/lm-sys/RouteLLM/blob/main/README.md)
</details>

# 阈值校准与基准评估

## 概述与设计目标

RouteLLM 在路由阶段通过一个介于 0 到 1 之间的"赢率分数"（win-rate score）决定查询应被路由到强模型还是弱模型。该分数来自训练好的矩阵分解（MF）或 BERT 路由器，但仅有一个相对排序并不足以直接决策——需要一个可调节的**阈值（threshold）**来控制成本与质量之间的权衡。`routellm/calibrate_threshold.py` 的作用即在已知基准胜率曲线的前提下，为指定路由器寻找一个满足给定成本节约比例（如保留 95% 强模型性能同时节省 50% 调用）的最佳阈值 资料来源：[routellm/calibrate_threshold.py:1-40]()。

阈值校准独立于路由器训练，使同一训练好的模型可在不同部署目标下重新校准，而无需重训。

## 校准工作流

`calibrate_threshold.py` 的核心逻辑由 `get_threshold` 与 `calibrate` 两个函数构成，配合外部评估脚本完成端到端计算。其工作流可总结为：

```mermaid
flowchart TD
    A[加载训练好的路由器 mf/bert] --> B[在基准数据集上<br/>批量打分]
    B --> C[生成 win-rate 曲线<br/>调用 generate_winrate.py]
    C --> D[扫描 threshold ∈ 0,1]
    D --> E{比较成本节约 vs<br/>质量保留率}
    E -- 满足约束 --> F[输出最优阈值]
    E -- 不满足 --> D
    F --> G[写入 router.threshold]
```

具体步骤上，`calibrate_threshold.py` 会接收四个核心参数：`--routers`（路由器标识）、`--config`（路由配置，如 config.example.yaml）、`--strong-model` 与 `--weak-model`（用于比较的一对模型）。脚本内 `calibrate` 函数利用 `compute_winrate` 计算不同阈值下的强模型使用率与剩余胜率，从而反推最优分割点 资料来源：[routellm/calibrate_threshold.py:42-120]()。

## 基准评估与胜率计算

`routellm/eval/` 子包承担所有评测任务。`generate_winrate.py` 是最常用的入口：它对一组样本（如 MT Bench、Chatbot Arena 子集）分别调用强、弱模型，再让一个评判模型（如 GPT-4）进行成对比较，最终统计"强模型赢率"。该结果以 JSONL 或 CSV 形式输出，可被校准脚本直接消费 资料来源：[routellm/eval/generate_winrate.py:1-60]()。

除胜率外，`routellm/eval/elo.py` 还实现了基于 Bradley–Terry 模型的 ELO 评分，可对多模型进行全局排序；而 `benchmarks/ifeval.py` 提供指令遵循基准（IFEval）的零样本评估，便于对路由器在不同能力维度下的表现做补充度量 资料来源：[routellm/eval/elo.py:1-80]()、资料来源：[routellm/eval/benchmarks/ifeval.py:1-90]()。

## 阈值在路由器中的使用

校准得到的阈值并非孤立的超参数，而是嵌入到运行时决策逻辑中。以矩阵分解路由器为例，`MatrixFactorizationRouter` 在 `__call__` 中计算查询嵌入与强、弱模型偏置的差值，得到胜率预测，再与 `self.threshold` 比较：低于阈值路由弱模型，反之路由强模型 资料来源：[routellm/routers/matrix_factorization/router.py:1-70]()。BERT 路由器 `BERTRouter` 采用同样的策略，使用最后一个隐藏层的 logits 经 sigmoid 后与阈值对比 资料来源：[routellm/routers/bert/router.py:1-60]()。

| 路由器类型 | 分数来源 | 默认行为 |
| --- | --- | --- |
| `mf` | 矩阵分解的隐向量点积 + sigmoid | 未校准时阈值=0.5，需运行 `calibrate_threshold.py` |
| `bert` | 分类头输出经 sigmoid | 同上 |
| `random` | 固定概率随机 | 无阈值概念，作为基线 |

> 注意：当用户部署自定义嵌入模型（如 `intfloat/e5-small-v2`）用于 MF 路由器时，必须重新校准阈值，否则仍使用默认值会导致偏差 资料来源：[README.md:60-110]()。社区中也出现过相关讨论（参见 Issue #84）。

## 实践建议与社区反馈

- **多模型扩展**：当前校准逻辑仅针对一对强、弱模型；若希望路由到更多模型，需要扩展 `compute_winrate` 以支持多类别排序（社区 Issue #23 多次提及此需求）。
- **独立基准 URL**：当强、弱模型运行在不同服务器时，需在控制器配置中分别指定 `base_url`，否则校准阶段会复用同一端点导致结果失真（社区 Issue #27）。
- **嵌入模型变更**：更换 MF 路由器底层嵌入模型后，`calibrate_threshold.py` 输出的 `.npy` 查询嵌入不再适用，必须重新生成并校准（社区 Issue #83 讨论的 `.npy` 文件即源自此流程）。

通过校准脚本与评测管线的配合，RouteLLM 在保持与强模型相近胜率的同时，显著降低了对昂贵模型的调用频率，这也是该框架核心价值所在。

---

<a id='page-7'></a>

## 模型训练与自定义嵌入

### 相关页面

相关主题：[路由器实现机制详解](#page-3), [扩展、集成与故障排除](#page-8)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- 资料来源： [routellm/routers/matrix_factorization/train_matrix_factorization.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/matrix_factorization/train_matrix_factorization.py)
- 资料来源： [routellm/routers/similarity_weighted/generate_embeddings.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/similarity_weighted/generate_embeddings.py)
- 资料来源： [routellm/routers/similarity_weighted/utils.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/similarity_weighted/utils.py)
- 资料来源： [config.example.yaml](https://github.com/lm-sys/RouteLLM/blob/main/config.example.yaml)
</details>

以下源码文件用于生成本页说明：

- [routellm/routers/matrix_factorization/train_matrix_factorization.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/matrix_factorization/train_matrix_factorization.py)
- [routellm/routers/matrix_factorization/utils.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/matrix_factorization/utils.py)
- [routellm/routers/similarity_weighted/generate_embeddings.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/similarity_weighted/generate_embeddings.py)
- [routellm/routers/similarity_weighted/utils.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/similarity_weighted/utils.py)
- [routellm/routers/router.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/router.py)
- [config.example.yaml](https://github.com/lm-sys/RouteLLM/blob/main/config.example.yaml)
- [routellm/eval/generate_predictions.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/eval/generate_predictions.py)
</details>

# 模型训练与自定义嵌入

RouteLLM 的路由器需要在「强模型」与「弱模型」之间做出路由决策，因此其核心机器学习组件——**模型训练**与**嵌入生成**——决定了路由器如何学习用户偏好并在线推理。本页说明仓库内可用的训练脚本、嵌入生成流程以及如何配置自定义嵌入。

## 路由器训练体系概览

RouteLLM 当前仓库主要提供两类可训练/可加载的路由器：

- **矩阵分解（Matrix Factorization, MF）路由器**：一个有监督训练流程，需要在标注好的「强模型 vs 弱模型」胜负数据上拟合参数。
- **相似度加权（Similarity Weighted, SW）路由器**：基于预计算的查询与响应嵌入做 k-NN 风格打分，本身不需要训练，但**依赖外部生成的嵌入**。

```mermaid
flowchart LR
    A[标注胜负数据] --> B[计算查询嵌入]
    B --> C[MF 训练脚本]
    C --> D[model_weights.npy]
    E[无标注对话] --> F[generate_embeddings.py]
    F --> G[embeddings.npy]
    D --> H[在线推理]
    G --> H[在线推理]
    H --> I[路由到强/弱模型]
```

社区 issue #67 与 #82 多次询问 BERT 路由器的训练代码，但截至目前仓库主分支未提供 BERT 训练脚本，MF 与 SW 是主要可复现的训练/嵌入路径（资料来源：[routellm/routers/matrix_factorization/train_matrix_factorization.py:1-80]()）。

## 矩阵分解（MF）路由器训练

`routellm/routers/matrix_factorization/train_matrix_factorization.py` 是 MF 路由器的训练入口。流程如下：

1. **加载数据**：使用 `load_chat_data`、`load_win_rate_data` 等工具加载 ChatBot Arena 上的对话与胜负标注。
2. **加载嵌入**：代码通过 `np.load(...)` 读取一个 `.npy` 文件作为固定查询嵌入向量；这些嵌入在训练期间**不可微**，仅作为 MF 模型的特征输入（资料来源：[routellm/routers/matrix_factorization/train_matrix_factorization.py:58-62]()）。
3. **构建模型**：`MFRouter` 通过矩阵分解将查询嵌入映射到一个标量 logits，预测选择强模型的概率。
4. **训练**：使用 PyTorch 优化器在 BCE 损失上做梯度下降。
5. **保存权重**：训练完成后将参数写入 `model_weights.npy` 以便在线推理加载。

关于社区中被反复问到的「`.npy` 文件是什么」、「为什么查询嵌入不参与训练」：这是因为 RouteLLM 论文与代码选择使用**冻结的预训练嵌入**（来自 Azure OpenAI 的 `text-embedding-3-small`）作为输入特征，仅学习路由器的线性投影参数，从而避免对底层 LLM 嵌入做反向传播（资料来源：[routellm/routers/matrix_factorization/utils.py:1-40]()）。

## 相似度加权（SW）路由器与自定义嵌入

SW 路由器无需训练，但需要预先计算所有训练/测试对话与「强模型响应」的嵌入。核心流程在 `routellm/routers/similarity_weighted/generate_embeddings.py` 中：

1. **并行调用嵌入 API**：脚本支持 `OpenAIEmbeddingProvider`，按对话分批调用嵌入接口。
2. **分词与截断**：`routellm/routers/similarity_weighted/utils.py` 提供 `tokenize` 与 `truncate` 工具，将长 prompt 控制在嵌入模型的上下文长度之内（资料来源：[routellm/routers/similarity_weighted/utils.py:1-60]()）。
3. **写盘**：最终保存为 `embeddings.npy`，推理时通过 `similarity_weighted` 路由器加载。

如果想替换为其他嵌入模型（例如社区在 #84 中提到的 `intfloat/e5-small-v2`），需要修改 `generate_embeddings.py` 中的 `OpenAIEmbeddingProvider` 实现，并保证嵌入维度与训练/推理脚本一致；直接更改 `config.example.yaml` 中的 `router_params` 不够，因为嵌入本身需要离线重新生成（资料来源：[routellm/routers/similarity_weighted/generate_embeddings.py:1-100]()）。

## 配置与在线推理对接

`config.example.yaml` 定义了路由器名称、模型对以及嵌入维度等关键参数。例如 MF 路由器的典型配置包含 `routers: mf` 与对应 weak/strong 模型名，并在启动 OpenAI 兼容服务时通过 `--config` 传入（资料来源：[config.example.yaml:1-60]()）。

在线推理侧，`routellm/routers/router.py` 中的通用路由器封装会读取 `.npy` 权重与嵌入，对请求的 `messages` 实时计算嵌入并输出路由概率（资料来源：[routellm/routers/router.py:1-120]()）。`routellm/eval/generate_predictions.py` 则用于在 ChatBot Arena 风格测试集上批量评估路由效果（资料来源：[routellm/eval/generate_predictions.py:1-80]()）。

## 常见实践与社区反馈

- **嵌入模型选择**：社区 #84 询问如何替换嵌入模型，答案是同时修改嵌入生成代码与保持维度一致，否则 `np.load` 阶段会因形状不匹配而报错。
- **速率限制**：issue #78 报告嵌入生成与模型请求都会触发 OpenAI 速率限制，建议在 `generate_embeddings.py` 中调小并发或加重试。
- **多模型支持**：issue #23 提到当前训练脚本仅支持二分类（强 vs 弱），MF 模型输出维度为 1；扩展到多模型需要重写 `train_matrix_factorization.py` 中的目标函数。
- **训练脚本缺失**：issue #67 与 #82 关注的 BERT 训练代码目前未在主仓库提供，建议改用 MF 或 SW 路径。

## 小结

总体而言，RouteLLM 的「模型训练」主要是 MF 路由器的参数拟合，而「自定义嵌入」则集中在 SW 路由器的离线 `.npy` 生成。两者通过 `config.example.yaml` 与 `routers/router.py` 在推理服务中统一加载。理解 `.npy` 文件的来源（冻结的预训练嵌入）以及嵌入与权重在训练/推理中的角色，是定制 RouteLLM 路由行为的关键。

---

<a id='page-8'></a>

## 扩展、集成与故障排除

### 相关页面

相关主题：[系统架构与代码组织](#page-2), [Python SDK 与 Controller](#page-4), [模型训练与自定义嵌入](#page-7)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [routellm/routers/routers.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/routers.py)
- [routellm/controller.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/controller.py)
- [routellm/openai_server.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/openai_server.py)
- [routellm/middleware.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/middleware.py)
- [routellm/routers/matrix_factorization/train_matrix_factorization.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/matrix_factorization/train_matrix_factorization.py)
- [routellm/routers/bert/train_bert.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/routers/bert/train_bert.py)
- [routellm/eval/eval.py](https://github.com/lm-sys/RouteLLM/blob/main/routellm/eval/eval.py)
</details>

# 扩展、集成与故障排除

## 概述

RouteLLM 是一个用于在「强模型」与「弱模型」之间动态路由查询的框架。其核心抽象由路由器（Router）、控制器（Controller）和 OpenAI 兼容服务三层构成，分别负责打分决策、调用下游模型和对外暴露标准接口。本页聚焦三个维度：如何扩展系统、如何与外部工具链集成，以及如何应对社区中高频报告的故障。

## 扩展机制

### 路由器抽象与自定义路由器

`routellm/routers/routers.py` 定义了路由器基类 `Router` 与若干内置实现，包括 `mf`、`bert`、`random`、`causal_llm`、`similarity` 等。所有路由器必须实现 `calculate_strong` 等接口，对查询返回 0–1 之间的「强模型概率」分数 `资料来源：[routellm/routers/routers.py:1-80]()`。新增路由策略只需继承该基类并注册到路由器工厂函数 `get_router` 中 `资料来源：[routellm/routers/routers.py:80-140]()`，即可被命令行参数 `--routers` 引用。

### 替换矩阵分解（MF）路由器的嵌入模型

MF 路由器训练时会加载预计算的查询嵌入文件（`.npy`），该文件由原始论文采用的嵌入模型离线编码得到，作为固定的非可训练张量参与训练 `资料来源：[routellm/routers/matrix_factorization/train_matrix_factorization.py:58-62]()`。如果希望换用 `intfloat/e5-small-v2` 等其他嵌入模型，需同时：(1) 用新模型重新编码训练语料的查询以生成对应的 `.npy` 文件；(2) 在路由器初始化时将 `embedding_model` 参数指向新模型。直接修改单边而不重算嵌入会导致维度不匹配，这正是社区问题 #84 报告的报错来源。

### 训练 BERT 路由器

社区多次询问 BERT 路由器训练代码（issue #67）。训练入口位于 `routellm/routers/bert/train_bert.py`，它加载标注好的「强/弱」偏好数据并微调 BERT 分类器，得到的 checkpoint 可被 `bert` 路由器加载 `资料来源：[routellm/routers/bert/train_bert.py:1-50]()`。如需自定义训练数据，应保持与原始数据相同的字段结构（prompt、strong_model_output、weak_model_output、preferred_model）。

## 集成方案

### OpenAI 兼容服务

`routellm/openai_server.py` 是项目对外提供服务的入口，启动命令为：

```
python -m routellm.openai_server --routers mf --weak-model ollama_chat/xxx --strong-model openai/gpt-4o
```

服务内部读取路由分数后，通过 `Controller` 选择目标模型并代理转发请求 `资料来源：[routellm/openai_server.py:1-80]()`。该服务兼容 `/v1/chat/completions` 接口，因此可与任何 OpenAI SDK 客户端协作。

### LangChain 集成

`routellm/middleware.py` 暴露了 `RouteLLMMiddleware`，可注入到 LangChain 的 `ChatModel` 调用链中，在 LLM 调用前根据 prompt 动态选择底层模型 `资料来源：[routellm/middleware.py:1-60]()`。使用方式详见 issue #28 的讨论：初始化中间件时传入所需的路由器实例与强/弱模型名称即可。

### 多模型与多后端

目前 `Controller` 在初始化时固定 `strong_model` 与 `weak_model` 两个字段 `资料来源：[routellm/controller.py:1-60]()`，因此原生支持二元路由。若需引入第三类模型（例如隐私专用或数学专用），社区 issue #23 提出了扩展建议：在路由器层增加多分类输出或在控制器层扩展模型池映射。

## 故障排除

### litellm.drop_params 报错

issue #63 报告在某些 litellm 版本下启动 OpenAI 服务并请求时，会触发 `litellm.drop_params` 相关异常。根本原因是底层 litellm 透传的某些采样参数不被目标模型支持。临时解决方案是在 `openai_server.py` 调用 `litellm.drop_params = True`，或在请求体中显式剔除不被识别的字段 `资料来源：[routellm/openai_server.py:80-140]()`。

### 不同后端的 Base URL

当强、弱模型分别运行在不同 OpenAI 兼容服务（如本地 Ollama 与远端 vLLM）时，issue #27 指出当前 `Controller` 不支持为两侧分别指定 `api_base`。一种可行做法是借助 litellm 的 provider 前缀（如 `openai/`、`hosted_vllm/`），并在环境变量中分别配置两侧端点；如需更深定制，则需在控制器初始化处扩展 `api_base` 字段。

### Ollama 与其他本地模型

使用 `ollama_chat/` 前缀路由本地模型时，必须保证 Ollama 服务在 `localhost:11434` 可用并已 `ollama pull` 对应权重。issue #76 与 #78 中「API 连接失败」多由服务未启动或模型未拉取引起，建议先用 `curl http://localhost:11434/api/tags` 验证连通性。

### 速率限制与配额

issue #78 中使用 `mf` 路由器始终返回「rate limit exceeded」通常并非路由器本身问题，而是底层模型（GPT-4o、Claude 等）的配额耗尽。`mf` 路由会优先把困难查询送到强模型，因此越界使用会迅速消耗配额；可临时切换到 `random` 或 `similarity` 路由器以验证问题是否与上游配额相关。

### BERT 路由器的 401/403 错误

`bert` 路由器加载 checkpoint 时若报授权错误（issue #78），通常是 Hugging Face Hub 上的私有模型访问受限。可改用本地路径或设置 `HF_TOKEN` 环境变量后再启动服务。

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：lm-sys/RouteLLM

摘要：发现 11 个潜在踩坑项，其中 1 个为 high/blocking；最高优先级：配置坑 - 来源证据：litellm.drop_params error when running the openapi server。

## 1. 配置坑 · 来源证据：litellm.drop_params error when running the openapi server

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个配置相关的待验证问题：litellm.drop_params error when running the openapi server
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/lm-sys/RouteLLM/issues/63 | 来源讨论提到 python 相关条件，需在安装/试用前复核。

## 2. 安装坑 · 来源证据：Add AgentWeb business data integration

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：Add AgentWeb business data integration
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/lm-sys/RouteLLM/issues/87 | 来源讨论提到 npm 相关条件，需在安装/试用前复核。

## 3. 配置坑 · 来源证据：Try to run 2 Ollam

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个配置相关的待验证问题：Try to run 2 Ollam
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/lm-sys/RouteLLM/issues/76 | 来源讨论提到 python 相关条件，需在安装/试用前复核。

## 4. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://github.com/lm-sys/RouteLLM | README/documentation is current enough for a first validation pass.

## 5. 运行坑 · 来源证据：How can I use the different embedding model for mf router

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个运行相关的待验证问题：How can I use the different embedding model for mf router
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/lm-sys/RouteLLM/issues/84 | 来源类型 github_issue 暴露的待验证使用条件。

## 6. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/lm-sys/RouteLLM | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/lm-sys/RouteLLM | no_demo; severity=medium

## 8. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://github.com/lm-sys/RouteLLM | no_demo; severity=medium

## 9. 安全/权限坑 · 来源证据：Following demo it doesn't work

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：Following demo it doesn't work
- 对用户的影响：可能影响授权、密钥配置或安全边界。
- 证据：community_evidence:github | https://github.com/lm-sys/RouteLLM/issues/78 | 来源讨论提到 python 相关条件，需在安装/试用前复核。

## 10. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://github.com/lm-sys/RouteLLM | issue_or_pr_quality=unknown

## 11. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://github.com/lm-sys/RouteLLM | release_recency=unknown

<!-- canonical_name: lm-sys/RouteLLM; human_manual_source: deepwiki_human_wiki -->
