transformers
9ddb2140 - Fix a destructive Qwen3 TP-plan override; split out the conversions

Commit
27 days ago
Fix a destructive Qwen3 TP-plan override; split out the conversions `update_tp_plan` carried `if "Qwen3" in config.__class__.__name__:` and then ASSIGNED a hand-written dense plan over `config.base_model_tp_plan`. Three things were wrong with it: - redundant: the module-keyed entries Qwen3 already ships reach a parameter's scale through the plan matcher's module fallback — `q_proj.weight_scale_inv` resolves to `colwise`, `down_proj.weight_scale_inv` to `rowwise` — so the parameter-keyed duplicates bought nothing; - destructive: assigning dropped what the model ships, including `q_norm`/`k_norm` `replicated_with_grad_allreduce`, and on Qwen3-MoE the whole expert plan (`experts: moe_tp_experts`, `experts.gate_up_proj: packed_colwise`, ...). The companion pass immediately below keys on `moe_tp_experts`, so it then found nothing and the expert scales got no entry either; - over-broad: 25 config classes contain "Qwen3". On the multimodal ones, whose plans live on a sub-config and whose outer config ships none, it stamped a dense text plan onto the outer config where those paths match nothing. Removed. Qwen3 and Qwen3-MoE now keep every shipped entry, Qwen3-MoE additionally gains the three expert companions it was being denied, and a multimodal config's outer plan stays empty. Three assertions cover it, against REAL configs — the existing plan tests build a SimpleNamespace, which a branch keyed on the config CLASS is structurally invisible to. Structure: - the conversion ops move to `integrations/finegrained_conversions.py` (finegrained.py 1631 -> 985). The dependency is one-way; `keep_swizzle_reverse_for_save` goes with them, which is what removes the cycle rather than needing a local import to break it. - `_nvfp4_conversions` splits per checkpoint layout. The two never interact — a checkpoint matches one set and the other never fires — so they were adjacent, not related. - `replace_with_finegrained_layer` hoists the kwargs every swap shares, leaving each branch showing only what is its own. Review comments: - TP styles are registered properly (`moe_experts_colwise` / `moe_experts_packed_colwise` / `moe_experts_rowwise`) instead of `ALL_PARALLEL_STYLES.register` at plan-build time. - the frozen-fp8 deprecation notices fired at IMPORT, for anyone importing `transformers.integrations` at all, one of them through `warnings.warn` rather than the logger. Now one `logger.warning_once` on quantizer construction. - `has_global_scale` dropped: `global_scale_dtype: torch.dtype | None` already answered it. - defensive `getattr` on declared config fields replaced with direct access. - `quantizers_utils.py`, `integrations/tensor_parallel.py` and `integrations/finegrained_fp8.py` are back to their upstream contents and leave this diff entirely. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Parents
Loading