From 53e8e62ce3d867b387710ede3bb88d011e9979fd Mon Sep 17 00:00:00 2001 From: vllm-omni-review-bot Date: Fri, 18 Sep 2026 15:41:11 +0800 Subject: [PATCH] knowledge: daily intake batch 2026-09-18 --- knowledge/repos/vllm-omni/benchmark/rules.md | 9 ++++++++- .../components/diffusion/rules-system-runtime.md | 9 ++++++++- knowledge/repos/vllm-omni/models/cosyvoice3/rules.md | 9 ++++++++- .../models/minicpm-o-4-5/rules-cuda-graphs.md | 10 +++++++++- .../vllm-omni/models/minicpm-o-4-5/rules-duplex.md | 9 ++++++++- knowledge/repos/vllm-omni/models/qwen-image/rules.md | 9 ++++++++- knowledge/repos/vllm-omni/models/qwen-omni/rules.md | 9 ++++++++- 7 files changed, 57 insertions(+), 7 deletions(-) diff --git a/knowledge/repos/vllm-omni/benchmark/rules.md b/knowledge/repos/vllm-omni/benchmark/rules.md index 33a1ef84..c5450feb 100644 --- a/knowledge/repos/vllm-omni/benchmark/rules.md +++ b/knowledge/repos/vllm-omni/benchmark/rules.md @@ -1,7 +1,7 @@ --- title: "vLLM-Omni Benchmark 规则" created: 2026-09-05 -updated: 2026-09-10 +updated: 2026-09-18 type: rule tags: [vllm-omni, benchmark] sources: ["PR #6817", tests/dfx/perf/scripts/run_benchmark.py, tests/benchmarks/test_omniinteract.py, "PR #7130", "PR #7259"] @@ -60,3 +60,10 @@ confidence: high - 强制:轮询 deadline 来自 per-request `video_job_timeout`(默认 900s,可 CLI 加大),从 job 创建后起算含排队;仅当 status 仍非 `completed`/`failed` 且超时才判失败。progress/latency 在 cleanup 路径更新,使失败请求也推进进度条;报告打印失败数与样例错误,JSON 写入全部 `request_errors`。 - 禁止:硬编码 600s 后删除仍可能完成的 job;成功路径才 `pbar.update`;只报告成功计数而隐藏失败原因。 - 验收:覆盖默认/加大 timeout、deadline 时已 `completed` 仍取回、混合成功/失败时进度与 `failed_requests`/`request_errors` 一致。^[PR #7259] + +## BENCH-1f — benchmark 结果必须始终导出样本计数,包括零 + +- 触发:修改 `benchmarks/patch` 的 result dict,或 DFX 对 `num_tpot_samples` 等计数字段的读取。 +- 强制:`calculate_metrics()` 已经产出的 `num_ttft_samples`、`num_tpot_samples`、`num_itl_samples`、`num_audio_ttfp_samples`、`num_audio_rtf_samples` 必须写入结果,包括 0,且与 percentile 是否被选中无关。JSON 往返后字段仍在。缺键是 `None`,不是 0;DFX 在 finite `mean_tpot_ms` 下仍会因 `isinstance(None, int)` 失败。 +- 禁止:只在选中 TPOT/ITL percentile 时写出计数;用均值存在代替样本数字段;改 DFX 判定去迁就缺字段的 JSON。 +- 验收:真实聚合加 JSON round-trip,分别覆盖 measured/unmeasured TPOT 与选中/未选中 percentile;省略 `num_tpot_samples` 而保留 finite mean 的结果必须被 baseline 拒绝。^[PR #7624] diff --git a/knowledge/repos/vllm-omni/components/diffusion/rules-system-runtime.md b/knowledge/repos/vllm-omni/components/diffusion/rules-system-runtime.md index 6bec90c7..bed26ca5 100644 --- a/knowledge/repos/vllm-omni/components/diffusion/rules-system-runtime.md +++ b/knowledge/repos/vllm-omni/components/diffusion/rules-system-runtime.md @@ -1,7 +1,7 @@ --- title: "Diffusion paged cache 与系统运行时规则" created: 2026-09-03 -updated: 2026-09-09 +updated: 2026-09-18 type: rule tags: [vllm-omni, components, diffusion] sources: ["PR #5255", "PR #5344", "PR #5543", "PR #5838", "PR #6094", "PR #6102", "PR #6385", "PR #6340", "PR #6714", "PR #6814", "PR #6563", "PR #5716", "PR #6786", vllm_omni/diffusion/attention/, vllm_omni/diffusion/attention/parallel/ulysses.py, vllm_omni/diffusion/attention/parallel/ring_kernels.py, vllm_omni/diffusion/diffusion_kv/, vllm_omni/diffusion/distributed/cfg_parallel.py, vllm_omni/diffusion/distributed/parallel_state.py, vllm_omni/diffusion/worker/diffusion_model_runner.py, vllm_omni/platforms/interface.py, vllm_omni/platforms/npu/platform.py, tests/diffusion/diffusion_kv/, tests/diffusion/distributed/test_cfg_parallel.py, tests/diffusion/attention/test_piecewise_attn.py, tests/diffusion/attention/test_ulysses_uaa.py, "PR #5491", "PR #5194", "vllm_omni/diffusion/data.py", "vllm_omni/diffusion/utils/hf_utils.py", "PR #7041", "PR #6463", "PR #6844"] @@ -226,3 +226,10 @@ confidence: high - 强制:一次 `generate()` 驱动整段 rollout:`prepare_encode` 只跑一次,随后多轮 `denoise_step`/`step_scheduler`,由 `post_decode` 产出每个 AR chunk。request-mode 与 stepwise 必须共用同一份 block/DMD math,禁止维护两套可漂移实现。runner 仅为实现该合同的 pipeline 打开 `step_execution`;绑定 runner-owned KV 时 `session_id == request_id`;错误路径 fail-closed 释放 session,完成或 scheduler abort 时退役。持有 AR-Diffusion paged KV 的 stage 必须保持 `max_num_seqs=1`。 - 禁止:用多次 `generate()`/tick 冒充同一 session;在 denoise step 内提交本应属于 `post_decode` 的 clean-x0 KV commit;或把逐步 camera/prompt mid-request interaction 写成已由本合同覆盖。 - 验收:覆盖 stepwise 与 request-mode 的共享 math 边界、session bind/release、abort/completion 退役,以及 `max_num_seqs=1` 拓扑;request-scoped camera script 等模型字段另由模型 owner 验收,不得外推为通用 mid-request interaction。^[PR #6844] + +## DIFF-4ad — 无法合成观测的 pipeline 必须退出通用文本 warmup + +- 触发:修改 `DiffusionEngine.run_startup_warmup`、`dummy_run_num_frames`,或新增必须携带非文本观测(如 `robot_obs`)的 diffusion pipeline。 +- 强制:通用 startup warmup 是文本、两步请求。pipeline 无法从该请求合成所需观测时,必须声明 `dummy_run_num_frames: ClassVar[int] = 0`,使 `run_startup_warmup` 不提交请求、也不因此 `close`。模型自有 warmup(如 AR-Diffusion 的 `ar_diffusion_warmup_requests`)保持可用。能接受文本 dummy 的模型仍走两步通用 warmup。 +- 禁止:把 DreamZero/LingBot 的 opt-out 扩成所有模型跳过 warmup;用一步 shortcut 让非法文本请求穿过观测检查;opt-out 后仍断言 engine 被关闭。 +- 验收:经真实 registry 查找,DreamZero 与 LingBot 的 startup 不调用 `add_req_and_wait_for_response` 且不 `close`;其余模型的两步 dummy 合同不变。^[PR #7548] diff --git a/knowledge/repos/vllm-omni/models/cosyvoice3/rules.md b/knowledge/repos/vllm-omni/models/cosyvoice3/rules.md index 98510708..c6fce6eb 100644 --- a/knowledge/repos/vllm-omni/models/cosyvoice3/rules.md +++ b/knowledge/repos/vllm-omni/models/cosyvoice3/rules.md @@ -1,7 +1,7 @@ --- title: "CosyVoice3 规则" created: 2026-09-04 -updated: 2026-09-05 +updated: 2026-09-18 type: rule tags: [vllm-omni, models] sources: ["PR #5673", "PR #6955", vllm_omni/model_executor/models/cosyvoice3/code2wav_core/cfm.py, vllm_omni/model_executor/models/cosyvoice3/flow_estimator_trt.py, tests/model_executor/models/cosyvoice3/test_cosyvoice3_components.py, benchmarks/tts/benchmark_cosyvoice3_trt_streams.py] @@ -50,3 +50,10 @@ confidence: high 证明 replace 失败保留旧 plan、cleanup 失败保留 replace error、partial write 清理 owned tmp、 collision 保留 foreign tmp,以及两条同步 publisher 使用不同 source path 且仅留下完整 final plan。 ^[PR #6955] + +## COSYVOICE3-1c — 流式 HiFT 必须在有界 mel 窗上增量计算并携带相位 + +- 触发:修改 CosyVoice3 `_stream_hift_from_feat`、`CausalHiFTGenerator`、`SineGen`/`SineGen2` 的 `phase_acc`,或 streaming chunk 的 noise/F0 cache。 +- 强制:每个 chunk 只在有界 mel 窗上计算(末 64 帧再加上 F0 感受野历史),不得对累积全谱重跑。谐波相位用共享的边界 `phase_acc` 带入下一窗。noise 必须是固定、按位置索引的 buffer,不能用随 chunk 变化的 `torch.randn_like`。F0 predictor 的左因果卷积要吃 window 左侧的真实历史,不能零填充;这段 margin 属于 `cache_state`,在进入 SineGen/decode 前切掉,且短于感受野的 chunk 不得饿死下一次调用。finalize 除 `conv_pre_look_right` 外还要释放 predictor 自己扣下的 `trim`,否则流末约 3 个 mel 帧丢失。 +- 禁止:用 PCM16 逐字节相等当正确性门槛(亚 LSB 的再结合误差会翻边界样本);只测未触发 voiced 的随机权重;把 `scipy`/`s3tokenizer` 放回 dev extra——它们是 base install 的硬依赖,scipy 下限保持 `>=1.11.0`。 +- 验收:相对全量重算,float64 应逐位一致;float32 用 `assert_close(atol=1e-6, rtol=1e-5)`。同时覆盖 SineGen(22050 Hz)与 SineGen2(24000 Hz)、强制 voiced,以及均匀 chunk 和单 mel 帧的小块。^[PR #7521] diff --git a/knowledge/repos/vllm-omni/models/minicpm-o-4-5/rules-cuda-graphs.md b/knowledge/repos/vllm-omni/models/minicpm-o-4-5/rules-cuda-graphs.md index 81684725..0b87a09c 100644 --- a/knowledge/repos/vllm-omni/models/minicpm-o-4-5/rules-cuda-graphs.md +++ b/knowledge/repos/vllm-omni/models/minicpm-o-4-5/rules-cuda-graphs.md @@ -1,7 +1,7 @@ --- title: "MiniCPM-o 4.5 Code2Wav CUDA graph 规则" created: 2026-09-04 -updated: 2026-09-04 +updated: 2026-09-18 type: rule tags: [vllm-omni, models, model-executor] sources: [vllm_omni/model_executor/models/cosyvoice3/code2wav_core/hifigan.py, vllm_omni/model_executor/models/minicpmo_4_5/batched_token2wav.py, vllm_omni/model_executor/models/minicpmo_4_5/cuda_graph_wrapper.py, tests/model_executor/models/minicpmo_4_5/test_cfm_graph_capture_gating.py, tests/model_executor/models/minicpmo_4_5/test_cuda_graph_wrapper.py, "PR #5869", "PR #6082", "PR #6587"] @@ -26,3 +26,11 @@ confidence: high - 强制:warmup 或 capture 发生异常时,在该 wrapper 的剩余生命周期内保持禁用并退休其自有 generation;不能在可能脏的 capture stream/allocator 状态继续捕获。无法由 key 重建的 dtype 仅标记该 shape eager,不得禁用其他可捕获 shape;capture admission 不得依赖 device free-memory。维护固定字段的 calls/hits/captures/flushes/eager 累计 telemetry。 - 禁止:捕获整个 `_estimator_step` 或手写替代 graph target;使用无界 shape cache、逐图 eviction、跨 owner 的 process-wide cleanup,或在 nested capture 中重放;捕获失败后伪装成功;把 CFM graph 的配置、性能或 parity 结论外推到 HiFT、encoder、TRT 或其他模型。 - 验收:CUDA 测试覆盖 uncached/cached shape 的 graph/eager 数值 parity、`None` cache parity、lazy capture、整代 flush 后 HiFT replay parity、capture/warmup failure 后不再 capture、unsupported dtype shape-local eager 与 `max_graphs <= 0` eager;CPU/mock 覆盖 active capture/non-CUDA、free-memory 非 gating、telemetry 和 inert non-CUDA memory reporting,并确认 deploy 配置值实际到达 estimator。^[PR #6082] ^[PR #6587] + +## MCPMO-1k — CFM graph 的变长 chunk 必须先对齐帧桶,padding 不得进入 cache + +- 触发:修改 MiniCPM-o 4.5 Code2Wav 的 CFM decode chunk、`cfm_graph_bucket_frames`、reference-audio 长度,或 attention/CNN cache 边界。 +- 强制:捕获前把 mel 帧 pad 到 `bucket_frames` 的倍数,输出再裁回有效帧,使 chunk 长度落在同一 grid。每份开启 CFM graph 的 shipping profile 必须显式写 `cfm_graph_bucket_frames`(当前 16),不能靠代码默认。`bucket_frames <= 1`、graphs 已禁用、ragged valid-lengths,或 pad 会越过 decoder noise capacity 时不 pad。 +- 强制:padded 列必须被真实 `attn_mask` 排除;零 key 仍会计入 softmax 分母。成为下一 chunk 的 key 或左上下文之前,清零 attention cache 的 padded 列,以及各 block CNN cache 中来自 padding 的尾部。speaker 向量会铺满每一帧,清零必须作用在 clone 上。conditioning pad 复制最后一帧有效值。reference audio 先转 mono、抗混叠重采样到 24 kHz,再按 `ref_audio_max_seconds`(默认 6s)截断或补零,使各请求共享一个 L0;默认 prompt 走同一路径,`soundfile` 的 `(samples, channels)` 先转置。 +- 禁止:让首尾 chunk 或 `plan_token2wav_encode_slices` 的任意长度各自成为 graph key;只清零 `x`/`mu`/`cond` 而留下非零 speaker 列;把桶化 parity 外推到 HiFT、TRT 或其他模型。 +- 验收:覆盖 pad/trim、noise overflow 不 pad、attn_mask 与 cache 清零、reference 归一化后的单一 L0,以及四份 CFM-graph profile 都带上 `cfm_graph_bucket_frames`。^[PR #7416] diff --git a/knowledge/repos/vllm-omni/models/minicpm-o-4-5/rules-duplex.md b/knowledge/repos/vllm-omni/models/minicpm-o-4-5/rules-duplex.md index 261f292e..b2777878 100644 --- a/knowledge/repos/vllm-omni/models/minicpm-o-4-5/rules-duplex.md +++ b/knowledge/repos/vllm-omni/models/minicpm-o-4-5/rules-duplex.md @@ -1,7 +1,7 @@ --- title: "MiniCPM-o 4.5 native duplex 规则" created: 2026-09-04 -updated: 2026-09-08 +updated: 2026-09-18 type: rule tags: [vllm-omni, models, model-executor] sources: ["PR #6318", "PR #6346", "PR #6404", "PR #6458", "PR #6619", "PR #6630", "PR #6678", "PR #6626", "PR #6767", "PR #6821", vllm_omni/deploy/minicpmo_4_5.yaml, vllm_omni/model_executor/models/minicpmo_4_5/minicpmo_4_5_omni_tts.py, vllm_omni/model_executor/stage_input_processors/minicpmo_4_5_omni.py, tests/model_executor/models/minicpmo_4_5/test_talker_batching.py, vllm_omni/deploy/minicpmo_4_5_2gpu.yaml, vllm_omni/deploy/minicpmo_4_5_3gpu.yaml, vllm_omni/deploy/minicpmo_4_5_8x4090.yaml, examples/online_serving/minicpmo/realtime_duplex_demo.py, vllm_omni/experimental/fullduplex/client.py, vllm_omni/model_executor/models/minicpmo_4_5/duplex/adapter.py, vllm_omni/model_executor/models/minicpmo_4_5/duplex/session.py, vllm_omni/model_executor/models/minicpmo_4_5/duplex/stage0.py, vllm_omni/entrypoints/duplex/realtime_input.py, vllm_omni/entrypoints/duplex/runtime_adapter.py, vllm_omni/entrypoints/duplex/runtime_bridge.py, vllm_omni/entrypoints/duplex/serving.py, vllm_omni/entrypoints/duplex/session_runner.py, vllm_omni/experimental/fullduplex/video_stacking.py, tests/config/test_config_factory.py, tests/engine/duplex/test_duplex_deploy_config.py, tests/e2e/online_serving/helpers/minicpmo_4_5_duplex.py, tests/e2e/online_serving/test_minicpmo_4_5_duplex_expansion.py, tests/entrypoints/openai_api/test_duplex_handler.py, tests/examples/test_minicpmo_realtime_duplex_simple_demo.py, "PR #6529", vllm_omni/entrypoints/duplex/protocol.py, vllm_omni/entrypoints/duplex/realtime_state.py, tests/entrypoints/openai/test_duplex_protocol.py, "PR #6799"] @@ -113,3 +113,10 @@ confidence: high - 强制:默认遵循 checkpoint 声明的 `full_attention`;在该模式下,只要「下一 condition + codec-generation reserve」仍落在由 runtime `max_model_len` 与 `tts_config.max_position_embeddings` 导出的有效上限内,就必须保留已累积的 Talker KV/history 并追加;仅在严格溢出时才重建受支持的 one-previous-condition 窗口,释放旧 KV/encoder 与 connector watermark,重置异步 replacement state,并让请求重新进入 admission。精确贴合上限时允许 append,之后继续累积直至下次溢出。显式 `sliding_recompute` 仍在每个 condition 边界重算;正整数 `meta.next_stage_prompt_len` 是 scheduler 的权威 placeholder 长度,合法 Talker condition 即使缺少 legacy `ids.prompt` 也必须先 append 真实 prompt 再推进 sequence/lifecycle。 - 禁止:把无条件 per-condition recompute 当作生产默认;硬编码 `4096` 当作有效上限;在未溢出时丢弃可保留的 Talker history;或把本路径写成已支持物理 KV preemption 后的增量 full-attention replay。 - 验收:覆盖 fit/exact-fit/overflow、producer-owned 与 receiver-owned sequencing 兼容、`next_stage_prompt_len` 驱动的 append,以及显式 `sliding_recompute` 仍按边界重算;不得用 capacity-triggered rollover 的通过外推为已修复无关 perf 回归。^[PR #6799] + +## MCPMO-4j — shipping profile 不得再写入正的 active_stream_window + +- 触发:修改四份 `minicpmo_4_5*.yaml` 的 `active_stream_window`,或 `ChunkTransferAdapter` 的有界 `_promote_active_streams` 路径。 +- 强制:这些 profile 省略该键,使默认 `0` 关闭 limiter,adapter 留在 unlimited path。配置测试断言 `active_stream_window == 0`,而不是 `== max_sessions`。8×4090 的并发上限仍由 stage `max_num_seqs=1` 承担,不靠窗口 1。 +- 禁止:为恢复 first-packet 并发把正窗口写回这四份 profile;把窗口等于 session capacity 的旧断言写回测试。任何正值都会离开 unlimited path。 +- 验收:四份 base profile 展开后窗口为 0,且默认 serve 不进入 K-bounded promote。^[PR #7416] diff --git a/knowledge/repos/vllm-omni/models/qwen-image/rules.md b/knowledge/repos/vllm-omni/models/qwen-image/rules.md index de22ce21..0f1b28bc 100644 --- a/knowledge/repos/vllm-omni/models/qwen-image/rules.md +++ b/knowledge/repos/vllm-omni/models/qwen-image/rules.md @@ -1,7 +1,7 @@ --- title: "Qwen-Image 实现规则" created: 2026-09-02 -updated: 2026-09-08 +updated: 2026-09-18 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"] @@ -44,3 +44,10 @@ confidence: high - 强制:有 negative prompt 且启用 true CFG 时,正负两侧都使用各自 embed width;无 negative prompt 时 negative length 必须是 `None`,不能伪造一个来自正分支 mask 的长度。 - 禁止:在 Edit path 回退到 `mask.sum()`,即使别的 Qwen-Image pipeline 仍正确;或仅以 helper test 证明 RoPE table 正确而不锁定实际 `forward()` call site。 - 验收:以 padded embeds 但较短 valid-token mask 的 request 覆盖 Edit `forward()`,精确断言传入 `diffuse()` 的长度等于 padded width;同时覆盖有/无 negative prompt 的 CFG 分支,防止单侧回归。^[PR #5586] + +## QWENIMG-1d — CUDA eager RoPE 必须走激活 dtype 的 RotaryEmbedding + +- 触发:修改 Qwen-Image `_qwen_image_qk_norm_rope` 的 CUDA/eager 分支、`RotaryEmbedding` 调用,或把 RoPE 放进 regional compile。 +- 强制:所有设备的 eager 路径在 RMSNorm 之后使用 `RotaryEmbedding`;`cos`/`sin` 由 `torch.real`/`torch.imag` 得到并 cast 到激活 dtype(BF16)。这是 pipeline 对 Diffusers 的路径。fused kernel 可以继续对照 FP32 complex multiply,但那不是 eager CUDA 路径。 +- 禁止:在 eager CUDA 上恢复 `_apply_qwen_image_rotary_emb` 或其它 FP32 复数乘。该 helper 能在单元测试里对齐 Diffusers `apply_rotary_emb_qwen(..., use_real=False)`,但 Inductor 不能 codegen 复数算子,且会把 Omni↔Diffusers pipeline PSNR 打到门限以下。不要用 `--enforce-eager` 掩盖,也不要为迁就 helper 去降 pipeline gate。 +- 验收:`use_fused=False` 对所有设备对照 `RotaryEmbedding`;fused 测试单独对照 FP32 complex reference。eager CUDA 与 fused reference 不得再共用同一个 expected。^[PR #7513] diff --git a/knowledge/repos/vllm-omni/models/qwen-omni/rules.md b/knowledge/repos/vllm-omni/models/qwen-omni/rules.md index db1db3c9..f145323c 100644 --- a/knowledge/repos/vllm-omni/models/qwen-omni/rules.md +++ b/knowledge/repos/vllm-omni/models/qwen-omni/rules.md @@ -1,7 +1,7 @@ --- title: "Qwen-Omni 规则" created: 2026-09-04 -updated: 2026-09-09 +updated: 2026-09-18 type: rule tags: [vllm-omni, models, qwen-omni] sources: ["PR #5687", "PR #6284", "PR #6449", "PR #4322", "PR #6748", "PR #6886", "PR #7019", vllm_omni/config/pipeline_registry.py, vllm_omni/deploy/qwen3_omni_moe.yaml, vllm_omni/deploy/qwen3_omni_moe_thinking.yaml, vllm_omni/engine/stage_init_utils.py, vllm_omni/model_executor/models/qwen2_5_omni/qwen2_5_omni.py, vllm_omni/model_executor/models/qwen3_omni/quantization.py, vllm_omni/model_executor/models/qwen3_omni/qwen3_omni.py, vllm_omni/model_executor/models/qwen3_omni/qwen3_omni_moe_thinker.py, vllm_omni/quantization/component_config.py, tests/config/test_config_factory.py, tests/diffusion/quantization/test_component_routing.py, tests/engine/test_stage_engine_args.py, tests/model_executor/models/qwen3_omni/test_qwen3_omni_quantization.py, "PR #7228"] @@ -86,3 +86,10 @@ confidence: high - 强制:构造 `inv_freq` 时优先 `config.rope_parameters["rope_theta"]`(若 mapping 存在),否则回退 top-level `rope_theta`,再默认 `10000.0`。Qwen3-Omni(Transformers 5.10+ 常把 checkpoint 的 `1_000_000` 只放在 nested 字段)与仍带 top-level 的 Qwen3-TTS/legacy 必须共用该顺序。 - 禁止:只读 top-level 导致静默回退 `10000`;把 nested 优先写成破坏 TTS top-level 兼容的唯一来源。 - 验收:参数化覆盖 nested-only、nested 优先于冲突 top-level、默认 `10000`,以及 TTS/legacy top-level(含删除 `rope_parameters`)重建正确 `inv_freq`。^[PR #7228] + +## QOMNI-1h — Thinker 中间态捕获必须补上延迟相加的 residual + +- 触发:修改 Qwen3-Omni Thinker 的 `capture_layer_indices` / `return_hidden_states`,或把 decoder 层输出交给 Talker。 +- 强制:vLLM 把 block 更新和 residual 分开,直到下一次 RMSNorm 才相加。有 residual 时捕获 `hidden_states + residual`;residual 为 `None` 时只 clone `hidden_states`。写入前 view 成 `(-1, hidden)`。捕获不得改变最终 Thinker 输出。 +- 禁止:只复制 update 张量;把无 residual 的 embedding clone 和有 residual 的层当成同一公式;用捕获开关改变主 forward 数值。 +- 验收:单 PP rank 上用会拆开 hidden/residual 的层断言捕获值等于逻辑状态(无 residual 为输入,下一层为 hidden+residual),且开启捕获后的最终输出与不捕获一致。^[PR #7304]