feat(target_utils): auto-detect embed/lm_head keys for LLM and VLM checkpoints#666
feat(target_utils): auto-detect embed/lm_head keys for LLM and VLM checkpoints#666curnane-lab wants to merge 3 commits into
Conversation
TargetEmbeddingsAndHead now falls back through common embedding and lm_head key names when the default 'model.embed_tokens.weight' / 'lm_head.weight' are not present. This supports plain LLMs, MLLMs, and renamed checkpoints without requiring manual --embedding-key / --lm-head-key arguments.
Include 'model.language_model.embed_tokens.weight' and 'language_model.embed_tokens.weight' in the auto-detection fallback list. These variants are used by Qwen3.5-A3B and similar MLLMs (see Domino NPU example's --embedding-key).
There was a problem hiding this comment.
Code Review
This pull request introduces auto-detection for embedding and language model head keys in _load_weights to support various LLM/MLLM checkpoint structures. The feedback highlights a critical runtime error where an invalid framework argument ("np") is passed to safe_open, and suggests refactoring duplicated candidate key lists into module-level constants to improve maintainability.
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.
| # Read the available keys so we can auto-detect embed/lm_head names | ||
| # in single-file checkpoints too. | ||
| if target_file.endswith(".safetensors"): | ||
| with safe_open(target_file, framework="np") as f: |
There was a problem hiding this comment.
The safe_open function from the safetensors library does not support "np" as a valid framework. Passing framework="np" will raise a ValueError: Invalid framework np at runtime. Please use framework="pt" (or framework="numpy") instead.
| with safe_open(target_file, framework="np") as f: | |
| with safe_open(target_file, framework="pt") as f: |
| candidate_embed_keys = [ | ||
| embed_key, | ||
| "model.embed_tokens.weight", | ||
| "embed_tokens.weight", | ||
| "model.language_model.model.embed_tokens.weight", | ||
| "model.language_model.embed_tokens.weight", | ||
| "language_model.model.embed_tokens.weight", | ||
| "language_model.embed_tokens.weight", | ||
| "model.model.embed_tokens.weight", | ||
| ] |
There was a problem hiding this comment.
The list of candidate embedding keys is duplicated here and in the single-file checkpoint loading block (lines 174-183). To improve maintainability and avoid potential desynchronization in the future, consider defining these candidate keys as module-level constants (e.g., CANDIDATE_EMBED_KEYS and CANDIDATE_HEAD_KEYS) at the top of the file.
c0d3aaf to
6d9cf6e
Compare
Motivation
TargetEmbeddingsAndHead.from_pretrained()currently hardcodesmodel.embed_tokens.weightandlm_head.weightas the keys to load from the target checkpoint. This breaks on multimodal models (e.g. Qwen3.5-4B / Qwen3.5-A3B VLM checkpoints) where the text decoder is nested undermodel.language_modelormodel.language_model.model, so the embedding key becomesmodel.language_model.model.embed_tokens.weightormodel.language_model.embed_tokens.weight.Without auto-detection, users must remember to pass
--embedding-keyand--lm-head-keyfor every VLM target, which is error-prone and makes example scripts model-specific.Modifications
specforge/modeling/target/target_utils.py:embed_tokensandlm_head, covering:model.embed_tokens.weight,embed_tokens.weightmodel.language_model.model.embed_tokens.weightmodel.language_model.embed_tokens.weight,language_model.*model.safetensors.index.json) and single-file checkpoints (*.safetensors).Related Issues
N/A
Accuracy Test
N/A (data-loading utility, no model math changes)
Benchmark & Profiling
N/A
Checklist