一个 OpenAI 兼容的 LLM 网关 + 智能路由:请求进来先由 Jev 决策模型判定任务类型与复杂度, 再转发到「最合适且最便宜」的下游大模型 —— 判定发生在首个 token 之前,全程可观测、可降级、可对账。
简体中文 | English
是:一个站在你的应用与各大模型厂商之间的转发与决策层。业务侧只认一个 OpenAI 兼容端点, 由网关决定这次请求该走哪个模型、失败了怎么退、花了多少钱。
不是:不是一个 Agent 框架,也不替调用方执行工具。
tools 字段会原样转发给下游,上游返回的 tool_calls 也原样回给调用方
(标准 OpenAI 语义,见下方「工具调用边界」)。网关只做转发与路由,不做编排。
「这次该用哪个模型」不是靠关键词表拍脑袋,也不是让一个大模型写段 JSON 再解析 —— 而是交给一个专门做判定的决策模型:Jev。 判定结果不是文本,是带校准概率的类型化值。这是本项目与同类网关最大的区别。
Jev 是 TypeSafe AI(旧金山;创始人 Diogo Almeida,前 OpenAI, 参与过 ChatGPT / RLHF 相关工作)于 2026-09-15 发布的 System One 决策模型。 它与「生成式大模型」是互补关系,而不是一个更小号的替代品:
| 常见做法:拿大模型当裁判 | Jev(本项目所用) | |
|---|---|---|
| 工作方式 | 自回归逐 token 生成,再解析 JSON | 非自回归:一次前向直接给出判定,不生成任何文本 |
| 输出 | 一段文字 + 需要二次校验/重试的 JSON | 类型化判定(选项必然落在给定枚举内)+ 校准过的概率 |
| 延迟 | 秒级(前沿模型 3~329s 量级) | 官方 70~500ms;本项目实测单次 0.4~1.2s(含跨网往返) |
| 置信度可信度 | 编出来的,只能当噪声 | 经 RLCD 训练校准:说 0.9 就真有约 90% 兑现 → 阈值才真正可用 |
| 可解释性 | 会附一段自然语言理由 | 不写理由(这是换来速度与成本所付的代价) |
| 出错方式 | 可能吐出枚举外的值或格式坏掉 | 类型层面不可能出错,但选项本身仍可能选错 |
计费口径:输入 $0.042 / 百万 token,输出 token 免费。
| 原语 | 回答什么 | 返回什么 | 本项目用它判定 |
|---|---|---|---|
| Choice | 从固定选项里选一个 | choice + probabilities + confidence |
task_type —— 6 类任务之一 |
| Score | 按 rubric 打分 | score + probabilities |
complexity —— 简单 / 中等 / 复杂 |
| Noul | 是 / 否 | noul(0~1 概率) |
has_code、is_sensitive |
一次调用、并行问 4 个原子问题(下为 app/deciders/jev_decider.py 发出的真实请求体):
| 层 | 技术 |
|---|---|
| 后端 | Python 3.11+(开发机 3.13)/ FastAPI / Uvicorn / SQLAlchemy 2.x(async) |
| 数据库 | PostgreSQL 14+(主,驱动 psycopg3);SQLite(零依赖兜底,无需任何外部服务) |
| 缓存 / 限流 | Redis 7+(可选;缺失时自动降级,不影响功能) |
| 前端 | Vue 3.4 + Vite 5 + TypeScript 5.4 + Element Plus 2.6 + Pinia 2.1 + Vue Router 4 |
| 路由内核 | 自研三层判定(L1 规则 / L2 Jev 判定器 / L3 兜底),实现全局唯一一份 |
| 加密 | AES-256-GCM(厂商密钥)+ JWT(控制台会话) |
| Web 服务器 | Nginx(Docker Compose 形态内置;裸机形态由安装脚本自动安装并配置) |
| 部署 | systemd(脚本安装)· Docker Compose(云端直拉)· Apple container(macOS)· 源码 |
- 默认口令
admin / admin123必须在首次登录后立即修改。 ENCRYPTION_MASTER_KEY必须备份。 厂商 API Key 用它加密落库, 一旦丢失,所有已录入的密钥永久无法解密(只能逐个重新填)。该值严禁提交 git。- 生产环境必须启用 HTTPS,并保持
.env的ALLOW_LOCAL_BASE_URL=false(该开关允许厂商base_url指向http://与私网地址,是 SSRF 风险面,仅开发机可开)。 - 模型池初始是空的,这是有意设计。 首次安装只预置接入商(13 家 / 24 条通道), 不预置模型 —— 你能用哪些 Model ID、什么价,取决于你的账号,网关不替你猜。 必须先在「模型池」页添加至少一个模型,并给通道填 Key,路由候选池才非空。
- 订阅类通道的单价是「参照值」,按套餐额度折算,不是真实边际成本; 条款限制(如「仅限编程工具交互式使用」)随通道原文落库并在控制台警示。
- 请只接入你有权使用的上游服务,并自行确认符合各厂商服务条款与适用法律。
四种方式,按你的环境挑一种:
| 方式 | 适用场景 | 前置依赖 | 一句话 |
|---|---|---|---|
| 方式一 · 脚本安装(推荐) | Linux 服务器生产部署 | Linux + Python 3.11+ | 一条 curl 装完 |
| 方式二 · Docker Compose(推荐) | 任意平台生产部署、交付给客户、省去环境折腾 | Docker + Compose v2,能访问容器库 | 生成配置 + docker compose up -d |
| 方式三 · Apple container | Apple Silicon Mac 本地开发 / 试用 | macOS 26+ + container 1.1.0+ |
三个子命令 |
| 方式四 · 源码编译 | 二次开发、离线交付、定制 | Python 3.11+ / Node.js 20+ | 见下文 |
完整步骤与验收记录另见
docs/阶段五-部署与交付/05-安装打包说明.md。
面向 Linux 裸机(systemd)。脚本自动完成:拉取源码 → 建运行用户 → 建虚拟环境 →
装依赖 → 生成 .env(随机密钥)→ 初始化数据 → 自动安装 Node.js 并构建控制台前端 →
注册并启动 systemd 服务 → 自动安装并配置 Nginx(写站点配置、放行 SELinux 与防火墙)→
打印控制台地址。
也就是说:装完就能用,不需要你再手工敲任何命令 —— 结束时直接给出
控制台地址 http://<服务器IP>/,浏览器打开即是后台管理界面。
- Linux(systemd 发行版;无 systemd 会提示改用
--no-service) - Python 3.11+(脚本会检测;不满足时给出各发行版的安装命令)
- Node.js —— 无需预装:脚本先试发行版仓库,版本不够就下载官方预编译包
(先官方源、不通再走国内镜像),装进
/usr/local/lib/nodejs并软链到/usr/local/bin, 不动系统包管理已有的文件。要自己管 Node 就用--no-node-install - Nginx —— 无需预装:脚本会用系统包管理器自动装好并配置
(
apt/dnf/yum/zypper/apk)。若你想用自己的 web 服务器,加--no-nginx跳过
curl -sSL https://raw.githubusercontent.com/dragonlin-ai/llmbridge/main/deploy/install.sh | sudo bash已 clone 仓库时,直接用本地源码(不联网下载):
sudo bash deploy/install.sh常用选项:
sudo bash deploy/install.sh --port 9000 # 后端改监听 9000
sudo bash deploy/install.sh --dir /srv/llmbridge # 换安装目录(默认 /opt/llmbridge)
sudo bash deploy/install.sh --postgres "postgresql+psycopg://user:pass@127.0.0.1:5432/llmbridge"
sudo bash deploy/install.sh --nginx-port 8080 # 控制台对外端口(默认 8081)
sudo bash deploy/install.sh --no-nginx # 不自动装/配 Nginx(改用你已有的 web 服务器)
sudo bash deploy/install.sh --no-node-install # 不自动装 Node.js(用机器上已有的)
sudo bash deploy/install.sh --node-version v22.14.0 # 指定要装的 Node.js 版本
sudo bash deploy/install.sh --npm-registry https://registry.npmmirror.com # 固定 npm 源
sudo bash deploy/install.sh --with-models # 额外灌入目录里的参考模型与参考单价
sudo bash deploy/install.sh --skip-frontend # 不构建前端(自备 dist 时)
sudo bash deploy/install.sh --frontend-only # 只补前端构建(顺带把 Node.js / Nginx 补齐)
sudo bash deploy/install.sh --no-service # 只铺代码与虚拟环境,不注册 systemd
sudo bash deploy/install.sh --help数据库默认策略:探测本机
5432。通则按 PostgreSQL 配置;不通则退到 SQLite (<安装目录>/llmbridge.db),保证「装完就能打开界面」。 生产建议显式用--postgres指定,或装好后改.env的DATABASE_URL再重启。
后端只提供 /v1 与 /admin 两套接口,不托管前端静态文件;控制台是需要 web 服务器
托管的独立 SPA。这些步骤脚本已经替你做完,结束时直接打印地址:
安装完成
控制台地址 http://<服务器IP>/ ← 浏览器打开即后台管理界面
默认账号 admin / admin123(首次登录后请立即修改密码)
配置 Nginx 时脚本顺带处理了三件最容易卡住的事,无需你手工做:
- 没装 Nginx → 自动用系统包管理器安装;
- 发行版自带默认站点占着 80 的
default_server→ 自动移走让位, 否则访问到的是 Nginx 欢迎页、反代完全没走; - SELinux / 防火墙拦截 → 自动
setsebool -P httpd_can_network_connect 1并放行端口 (RHEL / CentOS 上不做这一步就是一律 502)。
若服务器在云厂商安全组后面,仍需在云控制台放行该端口 —— 这一步在机器内做不到。
用 Caddy 等其它 web 服务器(或加
--no-nginx跳过自动配置)时,只需满足两点: 静态托管<安装目录>/admin-web/dist并对未命中路径回落index.html; 把/v1/、/admin/、/health反代到127.0.0.1:<port>。 站点配置模板见deploy/nginx-standalone.conf(__API_PORT__/__LISTEN_PORT__/__DIST_DIR__)。
重复执行同一条安装命令即可 —— 代码更新,.env、数据库、已录入的密钥一律不动:
curl -sSL https://raw.githubusercontent.com/dragonlin-ai/llmbridge/main/deploy/install.sh | sudo bash若上次卡在「前端没构建 / Nginx 没配好」,这条命令会把两件事一次补齐(不动其它任何东西):
sudo bash /opt/llmbridge/deploy/install.sh --frontend-onlysudo bash /opt/llmbridge/deploy/install.sh --uninstall # 停服务、移除单元,保留数据目录
sudo bash /opt/llmbridge/deploy/install.sh --purge -y # 连同安装目录与数据一起删除systemctl status llmbridge # 状态
systemctl restart llmbridge # 重启(改 .env 后必须重启才生效)
journalctl -u llmbridge -f # 实时日志
/opt/llmbridge/.venv/bin/llmbridge-seed # 手工执行初始化(幂等)
/opt/llmbridge/.venv/bin/llmbridge-catalog --dry-run # 查看厂商目录预置结果,不写库前置条件:Docker 20.10+(含 docker compose v2)、能访问容器库。
不需要源码、不需要 Node.js。
快速开始:
# 1. 创建部署目录
mkdir -p llmbridge && cd llmbridge
# 2. 下载并运行准备脚本(只生成 ./docker-compose.yml + ./.env,不碰 Docker)
curl -sSL https://raw.githubusercontent.com/dragonlin-ai/llmbridge/main/deploy/docker-deploy.sh | bash
# 3. 启动服务(首次自动拉取镜像)
docker compose up -d
# 4. 查看日志
docker compose logs -f api第 2 步访问不了 GitHub(国内常见)时,换这条等价命令从容器库镜像取脚本,效果完全相同:
docker run --rm --entrypoint cat registry.cn-hangzhou.aliyuncs.com/winyeahs/llmbridge-api:1.0.0 \ /opt/llmbridge/deploy/docker-deploy.sh | bash -s --
装完浏览器打开 http://<服务器IP>:8081/,用 admin / admin123 登录(首次登录后立即改密)。
之后启停全部用标准 compose 命令(同一目录下执行):
docker compose ps # 状态 + 健康检查
docker compose logs -f web # 看某个服务的日志
docker compose down # 停止(数据卷保留)
docker compose up -d # 再次启动
- 换端口 / 换镜像版本:编辑
./.env的HTTP_PORT/LLMBRIDGE_TAG,再docker compose up -d。- 让脚本连启动一起做完(生成配置 + 拉镜像 + 起容器 + 等健康检查):第 2 步末尾加
deploy。- 换镜像库:生成时追加
--registry <host>/<命名空间>;私有库再给REGISTRY_USER/REGISTRY_PASSWORD(拉取前自动登录,凭据不落盘)。- 升级回滚、数据迁移、常见问题、发布镜像,以及「本地有源码要自己改再构建」, 见
05-安装打包说明.md§6.1 与01-部署文档.md。
Apple Silicon Mac 在 macOS 26 上可用 Apple 原生 container(1.1.0+)跑起完整网关。
本方式定位是本地开发与人工运维,生产部署请用方式一或方式二。
- Apple Silicon Mac + macOS 26 或更高
- Apple
container1.1.0+:brew install container(或从 apple/container releases 下载) - 首次使用先执行一次
container system start(脚本也会自动尝试拉起)
git clone https://github.com/dragonlin-ai/llmbridge.git
cd llmbridge
./deploy/apple-container.sh init # 检查环境 + 生成密钥 + 构建镜像
./deploy/apple-container.sh up # 启动容器并等待 /health 就绪
./deploy/apple-container.sh status # 查看容器、镜像与健康状态之后打开 http://127.0.0.1:8000/,默认账号 admin / admin123。
默认形态是单容器 + SQLite,数据落在宿主机 ./llmbridge-data/(可删除容器而不丢数据)。
之所以不做「PostgreSQL + Redis + 应用」多容器编排:Apple container 是逐容器手工编排的
(没有 compose 那样的依赖顺序与健康检查等待),让它管三层服务就得自己写启动时序轮询,
脆弱且难排障 —— 需要完整形态时请用方式二。
./deploy/apple-container.sh logs # 跟随日志
./deploy/apple-container.sh shell # 进容器
./deploy/apple-container.sh restart
./deploy/apple-container.sh upgrade # 拉代码 + 重建镜像 + 重启(数据保留)
./deploy/apple-container.sh down # 停并删除容器(保留数据目录)
./deploy/apple-container.sh purge # 连数据目录一起删(不可恢复)可调环境变量:
LLMBRIDGE_PORT=9000 ./deploy/apple-container.sh up # 宿主机端口
LLMBRIDGE_BIND=0.0.0.0 ./deploy/apple-container.sh up # 对外暴露(请自备反代与 HTTPS)
LLMBRIDGE_DATA_DIR=/path ./deploy/apple-container.sh up先起一个 PG 容器(或用远程 PG),再把连接串写进配置文件并重启:
vim ./llmbridge-data/.env # 改 DATABASE_URL=postgresql+psycopg://user:pass@host:5432/llmbridge
./deploy/apple-container.sh restart注意:不要写
postgresql+asyncpg://—— asyncpg 不在依赖里,会在真正建连时才报错。
适合二次开发、定制,或需要产出离线发行包的场景。
| 组件 | 版本 |
|---|---|
| Python | 3.11+ |
| Node.js | 20+(仅控制台前端需要;脚本安装形态会自动装) |
| PostgreSQL | 14+(不装则自动回退 SQLite) |
| Redis | 7+(可选) |
# 1) 获取代码
git clone https://github.com/dragonlin-ai/llmbridge.git
cd llmbridge
# 2) 建虚拟环境并可编辑安装(改代码免重装)
python -m venv .venv
.venv/Scripts/python.exe -m pip install -e ".[dev]" # Windows
# source .venv/bin/activate && pip install -e ".[dev]" # Linux / macOS
# 3) 配置
cp .env.example .env
# 生产必改:JWT_SECRET、ENCRYPTION_MASTER_KEY、DATABASE_URL 里的密码
# 4) 启动(首次启动自动建表 / 默认管理员 / 预置接入商,幂等)
llmbridge-serve --host 127.0.0.1 --port 8000验证后端:
curl -f http://127.0.0.1:8000/health
# {"status":"ok"}
curl http://127.0.0.1:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model":"auto","messages":[{"role":"user","content":"用一句话解释什么是量子纠缠"}]}'构建并运行控制台:
cd admin-web
npm ci
npm run dev -- --host 127.0.0.1 # 开发模式,热更新:http://127.0.0.1:5173
npm run build # 生产产物:admin-web/distWindows + PostgreSQL 必读:
uvicorn app.main:app直接启动会连不上数据库。 uvicorn 默认的 loop 工厂返回ProactorEventLoop,而 psycopg3 主动拒绝它 —— 症状是「服务起来了、/health也是 200,但一访问数据库就 500」。 用llmbridge-serve即可,它内置了正确的SelectorEventLoop; 若坚持用裸 uvicorn,必须带--loop app.core.eventloop:selector_loop_factory。
# 后端(热重载)
llmbridge-serve --host 127.0.0.1 --port 8000 --reload
# 控制台(热重载,vite 代理 /admin 与 /v1 到 8000)
cd admin-web && npm run dev -- --host 127.0.0.1
# 测试
pytestWindows 本机也可用现成脚本:
.\deploy\windows\start-backend.ps1 # 只起后端
.\deploy\windows\start-dev.ps1 # 后端 + 控制台前端python -m build # 标准 wheel / sdist → dist/
python scripts/build_release.py # 项目自带:组装可离线交付的 zipbuild_release.py 产出 release/llmbridge-<版本>-<日期>.zip,内含后端代码、
数据库脚本、部署编排、前端静态产物,以及 BUILD-INFO.txt 与 SHA256SUMS.txt
(完整性清单)。常用选项:
python scripts/build_release.py --skip-frontend # 前端已构建,跳过 npm
python scripts/build_release.py --no-archive # 只组装目录,不压 zip全部配置走环境变量,模板见 .env.example。最关键的几项:
| 变量 | 默认 | 说明 |
|---|---|---|
DATABASE_URL |
sqlite:///./llmbridge.db |
PostgreSQL 用 postgresql+psycopg://…(勿写 asyncpg);生产必改 |
POSTGRES_PASSWORD |
change-me |
仅 Docker Compose 形态使用(注入 db 与 api 容器) |
HTTP_PORT |
8081 |
仅 Docker Compose 形态:控制台对外端口 |
AUTO_BOOTSTRAP |
true |
启动时自动建表 / 建管理员 / 预置接入商,幂等。生产由 DBA 管库时可设 false |
JWT_SECRET |
dev-only-change-me |
生产必改。控制台会话签名密钥 |
ENCRYPTION_MASTER_KEY |
dev-only-change-me… |
生产必改。厂商 Key 的 AES-256-GCM 主密钥,丢失不可恢复 |
ALLOW_LOCAL_BASE_URL |
false |
是否允许厂商 base_url 用 http:// 与私网地址。生产必须 false |
REDIS_URL |
空 | 留空则不启用缓存 / 限流(自动降级) |
JUDGE_PROVIDER |
mock |
判定器选择:mock = 内置无依赖判定(离线可用);jev = Jev 决策模型(TypeSafe AI 官方 API)。详见 决策内核:Jev |
JEV_API_KEY |
空 | Jev 的 API Key。judge_provider=jev 时必填;为空会静默退回 mock(看板会提示不一致) |
JEV_BASE_URL |
https://api.typesafe.ai/v1/systemone |
Jev 端点。 |
DECIDER_TIMEOUT_MS |
3000 |
判定器独立超时。实测单次 0.4~1.2s,3000ms 够用 |
ROUTE_CONFIDENCE_THRESHOLD_T2 |
0.5 |
L2 置信度阈值,低于此值走 L3 兜底 |
DEFAULT_MODEL_ID |
1 |
全部候选失败时的最终兜底模型 id。必须指向模型池里真实存在的 id |
ENABLE_TOOL_EXECUTION |
false |
见「工具调用边界」 |
REQUEST_TIMEOUT_MS |
30000 |
上游调用超时 |
| 命令 | 作用 |
|---|---|
llmbridge-serve [--host] [--port] [--workers] [--reload] |
启动网关。内置 psycopg3 兼容的事件循环,跨平台都是这一条。启动时自动完成首次引导(建表 / 默认管理员 / 内置评测样本 / 厂商接入目录),全部幂等 |
llmbridge-seed [--force] |
手工执行同一套引导。幂等;已就绪时全部跳过。生产用 AUTO_BOOTSTRAP=false 关掉自动引导后,由运维显式跑这一条 |
llmbridge-catalog [--with-models] [--dry-run] [--overwrite] [--keep-names] [--prune-orphans] [--report PATH] |
预置厂商接入目录。幂等,三级匹配认领旧行、不动已录密钥。默认只铺接入通道 |
源码内的运维脚本:
python scripts/seed_provider_catalog.py --dry-run # 同上(薄壳,逻辑在 app/data/catalog_seed.py)
python scripts/migrate_sqlite_to_pg.py # SQLite → PostgreSQL 数据搬迁
python scripts/migrate_add_provider_channels.py # 历史库补通道字段
python scripts/build_release.py # 打离线发行包
python scripts/verify_registry.py --tag 1.0.0 # 核验容器库上真有这个标签(不采信 push 退出码)
python scripts/verify_deploy.py --port 8099 # 装完做**功能性**核验(控制台/登录/读库/引导)
python scripts/check_compose_sync.py # 校验内嵌编排副本与真源一致(发布前自查)对外(/v1,OpenAI 兼容):
| 方法 | 路径 | 说明 |
|---|---|---|
POST |
/v1/chat/completions |
唯一对外端点。model 传 auto 走智能路由,传具体模型名则短路直达 |
对内(/admin,需 JWT)共 24 条路径 / 35 个操作,覆盖:
/admin/auth/login /admin/providers[/{id}][/test]
/admin/models[/{id}][/references] /admin/rules[/{id}][/priorities]
/admin/logs[/{trace_id}] /admin/samples
/admin/api-keys[/{id}] /admin/options
/admin/stats/overview /admin/usage/report
/admin/route/preview /admin/eval/report
/admin/decider/settings[/test]
响应元信息头(x-router-*,恒返回前 4 项):
| 头 | 恒返回 | 说明 |
|---|---|---|
x-router-trace-id |
✅ | 调用链唯一标识,与日志页、库内 request_log 对应 |
x-router-layer |
✅ | 命中层级 L1 / L2 / L3 |
x-router-model |
✅ | 实际服务的模型名(与决策值区分,降级后以后者为准) |
x-router-confidence |
✅ | 置信度;L1 恒 1.0,L3 按兜底口径 |
x-router-task-type |
仅 L2 | 任务类型;L1 短路与「显式指定模型」都不经判定器 |
x-router-tools |
仅执行过工具 | 工具执行轮数(ENABLE_TOOL_EXECUTION=true 时) |
网关默认纯透传(ENABLE_TOOL_EXECUTION=false):
- 请求里的
tools/tool_choice原样转发给下游; - 上游返回的正文与原生
tool_calls、SSE 字节一个字节都不改写; - 工具由调用方执行 —— 这是标准 OpenAI 语义,也是推荐用法。
若把 ENABLE_TOOL_EXECUTION 置 true,网关会自己执行白名单内的 WebFetch
(含 SSRF 拦截,私网/环回/链路本地地址一律拒绝)并续写多轮。
仅适用于调用方完全没有工具循环的场景 —— 打开后网关会吞掉中间轮并改写正文,
使得「模型只说了一句话」与「工具没执行」在现象上无法区分。
llmbridge/
├── app/ 后端(FastAPI)
│ ├── api/v1/ 对外入口:OpenAI 兼容 + SSE
│ ├── api/admin/ 对内入口:控制台全部接口
│ ├── router_engine/ 路由内核(L1/L2/L3 判定编排,全局唯一一份)
│ ├── deciders/ 判定器实现(mock / Jev)
│ ├── adapters/ 下游协议适配(差异只允许出现在这里)
│ ├── services/ 密钥、计费、日志缓冲、配额缓存、库级配置、工具、启动引导
│ ├── data/provider_catalog.py 内置厂商目录常量(只读)
│ ├── data/catalog_seed.py 厂商目录预置实现(包内,命令行与启动引导共用)
│ ├── db/ ORM 表定义与会话
│ ├── core/ 配置、加解密、安全、事件循环
│ └── cli.py 命令行入口
├── admin-web/ 控制台前端(Vue 3 + Vite + Element Plus)
├── scripts/ 幂等运维脚本(预置目录 / 历史库迁移 / 发行打包 / 交付核验)
├── deploy/ 部署产物
│ ├── install.sh ★ 方式一:Linux 一键安装(systemd)
│ ├── docker-deploy.sh ★ 方式二:Docker Compose 部署(默认只生成配置,启停用标准 docker compose)
│ ├── publish-image.sh ★ 容器库形态的发布侧:构建并推送 api + web + deploy 三个镜像
│ ├── apple-container.sh ★ 方式三:macOS Apple container
│ ├── Dockerfile 后端镜像
│ ├── Dockerfile.web 前端镜像(nginx + 内置 dist 与 nginx.conf)
│ ├── Dockerfile.deploy 安装器镜像(只打印 docker-deploy.sh,约 8 MB)
│ ├── docker-compose.yml 编排(api / db / redis / nginx)· 源码形态
│ ├── docker-compose.image.yml 编排(api / db / redis / web)· 容器库形态,无 build 段
│ ├── nginx.conf Compose 形态的反向代理(SSE 关键配置;web 镜像内置此文件)
│ ├── nginx-standalone.conf 裸机形态的站点配置模板
│ ├── entrypoint.sh 容器入口:先初始化再启动
│ ├── healthcheck.py 探活(仅标准库)
│ ├── linux/ systemd 单元
│ └── windows/ 本机启动脚本
├── docs/ 全阶段交付文档(需求 → 设计 → 开发 → 测试 → 部署)
├── tests/ 自动化测试
├── .env.example 环境变量模板
├── MANIFEST.in sdist 内容清单
└── pyproject.toml 构建配置与依赖
| 文档 | 内容 |
|---|---|
docs/README.md |
项目总纲(当前基线),架构、接口、约定、验收一次性看全 |
docs/阶段一-需求与规划/ |
需求规格、UI 设计、项目计划、验收标准、风险清单 |
docs/阶段二-设计与架构/ |
架构设计、接口设计、数据库设计、安全方案 |
docs/阶段三-开发与实现/ |
技术实现、代码审查、端到端联调验证记录 |
docs/阶段四-测试与验证/ |
测试计划、用例、缺陷报告、质量评估 |
docs/阶段五-部署与交付/ |
安装打包说明、部署文档、用户手册、运维手册 |
- Jev 官方 API 目前未对中国大陆开放,且
api.typesafe.ai为境外服务 —— 境内直连存在用户输入出境的 合规问题。本项目默认JUDGE_PROVIDER=mock;境内生产环境请保持 mock,或按BaseDecider接口换自建的 本地判定模型(详见 决策内核:Jev)。另:厂商自报判定准确率约 68%, 低于本项目 85% 的验收线,必须用自己的评测集实测 —— 评测看板可直接跑出准确率与混淆矩阵。 - 流式请求的 token 用量依赖上游:若客户端未传
stream_options.include_usage, 部分厂商不回usage,该条日志的 token / 成本会记 0 —— 是「缺数据」,不是「零消耗」。 - 纯 HTTP 抓取拿不到 JS 渲染站点正文(仅
ENABLE_TOOL_EXECUTION=true时相关)。 - 模型池默认是空的:首次安装只预置接入商,不预置模型(各账号可用模型与计费口径不同)。
必须先在「模型池」页添加至少一个模型、并给通道填 Key,路由候选池才非空;
否则
/v1请求会走兜底路径并如实报错,控制台概览也会是 0。.env的DEFAULT_MODEL_ID要指向真实存在的模型 id。 alembic/目录预留但未启用:当前建表走 ORMcreate_all(服务启动引导 /llmbridge-seed), 历史库升级走scripts/migrate_*.py。- 方式三(Apple container)未在真机端到端验证:脚本按 Apple
containerCLI 编写并做了 shell 静态检查,但开发机为 Windows,无法执行 macOS 特有路径。首次使用请留意脚本输出。 - 目录里厂商参考价来自官方公开页,订阅类套餐的单价是按额度折算的参照值, 不是真实边际成本;条款限制(如「仅限编程工具交互式使用」)原文随通道落库并在控制台警示。
我们欢迎所有开发者和用户加入社区:提问、分享经验、贡献代码,或者只是聊聊你把它用在了什么场景。
更多链接:
- 报告问题与建议(Issues): 到 GitHub Issues 提交你发现的 Bug 或功能建议。
- 参与讨论(Discussions): 到 GitHub Discussions 做更深入的技术探讨和想法交流。
- 联系我们(Contact): 如有商务合作或其他事宜,请发邮件至
93634776@qq.com。