Files
ModelRouter/README.md

139 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ModelRouter
> **仓库**: <https://atomgit.com/HeNanMU-EEA/ModelRouter>
>
> **English**: [README_EN.md](./README_EN.md)
>
> **AI-assisted**: 本项目使用 AI 辅助编程(代码与文档由 AI 协作完成,经人工复核)。
面向多 LLM 订阅者的内网网关:一次配置,多个服务共用一组上游额度。支持指定模型或
`AUTO` 模式,按配置的优先级选择可用模型提供服务。
网关本体是单个 Go 二进制(约 10 MB,零运行时依赖)。新增或切换上游只需在
`config.yaml`(或 WebUI)加一个 `sources` 条目、或挂一个 `.lua` 适配器——**不改 Go、
不重编译**。源与适配器的改动经 WebUI 提交时即时生效(热更新);直接编辑
`config.yaml` 或 `adapter_dir` 下的 `.lua` 文件需要重启进程生效。
## 核心能力
- **统一接口**:对内暴露 OpenAI 兼容的 `/v1/chat/completions`、`/v1/models`、
`/v1/images/generations`;所有源对外都是同一套格式(含 `reasoning_content`、
`tool_calls`、`usage`)。
- **多源 + AUTO 链**:一个进程内任意多个上游源;`default_model: AUTO` 时按优先级页
保存的档位逐档调度,源故障自动降级并冷却,恢复后半冷却探测自愈。
- **协议适配在 Lua 层**:每个源挂一个 `.lua` 适配器,完成请求/响应/流式分片的双向
转换,并可用 `build_headers(meta)` 注入签名头。协议差异不进 Go 内核。
- **插件独立**:业务扩展(计费、用量统计等)是外置 Lua 插件,由插件目录加载,
不编进二进制、不随发行包分发;插件只通过 `modelrouter` SDK 与内核交互。
- **多租户密钥**:网关 key 与上游 key 相互独立,按 key 限定模型范围、AUTO 链与配额。
- **加密存储**:上游 key、自定义请求头、网关 key 均以 AES-256-GCM 落盘,
`master.key` 单独 0600 权限(或由 `MODELROUTER_MASTER_KEY` 注入)。
- **可观测**:状态页实时探测源可达性;HTTP 访问日志、配置变更审计、请求与用量 CSV 导出;
写操作不落在请求热路径上。
## 快速开始
```bash
# 需要 LuaJIT 开发库;-tags luajit 是必须的
GOMODCACHE=... GOPROXY=off go build -tags luajit -o modelrouter ./cmd/modelrouter
# 首次运行会生成默认配置,并在日志里打印随机 admin key
./modelrouter -config config.yaml
```
> 依赖 [golua](https://github.com/aarzilli/golua)(LuaJIT 绑定)。不带 `-tags luajit`
> 会走 gopher-lua 路径,行为略有差异。
> **配置不入库**:仓库不携带任何 config 文件(其中含密钥)。默认配置只绑定
> `127.0.0.1:8080`,首次登录后请在 WebUI「密钥」页更换管理员密钥。
```bash
# 无 key -> 401
curl http://127.0.0.1:8080/v1/models
# 单次($KEY 换成首次启动日志打印的 admin key)
curl -H "Authorization: Bearer $KEY" \
-d '{"model":"AUTO","messages":[{"role":"user","content":"hi"}]}' \
http://127.0.0.1:8080/v1/chat/completions
# 流式
curl -N -H "Authorization: Bearer $KEY" \
-d '{"model":"AUTO","stream":true,"messages":[{"role":"user","content":"hi"}]}' \
http://127.0.0.1:8080/v1/chat/completions
```
任何 OpenAI SDK 把 `base_url` 指向网关、`api_key` 换成任一已授权的网关 key 即可。
## 文档
| 主题 | 文档 |
|---|---|
| 实现与完整特性清单 | [docs/features.md](docs/features.md) |
| 配置:`config.yaml`、自动探测模型、多密钥 | [docs/configuration.md](docs/configuration.md) |
| 路由:模型路由、AUTO 链、冷却与半冷却、源与适配器、源模板 | [docs/routing.md](docs/routing.md) |
| 适配器:Lua 协议、内置适配器清单 | [docs/adapters.md](docs/adapters.md) · [docs/lua-adapters.md](docs/lua-adapters.md)([EN](docs/lua-adapters-en.md)) |
| 插件:SDK 契约、钩子、UI 扩展、HTTP 端点 | [docs/plugins.md](docs/plugins.md) |
| 桌面端:Headless / Desktop 两种产物、构建与运行 | [docs/gui.md](docs/gui.md) |
| 性能:实测内存占用与调优、thinking 预算 | [docs/performance.md](docs/performance.md) |
| WebUI 使用 | [docs/webui.md](docs/webui.md) |
| 开发:目录职责、测试、分支与发布纪律 | [docs/development.md](docs/development.md) · [docs/git-workflow.md](docs/git-workflow.md)([EN](docs/git-workflow-en.md)) |
| 部署与迁移 | [docs/deployment.md](docs/deployment.md) |
## 从 llmsproxy 改名
产品名早已是 ModelRouter,二进制、配置目录、服务名与环境变量现已统一为
`modelrouter`:
| 旧 | 新 |
|---|---|
| `llmsproxy`(二进制) | `modelrouter` |
| `/etc/llmsproxy/` | `/etc/modelrouter/` |
| `llmsproxy.service` | `modelrouter.service` |
| `LLMSPROXY_*` | `MODELROUTER_*` |
已部署的机器用迁移脚本升级(**默认 dry-run**,复制不移动,可回滚):
```bash
sudo ./packaging/migrate-to-modelrouter.sh # 预演
sudo ./packaging/migrate-to-modelrouter.sh --apply # 执行
sudo ./packaging/migrate-to-modelrouter.sh --rollback --apply
```
旧路径与旧环境变量在读取侧仍被接受,因此升级不会因为顺序问题立刻失效。
`deploy.sh` 在检测到旧 `/etc/llmsproxy` 而新配置不存在时会**中止**,避免部署出
一个「能启动但没有 key / 没有源」的空实例。
插件 SDK 同名调整:唯一公开入口是 `modelrouter`(`llmsproxy` 仅作兼容别名),
详见 [docs/plugins.md](docs/plugins.md)。
## 目录结构
```text
cmd/modelrouter # 入口(纯 Go 服务端)
cmd/gui # Electron 桌面壳(内嵌同一份核心)
internal/config # 配置解析、加密存储、运行时文件
internal/core # 调度、内核动作、状态与审计
internal/lua # LuaJIT VM + 弹性 worker 池 + 内置适配器 (embed)
internal/lua/plugins # 可选插件示例(不随二进制/发行包分发)
internal/provider # Provider(HTTP) + Registry(路由)
internal/gateway # OpenAI 兼容 HTTP 服务 + 鉴权 + 流式 + WebUI
internal/types # 统一格式 & OpenAI wire 类型
packaging/ # deb/rpm/tar 打包、systemd unit、迁移脚本
docs/ # 主题文档
```
## 开发与测试
```bash
go test -tags luajit ./... # 全量
go test -tags luajit ./internal/lua # 单包(LuaJIT 相关改动必跑)
```
- 分支与发布纪律见 [docs/git-workflow.md](docs/git-workflow.md)。
- 插件放置在 `plugin_dir`,网关启动时**不会**创建、覆盖或删除任何插件文件;
升级桌面端也不会动它们。
## 许可
MIT License,见 [LICENSE](./LICENSE)。