快速开始

部署受支持的 Docker Compose 技术栈,接入供应商与模型,签发 API 密钥,并发出第一个请求。

本指南带你从零到一,向自部署的 Cordy Gateway 发出一个可用的请求。它采用受支持的部署路径——Docker Compose——并以一个真实的对话补全收尾,分别通过 curl、OpenAI Python SDK 与 OpenAI JavaScript SDK 完成。

预计约 15–20 分钟。你将:

  1. 检查前置条件。
  2. .env 文件中配置密钥。
  3. 用 Docker Compose 启动生产技术栈。
  4. 创建管理员用户。
  5. 在 Admin 中注册供应商、通道与模型。
  6. 签发一个 wnx_ API 密钥。
  7. 发出第一个请求。
  8. 验证健康状态。

1. 前置条件

  • Docker Engine 24+Docker Compose v2 插件docker compose,而非旧版 docker-compose)。
  • 主机上已有 Cordy Gateway 发行物(仓库或交付包),以便 docker-compose.prod.yml 以及 deploy/docker/ 目录齐备。
  • 主机为完整技术栈(Postgres、Redis、PgBouncer、Admin、Gateway、worker、nginx)预留至少 4 GB 空闲内存
  • 真实生产部署需要:域名TLS 证书。内置 nginx 终止的是明文 HTTP;请在 docker/nginx/ 中加入 443 server block 与证书,或用你自己的反向代理置于技术栈之前。本地试用可跳过 TLS(见第 2 步的说明)。

确认 Docker 就绪:

docker --version
docker compose version

2. 配置密钥

复制模板并填全占位符:

cp deploy/env.template .env

生成你必须设置的三个密钥:

# Django 密钥
python -c "import secrets; print(secrets.token_urlsafe(50))"

# 通道凭据加密密钥(Fernet)
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

# 一个强数据库口令——任意长随机串
python -c "import secrets; print(secrets.token_urlsafe(24))"

至少在 .env 中设置以下必填变量:

变量用途说明
DB_NAMEPostgres 数据库名例如 cordy
DB_USERPostgres 用户
DB_PASSWORDPostgres 口令使用生成的值
DJANGO_SECRET_KEYDjango 加密密钥使用生成的值
DJANGO_ALLOWED_HOSTSAdmin 服务的主机名逗号分隔;本地试用加 localhost,127.0.0.1
DJANGO_ADMIN_URLAdmin URL 路径前缀必须以 / 结尾;取一个不显而易见的值,例如 ops-7f3a/
CHANNEL_ENCRYPTION_KEYS上游凭据的 Fernet 密钥Admin 与 Gateway 服务必须一致

本地试用说明:内置 nginx 提供明文 HTTP。仅在无 TLS 的本地测试时,才在 .env 中设置 DJANGO_SECURE_SSL_REDIRECT=False,使 Admin 不强制跳转 HTTPS。任何真实部署都应保持其默认值 True

CHANNEL_ENCRYPTION_KEYS 在生产中为必填:Gateway 与 Admin 缺少它都会拒绝启动,且两者必须使用相同的值,否则通道凭据无法解密。请将 .env 排除在版本控制之外,并把密钥存放在你的密钥管理系统中。

每个变量详见配置参考

3. 启动技术栈

docker compose -f docker-compose.prod.yml --env-file .env up -d --build

它会启动完整的生产拓扑:

服务角色端口
nginx负载均衡 / TLS 终止点发布 GATEWAY_HTTP_PORT(默认 8002
gateway数据平面(Starlette + Granian,兼容 OpenAI 的 API)内部 8002,由 nginx 前置
admin控制平面(Django Admin)发布 ADMIN_HTTP_PORT(默认 8001
postgrespg_cron 的 PostgreSQL 18仅内部
pgbouncer网关热路径的事务连接池仅内部
redisRedis 8——速率限制、配额、缓存、缓冲仅内部
worker后台 worker(用量结算、审计上传)仅内部

Admin 容器会自动执行数据库迁移并收集静态文件,然后再启动。Postgres、PgBouncer 与 Redis 仅在内部网络,不对主机发布。

观察启动并确认服务健康:

docker compose -f docker-compose.prod.yml ps
docker compose -f docker-compose.prod.yml logs -f admin

4. 创建管理员用户

创建一个 Django 超级用户以登录 Admin:

docker compose -f docker-compose.prod.yml exec admin \
  uv run python manage.py createsuperuser

按提示输入邮箱与口令。随后在此登录:

http://<host>:8001/<DJANGO_ADMIN_URL>

例如,若 DJANGO_ADMIN_URL=ops-7f3a/,登录 URL 即为 http://<host>:8001/ops-7f3a/

5. 注册供应商、通道与模型

Cordy Gateway 通过一条记录链来解析客户端请求的 model。你在 Admin 的 Gateway Configuration 下一次性创建它们。服务一个模型所需的最小接线:

  1. Provider(供应商)——上游厂商集成(例如 OpenAI)。设置 nameprovider_type(例如 OPENAI)与状态 ACTIVE
  2. Public model(公开模型)——客户端在 model 字段中请求的公开标识(例如 slug gpt-4o-mini)。这是客户端唯一能看到的模型名。
  3. Provider model(供应商模型)——将 Provider 与 Public model 关联到具体上游模型名(例如 gpt-4o-mini),并带 input_price / output_price 与能力标志(supports_chatsupports_embeddingssupports_streaming)。
  4. Channel(通道)——该 Provider 上的一个路由目标。设置其上游凭据(API 密钥——以 Fernet 加密存储)、可选 base_urlweightpriority 与可选 region
  5. Channel provider model(通道-供应商模型绑定)——将 Channel 与 Provider model 绑定,使该模型可经由该通道提供服务。该供应商模型必须属于该通道所属的供应商。

一旦至少有一个活跃通道能服务你的公开模型,该模型即变为可路由。完整演练见供应商,链路在请求时如何解析见核心概念

6. 签发 API 密钥

在 Admin 中创建(或选定)一个用户,然后为该用户创建 API key。创建时,网关会生成一个以 wnx_ 为前缀的密钥,并仅一次显示完整明文——请立即复制;数据库只保存其 SHA-256 哈希。

创建密钥时,设置:

  • Scopes(作用域)——该密钥可调用的接口族(chatcompletionsembeddingsmodelsbalanceadmin)。只授予所需项;空作用域列表表示"允许所有该拥有者本可访问的接口"(遗留默认)。新密钥应遵循最小权限。
  • Quota(配额)——月度令牌额度。
  • Rate limit(速率限制)——每分钟请求数。

导出密钥以供下一步使用:

export CORDY_API_KEY="wnx_...你的密钥..."
export CORDY_BASE_URL="http://<host>:8002/v1"   # 生产环境使用 https://...

7. 发出第一个请求

curl

curl -sS "$CORDY_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $CORDY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [
      {"role": "user", "content": "用一句话向 Cordy Gateway 打个招呼。"}
    ]
  }'

请把 gpt-4o-mini 替换为你创建的公开模型 slug。成功的响应是一个标准的 OpenAI 对话补全对象。

Python(OpenAI SDK)

pip install openai
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["CORDY_API_KEY"],
    base_url=os.environ["CORDY_BASE_URL"],  # http://<host>:8002/v1
)

resp = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "user", "content": "用一句话向 Cordy Gateway 打个招呼。"}
    ],
)
print(resp.choices[0].message.content)

JavaScript / TypeScript(OpenAI SDK)

npm install openai
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.CORDY_API_KEY,
  baseURL: process.env.CORDY_BASE_URL, // http://<host>:8002/v1
});

const resp = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [
    { role: "user", content: "用一句话向 Cordy Gateway 打个招呼。" },
  ],
});

console.log(resp.choices[0].message.content);

8. 验证健康状态

健康接口为公开访问(无需 API 密钥):

# 存活——进程是否在运行?
curl -sS http://<host>:8002/health

# 就绪——此刻是否真能服务对话/嵌入?
curl -sS http://<host>:8002/health/ready

# 各供应商健康明细
curl -sS http://<host>:8002/health/providers

进程一旦运行,/health 即返回 200。在至少有一个通道可服务流量之前,/health/ready/health/detailed 会返回 503——这在你完成第 5 步接线之前属于预期;一旦有模型可路由即转为 200

故障排查

  • 部署后每个请求都返回 401 网关数据平面直接从 DB_NAME / DB_USER / DB_PASSWORD 构建数据库 DSN(它不解析 DATABASE_URL)。若这些在 gateway 服务上缺失或有误,它便无法连上数据库,所有请求鉴权失败。确认网关的 DB_* 值与 admin 一致。
  • 401 invalid_api_key 密钥有误或从未激活。在 Admin 中重新签发密钥,并原样复制那一次性明文,包括 wnx_ 前缀。
  • 404 model_not_found/v1/models 列表为空。 模型链不完整或未激活。确认 Public model、Provider model、Channel 与 Channel-provider-model 记录均存在且为 ACTIVE,且通道有有效的上游凭据。
  • /health/ready 一直是 503 尚无通道可服务流量。完成供应商/通道/模型接线,再查看 /health/providers 的各供应商状态以及 admingateway 日志。
  • 本地无 TLS 试用时 Admin 登录跳转到 HTTPS。.env 中设置 DJANGO_SECURE_SSL_REDIRECT=False 并重建 admin 服务。真实部署切勿如此。
  • CHANNEL_ENCRYPTION_KEYS 启动报错。 该变量未设置,或 Admin 与 Gateway 值不同。为两个服务设置相同的 Fernet 密钥。
  • 供应商调用返回上游鉴权错误。 通道存储的凭据有误。在 Admin 中编辑该通道并重新填入上游 API 密钥。

后续步骤

  • 客户端集成——流式、工具调用、嵌入与产品化请求头。
  • API 参考——每个接口、作用域与错误码。
  • 部署——扩展、可观测性、备份与升级。
  • 安全——信任模型与加固清单。