Normalize HunYuanVL's legacy field aliases via attribute_map (#48261)
* Drop legacy MoE/MLA keys from HunYuanVL config
The public HunYuanOCR checkpoints were exported from the Tencent MoE
codebase and still persist its routing and multi-head-latent-attention
hyperparameters in `config.json` — most visibly `num_experts=1`, but
also `moe_topk`, `num_shared_experts`, `use_mla`, `kv_lora_rank` and
friends, at both the top level and inside `text_config`.
HunYuanVL is a dense-only variant and declares none of these as fields,
so `PreTrainedConfig.__post_init__` re-attached every one of them as an
untyped attribute. `AutoConfig.from_pretrained("tencent/HunyuanOCR")`
therefore exposed `config.num_experts == 1`, which reads as a (1-expert)
MoE model to anything downstream that sniffs the config, and
`save_pretrained` wrote them all straight back out.
Pop the group in both `HunYuanVLTextConfig.__post_init__` and
`HunYuanVLConfig.__post_init__` (the latter also sees them at the root
for the legacy "flat" checkpoint layout) so they neither land on the
config object nor round-trip through serialization.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012FQcxFhKuwjoyGKJQGndHP
* Normalize HunYuanVL's legacy field aliases via attribute_map
`HunYuanVLTextConfig`'s docstring already claimed that `pad_id`,
`attention_head_dim` and `org_vocab_size` are mapped onto `pad_token_id`,
`head_dim` and `vocab_size` via `attribute_map`, but only `pad_id` was
actually in the map. The other two therefore landed as untyped duplicate
attributes on both the text config and the top-level config, and were
written back out by `save_pretrained`.
They are aliases rather than distinct hyperparameters: no HunYuan
modeling code reads either name, and `tencent/HunyuanOCR`,
`tencent/Hunyuan-7B-Instruct` and `tencent/Hunyuan-A13B-Instruct` all
store them with exactly the same value as the canonical field. So map
them instead of declaring them as fields.
Also fold the text config's `attribute_map` keys into the set of keys
`HunYuanVLConfig.__post_init__` routes into `text_config` for the legacy
"flat" checkpoint layout, so the aliases are normalized there too rather
than sticking to the root config (this covers `pad_id`, which leaked at
the top level for the same reason).
Reading an alias still works, it just isn't stored or serialized twice.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012FQcxFhKuwjoyGKJQGndHP
* Revert MoE/MLA key dropping now that the checkpoint is fixed
`tencent/HunyuanOCR`'s `config.json` no longer carries the MoE/MLA
hyperparameters it inherited from the Tencent MoE codebase (notably
`num_experts=1`), so transformers no longer needs to strip them on load.
This reverts the first commit of this PR and leaves only the
`attribute_map` fix, which makes the legacy field aliases
(`attention_head_dim`, `org_vocab_size`) actually resolve onto the
canonical fields the surrounding docstring already claimed they did.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012FQcxFhKuwjoyGKJQGndHP
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> H
Harry Mellor committed
2c889bf22c0744a51c4dd99c6cb634fe7fae3bce
Parent: fc5c5bd
Committed by GitHub <noreply@github.com>
on 8/26/2026, 12:38:59 PM