@@ -452,8 +452,7 @@ defmodule Bumblebee.Text.Gemma4Text do
452452 max_positions: spec . max_positions ,
453453 base: spec . rotary_embedding_base ,
454454 percentage: 1.0 ,
455- rotary_dim:
456- trunc ( spec . global_attention_head_size * spec . partial_rotary_factor )
455+ rotary_dim: trunc ( spec . global_attention_head_size * spec . partial_rotary_factor )
457456 ]
458457
459458 :sliding_attention ->
@@ -588,14 +587,13 @@ defmodule Bumblebee.Text.Gemma4Text do
588587
589588 shortcut_ple = hidden_state
590589
591- # Gate: project hidden_state DOWN to PLE dimension
590+ # Gate: project hidden_state DOWN to PLE dimension, then activation
592591 gated =
593592 Axon . dense ( hidden_state , spec . hidden_size_per_layer_input ,
594593 name: join ( name , "per_layer_input_gate" ) ,
595594 use_bias: false
596595 )
597596
598- # Activation (gelu_approx_tanh, same as FFN)
599597 gated = Layers . activation ( gated , spec . activation )
600598
601599 # Element-wise multiply with PLE signal
@@ -622,18 +620,19 @@ defmodule Bumblebee.Text.Gemma4Text do
622620 end
623621
624622 # 4. Layer scalar: multiply output by per-layer learned scalar
625- layer_scalar =
626- Axon . param ( "layer_scalar" , fn _ -> { 1 } end , initializer: :ones )
627-
628623 hidden_state =
629624 Axon . layer (
630625 fn hidden_state , scalar , _opts ->
631- Nx . multiply ( hidden_state , scalar )
626+ Nx . multiply ( hidden_state , Nx . reshape ( scalar , { } ) )
632627 end ,
633- [ hidden_state , layer_scalar ] ,
634- name: join ( name , "layer_scalar" )
628+ [
629+ hidden_state ,
630+ Axon . param ( "layer_scalar" , fn _ -> { 1 } end , initializer: Axon.Initializers . ones ( ) )
631+ ] ,
632+ name: join ( name , "layer_scalar_op" )
635633 )
636634
635+ # Handle cross-attention (required by block interface but not used by Gemma 4)
637636 { _hidden_state , cross_attention_info } =
638637 steps . cross_attention_maybe . ( hidden_state , fn _ ->
639638 raise "cross attention not supported"
@@ -756,59 +755,61 @@ defmodule Bumblebee.Text.Gemma4Text do
756755 end
757756
758757 defimpl Bumblebee.HuggingFace.Transformers.Model do
759- def params_mapping ( spec ) do
760- % {
761- "embedder.token_embedding" => "model.language_model.embed_tokens" ,
762- # PLE (Per-Layer Embeddings) global weights
763- "embedder.token_embedding_per_layer" => "model.language_model.embed_tokens_per_layer" ,
764- "per_layer_model_projection" => "model.language_model.per_layer_model_projection" ,
765- "per_layer_projection_norm" => "model.language_model.per_layer_projection_norm" ,
766- "decoder.blocks.{n}.per_layer_input_gate" =>
767- "model.language_model.layers.{n}.per_layer_input_gate" ,
768- "decoder.blocks.{n}.per_layer_projection" =>
769- "model.language_model.layers.{n}.per_layer_projection" ,
770- "decoder.blocks.{n}.post_per_layer_input_norm" =>
771- "model.language_model.layers.{n}.post_per_layer_input_norm" ,
772- # Per-layer scalar
773- "decoder.blocks.{n}.layer_scalar" =>
774- "model.language_model.layers.{n}" ,
775- # Attention projections
776- "decoder.blocks.{n}.self_attention.query" =>
777- "model.language_model.layers.{n}.self_attn.q_proj" ,
778- "decoder.blocks.{n}.self_attention.key" =>
779- "model.language_model.layers.{n}.self_attn.k_proj" ,
780- "decoder.blocks.{n}.self_attention.value" =>
781- "model.language_model.layers.{n}.self_attn.v_proj" ,
782- "decoder.blocks.{n}.self_attention.output" =>
783- "model.language_model.layers.{n}.self_attn.o_proj" ,
784- # QK-norm
785- "decoder.blocks.{n}.self_attention.query_norm" =>
786- "model.language_model.layers.{n}.self_attn.q_norm" ,
787- "decoder.blocks.{n}.self_attention.key_norm" =>
788- "model.language_model.layers.{n}.self_attn.k_norm" ,
789- # Layer norms
790- "decoder.blocks.{n}.self_attention_norm" =>
791- "model.language_model.layers.{n}.input_layernorm" ,
792- "decoder.blocks.{n}.post_attention_norm" =>
793- "model.language_model.layers.{n}.post_attention_layernorm" ,
794- # FFN layer norms
795- "decoder.blocks.{n}.pre_ffn_norm" =>
796- "model.language_model.layers.{n}.pre_feedforward_layernorm" ,
797- "decoder.blocks.{n}.post_ffn_norm" =>
798- "model.language_model.layers.{n}.post_feedforward_layernorm" ,
799- # FFN projections
800- "decoder.blocks.{n}.ffn.gate" => "model.language_model.layers.{n}.mlp.gate_proj" ,
801- "decoder.blocks.{n}.ffn.intermediate" => "model.language_model.layers.{n}.mlp.up_proj" ,
802- "decoder.blocks.{n}.ffn.output" => "model.language_model.layers.{n}.mlp.down_proj" ,
803- # Output
804- "output_norm" => "model.language_model.norm" ,
805- "language_modeling_head.output" =>
806- if ( spec . tie_word_embeddings ,
807- do: "model.language_model.embed_tokens" ,
808- else: "lm_head"
809- ) ,
810- "sequence_classification_head.output" => "score"
811- }
812- end
758+ def params_mapping ( spec ) do
759+ % {
760+ "embedder.token_embedding" => "model.language_model.embed_tokens" ,
761+ # PLE global weights
762+ "embedder.token_embedding_per_layer" => "model.language_model.embed_tokens_per_layer" ,
763+ "per_layer_model_projection" => "model.language_model.per_layer_model_projection" ,
764+ "per_layer_projection_norm" => "model.language_model.per_layer_projection_norm" ,
765+ # PLE per-layer weights
766+ "decoder.blocks.{n}.per_layer_input_gate" =>
767+ "model.language_model.layers.{n}.per_layer_input_gate" ,
768+ "decoder.blocks.{n}.per_layer_projection" =>
769+ "model.language_model.layers.{n}.per_layer_projection" ,
770+ "decoder.blocks.{n}.post_per_layer_input_norm" =>
771+ "model.language_model.layers.{n}.post_per_layer_input_norm" ,
772+ # Layer scalar
773+ "decoder.blocks.{n}.layer_scalar_op" => "model.language_model.layers.{n}" ,
774+ "decoder.blocks.{n}.layer_scalar_op.layer_scalar" =>
775+ "model.language_model.layers.{n}.layer_scalar" ,
776+ # Attention projections
777+ "decoder.blocks.{n}.self_attention.query" =>
778+ "model.language_model.layers.{n}.self_attn.q_proj" ,
779+ "decoder.blocks.{n}.self_attention.key" =>
780+ "model.language_model.layers.{n}.self_attn.k_proj" ,
781+ "decoder.blocks.{n}.self_attention.value" =>
782+ "model.language_model.layers.{n}.self_attn.v_proj" ,
783+ "decoder.blocks.{n}.self_attention.output" =>
784+ "model.language_model.layers.{n}.self_attn.o_proj" ,
785+ # QK-norm
786+ "decoder.blocks.{n}.self_attention.query_norm" =>
787+ "model.language_model.layers.{n}.self_attn.q_norm" ,
788+ "decoder.blocks.{n}.self_attention.key_norm" =>
789+ "model.language_model.layers.{n}.self_attn.k_norm" ,
790+ # Layer norms
791+ "decoder.blocks.{n}.self_attention_norm" =>
792+ "model.language_model.layers.{n}.input_layernorm" ,
793+ "decoder.blocks.{n}.post_attention_norm" =>
794+ "model.language_model.layers.{n}.post_attention_layernorm" ,
795+ # FFN layer norms
796+ "decoder.blocks.{n}.pre_ffn_norm" =>
797+ "model.language_model.layers.{n}.pre_feedforward_layernorm" ,
798+ "decoder.blocks.{n}.post_ffn_norm" =>
799+ "model.language_model.layers.{n}.post_feedforward_layernorm" ,
800+ # FFN projections
801+ "decoder.blocks.{n}.ffn.gate" => "model.language_model.layers.{n}.mlp.gate_proj" ,
802+ "decoder.blocks.{n}.ffn.intermediate" => "model.language_model.layers.{n}.mlp.up_proj" ,
803+ "decoder.blocks.{n}.ffn.output" => "model.language_model.layers.{n}.mlp.down_proj" ,
804+ # Output
805+ "output_norm" => "model.language_model.norm" ,
806+ "language_modeling_head.output" =>
807+ if ( spec . tie_word_embeddings ,
808+ do: "model.language_model.embed_tokens" ,
809+ else: "lm_head"
810+ ) ,
811+ "sequence_classification_head.output" => "score"
812+ }
813+ end
813814 end
814815end
0 commit comments