安装
本页介绍怎样把 HybridInference 网关跑起来:用 Docker 服务栈,或者直接从源码运行、方便自己修改。
如果想先什么都不配、看网关实际应答一次请求,那就先看快速开始。它用一个固定回复的假 provider,不需要 provider 账号,不需要 API key,连 .env 都不用。本页是下一步:用你自己的 provider,搭你自己的部署。
需要准备什么
运行方式 |
要求 |
|---|---|
Docker 服务栈 |
Docker Engine 24+ 与 Docker Compose v2+ |
从源码运行 |
Python 3.10–3.13(推荐 3.12,以 |
在 Docker 之外运行控制台 |
Node.js 22(CI 安装的版本) |
Linux 或 macOS。
用 Docker 运行
git clone https://github.com/HarvardMadSys/hybridInference.git hybridinference
cd hybridinference
cp .env.example .env
第一次运行 make up 之前,先在 .env 里填好三样东西:
数据库登录信息。
DB_USER和DB_PASSWORD默认是空的,DB_NAME已经设为hybridinference。三个都有值之前,Compose 不会启动。三个密钥。
JWT_SECRET_KEY用来给登录 token 签名,API_KEY_SECRET是网关对 API key 做哈希时用的密钥,ERASURE_FENCE_SECRET用来保护已删除账号的记录。没有前两个,后端会拒绝启动;第三个留空时,会悄悄沿用API_KEY_SECRET的值。三个要分别生成:python3 -c "import secrets; print(secrets.token_urlsafe(48))"
模型要用的凭据。默认情况下,网关提供
config/examples/models.openrouter.yaml里的三个示例模型,它们都走 OpenRouter(其中一个会先尝试本地的 Ollama 服务器)。设置好OPENROUTER_API_KEY就能用。要换成你自己的模型,见添加新模型。
把这些密钥和部署的其他配置放在一起,并且一直保留:每次重启、每个副本都用同一组,升级时也原样带过去。改了 JWT_SECRET_KEY,已经签发的访问 token 会全部失效;改了 API_KEY_SECRET,所有现有的 API key 都将无法使用。改了 ERASURE_FENCE_SECRET(或者在它留空时代替它的 API_KEY_SECRET),后端会直接拒绝启动,见数据库。网关从不替你生成或轮换这些密钥。
备注
只有不带数据库、也没有账号体系的网关才能不设这些密钥:DB_ENABLED=false 并且 USER_AUTH_ENABLED=false,就像快速开始的阶段 1 那样。ADMIN_TOKEN 是可选的;留空只会关闭旧式的管理员 token 访问方式。
然后启动这套服务栈:
make up # creates the external volume, then brings up Compose
make ps # show the services and their health
curl -s http://localhost:8080/health
第一次 make up 还会创建存放数据库的 Docker 卷 hybridinference_postgres_data。docker compose down -v 不会删除它;如果需要干净的数据库,见重置这套服务栈。
之后如果改了 .env,要重新运行 make up,而不是 make restart。容器只在创建时读取 .env,所以重启后用的还是旧值。
会启动三个容器:
服务 |
宿主机地址 |
说明 |
|---|---|---|
|
|
FastAPI 网关;用 |
|
|
Next.js 控制台;用 |
|
|
用 |
这些端口默认可从宿主机访问。同机运行的反向代理可以使用回环地址;从其他机器访问则需要显式覆盖监听地址。控制台也会转发 API 请求,公开它之前请先阅读部署指南。
Compose 文件中也包含 pgAdmin,通过可选的 admin profile 启动。
本地开发(不用 Docker)
git clone https://github.com/HarvardMadSys/hybridInference.git hybridinference
cd hybridinference
make setup-dev
make setup-dev 会用 Python 3.12 创建 .venv(如果已有的 .venv 是别的次版本,它会拒绝继续),以可编辑方式安装本项目,同步 dev 依赖组,并装好 pre-commit hooks。手动来做的话:
uv venv -p 3.12
source .venv/bin/activate
uv sync --group dev
请在仓库根目录下运行网关,因为默认的配置路径都相对于仓库根目录:
cp .env.example .env # edit as above; a process started here reads it
uv run uvicorn serving.servers.app:app --no-proxy-headers --host 127.0.0.1 --port 8080
在另一个终端里运行控制台:
cd apps/frontend
npm ci
BACKEND_INTERNAL_URL=http://127.0.0.1:8080 npm run dev -- --hostname 127.0.0.1
打开 http://localhost:3001。控制台会把 API 路径转发给网关,BACKEND_INTERNAL_URL 告诉它网关在哪。这个变量的默认值 http://backend:8080 只在 Docker 内部有效,而控制台又不读仓库里的 .env,所以每次启动控制台都要设置它。用 curl http://localhost:3001/health 检查整条链路。
如果想连着 Postgres 开发、又不想启动整套服务栈,可以只起数据库容器:
make docker-volumes
docker compose -f deploy/docker/docker-compose.yml --env-file .env up -d postgres
如果本地网关不需要账号或数据库,在 .env 中同时设置 DB_ENABLED=false 和 USER_AUTH_ENABLED=false。它仍能路由请求,/health 会报告 "database_configured": false。账号、API key 和请求历史需要数据库及两个认证密钥。
配置
环境变量
只有一个文件:仓库根目录下的 .env。从仓库根目录启动后端时,它会读取这个文件;Compose 也会把它传给各个容器。
除了上面 Docker 步骤里的这些变量(DB_NAME、DB_USER、DB_PASSWORD、JWT_SECRET_KEY、API_KEY_SECRET、ERASURE_FENCE_SECRET),以及默认注册表需要的 OPENROUTER_API_KEY,.env.example 里的其他变量都是可选的。最可能用得上的是这些:
变量 |
作用 |
|---|---|
|
|
|
|
|
管理控制台可以按 provider 添加的路由类型,写成逗号分隔的 |
|
|
|
|
|
用户在验证邮件和重置邮件里点击的绝对 URL |
|
本网关自己对外的 origin,用来拼装注册和密码重置邮件里的绝对链接。请设置它:服务器不解析 |
|
日志详细程度,以及 |
|
进程内告警,默认关闭 |
|
信任 |
|
可选,直接从私有网络连入的客户端所在网段(CIDR);不会因此信任转发头 |
|
信任所列对端发来的 Cloudflare |
按你的部署方式该设上面哪几项代理设置,见可信代理与客户端 IP。
Provider 凭据
模型注册表自己指定要用哪些凭据。它的 api_key、api_keys、base_url 和 provider_model_id 字段都可以写成 ${VAR},在加载注册表时从环境变量中读取。所以一个部署需要哪些 provider key,就看它的注册表写了哪些变量,变量名随你起。
route:
- kind: openrouter
base_url: https://openrouter.ai/api/v1
api_keys:
- ${OPENROUTER_API_KEY}
只有整个值才会被替换:${VAR:-default},以及嵌在更长字符串里的 ${VAR},都不会被替换。详见配置。
.env.example 里为本项目已有 adapter 或示例的 provider 预留了空的占位变量;你也可以随意添加自己的变量名。内置的默认注册表只需要 OPENROUTER_API_KEY。
配置了数据库之后,也可以在管理控制台(Providers → Keys)里添加 key,无需重启;这些 key 和注册表里指定的 key 放在同一个池子里。见从管理控制台做运行时配置。
配置文件在哪里
网关通过环境变量或发行版的 manifest 找到自己的模型注册表、路由配置文件和告警规则;两者都没有指定时,就回退到 config/examples/ 下的示例。具体规则见网关如何找到自己的配置,文件里该写什么,那一页后面都有讲。
Compose 文件把 config/ 和 distributions/ 都以只读方式挂载进后端,所以在宿主机上改了其中任何一个,重启后端就行——不用重新构建镜像。
备注
直接跑在宿主机上的后端,可以通过 localhost 访问宿主机上的推理服务器。跑在 Docker 里的后端则必须用 Docker 内能访问到的地址,例如 host.docker.internal,并且要在模型注册表里显式写出来;HybridInference 不会替你改写 provider 的 URL。
验证安装
对着运行中的网关执行:
curl -s http://localhost:8080/v1/models
curl -s http://localhost:8080/v1/chat/completions \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${HYBRIDINFERENCE_API_KEY}" \
-d '{"model":"<model-id>","messages":[{"role":"user","content":"Say hello."}]}'
如果设了 USER_AUTH_ENABLED=0,就去掉 Authorization 头。模型 id 要用 /v1/models 真的列出来的那些。
同一个调用,用 OpenAI 的 Python SDK 来发——网关就是那个 base_url,现有客户端别的什么都不用改:
from openai import OpenAI
client = OpenAI(api_key="<your-api-key>", base_url="http://localhost:8080/v1")
response = client.chat.completions.create(
model="<model-id>",
messages=[{"role": "user", "content": "Say hello."}],
)
print(response.choices[0].message.content)
本地开发时,make check 会运行 linter 和默认测试套件;其他检查见贡献指南。
故障排查
required variable DB_USER is missing a value: DB_USER must be set in .env file——Compose 还没启动任何东西就停了。按上面第 1 步,在 .env 里填上 DB_USER 和 DB_PASSWORD。
env file ... .env not found——在 make up 之前先用 cp .env.example .env 创建它。
从源码运行时报导入错误——运行 make setup-dev(或 uv sync --group dev),把后端装进 .venv,然后用 uv run 启动网关,或者先激活 .venv 再启动。
所有请求都 404,且 /v1/models 为空——说明注册表什么都没加载进来。启动时后端要么打印 Registered N routes from <path>,要么打印一条错误,指出它找不到的注册表路径;把这个路径和配置里的优先级列表对照一下。
端口已被占用——在 .env 里覆盖 BACKEND_PORT、FRONTEND_PORT 或 DB_PORT。