Verify full Qwen layer trace

This commit is contained in:
Daniel Maddern 2026-08-13 00:05:32 +07:00
parent ab10de7521
commit abc651fadb
2 changed files with 36 additions and 16 deletions

View file

@ -38,6 +38,7 @@ diagnose preview output.
| Qwen embedding loading, after fix | Direct rows multiplied by `weight_scale` in FP32 | Input embeddings matched the Comfy capture exactly | Passed for the captured nonempty text-only reference |
| Qwen layer-50, before embedding fix | Direct versus Comfy layer-50 capture | Mean absolute delta `23.50596`, max `38977.09375` | Failed; invalidated direct text conditioning |
| Qwen layer-50, after embedding fix but before projection fix | Direct versus Comfy layer-50 capture | Mean absolute delta improved to about `5.63` | Embedding issue fixed; remaining error was material |
| Qwen all-layer replay, after FP32 fix | `compare_qwen_layer_trace.py` replayed `/tmp/fl2va-qwen-trace` without new Comfy inference | Layers `00` through `49` and `qwen_layer50.pt` all reported mean/max `0` / `0` | **Passed: prompt-only Qwen conditioning is bit-exact for the immutable 17-token FL2VA reference.** |
| Qwen layer-0 normalization | Direct `F.rms_norm` versus `qwen0_norm1.pt` | Mean absolute delta about `8.96e-06` | Passed to expected BF16-level tolerance |
| Qwen layer-0 attention, before projection fix | Direct versus `qwen0_attention.pt` | Mean absolute delta about `0.0357`; layer output about `0.1496` | First material Qwen divergence was at projection/attention boundary, not tokenization, embeddings, RMSNorm, or RoPE |
| Qwen attention backend | Comfy source inspection | Qwen chooses Comfy small-input attention, i.e. SDPA path, not Sage2 | Direct Qwen was changed to BF16 causal-mask SDPA with GQA |
@ -193,35 +194,27 @@ gate and is exact.
Only these are outstanding. Do not recapture or revisit rows marked complete
unless the checkpoint, Comfy version, prompt, or backend changes.
1. **Qwen all-layer replay after `0cad1db`.** The layer-0 projection capture
was completed: errors are recorded above. Replay the existing 50 layer
tensors in `/tmp/fl2va-qwen-trace`; report first failing layer and mean/max
error. Do not generate another video before this is recorded.
2. **Qwen projection precision follow-up if layer replay fails at layer 0.**
Do not repeat the capture. Use `/tmp/fl2va-qwen0-projections` to isolate the
remaining `down_proj` max error `0.0749016` and its BF16/dequantization
boundary.
3. **Token-refiner capture and comparison.** Capture exact Comfy pre-refiner,
1. **Token-refiner capture and comparison.** Capture exact Comfy pre-refiner,
block 0, block 1, and final refined states once, then compare direct using
the matched Qwen layer-50 tensor.
4. **H3 assembled input comparison.** Use the existing FL2VA input capture to
2. **H3 assembled input comparison.** Use the existing FL2VA input capture to
compare text rows, audio/video rows, positions, times, and segments. This
isolates packing from DiT error.
5. **H3 first-divergence repair.** Reuse the existing block trace. Start at
3. **H3 first-divergence repair.** Reuse the existing block trace. Start at
block 0 sublayers, repair the first mismatch, then use Comfy block output as
the next direct input to distinguish local error from accumulation. Existing
evidence says block 0 is close but accumulation is unresolved.
6. **Final rows and video latent.** Compare final packed video rows and
4. **Final rows and video latent.** Compare final packed video rows and
`unpatchify_video` output with Comfy before entering the sampler.
7. **Sampler replay using Comfy state.** Feed `initial.pt` and captured
5. **Sampler replay using Comfy state.** Feed `initial.pt` and captured
`sigmas` directly to the sampler. Compare video and audio denoised/update
states for all 12 saved steps. Do not test seed equality until this passes.
8. **VAE pixel gate.** Decode the identical captured final video latent in
6. **VAE pixel gate.** Decode the identical captured final video latent in
direct and Comfy and compare pixels before ffmpeg. This decides whether any
residual grid comes from decoder behavior.
9. **End-to-end FL2VA preview.** Generate the reference dragon only after
7. **End-to-end FL2VA preview.** Generate the reference dragon only after
gates 1-8 pass. Compare its raw final latent first, then video.
10. **Feature/performance work.** Only then add audio, Ref2VA/reference paths,
8. **Feature/performance work.** Only then add audio, Ref2VA/reference paths,
Sage3, CUDA graphs, and multi-GPU execution.
## Existing Tools And Their Intended Gate

View file

@ -0,0 +1,27 @@
"""Replay direct Qwen against an immutable per-layer Comfy trace."""
import argparse
from pathlib import Path
import torch
from h3_blackwell_runtime.qwen3vl_text import Qwen3VL32BTextEncoder
parser = argparse.ArgumentParser()
parser.add_argument("--trace-dir", type=Path, required=True)
parser.add_argument("--checkpoint", default="/text-encoders/qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors")
args = parser.parse_args()
encoder = Qwen3VL32BTextEncoder(args.checkpoint).eval()
hidden = torch.load(args.trace_dir / "qwen_input_embeds.pt", map_location="cuda", weights_only=False).to(encoder.dtype)
with torch.inference_mode():
for index, layer in enumerate(encoder.layers):
hidden = layer(hidden)
expected = torch.load(args.trace_dir / "qwen_layers" / f"{index:02d}.pt", map_location="cuda", weights_only=False)
delta = (hidden.float() - expected.float()).abs()
print(f"layer={index:02d} max_abs={delta.max().item():.6g} mean_abs={delta.mean().item():.6g}")
expected = torch.load(args.trace_dir / "qwen_layer50.pt", map_location="cuda", weights_only=False)
delta = (hidden.float() - expected.float()).abs()
print(f"layer50 max_abs={delta.max().item():.6g} mean_abs={delta.mean().item():.6g}")