Files
sub2api-cn-relay-manager/docs/PROVIDER_ONBOARDING_PLAYBOOK.md
2026-05-22 07:43:42 +08:00

12 KiB
Raw Permalink Blame History

Provider Onboarding Playbook

日期2026-05-21

目的

这份文档面向两类场景:

  1. 需要把一个新的 OpenAI-compatible 国产模型中转接入到 sub2api-cn-relay-manager
  2. sub2api 宿主版本发生变化后,需要快速确认现有导入链路是否仍然兼容,并稳定完成重新导入与验收

它不是当前 gate 文档,也不替代真实宿主验收步骤文档。

分工如下:

  • docs/SOURCE_OF_TRUTH.md
    • 回答“当前最新真相是什么”
  • docs/PROVIDER_VALIDATION_MATRIX.md
    • 回答“哪些 provider 已有模板、哪些已有官方 key、哪些已经完成 live 验收”
  • docs/REAL_HOST_ACCEPTANCE_RUNBOOK.md
    • 回答“标准真实宿主验收怎么跑”
  • docs/REAL_HOST_ACCEPTANCE_LEARNINGS.md
    • 回答“之前踩过哪些坑”
  • 本文
    • 回答“以后要新增 provider / 宿主升级后重跑时,最稳妥的工程步骤是什么”

适用边界

本文假设:

  1. 目标上游是 OpenAI-compatible 接口
  2. 目标宿主仍然是 sub2api
  3. 控制面仍然遵守当前 PRD 首版范围:
    • 不修改宿主源码
    • 不写宿主数据库
    • 通过宿主管理 API 完成 group/channel/account/subscription 等资源编排

如果未来要接入“非 OpenAI-compatible”上游这份文档只能复用框架不能直接照抄字段约定。

先记住 8 条不变量

后续所有操作都围绕这 8 条不变量展开。只要其中一条被破坏,导入就容易出现“看起来像通了,实际上没通”的假阳性。

  1. provider 的 account 视角模型暴露必须正确

    • credentials.model_mapping 必须真实落到宿主 account
    • GET /api/v1/admin/accounts/:id/models 必须返回目标 provider 模型,而不是 GPT 默认集
  2. channel 的网关视角模型约束必须完整

    • model_mapping
    • model_pricing
    • restrict_models=true
    • billing_model_source=channel_mapped
    • 这四项缺一不可
  3. access ready 不能只看 /v1/models

    • 当前代码已经把 ready gate 提升到 completion 层
    • 必须同时通过 /v1/models/v1/chat/completions
  4. subscriptionself_service 的 probe key 语义不同

    • subscription 最终 probe key 是宿主 managed key
    • self_service 最终 probe key 是普通用户 gateway key
  5. self_service 普通用户 key 的真实认证方式是 Authorization: Bearer

    • 不是 x-api-key
  6. account test 不能默认回退到 gpt-5.4

    • 必须显式传 provider.SmokeTestModel
    • 否则会把非 GPT provider 错误判成 failed
  7. remote/provider 验收要保留 upstream 直探证据

    • upstream /models
    • upstream /chat/completions
    • 21-summary.json
  8. shared fresh-host 上 reconcile=drifted 不能直接覆盖 import/access 成功结论

    • 先看 05-import.json
    • 再看 07-access-status.json
    • 最后才解释 09-reconcile.json

一图理解完整链路

把一次稳定 onboarding 看成 5 个阶段:

  1. 定义 provider
  2. 落 pack
  3. 导入宿主
  4. 验证 access
  5. 固化 artifact 与经验

只有这 5 个阶段都闭环,后续宿主升级或换 key 时才能快速复用。

阶段 1定义 provider

1.1 先判断这个上游是否值得接

最先回答 5 个问题:

  1. base_url 是否稳定,是否明确兼容 OpenAI-style /models/chat/completions
  2. 是否有至少一个可用于真实 completion 的 key
  3. 上游返回的模型名是否稳定,是否可能带 vendor/model 前缀
  4. 这个 provider 目标走 self_servicesubscription,还是两者都要支持
  5. 是否需要独立的 host 兼容性结论,而不是直接复用别的 provider 结论

如果连第 2 条都不满足,就不要把“导入失败”先归因为控制面。

1.2 provider 清单里必须关注的字段

至少明确这些信息:

  1. provider_id
  2. platform
  3. default_model
  4. smoke_test_model
  5. channel_template.model_mapping
  6. channel_template.model_pricing
  7. account_template.credentials.model_mapping

经验规则:

  • smoke_test_model 不要留空
  • default_modelsmoke_test_model 可以相同,但不要依赖宿主默认值
  • 若 upstream 返回模型名带厂商前缀,要在验收脚本侧考虑归一化,而不是强行修改上游

1.3 什么时候要新增模型别名归一化

如果你看到的是这类模型名:

  • deepseek-ai/DeepSeek-V4-Pro
  • vendor-x/model-y

而 pack 里写的是:

  • deepseek-v4-pro
  • model-y

就不要把 upstream_models_has_expected_model=false 直接当失败。先补脚本归一化规则,再看真实 chat 是否通。

阶段 2落 pack

2.1 最小改动原则

优先只改下面几类文件:

  1. packs/openai-cn-pack/providers/<provider>.json
  2. 必要时更新 checksums.txt
  3. 若需要测试临时线路,优先复制出临时 pack不要先污染正式 pack

不要为了一个新 provider 先改控制面逻辑。先让 pack 描述能力足够完整,再判断是否真的需要动 Go 代码。

2.2 pack 完成后的本地静态检查

至少确认:

  1. pack 能被 loader 成功读取
  2. provider schema 通过
  3. checksum 对齐
  4. smoke_test_model 非空

如果 pack 里已经缺字段,后面的导入问题会越来越难解释。

阶段 3导入宿主

3.1 导入前先选 access mode

两条链路语义不同,不要混着看。

self_service

  1. 目标用户真实存在
  2. 普通用户 key 可用
  3. key 已绑定目标标准 group
  4. 用户有可用余额

subscription

  1. 目标用户真实存在
  2. 普通用户 key 可用
  3. 目标 group 是 subscription 类型
  4. 用户有 active subscription
  5. key 已绑定该 subscription group

3.2 导入时最容易漏掉的三件事

  1. account credentials.model_mapping

    • 漏掉就会回退 GPT 默认模型集
  2. channel model_pricing

    • 只有 model_mapping 不够
  3. account test 的 provider.SmokeTestModel

    • 不显式传递就可能被宿主默认拿 gpt-5.4 去测

3.3 既有 channel 与新建 channel 的处理方式不同

对于新建 channel

  • 创建时就要带全量字段

对于既有 channel

  • 不能假设历史字段完整
  • 必须走 update 纠偏

如果 live host 上出现“有 model_mapping 但没有 model_pricing”,先别急着怀疑当前代码。先确认在线 CRM 进程是不是旧版本。

阶段 4验证 access

4.1 必须分三层落证据

每次 onboarding 至少保留这三层:

  1. account 单体视角

    • GET /api/v1/admin/accounts/:id
    • GET /api/v1/admin/accounts/:id/models
  2. group / 普通用户聚合视角

    • GET /v1/models
  3. completion 视角

    • POST /v1/chat/completions

任何时候都不要用前一层去替代后一层。

4.2 当前 completion-gated 判定标准

对外宣称 ready 之前,至少要满足:

  1. /v1/models 命中目标 smoke_test_model
  2. /v1/chat/completions 返回成功

否则最多只能说:

  • 模型暴露对了
  • 还不能说真实调用链路对了

4.3 upstream 直探的意义

当 host chat 失败时,必须做 upstream 直探,目的是把问题分成两类:

  1. host_compatibility_gap

    • host /chat/completions 失败
    • upstream /chat/completions 成功
  2. upstream_key_quota_issue

    • upstream 自己就失败

这一步非常关键,因为它决定后续是修控制面、提宿主 issue还是换 key。

阶段 5固化 artifact 与经验

5.1 哪些 artifact 算“最终有效证据”

只有这类证据值得长期保留:

  1. latest-head
  2. fresh-host
  3. 同时包含 import/access/status/reconcile/rollback 或至少 import + access + completion
  4. 已能解释失败分类或通过结论

中间大量半失败、参数错误、旧进程产物,不要全部纳入版本库。

5.2 文档必须同步的三处

每次完成一次新的 provider onboarding 或宿主版本重适配,至少同步:

  1. docs/EXECUTION_BOARD.md
  2. docs/SOURCE_OF_TRUTH.md
  3. 本文或 docs/REAL_HOST_ACCEPTANCE_LEARNINGS.md

同步原则:

  • 执行板写当前真相
  • 真相索引写当前优先证据
  • playbook / learnings 写可复用方法和误判点

宿主版本变更时的稳定重验流程

如果 sub2api 宿主版本升级了,不要立刻重跑全套试错。按下面顺序来。

第一步:先验证宿主契约有没有变

重点确认 6 个点:

  1. channel create/update 的字段契约有没有变
  2. accounts/:id/test 是否仍接受显式模型
  3. /v1/models 的普通用户认证语义有没有变
  4. /v1/chat/completions 的普通用户认证语义有没有变
  5. subscription key/group/balance 前置有没有变
  6. admin bearer/api-key 认证入口有没有变

如果这一步没确认,后面所有“导入失败”都没有解释力。

第二步:只挑一个最稳定的 provider 先复验

推荐顺序:

  1. 先挑一条历史上最稳定、completion 已验证通过的 provider
  2. 先跑 subscription
  3. 再跑 self_service

原因很简单:

  • 这样可以先区分“宿主整体契约变了”还是“某个 provider 自己有问题”

第三步:再放大到 provider matrix

当基线 provider 通过后,再去补:

  1. 新 provider
  2. 较不稳定中转
  3. 多 key / replacement account / reconcile / rollback 场景

新增 provider 的推荐最短路径

如果目标是“尽快把一个新 provider 接入并完成真实验收”,建议按这个顺序:

  1. 准备 provider JSON
  2. 明确 smoke_test_model
  3. 明确 model_mappingmodel_pricing
  4. 用临时 pack 跑 dry-run
  5. 跑一轮 fresh-host subscription
  6. 验证三层证据
  7. 跑 upstream /models/chat/completions
  8. 若通过,再补 self_service
  9. 固化 artifact
  10. 更新文档板面

不要一开始就:

  • 同时改 pack、脚本、Go 逻辑、多个 provider
  • 同时在多个宿主环境上跑
  • 同时把 self_service 与 subscription 混成一个结论

常见失败与最短定位法

现象 1/accounts/:id/models 正确,但 /v1/models

优先检查:

  1. key/group 绑定
  2. subscription 分配
  3. 普通用户余额
  4. probe key 语义是否用错

现象 2/v1/models 正确,但 /chat/completions 失败

优先检查:

  1. host /chat/completions
  2. upstream /chat/completions
  3. 21-summary.json

现象 3provider 导入成功,但 account probe 失败

优先检查:

  1. provider.SmokeTestModel 是否真的传到了 /accounts/:id/test
  2. SSE type=error 是否被正确解析
  3. 宿主默认模型是否回退到了 GPT

现象 4CRM 显示 self_service broken,但用户 key 直打宿主已经通

优先检查:

  1. gateway probe 是否错误用了 x-api-key
  2. 在线 CRM 进程是否已切到最新修复版本

现象 5刚升级宿主后最前面的 create-host/probe-host 就失败

优先检查:

  1. host bearer token 是否过期
  2. host admin auth 契约是否变更
  3. 不要先把它归因为 provider 本身问题

推荐沉淀模板

每新增一个 provider建议至少补这 6 项记录:

  1. provider 名称与 base_url
  2. smoke_test_model
  3. subscription 是否通过
  4. self_service 是否通过
  5. upstream /models/chat/completions 是否稳定
  6. 当前已知限制或宿主兼容性差异

最后结论

把新增 provider 做稳定,不在于“多快把 key 导进宿主”,而在于这 4 件事是否同时完成:

  1. pack 定义完整
  2. access gate 真实闭环
  3. upstream 失败能分层归因
  4. 经验和证据能复用

如果只完成前两项,系统还只是“能跑一次”。 只有四项都完成,后续宿主升级、换 key、补 provider 时才会稳定且快。