fix(tools): fp8_cast_bf16 upcast weights missing scale_inv to bf16#1641
fix(tools): fp8_cast_bf16 upcast weights missing scale_inv to bf16#1641nick-rui wants to merge 2 commits into
Conversation
FP8 tensors without a scale_inv were passed through unconverted, producing a mixed-dtype checkpoint that later fails dist-ckpt serialization. Reported in radixark#1583.
There was a problem hiding this comment.
Code Review
This pull request updates the FP8 to BF16 casting script to upcast weights to the default PyTorch data type when a scale_inv tensor is missing, instead of skipping the conversion. The reviewer identified a potential issue where non-floating-point 1-byte tensors (like boolean masks or integer tensors) could be incorrectly upcast, and suggested adding a check to only upcast floating-point tensors.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| print(f"Warning: Missing scale_inv tensor for {weight_name}, upcasting to {torch.get_default_dtype()}") | ||
| new_state_dict[weight_name] = weight.to(torch.get_default_dtype()) |
There was a problem hiding this comment.
The check weight.element_size() == 1 on line 95 matches any 1-byte tensor, including torch.bool, torch.int8, and torch.uint8 (such as boolean masks or index tensors). If any such non-FP8 1-byte tensors do not have a corresponding _scale_inv tensor, they will trigger the KeyError and be incorrectly upcast to bfloat16. To prevent this, we should ensure that we only upcast actual floating-point (FP8) tensors by checking weight.is_floating_point().
| print(f"Warning: Missing scale_inv tensor for {weight_name}, upcasting to {torch.get_default_dtype()}") | |
| new_state_dict[weight_name] = weight.to(torch.get_default_dtype()) | |
| if weight.is_floating_point(): | |
| print(f"Warning: Missing scale_inv tensor for {weight_name}, upcasting to {torch.get_default_dtype()}") | |
| new_state_dict[weight_name] = weight.to(torch.get_default_dtype()) | |
| else: | |
| new_state_dict[weight_name] = weight |
There was a problem hiding this comment.
Good catch. Fixed in 88f7db8 by guarding the FP8 branch condition itself (weight.element_size() == 1 and weight.is_floating_point()) instead of adding a check inside the except block — this keeps non-float 1-byte tensors on the pass-through path and also keeps them out of the dequant path entirely.
fp8_cast_bf16.pypasses FP8 tensors through unconverted when they have no matching*_scale_inv(e.g.mtp.0.e_proj.weight/mtp.0.h_proj.weightinsgl-project/DeepSeek-V4-Flash-FP8), so the output checkpoint is mixed-dtype and later fails dist-ckpt serialization. Upcast them to bf16 instead.Fixes the "Minor" item in #1583.