Fix: resolve Qwen3 text encoder loading issues for FP8 and GGUF formats - #1904
arifanchan wants to merge 8 commits into
Conversation
Added a preprocessing function to fix tied weights for Qwen FP8 models during loading.
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds a state-dict preprocessing hook when loading the Qwen3 text encoder to handle FP8 checkpoints that omit lm_head.weight.
Changes:
- Replaces direct
fast_load_transformers_modelcall with a wrapper that injects missinglm_head.weight. - Introduces
fix_qwen_fp8_sdto patch the loaded state dict before model instantiation.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Added a function to restore lm_head.weight from model.embed_tokens.weight for Qwen FP8 models.
arifanchan
left a comment
There was a problem hiding this comment.
Good catch on the semantics. We specifically want the tensor alias here rather than a .clone() to preserve the tied weights and avoid re-allocating the vocab matrix in VRAM. Updated the comment to clarify.
Good call on keeping the scope clean. Even though the loading script only runs once per model initialization, moving it to the module level as a private helper _fix_qwen_fp8_sd is tidier. Updated!
Added dtype conversion for text encoder to resolve SDPA mismatch.
fix: strip GGUF subclass from text embeddings to prevent Dynamo RecursionError
Description
This PR resolves three sequential crashing issues that occur when loading and compiling the Qwen3 text encoder in different quantized formats (FP8 Safetensors and GGUF) alongside the Z-Image model.
Issue 1: Missing
lm_head.weightin FP8 SafetensorsError:
Exception: Missing keys: ['lm_head.weight']lm_head.weightkey to save disk space, causingmmgp/offload.pystrict key checks to fail._fix_qwen_fp8_sdpreprocessor inz_image_main.pyto dynamically alias themodel.embed_tokens.weightmemory reference into thelm_head.weightslot on the fly.Issue 2: SDPA Dtype Mismatch in GGUF
Error:
RuntimeError: Expected query, key, and value to have the same dtypellama.cppintegration often provides theValuetensor inbfloat16, while HFtransformerscomputes RoPE forQuery/Keyinfloat32. PyTorch SDPA strictly requires uniformity..to(dtype)cast immediately after loading the text encoder inz_image_main.pyto enforce strict dtype uniformity.Issue 3: Dynamo RecursionError with Q8_0 GGUF
Error:
torch._dynamo.exc.InternalTorchDynamoError: RecursionError: maximum recursion depth exceededQ8_0GGUF format lacks an embedding fast path, causing it to fall back to a custom Python__torch_function__subclass wrapper. When these embeddings are passed to thetorch.compilewrapped Z-Image transformer, Dynamo tries to trace the custom wrapper and enters an infinite loop..as_subclass(torch.Tensor)cast to the embeddings inmodels/z_image/pipeline_z_image.pyto strip the GGUF wrapper before they enter the compiled transformer. This has zero VRAM/performance penalty and acts as a safe bridge to eager mode.