fix(checkpoint): restore Gemma4 Unified HF export keys (#3260)
* fix(checkpoint): restore Gemma4 Unified HF export keys Signed-off-by: khazic <khazzz1c@gmail.com> * fix(checkpoint): keep the Gemma4 Unified key rename off the base-model load path The rename lived inside _maybe_adapt_state_dict_to_hf, which runs on three paths: save, DCP resume, and base-model init load. That broke two of them. DCP resume had no inverse: save wrote HF FQNs into the shards, load renamed the destinations to HF FQNs, and _maybe_adapt_state_dict_from_hf left them there. gemma4_unified is HF-native, so set_model_state_dict runs with strict=True and the six vision weights surfaced as missing plus unexpected. Base-model init already translates keys through the storage reader's key_mapping, built from the model's _checkpoint_conversion_mapping. Renaming the destinations on top of that double-transformed them and the vision weights no longer matched the checkpoint. Move the rename into _maybe_rename_gemma4_unified_keys, apply it explicitly on save and on both directions of the DCP resume path, and skip it entirely when is_init_step. Signed-off-by: khazic <khazzz1c@gmail.com> * refactor(checkpoint): move Gemma4 Unified key renames to a gemma4 module Address review feedback: the gemma4_unified HF export key table and the rename helper now live in nemo_automodel/components/models/gemma4_unified/hf_key_renames.py, and checkpointing.py only calls the public helper. Tests move alongside. Signed-off-by: khazic <khazzz1c@gmail.com> * refactor(checkpoint): handle Gemma4 Unified keys via a state dict adapter Address review feedback: instead of gemma-specific renames in the common checkpointer, gemma4_unified now gets a Gemma4UnifiedStateDictAdapter attached at model init, so the existing to_hf/from_hf hooks cover save, base-model init, and DCP resume symmetrically and the storage reader's key_mapping is disabled to avoid double conversion. checkpointing.py is back to being model-agnostic. DCP checkpoints written before a model gained an adapter store the model's own FQNs, so the load path now detects that layout and loads them with the model names instead of the adapter's Hugging Face names. Signed-off-by: khazic <khazzz1c@gmail.com> * refactor(checkpoint): use str | None in the Gemma4 Unified adapter signature Signed-off-by: khazic <khazzz1c@gmail.com> * refactor(checkpoint): derive HF export key renames generically Transformers can load a model under FQNs that differ from the ones its own checkpoint publishes, so the consolidated export was writing the in-memory names instead of the published ones. Handle this at consolidation time rather than with a per-model state dict adapter. The renames are derived from the load-time conversion mapping by pushing each published FQN of the reference checkpoint through it, so they are exact strings rather than reversed regexes, and ambiguous collapses are rejected. DCP shards keep the model's own FQNs, which leaves base-model initialization and resume untouched and removes the need for a compatibility branch. The renames are applied only to the consolidated safetensors headers and the weight index, across the inline, async, single-rank, and offline paths. Models whose experts Transformers merges, and NemotronH remote code, are excluded so the export keeps matching the tensors actually written. Signed-off-by: khazic <khazzz1c@gmail.com> * test(tools): update the offline consolidation stub for export_key_renames The happy-path test replaces consolidate_safetensors_files_on_every_rank with a hand-written stub whose signature predates the export_key_renames argument, so main() raised TypeError once the tool started forwarding the sidecar. Extend the stub and assert the argument, and add a case covering a checkpoint that ships an export_key_renames.json sidecar. Signed-off-by: khazic <khazzz1c@gmail.com> * refactor(checkpoint): update consolidated tensor metadata in place Signed-off-by: HuiyingLi <willwin.lee@gmail.com> * refactor(checkpoint): preserve export name across metadata rebuild Signed-off-by: HuiyingLi <willwin.lee@gmail.com> * refactor(checkpoint): use Gemma4 state dict adapter Signed-off-by: HuiyingLi <willwin.lee@gmail.com> * refactor(gemma4): localize adapter attachment Signed-off-by: HuiyingLi <willwin.lee@gmail.com> * refactor(gemma4): use custom unified model wrapper Signed-off-by: HuiyingLi <willwin.lee@gmail.com> * chore(gemma4): remove unused model type constant Signed-off-by: HuiyingLi <willwin.lee@gmail.com> --------- Signed-off-by: khazic <khazzz1c@gmail.com> Signed-off-by: HuiyingLi <willwin.lee@gmail.com> Co-authored-by: HuiyingLi <willwin.lee@gmail.com>
K
khazzz1c committed
f5e71638f7ae93cfd68fcd14e7cd4af3632aee93
Parent: 5001dd4
Committed by GitHub <noreply@github.com>
on 8/16/2026, 11:00:49 AM