模型中转与 API Key
使用受限 API Key 调用模型,管理渠道部署,并查询实际消费。
启用模型中转的 Federation 提供标准 GET /v1/models 和 POST /v1/chat/completions。OpenAI 客户端的 Base URL 设置为你的 Federation 地址加 /v1。流式与非流式请求、工具调用和 usage 都经过同一条 AIService 执行与结算链路。
创建和管理 Key
官网用户可以在 用户中心 → API Keys 管理自己的 Key;完整明文只在创建成功的弹窗中显示一次。SDK 集成使用账户登录得到的 user_token 管理自己的 Key。调用 Key 不能访问账户、支付、Key 管理或调用记录查询接口。
import { Embassy } from "@downcity/federation";
const embassy = new Embassy({
federation_url: "https://your-federation.example",
user_token,
});
const issued = await embassy.user.relay.create_key({
name: "编辑器",
allowed_models: ["deepseek-v4-flash"],
spend_limit: 10000,
expires_at: null,
});
// 将 issued.api_key 安全保存到调用客户端;服务端此后无法再次返回明文。
const keys = await embassy.user.relay.list_keys();
await embassy.user.relay.update_key({ key_id: issued.key.key_id, status: "disabled" });
await embassy.user.relay.update_key({ key_id: issued.key.key_id, status: "active" });
await embassy.user.relay.revoke_key(issued.key.key_id);allowed_models 填模型或 route 的公开 ID。[] 不允许调用任何入口;["*"] 允许所有已发布入口。只授权某个 route 不会同时授权其绑定模型。Key 可以重命名、修改权限、额度与到期时间;停用可以恢复,撤销不可恢复。撤销和停用阻断后续新请求,已经开始的调用仍会完成结算。
spend_limit 的单位是 Credits,null 表示不设 Key 消费上限。调用前检查账户余额和该 Key 已经成功结算的消费,不预占资金。多个并发在途请求可能使最终消费超过设定值,因此它是软上限。Key 没有独立钱包,实际扣费仍由账户 Credits 账本处理。
在 OpenAI 客户端调用
官网 模型与接入 提供当前可用目录、后端声明价格、配置推导的 Base URL 和占位 Key 示例;不会读取真实 Key 或推断未声明能力。
curl "$FEDERATION_URL/v1/models" \
-H "Authorization: Bearer $DOWNCITY_API_KEY"
curl "$FEDERATION_URL/v1/chat/completions" \
-H "Authorization: Bearer $DOWNCITY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"deepseek-v4-flash","messages":[{"role":"user","content":"你好"}],"stream":true}'原生 POST /v1/ai/stream 也接受调用 Key,使用 Downcity Model Protocol 的 model_id 和 call。启用中转后,语言模型入口保持指定模型的能力和售价;不自动跨模型处理最新媒体。如果模型不支持本轮媒体,显式选择具备相应能力的模型。
查询调用与消费
官网 调用记录 支持本人请求的 Key 筛选、游标分页和安全 attempt 详情。未知计量与未结算费用保留为未知,不显示为零。
const page = await embassy.user.relay.list_requests({ limit: 50 });
const record = page.items[0];
if (record) {
const attempts = await embassy.user.relay.list_attempts(record.request_id);
const next_page = await embassy.user.relay.list_requests({ before: record.request_id });
}响应头 x-request-id 关联一次逻辑调用,每次上游尝试另有 attempt_id。调用记录返回 Key 归属、模型、渠道、Token、耗时和结算状态;尝试记录包含首个内容事件耗时。charged_credits 只在结算 completed 后显示。失败尝试、缺少 usage 或尚未结算不能解释为零消费。记录不保存提示词、回答正文、调用 Key 或渠道凭据。
自建 Federation 启用中转
const ai = new AIService({
relay: true,
credits: {
precheck: (user_id, needed_credits) => credits.precheck(user_id, needed_credits),
charge: (input) => credits.charge(input),
},
}).use(models);
federation.use(ai);第一次启动会将已注册语言模型导入持久化目录,保留原有适配器和计费函数。后续新增模板需通过管理 SDK 发布到目录。公开模型的能力、reasoning 与售价取自已注册模板,管理员可以配置启停、渠道、上游映射、优先级、权重与 route。官网提供用户自己的 Key 管理页。管理员可在 Fedman 的「渠道与路由」管理公开模型、渠道、部署和 route,或使用下列管理员 SDK。
const admin = new Embassy({ federation_url, admin_token });
const metadata = await admin.admin.relay.metadata(); // 已注册模板与适配器,不含凭据
const health = await admin.admin.relay.health(); // 共享部署冷却快照,不是主动探测
const snapshot = await admin.admin.relay.catalog();
// 按需要修改 snapshot.catalog,再用读取时的 revision 提交。
await admin.admin.relay.configure(snapshot.catalog, snapshot.revision);Fedman 表单从实际目录与 metadata() 生成可选项。支持创建、编辑、启停和确认删除;有依赖引用时删除被拒绝,不隐式级联。每次保存提交读取时的 revision,409 冲突需刷新最新目录后重新编辑,不自动覆盖。registered 渠道必须已安装,runtime 与上游映射固定;OpenAI 渠道只填写服务端凭据环境变量名称,不在表单填写密钥。部署列表展示共享冷却截止时间;无冷却记录不代表上游健康,不提供主动付费探测。
目录将 Model、Channel、Deployment 与 Route 分开管理:Model 绑定能力和售价模板;Channel 选择 registered 或 openai_chat_completions 适配器;Deployment 关联公开模型、渠道和真实上游模型;Route 选择同一公开模型的部署集合。标准 OpenAI 渠道的 base_url 使用不含凭据的 HTTPS API 根地址,credential_env 引用 Federation 的环境变量;目录接口不会返回凭据明文。新增渠道必须确实支持模型模板声明的能力。
默认策略 priority_weighted 优先选择较高 priority,同层按正整数 weight 抽样。直接模型入口最多尝试两次;route 的 max_attempts 可设为 1–3。明确的 401、403、429 拒绝允许切换其他候选;网络异常、5xx、超时或开始读取上游流后不自动重试。健康冷却保存在共享数据库,429 尊重 Retry-After,最长五分钟,其他故障短暂冷却,到期后恢复正常选取。渠道 timeout_ms 默认为 120000,范围 1000–300000,适配器需响应取消信号。
目录在实例中缓存五秒,修改通过 revision 防止覆盖并发更新,其他实例最多经过一个缓存周期看到新配置。路由不额外调用模型;Key 状态每次读取,有限额 Key 的已结算消费检查与账户余额检查并行。调用开始前仍需持久化请求和尝试日志,并读取共享健康状态,真实增加的延迟取决于数据库部署和上游,需在实际环境测量。
当前不提供 RPM、TPM、全局并发租约、Responses、Anthropic Messages 或 OAuth 账号池。