Driver 1.x 云端转写模型列表合同
后端管理可扩展的模型列表,并把客户端稳定 ID 映射到实际网关 ASR 模型。Driver Host/Voice 由 ai-vibe-board 项目独立接入、合并和发行。本文是新接口合同;不代表现有 Driver 已完成接入。
产品版本
- 0.x:当前已发布版本(根目录
src-tauri/、web/)。从模型网关目录读取真实模型,由用户在客户端选择;仅请求 client-config 的 endpoints、vibeBoard,不读取本文列表或早期单模型映射。 - 1.x(SDK-driver 版):
driver-v2/正在开发的版本,使用本文列表合同。润色跟随 Agent。 archive/driver-v1/从未发布、无线上用户,已归档,不是兼容目标。schemaVersion:1和网关路径/v1是数据/API 版本,不是产品版本。
2026-09-09 ask-project 核对:1.x 开发代码仍读取早期 transcriptionTiers,需由 ai-vibe-board 独立接入本文接口。删除早期映射不影响线上 0.x;不代表当前 1.x 开发版已完成接入。
管理端
GET /admin/app-settings/driver-transcription-config 和同路径 PUT 均要求 JWT 与 site:admin,API key 不可调用,响应 Cache-Control: no-store。
GET 返回 {success:true,data:{config:null,revision:null}} 表示尚未配置;有记录时返回完整 config 和原始微秒精度 revision。PUT 示例:
{
"expectedRevision": null,
"config": {
"schemaVersion": 1,
"defaultOptionId": "transcribe-fast",
"options": [
{"id":"transcribe-fast","labels":{"zh-CN":"快速模型","en-US":"Fast model"},"modelId":"actual-asr-model-a","enabled":true},
{"id":"transcribe-accurate","labels":{"zh-CN":"精准模型","en-US":"Accurate model"},"modelId":"actual-asr-model-b","enabled":true}
]
}
}2
3
4
5
6
7
8
9
10
11
示例实际模型不是生产预设,也不代表速度或准确率测评。模型目录沿用 GET /admin/app-settings/client-config/transcription-models。
- 首次写入
expectedRevision:null;后续必须原样发送 GET/PUT 返回的 revision,不能转成毫秒日期再序列化。成功仍返回{success:true,data:{config,revision}}。 - 缺 revision 为 428
driver_asr_revision_required,格式错为 400driver_asr_revision_invalid,并发冲突为 409driver_asr_revision_conflict。不自动重试或覆盖。 - options 最多 50 项;id 唯一,匹配
^transcribe-[a-z0-9]+(?:-[a-z0-9]+)*$,总长不超过 64,transcribe-default保留。名称修改不改变 id。 - labels 恰含
zh-CN和en-US,均为非空、无首尾空格、最多 80 字符;modelId 同规则最多 200 字符。enabled 必须布尔值。拒绝未知字段。 - 启用项不得映射同一实际模型。存在启用项时默认 ID 必须命中启用项,否则默认必须 null。保存只验证启用项引用的实际模型是否已发布、支持 ASR 且供应商已配置;禁用的下架项可保留。
- 校验错为 400
driver_asr_config_invalid,模型不可用为 400driver_asr_model_unavailable;数据库失败为 503driver_asr_config_unavailable。失败不写配置。 - 空列表
{schemaVersion:1,defaultOptionId:null,options:[]}是明确清空,区别于从未配置。
后台点击“增加模型”,填写一个“模型显示名”,再选择已上架的实际模型,即为一条配置,可重复添加。页面输入的显示名同时用于中英文客户端;API 仍支持分别提供两种语言的 labels。该区域有独立的“保存模型列表”按钮,页面顶部按钮不保存此列表。保存失败保留编辑内容并持续提示,直到管理员关闭。0.x 区域提供真实模型管理入口;1.x 区域只维护此列表。下方本地模型有“保存 App 配置”按钮,调用通用配置保存;与列表保存独立。
公开配置
GET /public/driver-transcription-config 无需认证,从当前节点数据库读取,无跨环境回退。
{
"schemaVersion": 1,
"version": 1788858000000,
"updatedAt": "2026-09-08T09:00:00.000Z",
"configured": true,
"defaultOptionId": "transcribe-fast",
"options": [
{"id":"transcribe-fast","labels":{"zh-CN":"快速模型","en-US":"Fast model"},"enabled":true},
{"id":"transcribe-accurate","labels":{"zh-CN":"精准模型","en-US":"Accurate model"},"enabled":true}
]
}2
3
4
5
6
7
8
9
10
11
只返回上述白名单字段,不包含实际 modelId、provider 或凭据,也不返回 legacyOption。enabled 代表管理员开关,不承诺供应商实时健康或账户准入。
尚未配置:{schemaVersion:1,version:0,updatedAt:null,configured:false,defaultOptionId:null,options:[]}。明确清空时 configured 为 true。私有配置非法或 DB 失败返回 503,错误体 {error:{code,message}},code 分别为 driver_asr_config_invalid / driver_asr_config_unavailable,Cache-Control:no-store。
正常响应使用强 ETag,Cache-Control: public, max-age=60, s-maxage=60, must-revalidate。If-None-Match 支持弱标签、标签列表和 *,命中返回 304 和相同缓存头。仅私有模型列表的原始 revision 参与摘要;只更换后台真实模型也会失效 ETag。公共 client-config 的变更不影响此接口版本,客户端不得无限延用过期配置。
语音调用
沿用 POST /api/model-gateway/v1/audio/transcriptions、OAuth scopes(vibe-board:cloud / mobile:full / model-gateway:invoke)或原 API key 权限。用 multipart/form-data:
model: driver-asr:transcribe-fast
file: <audio binary>
language: auto
response_format: json2
3
4
ASR 执行前会重新核对供应商启用状态、协议渠道可用性和实际凭据。禁用供应商、blocked/不可用渠道或缺失凭据不会发起转写,也不产生该供应的计费 attempt;其他有效后备供应仍可按原顺序执行。已发布但暂不可用的模型继续出现在统一模型目录,并标明 availability;配置页的可选择列表只保留配置就绪的供应。两种 ASR 协议都遵循 variant 显式凭据组优先于 route 默认组的规则,客户端不能指定供应商密钥。
环境 URL 从 Driver 当前受信任 API origin 派生,不能硬编码 ReAI 域名。language、prompt、temperature 等遵循原网关合同。成功 {text:"..."},请求追踪头 X-Wainao-Request-Id。原调用方身份、OAuth App 归属、余额/订阅准入、实际模型计费保留。
| 情况 | 状态 | error.code |
|---|---|---|
| 别名格式错误 | 400 | driver_asr_alias_invalid |
| 没有配置 | 503 | driver_asr_not_configured |
| 配置损坏 | 503 | driver_asr_config_invalid |
| 读取配置失败 | 503 | driver_asr_config_unavailable |
| 选项不存在 | 404 | driver_asr_option_not_found |
| 选项禁用 | 403 | driver_asr_option_disabled |
| 真实模型已下架或不支持 ASR | 503 | driver_asr_model_unavailable |
错误格式沿用 OpenAI {error:{message,type,code,param?}}。别名调用隐藏真实模型/供应商错误文案;其他鉴权、余额、供应商错误状态/代码沿用现有网关。请求时重新查当前配置和目录,不用过期别名缓存。driver-asr: 前缀永远只走别名,解析失败不会当真实模型、第一项或旧默认继续请求。
1.x 客户端选择规则
| 场景 | Driver 行为 |
|---|---|
| 无持久化选择 + 配置成功 | 可用有效、启用的 defaultOptionId 初始化 |
| 已保存新 ID | 保持该 ID;名称随当前语言 labels 更新 |
| 已保存 ID 被删/禁用 | 保留选择并提示不可用;不换成新默认或第一项 |
| 开发阶段保存了 transcribe-default 或真实模型 ID | 不能猜测对应关系,提示重新选择 |
| configured=false、空列表、配置非法或加载失败 | 分别提示未配置、无可用模型或错误;不回退早期映射 |
transcribe-default 是禁止使用的保留 ID,网关在查询配置前即返回 400 driver_asr_alias_invalid。不提供早期开发接口回退。0.x 的真实模型调用路径保留。
真实映射存 public.driver_transcription_config 私有单例表,启用 RLS/显式 deny-all,撤销 PUBLIC/anon/authenticated 读写权限,仅 service_role 可访问。site_settings 历史存储中的 cloud.transcriptionTiers 在公开与管理 client-config 输出时均被移除,新提交含此字段返回 400、issues code retired_driver_config;不执行生产数据清理。通用 App 的 cloud.asrModel/refineModel 字段仍保留,可在后台“高级 JSON → 通用 App 云端模型”编辑并点击“保存 App 配置”保存(例如省略 model 的通用转写请求使用 asrModel),这些不是 0.x Driver 默认设置,也不承诺隐藏历史公开模型数据。
迁移 20260908190000_driver_transcription_config.sql 只建私有表、ACL 和单调 revision 触发器,不初始化模型;不修改订阅/成本或旧配置。后端先上线,再上线管理页面,再由管理员选择真实模型列表,最后由 Driver 项目接入发行并真机验收。应用回滚保留私有表和 ACL;删除表前必须备份后续写入的配置并另行授权。
免费默认与 v2 公开合同
新增 GET /public/driver-transcription-config-v2,无需认证。旧 /public/driver-transcription-config 的 schemaVersion 1 与字段保持原样,私有管理配置也仍为 schemaVersion 1,不需要数据库迁移或新增管理员价格开关。
v2 保留 version/updatedAt/configured/defaultOptionId/options,schemaVersion 为 2,新增:
supportsFreeOnly: true:服务器理解并强制执行免费请求约束。freeDefaultOptionId: string | null:仅当生效默认项(见下文「生效默认项」)对应真实已发布、未归档计费规则明确billing_unit=second、合法正unit_size、price_per_unit_cents=0时返回该 ID,否则为 null;不根据显示名称或订阅特权推断免费。管理员仍可保存收费默认,客户端须显示免费默认不可用。
只返回安全选项字段,不公开真实模型、计费规则或供应商。v2 的 version 是私有配置与全部选项计费规则 revision 的最大毫秒时间(见「生效默认项」),updatedAt 同源。缺失配置仍为 version 0;非法或缺失的已存在记录 revision 返回 503,不伪造时间。强 ETag 包含当前安全投影、配置与计费规则原始 revision,价格单独变更会失效缓存;缓存上限仍为 60 秒。读取配置/价格失败为 503、Cache-Control:no-store。默认项不可用时按「生效默认项」规则回退。
自动初始化免费默认的客户端调用 ASR 时必须发送 multipart 字段 billing_policy: free-only,并在持久化、录音快照与重试中保留该策略。服务器仅允许当前明确默认别名:真实模型 ID、非默认别名、默认删除/禁用/换价、缺价均在供应商调用前拒绝,免费不可用为 403 driver_asr_free_unavailable,配置/价格读取故障为 503。未知政策值为 400 invalid_billing_policy。未发送此字段的现有按量请求行为保持原样。
已证明零价的免费请求不受余额为零或无有效订阅阻挡;鉴权、scope、API Key 权限与限额、其他现有准入保持生效。该承诺与订阅免扣无关,subscription_privilege 不能把真实正价模型变成通用免费。
在每次供应商尝试(包含 fallback)前,计费服务读取并冻结真实报价,再验证明确按秒零价、合法正 unitSize 且未要求工具用量。供应商工具价目表非空不代表 ASR 实际使用工具,零价 ASR 仍可调用;若免费 attempt 意外收到实际工具用量,只留未知账证,不结算工具费。报价变为正价/未知时在创建消费事件和调用供应商前失败关闭。读取报价故障沿用 503 billing_event_begin_failed,不会调用供应商。零价成功仍记录音频用量与计费事件,沿用既有零金额结算;不伪造模型、不改写实际价格、不切本地。免费政策进入幂等来源 hash,同一 Idempotency-Key 改变政策会产生请求绑定冲突。
这是代码与 API 合同变更;未初始化或修改生产模型配置、未连接生产数据库、未部署,也不证明当前节点已经存在可用零价默认模型。上线前必须由管理员核对真实模型价格与供应配置,Host/Voice 独立接入发行并完成授权真机验收。
生效默认项(2026-10-14)
公开 v2 与账户 v3 返回的 defaultOptionId 是生效默认项,不再原样回显管理员配置值;字段集合不变(Driver 对两份响应严格校验,不能新增字段)。规则:
- 管理员配置的默认项可用 → 用它。
- 默认项不可用 → 按管理员配置的列表顺序,取第一个启用且可用的选项。不按名称、价格或免费与否挑选。
- 存在启用项但全部不可用 → 保留管理员配置的默认项(客户端要求有启用项时默认非 null),v2 的
freeDefaultOptionId为 null,v3 的prices为空,客户端据此给出明确的"模型不可用"。没有启用项或未配置时维持 null。
"可用"与管理端保存时的校验一致:网关目录已上架、支持 ASR,且至少一个启用路由已配置供应(按当前节点)。v3 再要求当前账户报价冻结成功;报价读取故障仍整体失败,不跳过。就绪查询(汇率、目录、路由、供应视图、凭据)读取故障或超过 10 秒总期限时,v2 / v3 / free-only 一律返回 503 driver_asr_config_unavailable,不当作"不可用"触发回退。就绪检查先只查配置默认,默认可用即结束;否则以最多 5 路并发检查其余启用项。默认与回退两阶段共享同一 10 秒期限;超时或任一检查失败后不再发起新的检查,已在途的单项查询无法中断,只等其自然结束。freeDefaultOptionId 针对生效默认判断。管理员配置值本身不被改写;发生回退时后端记 [driver-asr] default_fallback 日志(仅 optionId)。
free-only 请求只接受请求当时的生效默认别名。客户端拿到配置后若默认项状态又变化(如原默认恢复),旧快照的别名按 403 driver_asr_free_unavailable 拒绝,不自动换模型、不转为付费请求。
v2 的 version 取私有配置 revision 与配置中全部选项(含禁用)对应模型计费规则修订时间(不过滤发布/软删除状态)的最大值,生效默认切换不会让 version 变小;规则被物理删除不在此保证内。仅因供应状态变化导致默认切换时 version 可能不变,ETag 随响应体变化。