diff --git a/knowledge/repos/vllm-omni/models/minimax-h3/_index.md b/knowledge/repos/vllm-omni/models/minimax-h3/_index.md index 39d21659..85aa71cc 100644 --- a/knowledge/repos/vllm-omni/models/minimax-h3/_index.md +++ b/knowledge/repos/vllm-omni/models/minimax-h3/_index.md @@ -171,3 +171,4 @@ CPU-only validation limit 见 [encoder state rules](rules-encoder-state.md)。 - [latent upscaler、second-pass refinement 与容量门禁](rules-latent-refinement.md) - [MiniMax-H3 VDNH3 checkpoint 与请求合同](rules-vdnh3.md)。 +- [MiniMax-H3 audio VAE 确定性规则](rules-audio-vae-determinism.md) diff --git a/knowledge/repos/vllm-omni/models/minimax-h3/rules-audio-vae-determinism.md b/knowledge/repos/vllm-omni/models/minimax-h3/rules-audio-vae-determinism.md new file mode 100644 index 00000000..b6f35b3c --- /dev/null +++ b/knowledge/repos/vllm-omni/models/minimax-h3/rules-audio-vae-determinism.md @@ -0,0 +1,19 @@ +--- +title: "MiniMax-H3 audio VAE 确定性规则" +created: 2026-10-23 +updated: 2026-10-23 +type: rule +tags: [vllm-omni, models, diffusion] +sources: ["PR #8802"] +--- + +# MiniMax-H3 audio VAE 确定性规则 + +## VLLM-OMNI-PR8802-AUDIO-JIT-DETERMINISM — audio VAE 必须固定 TorchScript executor 路径,输出不得依赖请求顺序 + +- 触发:修改 MiniMax-H3 audio VAE 的 `decode_latent`/encode 调用、`_AudioVAEDeterminismContext`,或任何调用远端 checkpoint `@torch.jit.script` 代码(本例为远端 `dac_activations.py` 的 `snakebeta`/SnakeBeta activation)的执行路径。 +- 强制:TorchScript profiling executor 首次调用按 unfused 运行、后续调用按 fused 运行,两条路径的 FP32 舍入不同,会使同一 server 进程内首个请求与后续相同请求的音频输出不同。`MiniMaxH3AudioVAE.decode_latent` 必须在 `torch.jit.optimized_execution(False)` 上下文中调用 `self.remote.decode(...)`;encode 路径已复用的 `_AudioVAEDeterminismContext` 必须在 `__enter__` 进入同一设置、`__exit__` 恢复进入前的 executor optimize 状态,不得把全局设置泄漏给进程其余部分。 +- 禁止:把“第二次请求起输出稳定”当作 fixed-seed 确定性合格;仅凭 audio latent 逐位相同或视频 bitwise 一致断言音频输出确定(本例两者均相同,差异来自 decoder 舍入);在 decode/encode 作用域之外关闭 executor 优化且不恢复;隐瞒修复后音频 md5 相对 `main` 稳态输出改变的事实而不按舍入幅度论证(PR 实测:unfused/fused 两条 executor 路径的 waveform 最大绝对差为 2.4e-7、AAC 编码后可见;修复后 waveform 与 `main` 输出的最大绝对差 ≤7.3e-7,属 FP32 舍入幅度,不是解码音频流的端到端差值)。 +- 验收:CPU 单测以 recording decoder 断言 `decode_latent` 的每次远端调用期间 `torch._C._get_graph_executor_optimize()` 为 False、调用结束后恢复原值,`_AudioVAEDeterminismContext` 同样禁用并恢复(PR 中两个测试在 `main` 上失败);E2E 在真实 recipe profile(PR:2×Radeon AI PRO R9700、ROCm 7.2、TP2)下对同一 server 进程连发 3 个相同 T2VA 请求(PR:1344×768、4 s、1 step、seed 42),断言解码音频流 md5(`ffmpeg -map 0:a -f md5`)三次全部一致且视频 md5 不变;可用 hook 比对 `decode_latent` 的输入/输出定位差异层,并测量 audio decode 耗时无可测回归(PR:812-819 ms 不变)。^[PR #8802] + + diff --git a/knowledge/repos/vllm-omni/models/qwen-image/rules.md b/knowledge/repos/vllm-omni/models/qwen-image/rules.md index 6be67383..8663f1b6 100644 --- a/knowledge/repos/vllm-omni/models/qwen-image/rules.md +++ b/knowledge/repos/vllm-omni/models/qwen-image/rules.md @@ -1,10 +1,10 @@ --- title: "Qwen-Image 实现规则" created: 2026-09-02 -updated: 2026-10-10 +updated: 2026-10-23 type: rule tags: [vllm-omni, models, diffusion] -sources: ["PR #5887", tests/e2e/accuracy/test_qwen_image.py, "PR #6110", vllm_omni/diffusion/models/qwen_image/qwen_image_transformer.py, "PR #5586", "PR #7513", "PR #8699"] +sources: ["PR #5887", tests/e2e/accuracy/test_qwen_image.py, "PR #6110", vllm_omni/diffusion/models/qwen_image/qwen_image_transformer.py, "PR #5586", "PR #7513", "PR #8699", "PR #9272"] confidence: high --- @@ -60,3 +60,13 @@ confidence: high - 验收:CPU 单测覆盖 extras 三种情形(从 model_index 提取、缺失不写入、显式非 `None` extras 不被覆盖)与 `prepare_timesteps` 优先级(请求 sigmas 胜出、config 网格决定步数并压过 `num_inference_steps`、无网格回退 linspace);断言请求未携带 sigmas 时步数解析等于网格长度;extra_body `sigmas` 在 `/v1/chat/completions` 与 `/v1/images/generations` 均可覆盖默认网格。Turbo 的 CFG=1 用法与 Qwen Research License 属 checkpoint 使用约束,不是本规则的验收对象。^[PR #8699] + +## VLLM-OMNI-PR9272-QWEN21-IDLE-KV-GRAPHS — decode graph 静态 prefix KV 必须在下次 prefill 前按 owner 存活状态释放 + +- 触发:修改 `vllm_omni/diffusion/models/qwen_image_21/decode_graph.py` 中 `QwenImage21DecodeGraphManager` 的 entry/owner 生命周期(`release_idle_entries`、`_owners` weakref 表、`max_entries` LRU、`clear`),或 `pipeline_qwen_image_21.py` 的 `release_step_request`、`_release_idle_decode_graphs`、`_denoise_step_homogeneous` 的 prefill 相位判定,或 `cfg_parallel.py` `diffuse()` 中 prefill 前的清理,以及 Qwen-Image-2.1 前缀 K/V(`_scatter_kv_cache` clone)与 request geometry 的请求退役路径。 +- 强制:graph key 含 batch size、prefix length 与完整 `img_shapes`,每个 entry 由指向请求 prefix K tensor 的 weakref 拥有。owner 已死亡或未记录的 entry 必须在下一次 prefill clone 新 prefix 之前经 `release_idle_entries()` 释放:`cfg_parallel.diffuse()` 与 step 路径 `_denoise_step_homogeneous`(`_kv_cache_phase(...) == "prefill"` 时)都要触发,确有释放时调用 `current_omni_platform.empty_cache()`;owner 仍存活的 entry 必须保留,让并发请求继续 replay——放弃同 key 复用的代价只是下一次请求多付一次 recapture。 +- 强制:请求退役走 `release_step_request`:显式置空 `extra["kv_cache"]` 并调用 `release_request_geometry()`,但不动 graph 表,dead entry 留到下一次 prefill 释放。跨请求累积的是 graph 侧静态 prefix 拷贝(普通 tensor,不是 CUDA graph private pool),不是随请求结束被丢弃的 `state.extra["kv_cache"]`。 +- 禁止:把 `max_entries`(默认 8)的 LRU 淘汰当成唯一回收路径——每张图按自身宽高比 resize(`calculate_dimensions`)后重排即改变 `img_shapes`、更换 key,静态拷贝跨请求堆积,在下一次 `_scatter_kv_cache` clone 时 OOM(#8831;#8760 的 retention 修复不覆盖这份拷贝);为保留同 key 复用而留下 dead-owner entry;请求退役时 `clear()` 整个 graph 表或释放 live-owner entry;用关闭默认开启的 `causal_condition` 掩盖泄漏(报告中延迟约 11 s → 36 s)。 +- 验收:CPU 单测以 weakref + `gc.collect()` 断言 `release_idle_entries()` 后 dead-owner key 从 `entries`/`_owners` 消失且静态 prefix 张量可回收(weakref 归 None)、live key 保留且 `_owners[live_key]()` 仍指向在飞请求的 key tensor;`release_step_request` 置空 kv_cache 与 geometry 且不调用 `clear`/`release_idle_entries`;prefill 路径断言 `release_idle_entries` 恰好被调用一次。weakref 单测证明的是 entry 生命周期机制,不构成 GPU 端到端 OOM 已消除的证据。^[PR #9272] + +