Commit 70eee74e876fca6fdbd14ee30ba834499fd79265

Authored by yibo
1 parent e4edb075

补 docs/todo:记录 FL2VA/Ref2VA 互斥 bug(keyframes 会被 references 静默吃掉)

查 DiffSynth-Studio pipeline 源码确认:references 非空时 keyframes 被
静默忽略,不报错。api.py 没有校验,今天的真实任务因为 prompt 里写
@图片N 但没真的挂 reference_image_urls,误以为身份参考图生效了。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
docs/README.md
... ... @@ -18,6 +18,10 @@
18 18 时长——调研阶段,确认现有 DiffSynth-Studio 架构不支持多卡拆分;Raylight 确认支持 Turing+PCIe+
19 19 MiniMax-H3,但要换整套推理引擎,是独立迁移项目不是顺手能试的,建议先做完
20 20 quality-tuning-plan.md 里不用下载东西的两项再决定要不要推进
  21 +- [fl2va-ref2va-mutual-exclusive-bug.md](todo/fl2va-ref2va-mutual-exclusive-bug.md) — `api.py`
  22 + 同时传首尾帧和参考图时,pipeline 层会静默丢弃首尾帧、没有报错,今天的真实任务已经因为
  23 + prompt 里瞎写 `@图片N` 误以为挂了参考图踩过这个坑;要加一条校验直接拒绝这种组合,
  24 + 优先级不高但成本低,顺手做掉
21 25  
22 26 ## done
23 27  
... ...
docs/todo/fl2va-ref2va-mutual-exclusive-bug.md 0 → 100644
  1 +# api.py 的坑:同时传首尾帧和参考图,`references` 会静默吃掉 `keyframes`
  2 +
  3 +**背景**:用户问"H3 怎么把首尾帧和人物设定图一次性都给模型",对照 DiffSynth-Studio 官方
  4 +`MiniMaxH3Pipeline.__call__` 源码查清楚了——不是我们代码的锅,是这个 pipeline 本身的设计:
  5 +`keyframes`(FL2VA,首尾帧)和 `references`(Ref2VA,参考图)在打包序列这一层是**互斥**的,
  6 +`MiniMax H3Unit_PackedSequenceBuilder` 里 `if ref_blocks is not None` 走 ref2va 分支,
  7 +否则才用 keyframes——**只要 `references` 非空,`keyframes` 会被直接忽略,不报错,静默丢弃**。
  8 +
  9 +官方倒是有个 `H3-Context-IR`(真实存在,查到了官方 API 文档),专门负责编排"首帧/尾帧/身份参考图/
  10 +参考视频各自扮演什么角色"这种复杂多模态输入,但官方原话明确写了"不包含在开源发布里"——只有
  11 +调用 MiniMax 付费云端 API 才能用,本地部署这条路走不通。
  12 +
  13 +## 更麻烦的:我们自己的 `api.py` 没有任何防护,而且已经真的踩过
  14 +
  15 +`worker()` 里无条件把 `keyframes`(来自 `first_frame_url`/`last_frame_url`)和 `references`
  16 +(来自 `reference_image_urls`/`reference_video_urls`)**一起**传给 `pipe()`,`GenReq` 这个
  17 +pydantic 模型也完全没有互斥校验——用户完全可以同时填首尾帧 URL 和参考图 URL 提交,系统照单全收,
  18 +但底层会按 references 非空走 ref2va 打包,首尾帧完全不起作用,**没有任何报错或警告**。
  19 +
  20 +查了今天真实提交的任务 `ed3663dcda7f`:请求里 `reference_image_urls` 是空数组 `[]`。
  21 +prompt 文本里写的"女子、捕快面部由@图片3、@图片5锁定"这类 `@图片N` 写法是照抄官方
  22 +Context-IR 的约定,但我们本地这条链路根本不认识这个约定——那两张"设定图"从来没真的作为
  23 +图片数据挂载给模型,纯粹是 prompt 里的文字,模型只是把这几个字当普通文字理解,没有对应的
  24 +图片输入。以后写 prompt 不要用这种 `@图片N` 的写法指望它会自动关联图片,除非真的把对应
  25 +URL 填进 `reference_image_urls`。
  26 +
  27 +## 要做的事
  28 +
  29 +1. **给 `GenReq` 加一条 `model_validator`**:如果 `(first_frame_url or last_frame_url)` 和
  30 + `(reference_image_urls or reference_video_urls)` 同时非空,直接 422 拒绝,错误信息写清楚
  31 + "FL2VA 首尾帧和 Ref2VA 参考图/参考视频不能同时传,pipeline 层会静默丢弃 keyframes"——
  32 + 参考 `ROWS_LIMIT` 那条校验的写法(`api.py` 里已有先例),不是新模式。
  33 +2. **h3-console 前端也要同步**:现在"首尾帧生视频"(fl2va tab)和"多参考图生视频"(ref2va tab)
  34 + 是两个独立表单,UI 层面本来就不会让用户在同一次提交里同时填两种,这条主要是防后端被绕过
  35 + (比如有人直接调 API 不走 console),前端不用大改,但可以在 fl2va tab 的 hint 里加一句
  36 + "这个模式不支持额外挂参考图做身份锁定,要锁身份得改用 Ref2VA 模式",减少以后再犯同样的
  37 + prompt 写法误解。
  38 +3. **给用户的实际建议**(不是代码改动,是使用方式):像"延长视频+保持人物身份"这种场景,
  39 + 本地开源版做不到"首尾帧强约束 + 身份参考图"同时要,只能二选一改用纯 Ref2VA:不设
  40 + `first_frame_url`/`last_frame_url`,把"原视频最后一帧截图 + 女子设定图 + 捕快设定图"
  41 + 都塞进 `reference_image_urls`(最多 9 张),需要运镜连贯性的话再加 `reference_video_urls`
  42 + (2026-08-20 新加的字段,还没在真实 GPU 上跑过一次,见 `verify-video-reference-on-gpu.md`)。
  43 + 代价是失去"第一帧/最后一帧精确锁定"这个强约束,换成"多张参考图做柔性引导",不是等价替换。
  44 +
  45 +## 优先级
  46 +
  47 +不着急——这是个"用错了会静默出错"的边界情况,不是现在正在发生的故障。但比起线上突然出现
  48 +"明明传了首尾帧却不起作用"的困惑,加一条清晰的 422 报错成本很低(半小时内能写完,参考
  49 +`ROWS_LIMIT` 校验抄一遍就行),建议跟 `quality-tuning-plan.md` 里的实测一起顺手做掉,
  50 +不用单独排期。
... ...