从 0 部署一个多模型 AI 网关:Docker、渠道、令牌与模型映射
本文以 OpenStarry(基于 New API 的二次开发版本)为例。不同版本的界面文案可能略有差异,但核心链路一致:客户端 → 网关 → 渠道 → 上游模型。
先说结论
多模型接入真正难的不是“把 Key 填进去”,而是把下面三件事同时做对:
- 客户端只认一个 Base URL;
- 网关知道每个请求该走哪条渠道;
- 模型名、令牌分组和上游模型 ID 能对上。
这篇不追求一次接 20 个模型。目标只有一个:先用最小配置跑通 1 个模型,再复制这套方法批量接渠道。
一、为什么不是多填几个 Key
早期最直接的做法,是在每个项目里分别配置不同供应商的 Key:
项目 A -> OpenAI SDK -> 供应商 1
项目 B -> OpenAI SDK -> 供应商 2
项目 C -> 另一套 SDK -> 供应商 3
短期能跑,项目一多就会出现四个问题:
- Key 散落在不同项目和环境变量里;
- 每个项目都要单独改模型名和请求地址;
- 无法按项目统计额度和成本;
- 某个渠道不稳定时,只能手工改配置。
AI 网关的价值,是把这些差异收口到一层:
项目 A ─┐
项目 B ─┼─> AI 网关 ─> 渠道 1 / 2 / 3 ─> 上游模型
项目 C ─┘
客户端仍然使用 OpenAI 兼容接口,只把 Base URL 和令牌换成网关的。至于后面是 Qwen、DeepSeek、Kimi、GLM 还是 MiniMax,由网关决定。
二、部署目标与非目标
这次部署的目标:
- 单机 Docker 可运行;
- 支持 OpenAI 兼容请求;
- 能配置多个上游渠道;
- 能按项目发令牌、看额度;
- 支持模型名映射和失败重试。
这次不追求:
- 一上来就做高可用集群;
- 直接对外提供生成式 AI 服务;
- 把支付、告警、审计全部配完。
如果用于组织内部或自用场景,建议先跑通链路。对外提供生成式 AI 服务时,需要自行完成备案、内容安全、实名、日志留存、税务和上游授权等合规义务。
三、环境准备
最低建议:
| 项目 | 建议 |
|---|---|
| 系统 | Linux x86_64 |
| Docker | 24+ |
| Docker Compose | v2 |
| 内存 | 2 GB 起步,4 GB 更稳 |
| 磁盘 | 20 GB 起步 |
| 端口 | 3000 |
先确认环境:
docker --version
docker compose version
四、第一步:启动最小服务
第一次部署不建议直接上完整生产 Compose。仓库里的完整编排通常还会带 MySQL、Redis、告警和支付服务,变量没填全,容易卡在启动阶段。
先做一个最小启动文件 compose.first-run.yml:
services:
new-api:
image: openstarry/api:local
container_name: openstarry
restart: unless-stopped
ports:
- "3000:3000"
environment:
TZ: Asia/Shanghai
volumes:
- ./data:/data
如果你已经有镜像,直接替换 image。没有镜像就先在项目根目录构建:
git clone https://gitee.com/wlkj/openstarry.git
cd openstarry
docker build -t openstarry/api:local .
启动:
docker compose -f compose.first-run.yml up -d
docker compose -f compose.first-run.yml ps
docker compose -f compose.first-run.yml logs -f new-api
检查服务是否正常:
curl -sS http://127.0.0.1:3000/api/status
浏览器打开:
http://<服务器IP>:3000
首次访问会进入初始化页面。管理员用户名最长 12 个字符,密码至少 8 位。内部自用场景可以开启自用模式,减少不必要的注册和支付入口。
SQLite 适合第一次验证链路。正式环境建议直接用 MySQL 或 PostgreSQL,并配上 Redis,避免后期再做数据迁移。
五、第二步:配置第一个渠道
进入后台后,先只加一个渠道,不要批量导入。
以 OpenAI 兼容渠道为例,重点填这几项:
| 配置 | 说明 |
|---|---|
| 渠道类型 | 优先选供应商对应的类型;没有就选 OpenAI 兼容 |
| Base URL | 供应商的 API 地址,注意是否已经包含 /v1 |
| Key | 供应商控制台创建的 API Key |
| 模型列表 | 客户端要调用的模型名 |
| 模型重定向 | 把请求名映射到上游真实模型 ID |
| 分组 | 先保持 default |
| 优先级 / 权重 | 第一次部署先不配 |
这里最容易混的是三个“名字”:
渠道名称 -> 后台管理用的标签,不参与请求
模型列表 -> 客户端请求时传的 model
上游模型 ID -> 供应商真正接受的 model
如果客户端传的模型名和上游完全一致,模型重定向可以留空。
如果不一致,用 JSON 做映射:
{
"team-qwen": "qwen-plus-2025-xx"
}
含义是:
客户端请求 model=team-qwen
↓
网关查 model_mapping
↓
向上游发送 model=qwen-plus-2025-xx
左边的 team-qwen 是对外名字,右边的值必须以供应商文档为准。不要凭感觉补版本后缀。
配置完成后,先在渠道列表里点一次测试。测试不通过,不要继续创建令牌。
六、第三步:创建令牌
进入令牌管理,新建一个测试令牌。
重点看四项:
- 分组:必须和渠道分组一致,默认都用
default; - 额度:先设一个小额度,避免测试时消耗过多;
- 可用模型:如果开启限制,填对外模型名,例如
team-qwen,不要填上游 ID; - IP 白名单:测试阶段可以先不填,生产环境建议加上。
创建后复制一次令牌,格式通常是:
sk-xxxxxxxxxxxxxxxx
令牌只展示一次,保存到测试环境的变量里,不要提交到 Git。
七、第四步:发第一次请求
先测非流式:
export BASE_URL="http://127.0.0.1:3000"
export OPENSTARRY_KEY="sk-你的测试令牌"
curl -sS "$BASE_URL/v1/chat/completions" \
-H "Authorization: Bearer $OPENSTARRY_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "team-qwen",
"messages": [
{"role": "user", "content": "用一句话解释什么是 AI 网关"}
],
"stream": false
}'
正常返回会包含:
choices:模型输出;usage:输入、输出和总 token;model:本次请求使用的模型信息。
再测流式:
curl -N "$BASE_URL/v1/chat/completions" \
-H "Authorization: Bearer $OPENSTARRY_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "team-qwen",
"messages": [
{"role": "user", "content": "写一个 5 行的 shell 脚本"}
],
"stream": true
}'
最后去后台看三处:
- 请求日志里有没有这次调用;
- 令牌额度有没有减少;
- 渠道用量有没有记录。
这三处都对上,才算真正跑通。
八、常见错误怎么判断
不要只看 HTTP 状态码,先看响应体里的 error.code 和 error.message。
| 现象 | 常见原因 | 先查 |
|---|---|---|
| 401 | 令牌错误、被禁用或没带 Bearer | Authorization 头 |
404 model_not_found | 模型不在渠道列表,或映射缺失 | 渠道模型列表、model_mapping |
503 model_not_found | 当前分组没有可用渠道 | 令牌分组、渠道分组、渠道状态 |
| 429 | 限流或额度不足 | 令牌额度、渠道限流 |
| 请求超时 | 流式超时或上游响应慢 | STREAMING_TIMEOUT、上游日志 |
这里有一个容易误判的点:
模型不存在 -> 可能返回 404
当前分组没有可用渠道 -> 也可能带 model_not_found,但状态码是 503
所以排查顺序应该是:
先看完整响应体
再确认客户端传的 model
再对照渠道模型列表和映射
最后检查令牌分组与渠道分组
一次只改一个变量。一次改五项,即使恢复了,也不知道是哪一项修好的。
九、生产环境还要补什么
最小链路跑通后,再补这些:
1. 数据库和缓存
- SQLite 换成 MySQL 或 PostgreSQL;
- 配置 Redis;
SESSION_SECRET和CRYPTO_SECRET必须长期稳定;- 修改
CRYPTO_SECRET可能导致已加密配置无法解密。
2. 网络安全
- 只暴露 3000 端口给反向代理;
- 不要把 3306、6379 直接暴露到公网;
- 用 Nginx 或 Caddy 做 HTTPS;
- 管理后台限制来源 IP。
3. 镜像和升级
- 生产不要使用
latest; - 固定镜像 tag;
- 升级前备份数据库;
- 先看发布说明,再执行迁移;
- 不要直接
git pull && docker compose up --build。
4. 日志和成本
- 打开请求日志;
- 按项目、令牌、模型看用量;
- 给令牌设置额度;
- 定期检查异常渠道和重试次数。
5. 合规
- 遵守上游服务条款;
- 不把未授权的账号或额度对外转售;
- 对外提供生成式 AI 服务时,完成相应备案和内容安全义务;
- 注意项目 AGPLv3 许可证的使用边界。
十、最后
这套部署最重要的不是“接了多少个模型”,而是形成一条可重复的路径:
启动服务
-> 接 1 个渠道
-> 对齐 1 个模型名
-> 发 1 个令牌
-> 跑通 1 次请求
-> 看日志和额度
-> 再复制到第 2 个、第 3 个模型
先把一个模型跑通,比一次导入 20 个渠道更省时间。
下一篇我会写:模型映射为什么总是 404,以及三个名字到底怎么对齐。
访问地址:<OpenStarry — 注册即赠200次免费调用 | 国产大模型 API 聚合中转 · GLM · DeepSeek · Kimi>
我是小雨,记录 AI 中台、多模型接入和真实踩坑。