From 89acb08ea9092a22b55e35a3eb0bd7ae950fcec6 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Sun, 6 Sep 2026 20:45:44 +0800 Subject: [PATCH] =?UTF-8?q?fix(platform):=20r2v=E5=AA=92=E4=BD=93=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E9=9D=9E=E5=BF=85=E5=A1=AB+=E5=90=88=E6=88=90?= =?UTF-8?q?=E6=A8=A1=E6=9D=BFmedia=E9=94=AE=E6=9D=A1=E4=BB=B6=E6=B8=B2?= =?UTF-8?q?=E6=9F=93(2026-09-06=E7=94=A8=E6=88=B7=E7=BA=A0=E6=AD=A3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户纠正:wan3.0全能参考三种媒体一个不传=纯文生视频(t2v),完全合法(文档明示 「prompt和media必填其一」「文生视频不传入任何媒体文件」)。此前required=True把 合法t2v/部分组合模式堵死,且无条件渲染发出"media": []空数组(文档t2v形态不带 media键,API未承诺接受空数组,不能赌)。 - _build_param_schema: 媒体字段一律required=False(prompt保持必填作锚); 纯参考模型空媒体提交由API拒绝+test_model_call当场暴露,非静默失败 - r2v合成模板media键包Jinja条件:有媒体渲染media键,零媒体整个省略, 两形态逐字对齐官方API参考(wan3-video-generation-api-reference已核实) - 拼接空格防"{{%"词法错(单测实抓) - _dry_render_check增零媒体形态干跑(StrictUndefined下测空数组[],不测缺键) - 单测9项:零媒体省略/部分组合/三模态顺序/干跑/schema非必填 --- pipeline_platform/platform_ability.py | 39 ++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/pipeline_platform/platform_ability.py b/pipeline_platform/platform_ability.py index f7e5571..f832eae 100644 --- a/pipeline_platform/platform_ability.py +++ b/pipeline_platform/platform_ability.py @@ -1272,14 +1272,29 @@ def _gen_templates(protocol: str, capability: str, spec: dict) -> dict: expr, mps = _media_array_expr(synth) m = _re.search(r'("input"\s*:\s*\{)', req) if expr and m: + # 条件渲染(2026-09-06 用户纠正后补):wan3.0 类全能参考模型 + # 文档明示「prompt 和 media 必填其一」「文生视频不传入任何媒体 + # 文件」——零媒体是合法 t2v 形态,且文档 t2v 示例**不带 media + # 键**;无条件渲染会发出 "media": [] 空数组(API 未承诺接受, + # 不能赌)。有媒体才渲染 media 键,零媒体整个省略。 + anyexpr = ' or '.join( + '(params.%s if params.%s is not string and params.%s else ' + '([params.%s] if params.%s is string else []))' + % ((mp,) * 5) for mp in mps) + # 空格不可省:media_seg 以 {% 开头,紧跟 input 的 { 会拼成 + # "{{%" —— Jinja 词法把 {{ 当变量表达式开始 → unexpected '%' + # (2026-09-06 单测实抓)。JSON 空白无副作用。 + media_seg = (' {%% if %s %%}"media": %s, {%% endif %%}' + % (anyexpr, expr)) pos = m.end() - req = req[:pos] + '"media": %s, ' % expr + req[pos:] + req = req[:pos] + media_seg + req[pos:] for mp in mps: if mp not in media_params: media_params.append(mp) notes.append("示例未见参考媒体(页面示例为纯文本最简形态)," "r2v 契约合成 input.media 数组(reference_image/" - "video/audio 三类,DashScope 家族契约)——" + "video/audio 三类,DashScope 家族契约),零媒体时" + "省略 media 键(对齐文档 t2v 形态)——" "建议对照供应商 API 参考页人工核对") except Exception as _e: notes.append("r2v 媒体合成失败(%s),示例未见上传字段,请人工核对" % str(_e)[:80]) @@ -1478,7 +1493,15 @@ def _build_param_schema(capability, media_params, biz_params, enums=None): continue seen.add(mp) schema.append({'name': mp, 'label': _MEDIA_LABEL.get(mp, mp), - 'uitype': _MEDIA_UITYPE.get(mp, 'file'), 'required': True, + 'uitype': _MEDIA_UITYPE.get(mp, 'file'), + # 媒体一律非必填(2026-09-06 用户纠正):全能参考模型(wan3.0) + # 三类媒体可自由组合、且允许全不传——全不传即纯文生视频(t2v)。 + # 文档明示「prompt 和 media 必填其一」「文生视频仅通过 prompt, + # 不传入任何媒体文件」。required=True 会把合法的 t2v / 部分组合 + # 模式全堵死。prompt 保持必填,作「必填其一」的锚。 + # 纯参考模型(无 t2v 模式)若空媒体提交,API 会拒、test_model_call + # 当场暴露,非静默失败——故 UI 层一律非必填是安全默认。 + 'required': False, # 三数组契约:UI 允许多选,值成数组;运行时兼容字符串/数组两形态 'multiple': True}) for b in biz_params: @@ -1526,7 +1549,15 @@ def _dry_render_check(req_tpl, capability, biz_params, media_params): params_arr[mp] = ['https://dry-run.invalid/sample.bin'] params_str[mp] = 'https://dry-run.invalid/sample.bin' errors = [] - for tag, params in (('数组形态', params_arr), ('字符串形态', params_str)): + for tag, params in (('数组形态', params_arr), ('字符串形态', params_str), + # 零媒体形态(2026-09-06):全能参考模型(r2v)文档明示 + # 「prompt 和 media 必填其一」,零媒体=合法 t2v 模式且 + # 文档示例不带 media 键——模板条件渲染的 False 分支 + # 必须干跑出合法 JSON(省略 media 键,非空数组)。 + # 只测空数组 [](运行时真实「未选媒体」场景,schema 字段 + # 存在值为空);不测缺键——运行时用默认 Undefined 容错, + # StrictUndefined 下缺键会误报,二者行为不一致。 + ('零媒体形态', dict(params_arr, **{mp: [] for mp in media_params or []}))): ns = {'model': 'dry-run-model', 'prompt': '干跑校验', 'messages': [], 'params': params, 'api_key': 'sk-dry-run', 'org_id': '0', 'request': None, 'json': json,