mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-11-07 09:47:23 +00:00
README 从 642 行降到 131 行,只保留简介、核心能力、最小快速开始、文档索引、 改名说明、目录结构与测试入口。其余内容迁到 docs/,中英文索引一一对应: docs/features.md 实现与完整特性清单(原 README 的"实现/特性") docs/configuration.md 配置文件、自动探测模型、多密钥与配额 docs/routing.md 模型路由、AUTO 链、冷却与半冷却、源/适配器、源模板 docs/performance.md 实测内存占用与调优、thinking 预算 docs/webui.md WebUI 使用 docs/adapters.md Lua 适配器协议与内置适配器清单 docs/gui.md 桌面端 Headless/Desktop 两种产物与构建 docs/development.md 目录职责、开发协作、测试 docs/deployment.md 部署、发行包、目录权限、llmsproxy 迁移与验证清单 中性化:README / README_EN / GUI 注释里的 `Clash Verge` 类比全部改为 「桌面壳 / desktop shell」,仓库内(源码与文档)已无该表述。
112 lines
6.7 KiB
Markdown
112 lines
6.7 KiB
Markdown
# 路由与调度
|
||
|
||
> 本文档由 README 拆分而来:模型路由、AUTO 链、冷却与半冷却、源与适配器、源模板。
|
||
> 返回 [README](../README.md)。
|
||
|
||
## 模型路由
|
||
|
||
`/v1/chat/completions` 的 `model` 解析顺序:
|
||
|
||
1. `source/model` 或 `source:model` 前缀 → 指定源;
|
||
2. 精确匹配某个源的 `model`;
|
||
3. 配置 `default_model: AUTO` 时 → 走优先级页保存的 AUTO 链(见下);
|
||
4. 否则回落(返回错误)。
|
||
|
||
任何 OpenAI 客户端,只要 `model` 设为某个源的 `name/任意名`,即可锁定走该源;
|
||
设为 `AUTO`(或网关配了 `default_model: AUTO`)即自动按优先级链选源。
|
||
|
||
## AUTO 链(优先级页)
|
||
|
||
AUTO 调度**只**由优先级页保存的规则决定,源配置里的 `models[].priority` 数字不再
|
||
参与调度、也不再显示。**聊天与生图是两套独立的链**,在优先级页面通过「聊天 / 生图」
|
||
按钮切换编辑:
|
||
|
||
- **聊天链**(`runtime_file` 的 `auto` 字段):服务 `POST /v1/chat/completions`
|
||
的 `model: AUTO` 请求;只接受 `kind: chat` 模型,配置在链里的生图槽位会被忽略。
|
||
- **生图链**(`runtime_file` 的 `auto_image` 字段):服务 `POST /v1/images/generations`
|
||
的 `model: AUTO` 请求;只接受 `kind: image` 模型。未配置生图链时,AUTO 生图回落
|
||
到「所有含生图模型的源、按注册顺序」的旧行为,兼容旧配置。
|
||
|
||
每条规则 = 一个「槽位」:`{ model, source, tier, token_quota, period, hours }`。
|
||
|
||
- `tier` 表示优先级档位:同一档的模型并排、共享该优先级;档位从上到下递减。
|
||
- 同一模型可配置多个槽位(如 A 源低配 → B 源低配 → A 源高配 → B 源高配),按档位顺延。
|
||
- `token_quota` > 0 时该槽位在重置周期内用满即顺延到下一槽位;`period` 支持
|
||
`hour` / `week` / `month` / `nhour`(配合 `hours`),空 = 不限。
|
||
- 同 tier 内按「偏好分」排序,失败槽位冷却后自动跳过;冷却 / 配额耗尽 / hard
|
||
错误会顺延到下一 tier,全部失败时返回 503 并附上每档失败摘要。
|
||
|
||
## 冷却与半冷却探测(自愈调度)
|
||
|
||
槽位失败后进入指数退避冷却(5s → 10s → 20s …,上限 **5 分钟**)。冷却不是全时段
|
||
硬闸:
|
||
|
||
- **前半段完全静默**:刚失败的槽位不接任何流量,避免对故障上游持续施压。
|
||
- **后半段放行 1 个探测**:窗口过半后,同一 `(源, 模型)` 最多允许 **一个** 请求作为
|
||
探测通过。探测槽数 = `clamp(max_concurrent / 10, 1, 2)`——`max_concurrent: 10`
|
||
的源恰好放行 1 个探测请求。
|
||
- **探测排在最后**:同 tier 内探测候选永远排在健康候选之后,只有没有正常槽可用时
|
||
才承接真实流量,因此探测不会抢走可用容量。
|
||
- **探测即真实请求**:成功则立即清零失败计数与冷却,槽位当场回到正常轮询——
|
||
上游恢复/额度恢复后不必等满整个冷却窗口。失败则重开一个新窗口,下次探测顺延到
|
||
新窗口的中点,不会连续重试。
|
||
|
||
分类冷却策略:
|
||
|
||
| 情况 | 冷却 | 说明 |
|
||
|---|---|---|
|
||
| 传输错误 / 5xx | 5s→10s→20s…,上限 5min | 指数退避 |
|
||
| 401 / 403 凭据错误 | 10min | 换 key 后由下一次探测自动接回 |
|
||
| 429 限流 | 30s 固定 | 「太快」不等于「坏了」,不进指数阶梯 |
|
||
| 配额耗尽(`insufficient_quota` / `余额不足` 等) | 对齐配额窗口,上限 30min | **不进指数阶梯、不涨失败计数**,额度恢复即可用 |
|
||
|
||
WebUI「优先级」页的槽位健康标签会区分 `冷却` / `待探测` / `探测中`,悬停可看窗口
|
||
起点、探测放行时刻与完全恢复时刻。
|
||
|
||
## 源(Source)与适配器(Adapter)的关系
|
||
|
||
- **源** 是到某个上游的连接描述:`name`、`base_url`、`api_key`、模型列表与优先级。
|
||
- **适配器** 是协议转换逻辑(Lua 脚本):把统一 OpenAI 格式请求转成上游原生格式,
|
||
再把上游响应/流式分块转回统一格式。
|
||
- 一个适配器可被多个源复用(如 `openai.lua` 同时服务多个 OpenAI 兼容站点);
|
||
同一个源也可以切换不同适配器(改 `adapter` 字段即可)。
|
||
- 源决定“连谁、暴露哪些模型”,适配器决定“怎么对话”——二者在 `sources[]` 条目中
|
||
通过 `adapter` 字段关联。
|
||
|
||
加载流程(`internal/core` 的 `Core` 负责装配):
|
||
|
||
1. 启动时 `lua.NewVM(adapter_dir)` 加载全部适配器:内置适配器(编译期 embed)+
|
||
`adapter_dir` 下的同名覆盖文件;内置文件写在代码内,覆盖文件要求更高优先级。
|
||
2. `config.Load` 读取 `config.yaml`,`config.NewStore(runtime_file)` 读 WebUI 改动的
|
||
运行时源,二者按名称合并成完整源列表。
|
||
3. `rebuildRegistry` 为每个源创建 `provider.Provider`(持有目标适配器),并按源的
|
||
并发上限配置适配器 worker 池**上限**(不预分配,见下)。
|
||
4. 请求进来时 `Registry` 按 `model` 路由到 Provider,Provider 调适配器
|
||
`transform_request` → HTTP 发送 → `transform_response` / `transform_stream_chunk`。
|
||
|
||
WebUI 上的"新增/编辑源"、"上传 Lua 适配器"、"改 AUTO 优先级链"与"密钥模型范围"
|
||
都即时生效(写入运行时文件或 `adapter_dir` 后重新装配,无需重启);直接编辑
|
||
`config.yaml` / `adapter_dir` 下的文件则需要重启进程才会重新加载。
|
||
|
||
在 WebUI 删除源/适配器时:运行时(WebUI 创建)的源与 `.lua` 文件会真正移除;
|
||
`config.yaml` 中定义的基源无法改写配置文件,采用删除标记隐藏(重启后仍隐藏),
|
||
在 UI 里重新添加同名源即可恢复。
|
||
|
||
## 源模板(多 key 负载均衡)
|
||
|
||
多个上游 key 共享同一套配置(URL / 适配器 / 模型列表 / 并发 / rpm)时,逐一复制
|
||
整段 source 太冗余。**源模板**保存除 `name` 和 `api_key` 以外的全部源字段,
|
||
从模板一键创建多个仅 key 不同的源,天然支持多 key 负载均衡(每个展开源独立调度、
|
||
独立冷却、独立健康状态)。
|
||
|
||
- WebUI「源」页右上角「**模板管理**」按钮:列出全部模板,可编辑 / 删除 / 新建。
|
||
- 添加源弹窗右上角两个按钮:
|
||
- **从模板创建** → 选模板 → 表单自动填充(name + key 仍需你填);
|
||
- **存为模板** → 把当前表单非 key/name 字段存为新模板。
|
||
- 模板持久化在 `runtime_file` 的 `source_templates` 字段,与运行时源一样热管理,
|
||
改完即时生效。模板本身不含密钥,可以安全共享 / 纳管。
|
||
|
||
模板不会自己变成源——它只是「配方」。真正承担流量的是从模板创建出来的、带 key
|
||
的具体源。
|
||
|