Skip to content

feat(target_utils): auto-detect embed/lm_head keys for LLM and VLM checkpoints#666

Open
curnane-lab wants to merge 3 commits into
sgl-project:mainfrom
curnane-lab:detect-embedding-key
Open

feat(target_utils): auto-detect embed/lm_head keys for LLM and VLM checkpoints#666
curnane-lab wants to merge 3 commits into
sgl-project:mainfrom
curnane-lab:detect-embedding-key

Conversation

@curnane-lab

@curnane-lab curnane-lab commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Motivation

TargetEmbeddingsAndHead.from_pretrained() currently hardcodes model.embed_tokens.weight and lm_head.weight as 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 under model.language_model or model.language_model.model, so the embedding key becomes model.language_model.model.embed_tokens.weight or model.language_model.embed_tokens.weight.

Without auto-detection, users must remember to pass --embedding-key and --lm-head-key for every VLM target, which is error-prone and makes example scripts model-specific.

Modifications

  • specforge/modeling/target/target_utils.py:
    • Add candidate key lists for both embed_tokens and lm_head, covering:
      • Plain causal LMs: model.embed_tokens.weight, embed_tokens.weight
      • Qwen3.5-4B-style VLMs: model.language_model.model.embed_tokens.weight
      • Qwen3.5-A3B-style VLMs: model.language_model.embed_tokens.weight, language_model.*
    • Try candidates in order for both sharded checkpoints (model.safetensors.index.json) and single-file checkpoints (*.safetensors).
    • Print a message when a non-default key is resolved.
    • Improve error diagnostics by listing available keys when no candidate matches.

Related Issues

N/A

Accuracy Test

N/A (data-loading utility, no model math changes)

Benchmark & Profiling

N/A

Checklist

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).

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

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.

Suggested change
with safe_open(target_file, framework="np") as f:
with safe_open(target_file, framework="pt") as f:

Comment on lines +104 to +113
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",
]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

@curnane-lab curnane-lab changed the title Detect embedding key feat(target_utils): auto-detect embed/lm_head keys for LLM and VLM checkpoints Jul 9, 2026
@curnane-lab curnane-lab force-pushed the detect-embedding-key branch from c0d3aaf to 6d9cf6e Compare July 9, 2026 10:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants