mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-11-07 09:47:23 +00:00
G-Star 合规要求下,把"模拟官方客户端、复刻私有协议、自动领取平台额度"这一类 能力整体移出仓库。这些实现依赖各平台未公开的端点、签名算法与官方 client id, 属于绕过客户端校验获取额度,风险高于普通协议适配。 移除(93 个文件): - 适配器:opencodezen(伪装 UA 取免费池)、trae、buddy、kimicode - 插件:channels.lua(12 个平台登录/领额度/签到)、quota.lua(厂商额度探针) - 随之删除的 78 个渠道/额度专用测试与 3 份渠道文档 同时修掉的既有问题: - **硬编码第三方 OAuth client_secret**(Google Cloud Code 的 GOCSPX-…,两处) 随 channels.lua 一起消失。 - `deploy.sh` 的 `sync_plugins` 整段删除:它仍按"内置插件是发行物"的旧前提 把插件复制/覆盖进 plugin_dir,与"插件属运维资产、网关不安装不覆盖"的契约 冲突。现在部署脚本只同步适配器与二进制/配置。 - 适配器清单去掉已移除项;e2e 配置改用显式 `auto:` 链(`models.priority` 早已 移除,该测试此前已失效)。 保留(公开协议):openai / anthropic / gemini / deepseek / github / groq / mistral / ollama / qwen38 / sensenova = 10 个适配器;插件示例 billing / usage。 验证:go build -tags luajit ./... OK;internal/lua 21.4s、provider、core 51s、 gateway 122.8s、e2e 9.0s 全绿。
152 lines
6.9 KiB
Markdown
152 lines
6.9 KiB
Markdown
# ModelRouter
|
|
|
|
> **Repository**: <https://atomgit.com/HeNanMU-EEA/ModelRouter>
|
|
>
|
|
> **中文**: [README.md](./README.md)
|
|
>
|
|
> **AI-assisted**: code and documentation were produced with AI assistance and
|
|
> reviewed by a human.
|
|
|
|
An intranet gateway for people with several LLM subscriptions: configure once and
|
|
let multiple services share the upstream capacity. Pick a model explicitly, or let
|
|
`AUTO` choose by priority among the sources that are currently healthy.
|
|
|
|
The gateway itself is a single Go binary (~10 MB, no runtime dependencies). Adding
|
|
or switching an upstream is a `sources` entry in `config.yaml` (or the WebUI), or a
|
|
dropped-in `.lua` adapter — **no Go changes, no rebuild**. Changes submitted through
|
|
the WebUI take effect immediately; editing `config.yaml` or a `.lua` adapter file
|
|
directly requires a restart.
|
|
|
|
## What it does
|
|
|
|
- **One OpenAI-compatible API**: `/v1/chat/completions`, `/v1/models`,
|
|
`/v1/images/generations`. Every source speaks the same shape outwards, including
|
|
`reasoning_content`, `tool_calls` and `usage`.
|
|
- **Many sources, one AUTO chain**: configure any number of upstreams; `AUTO`
|
|
follows the priority tiers saved in the WebUI, fails over between them, cools
|
|
down broken sources and probes them back to health at half-cool.
|
|
- **Protocol differences live in Lua**: each source binds a `.lua` adapter that
|
|
transforms requests, responses and stream chunks both ways, and can sign headers
|
|
via `build_headers(meta)`. Vendor knowledge stays out of the Go kernel.
|
|
- **Plugins are independent**: business extensions (channel login, billing, quota
|
|
probing) are external Lua plugins loaded from `plugin_dir`. They are not compiled
|
|
into the binary and not shipped in release archives, and they talk to the kernel
|
|
only through the `modelrouter` SDK.
|
|
- **Multi-tenant keys**: gateway keys are separate from upstream keys, and can be
|
|
scoped to a model set, an AUTO chain and a quota.
|
|
- **Encrypted at rest**: upstream keys, custom header values and gateway keys are
|
|
sealed with AES-256-GCM; `master.key` is 0600, or injected via
|
|
`MODELROUTER_MASTER_KEY`.
|
|
- **Observability**: live source probing, HTTP access log, config-change audit,
|
|
request and usage CSV export. Writes are kept off the request hot path.
|
|
|
|
## Quick start
|
|
|
|
```bash
|
|
# LuaJIT development libraries are required; -tags luajit is mandatory
|
|
GOMODCACHE=... GOPROXY=off go build -tags luajit -o modelrouter ./cmd/modelrouter
|
|
|
|
# First run generates a default config and prints a random admin key
|
|
./modelrouter -config config.yaml
|
|
```
|
|
|
|
> Depends on [golua](https://github.com/aarzilli/golua) (LuaJIT bindings). Without
|
|
> `-tags luajit` the build falls back to gopher-lua, which behaves slightly
|
|
> differently.
|
|
|
|
> **No config in the repo**: the repository ships no config file (they contain
|
|
> keys). The generated default binds `127.0.0.1:8080` only; rotate the admin key in
|
|
> the WebUI after the first login.
|
|
|
|
```bash
|
|
# No key -> 401
|
|
curl http://127.0.0.1:8080/v1/models
|
|
|
|
# Non-streaming ($KEY = the admin key printed at first start)
|
|
curl -H "Authorization: Bearer $KEY" \
|
|
-d '{"model":"AUTO","messages":[{"role":"user","content":"hi"}]}' \
|
|
http://127.0.0.1:8080/v1/chat/completions
|
|
|
|
# Streaming
|
|
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
|
|
```
|
|
|
|
Any OpenAI SDK works: point `base_url` at the gateway and use an authorized gateway
|
|
key as `api_key`.
|
|
|
|
## Documentation
|
|
|
|
The detailed documentation is currently written in Chinese.
|
|
|
|
| Topic | Document |
|
|
|---|---|
|
|
| Implementation and the full feature list | [docs/features.md](docs/features.md) |
|
|
| Configuration: `config.yaml`, model discovery, multiple keys | [docs/configuration.md](docs/configuration.md) |
|
|
| Routing: model routing, AUTO chain, cooldown, sources vs adapters, source templates | [docs/routing.md](docs/routing.md) |
|
|
| Adapters: Lua protocol and built-in adapters | [docs/adapters.md](docs/adapters.md) · [docs/lua-adapters-en.md](docs/lua-adapters-en.md) (English) |
|
|
| Plugins: SDK contract, hooks, UI extensions, HTTP endpoints | [docs/plugins.md](docs/plugins.md) |
|
|
| Desktop app: Headless / Desktop artifacts, build and run | [docs/gui.md](docs/gui.md) |
|
|
| Performance: measured memory use, tuning, thinking budget | [docs/performance.md](docs/performance.md) |
|
|
| WebUI usage | [docs/webui.md](docs/webui.md) |
|
|
| Development: layout, tests, branch and release discipline | [docs/development.md](docs/development.md) · [docs/git-workflow-en.md](docs/git-workflow-en.md) (English) |
|
|
| Deployment and migration | [docs/deployment.md](docs/deployment.md) |
|
|
|
|
## Renamed from llmsproxy
|
|
|
|
The product name has been ModelRouter for a while; the binary, config directory,
|
|
service name and environment variables are now `modelrouter` as well:
|
|
|
|
| Before | After |
|
|
|---|---|
|
|
| `llmsproxy` (binary) | `modelrouter` |
|
|
| `/etc/llmsproxy/` | `/etc/modelrouter/` |
|
|
| `llmsproxy.service` | `modelrouter.service` |
|
|
| `LLMSPROXY_*` | `MODELROUTER_*` |
|
|
|
|
Existing installs migrate with a dry-run-by-default script (copies, never moves,
|
|
and can roll back):
|
|
|
|
```bash
|
|
sudo ./packaging/migrate-to-modelrouter.sh # preview
|
|
sudo ./packaging/migrate-to-modelrouter.sh --apply # apply
|
|
sudo ./packaging/migrate-to-modelrouter.sh --rollback --apply
|
|
```
|
|
|
|
Old paths and old environment variable names are still accepted on the read side,
|
|
so an upgrade cannot fail merely because of ordering. `deploy.sh` refuses to run
|
|
when it finds the old `/etc/llmsproxy` without a new config, because that would
|
|
deploy a gateway with no key and no sources.
|
|
|
|
The plugin SDK follows the same naming: the only public entry point is
|
|
`modelrouter` (`llmsproxy` remains a compatibility alias). See
|
|
[docs/plugins.md](docs/plugins.md).
|
|
|
|
## Layout
|
|
|
|
```text
|
|
cmd/modelrouter # entry point (pure Go server)
|
|
cmd/gui # Electron desktop shell (embeds the same core)
|
|
internal/config # config parsing, sealed storage, runtime file
|
|
internal/core # scheduling, kernel actions, state and audit
|
|
internal/lua # LuaJIT VM + elastic worker pool + built-in adapters (embed)
|
|
internal/lua/plugins # optional plugin examples (not shipped in binary/archives)
|
|
internal/provider # Provider(HTTP) + Registry(routing)
|
|
internal/gateway # OpenAI-compatible HTTP service + auth + streaming + WebUI
|
|
internal/types # unified format and OpenAI wire types
|
|
packaging/ # deb/rpm/tar packaging, systemd unit, migration script
|
|
docs/ # topic documentation
|
|
```
|
|
|
|
## Development and tests
|
|
|
|
```bash
|
|
go test -tags luajit ./... # everything
|
|
go test -tags luajit ./internal/lua # one package (required for LuaJIT changes)
|
|
```
|
|
|
|
- Branch and release discipline: [docs/git-workflow-en.md](docs/git-workflow-en.md).
|
|
- Plugins live in `plugin_dir`. The gateway never creates, overwrites or deletes
|
|
plugin files, and a desktop upgrade never touches them either.
|