-
Notifications
You must be signed in to change notification settings - Fork 544
feat(speculative): support Gemma-4-E4B as a streaming DFlash/DSpark target #2186
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
h-guo18
wants to merge
1
commit into
main
Choose a base branch
from
haoguo/gemma4-e4b-support
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
modelopt_recipes/general/speculative_decoding/dspark_gemma4_e4b.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| # DSpark (full-train, from scratch) recipe for Gemma-4-E4B-it. | ||
| # | ||
| # Streaming: the real Gemma-4-E4B-it base is served by vLLM; the trainer uses a | ||
| # fake base (FakeBaseModel carries embed_tokens + the final norm). DSpark | ||
| # reconstructs the base teacher distribution from the captured PRE-norm hidden | ||
| # and re-applies the base final norm before lm_head. | ||
| # | ||
| # Gemma-4-E4B-specific notes (all verified on PDX 2026-08-12): | ||
| # | ||
| # * FINAL NORM: Gemma 4 nests the LLM under text_config with model_type | ||
| # "gemma4_text", so modeling_final_norm.py needed BOTH "gemma4_text" and | ||
| # "gemma4" added to _FINAL_NORM_TYPE_BY_MODEL_TYPE. Verified numerically that | ||
| # Gemma4RMSNorm is plain `normed * weight` (NOT Gemma 2/3's `(1 + weight)`), | ||
| # reproducing HF hidden_states[-1] at cos=0.999999, so the existing | ||
| # _FinalRMSNorm is correct as-is. | ||
| # | ||
| # * ROPE: Gemma 4 has NO flat `rope_theta`; it nests per-attention-kind settings | ||
| # under `rope_parameters` (full_attention: theta 1e6 + rope_type | ||
| # "proportional" + partial_rotary_factor 0.25; sliding_attention: theta 1e4 + | ||
| # rope_type "default"). modeling_fakebase.py needed _resolve_rope_theta() to | ||
| # read the nested form. hf_dflash.py ENFORCES rope_theta from the base config | ||
| # and overwrites any value set here, so this could NOT be fixed from the yaml. | ||
| # We take the sliding_attention entry -> rope_theta 10000.0, matching the SWA | ||
| # draft below. (The full_attention entry's "proportional" rope + | ||
| # partial_rotary_factor is not implemented in the draft classes.) | ||
| # | ||
| # * CAPTURE IDS: vLLM's EagleModelMixin captures POST-layer with residual added | ||
| # and indexes as layer_idx+1, so valid ids are 1..42 and 42 is the TRUE final | ||
| # layer (verified: cos(id42, final_norm_INPUT) = 1.0000, and ids 9/18/27/36 | ||
| # match HF hidden_states[id] at cos=1.0000 with off-by-one dropping to | ||
| # 0.55-0.98). Gemma 4 repeats 5x sliding + 1x full attention, so the | ||
| # full_attention layers (0-based [5,11,17,23,29,35,41]) correspond to capture | ||
| # ids [6,12,18,24,30,36,42]; we sample those to land on residual-stream | ||
| # boundaries rather than spacing uniformly. | ||
| # | ||
| # * MASK TOKEN: Gemma 4's vocab is fully packed (no free/unused ids), but it | ||
| # ships a native `<mask>` token at id 4 — used directly. | ||
|
|
||
| metadata: | ||
| recipe_type: speculative_dflash | ||
| description: DSpark (DFlash backbone + Markov + confidence head) for Gemma-4-E4B-it, SWA draft. | ||
|
|
||
| model: | ||
| model_name_or_path: | ||
| trust_remote_code: true | ||
| use_fake_base_for_offline: true | ||
|
|
||
| data: | ||
| mode: streaming | ||
| data_path: | ||
| offline_data_path: | ||
| chat_template: | ||
|
|
||
| training: | ||
| output_dir: | ||
| num_train_epochs: 1 | ||
| per_device_train_batch_size: 4 | ||
| gradient_accumulation_steps: 1 | ||
| learning_rate: 1.0e-4 | ||
| warmup_steps: 500 | ||
| training_seq_len: 4096 | ||
| logging_steps: 20 | ||
| save_steps: 1000 | ||
| cp_size: 1 | ||
| dp_shard_size: 1 | ||
| disable_tqdm: true | ||
| # Eval runs the DFlash backbone only (Markov head not applied in eval forward), | ||
| # so AR would misreport. Compare via export + offline AL harness instead. | ||
| estimate_ar: false | ||
| ar_validate_steps: 0 | ||
| answer_only_loss: true | ||
| do_eval: false | ||
| lr_scheduler_type: linear | ||
| save_strategy: steps | ||
| weight_decay: 0.0 | ||
| max_grad_norm: 1.0 | ||
| dataloader_drop_last: true | ||
| bf16: true | ||
| tf32: true | ||
| remove_unused_columns: false | ||
| ddp_find_unused_parameters: true | ||
| ddp_timeout: 1800 | ||
| report_to: none | ||
|
|
||
| dflash: | ||
| dflash_block_size: 8 | ||
| dflash_num_anchors: 512 | ||
| dflash_use_torch_compile: false | ||
| dflash_self_logit_distillation: false | ||
| # block_size=8 -> decay gamma 4 (matches the K2.6 DSpark regime). | ||
| dflash_loss_decay_factor: 4.0 | ||
| # Gemma 4 ships a native <mask> token at id 4 (vocab is fully packed, so there | ||
| # is no spare/unused id to borrow the way Kimi's 163838 was). | ||
| dflash_mask_token_id: 4 | ||
| # --- DSpark three-term loss (DeepSpec L1/TVD-dominant defaults) --- | ||
| dflash_ce_loss_alpha: 0.1 | ||
| dflash_l1_loss_alpha: 0.9 | ||
| dflash_confidence_head_alpha: 1.0 | ||
| dflash_architecture_config: | ||
| # Draft dims are set explicitly — the draft is an independent model and does | ||
| # NOT inherit these from the base (hidden_size/vocab/rope_theta ARE forced to | ||
| # the base and need not be set here). | ||
| num_hidden_layers: 5 | ||
| num_attention_heads: 16 | ||
| num_key_value_heads: 4 | ||
| head_dim: 256 | ||
| intermediate_size: 10240 | ||
| projector_type: dspark | ||
| # Markov head: low-rank first-order transition bias, memoryless variant. | ||
| markov_rank: 256 | ||
| markov_head_type: vanilla | ||
| use_confidence_head: true | ||
| # --- SWA draft (user decision 2026-08-12: try SWA first) --- | ||
| # DFlashAttention enables sliding-window attention only when the draft config | ||
| # carries BOTH `layer_types` and `sliding_window`; it then applies the window | ||
| # on layers whose layer_types entry is "sliding_attention". Matching the base's | ||
| # window of 512 and its sliding-layer rope_theta of 10000. | ||
| # NOTE: K3 measured SWA costing ~23% AL vs full attention at window 1024, and | ||
| # this window is smaller still — expect an AL hit and compare against a | ||
| # full-attention control before concluding. | ||
| sliding_window: 512 | ||
| layer_types: | ||
| - sliding_attention | ||
| - sliding_attention | ||
| - sliding_attention | ||
| - sliding_attention | ||
| - sliding_attention | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: NVIDIA/Model-Optimizer
Length of output: 43312
🏁 Script executed:
Repository: NVIDIA/Model-Optimizer
Length of output: 38547
🏁 Script executed:
Repository: NVIDIA/Model-Optimizer
Length of output: 50378
🌐 Web query:
Google Gemma 4 E4B-it Hugging Face Transformers trust_remote_code native support💡 Result:
Google Gemma 4 E4B-it has native support in the Hugging Face Transformers library [1][2]. Because it is natively supported, you do not need to set
trust_remote_code=Truewhen loading the model [3][4]. To use the model, ensure you have the latest version of thetransformerslibrary installed [5][2]. You can load the model using the standardAutoModelForMultimodalLMclass for multimodal tasks (as Gemma 4 E4B-it supports text, image, and audio inputs) [5][1]: from transformers import AutoProcessor, AutoModelForMultimodalLM MODEL_ID = "google/gemma-4-E4B-it" # Load processor and model processor = AutoProcessor.from_pretrained(MODEL_ID) model = AutoModelForMultimodalLM.from_pretrained( MODEL_ID, dtype="auto", device_map="auto") Official documentation confirms that the Gemma 4 architecture is integrated directly into the Transformers codebase, eliminating the requirement for custom code execution from the model repository [1][6][7].Citations:
Disable remote code by default.
Gemma 4 has native Transformers support and does not require remote code. This recipe accepts a caller-provided
model_name_or_path, sotrust_remote_code: truecan execute Python from an arbitrary model repository. Set it tofalseand require explicit opt-in for trusted custom models.Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents