Studio 模型目录设计

Studio 要同时对接十来个 AI 模型厂商(DashScope/Kling/Vidu/PixVerse/Seedance/ElevenLabs/MuleRouter……),"支持哪些模型、每个模型怎么调、前端下拉框怎么露出"这件事如果散落在代码各处会迅速失控。模型目录(Model Catalog)是 Studio 里为解决这个问题专门设计的一套声明式配置系统,是 Studio 后端最核心的架构设计之一。

要解决的问题

早期做法是把模型支持信息散落在三处:后端默认值、前端下拉框选项、代码里零散的 if model == "xxx" 判断。三处各自维护,新增/下线一个模型要改多个文件,很容易漏改一处(比如改了默认值却忘了让它在某个页面的下拉框里出现)。

三层架构

声明层                    构建层                           消费层
config/model_catalog/  →  scripts/build_model_catalog.py →  后端 ModelSettings 默认值
  catalog.meta.yaml        (生成 JSON)                    provider_registry.py 路由表
  families/{wan,kling,       │                              前端模型选择器 UI
  vidu,pixverse,seedance,    ▼
  qwen,gpt-image,          config/model_catalog/generated/
  happyhorse}.yaml          model_catalog.json
                             │  同步镜像

                          web/src/generated/modelCatalog.json
  • 声明层:每个厂商族一份 YAML(config/model_catalog/families/*.yaml,共 8 家:wan/kling/vidu/pixverse/seedance/qwen/gpt-image/happyhorse),描述该家族的路由前缀(如 wan2.7-kling/kling-)、支持哪些后端(dashscope/vendor/mulerouter)、默认走哪个、凭证取自哪个环境变量、输入媒体的传输方式(不同 provider 收图片的方式不一样,有的要 base64、有的要临时 URL),以及每个具体模型/模式的能力(t2i/i2i/i2v/r2v)和 UI 可见性。
  • 构建层scripts/build_model_catalog.py 把多份 YAML 编译成一份 generated/model_catalog.json,同步把一份镜像写到前端 web/src/generated/modelCatalog.json(后端只读文件,供 src/lib/modelCatalog.ts 消费)。这一步需要人工/CI 手动执行,不是 pnpm build/服务启动自动触发的。
  • 消费层:后端 get_default_model_settings()provider_registry.py 的路由表,以及前端所有模型选择器组件,全部从生成产物读取,不再各自硬编码。

legacy ID 兼容映射

这套系统里最有设计感的一点:历史上一个模型对应一个扁平字符串 ID(如 wan2.7-i2v),但现实中同一条"模型线"(model line,如 Wan2.7)会有多个"模式"(t2i/i2v/r2v)。新设计把"模型线 + 模式"当成第一等公民——canonical_mode_id = "{model_line_id}#{mode}"——旧的扁平 ID 变成兼容层里的别名(compat.legacy_model_ids)。这样新增一个模式不用发明新的顶层模型 ID,也不会破坏存量项目里已经存下的旧 model_id 字符串。

一致性校验

scripts/validate_model_catalog.py 会检查一批规则,比如"默认模型必须在它被使用的 UI 界面里可见""可见模型必须有对应的文档链路",防止"改了默认值却忘了让它在下拉框出现"这类问题重演。

接入新模型的标准流程

参考 platform/studio/docs/2-model-catalog-design/model-onboarding-implementation.md(这是仓库内质量最高的一份设计文档,本页据此复述,已剥离其中的 upstream 特定绝对路径):

  1. 把厂商原始 API 文档的抓取证据落到 platform/studio/docs/1-api-reference/(现有三篇分别对应可灵/Vidu/万相的图生视频接口)。
  2. 在对应厂商族的 YAML 里新增/修改声明。
  3. scripts/build_model_catalog.py 生成 artifact。
  4. scripts/validate_model_catalog.py 校验一致性。
  5. 如果涉及新认证方式、新 endpoint、新媒体传输方式,才需要补运行时代码(src/models/*.py);纯参数调整通常只改 YAML 就够。
  6. tests/test_model_catalog.py 等相关测试。

已知裂痕

  • ModelFactorysrc/models/factory.py)与实际运行时路由是两套逻辑ModelFactory 只认 'wanx'/'kling'/'vidu'/'seedance' 四个粗粒度字符串,不理解 wan2.7-/happyhorse- 这类前缀和 backend-mode 概念;而 pipeline.py: process_video_task()playground/service.py 各自手写了一遍基于模型名前缀 + provider_registry 的路由逻辑(后者代码注释明确写"mirrors the routing logic in pipeline.py")。同一件"给模型名选 provider 适配器"的事情,代码里有三份不同实现,ModelFactory 看起来是已经过时但没删除的早期设计。
  • ARK_API_KEY(豆包/方舟)是孤儿配置:README 里有文档说明,src/models/doubao.py 也定义了对应的 DoubaoModel 类并读取这个环境变量,但全仓库搜索没有任何地方引用它——Seedance 系列实际是经 MuleRouter 接入的,豆包/方舟并没有独立的 family 声明接进这套系统。

相关页面