Studio 模型目录设计
Studio 要同时对接十来个 AI 模型厂商(DashScope/Kling/Vidu/PixVerse/Seedance/ElevenLabs/MuleRouter……),"支持哪些模型、每个模型怎么调、前端下拉框怎么露出"这件事如果散落在代码各处会迅速失控。模型目录(Model Catalog)是 Studio 里为解决这个问题专门设计的一套声明式配置系统,是 Studio 后端最核心的架构设计之一。
要解决的问题
早期做法是把模型支持信息散落在三处:后端默认值、前端下拉框选项、代码里零散的 if model == "xxx" 判断。三处各自维护,新增/下线一个模型要改多个文件,很容易漏改一处(比如改了默认值却忘了让它在某个页面的下拉框里出现)。
三层架构
- 声明层:每个厂商族一份 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 特定绝对路径):
- 把厂商原始 API 文档的抓取证据落到
platform/studio/docs/1-api-reference/(现有三篇分别对应可灵/Vidu/万相的图生视频接口)。 - 在对应厂商族的 YAML 里新增/修改声明。
- 跑
scripts/build_model_catalog.py生成 artifact。 - 跑
scripts/validate_model_catalog.py校验一致性。 - 如果涉及新认证方式、新 endpoint、新媒体传输方式,才需要补运行时代码(
src/models/*.py);纯参数调整通常只改 YAML 就够。 - 跑
tests/test_model_catalog.py等相关测试。
已知裂痕
ModelFactory(src/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 声明接进这套系统。