@@ -4730,6 +4730,9 @@ def __init__(self, dir_model: Path, *args, **kwargs):
4730
4730
with open (dir_model / "config.json" , "r" , encoding = "utf-8" ) as f :
4731
4731
hparams = json .load (f )
4732
4732
super ().__init__ (dir_model , * args , hparams = hparams , ** kwargs )
4733
+ self .d_model = self .find_hparam (["hidden_size" , "d_model" , "dim" ])
4734
+ self .d_inner = self .find_hparam (["intermediate_size" , "d_inner" ], optional = True ) or 2 * self .d_model
4735
+ self .n_group = self .hparams .get ("n_groups" , 1 )
4733
4736
4734
4737
def set_vocab (self ):
4735
4738
vocab_size = self .hparams ["vocab_size" ]
@@ -4800,10 +4803,7 @@ def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iter
4800
4803
# (D is also unsqueezed, but for more straightforward broadcast internally)
4801
4804
data_torch = data_torch .reshape ((* data_torch .shape , 1 ))
4802
4805
elif self .match_model_tensor_name (new_name , gguf .MODEL_TENSOR .SSM_NORM , bid ):
4803
- d_model = self .find_hparam (["hidden_size" , "d_model" , "dim" ])
4804
- d_inner = self .find_hparam (["intermediate_size" , "d_inner" ], optional = True ) or 2 * d_model
4805
- n_group = self .hparams .get ("n_groups" , 1 )
4806
- data_torch = data_torch .reshape ((n_group , d_inner // n_group ))
4806
+ data_torch = data_torch .reshape ((self .n_group , self .d_inner // self .n_group ))
4807
4807
4808
4808
if name .endswith (".A_log" ):
4809
4809
logger .debug ("A_log --> A ==> " + new_name )
@@ -4812,6 +4812,107 @@ def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iter
4812
4812
yield (new_name , data_torch )
4813
4813
4814
4814
4815
+ @ModelBase .register ("BambaForCausalLM" )
4816
+ class BambaModel (Mamba2Model ):
4817
+ """Bamba is a hybrid SSM + Attention model that uses Mamba2 SSM layers"""
4818
+ model_arch = gguf .MODEL_ARCH .BAMBA
4819
+ undo_permute = True
4820
+
4821
+ def __init__ (self , * args , ** kwargs ):
4822
+
4823
+ # Hybrid mamba models use a prefix for the mamba-specific params.
4824
+ # TODO: Extend this if the prefix(es) need to be configurable
4825
+ self .hparam_prefixes = ["mamba" ]
4826
+
4827
+ super ().__init__ (* args , ** kwargs )
4828
+
4829
+ # Use Llama conversion for attention
4830
+ self ._transformer_model_class : type [TextModel ] = LlamaModel
4831
+
4832
+ # Lists of which layers use ssm vs attention
4833
+ self ._attn_layers = self .hparams .get ("attn_layer_indices" , [])
4834
+ if not self ._attn_layers :
4835
+ attn_period = self .hparams .get ("attn_layer_period" )
4836
+ assert attn_period , "Didn't find attn_layer_indices or attn_layer_period"
4837
+ attn_offset = self .hparams .get ("attn_layer_offset" )
4838
+ assert attn_offset is not None , "No attention layer offset set with attn_layer_period"
4839
+ self ._attn_layers = [
4840
+ i for i in range (self .block_count )
4841
+ if i % attn_period == attn_offset
4842
+ ]
4843
+ self ._ssm_layers = [
4844
+ i for i in range (self .block_count )
4845
+ if i not in self ._attn_layers
4846
+ ]
4847
+
4848
+ # n_group and d_inner are used during reshape_tensors for mamaba2
4849
+ self .d_model = self .find_hparam (["hidden_size" , "d_model" ])
4850
+ self .n_group = self .find_hparam (["n_groups" ])
4851
+ self .d_inner = self .find_hparam (["expand" ]) * self .d_model
4852
+
4853
+ def find_hparam (self , keys : Iterable [str ], * args , ** kwargs ) -> Any :
4854
+ prefixed = []
4855
+ for pfx in self .hparam_prefixes :
4856
+ prefixed .extend (
4857
+ "_" .join ([pfx , k ])
4858
+ for k in keys
4859
+ )
4860
+ keys = list (keys ) + prefixed
4861
+ return super ().find_hparam (keys , * args , ** kwargs )
4862
+
4863
+ def set_gguf_parameters (self ):
4864
+
4865
+ ## General Params ##
4866
+ self .gguf_writer .add_embedding_length (self .d_model )
4867
+ self .gguf_writer .add_block_count (self .block_count )
4868
+ self .gguf_writer .add_context_length (self .hparams .get ("max_position_embeddings" , 0 ))
4869
+ self .gguf_writer .add_vocab_size (self .hparams ["vocab_size" ])
4870
+ self .gguf_writer .add_feed_forward_length (self .hparams ["intermediate_size" ])
4871
+
4872
+ ## Mamba mixer params ##
4873
+ self .gguf_writer .add_ssm_conv_kernel (self .find_hparam (["conv_kernel" , "d_conv" ]))
4874
+ self .gguf_writer .add_ssm_state_size (self .find_hparam (["state_size" , "d_state" ]))
4875
+ self .gguf_writer .add_ssm_group_count (self .n_group )
4876
+ self .gguf_writer .add_ssm_inner_size (self .d_inner )
4877
+ # NOTE: The mamba_dt_rank is _not_ the right field for how this is used
4878
+ # in llama.cpp
4879
+ self .gguf_writer .add_ssm_time_step_rank (self .find_hparam (["n_heads" ]))
4880
+
4881
+ ## Attention params ##
4882
+ self .gguf_writer .add_attn_layer_indices (self ._attn_layers )
4883
+ self .gguf_writer .add_rope_dimension_count (self .hparams ["attn_rotary_emb" ])
4884
+ self .gguf_writer .add_head_count (self .hparams ["num_attention_heads" ])
4885
+ self .gguf_writer .add_head_count_kv (self .find_hparam (["num_key_value_heads" , "n_head_kv" ]))
4886
+
4887
+ ## Feed Forward Params ##
4888
+ self .gguf_writer .add_layer_norm_rms_eps (
4889
+ self .find_hparam (["layer_norm_epsilon" , "rms_norm_eps" ], optional = True ) or 1e-5
4890
+ )
4891
+
4892
+ ## Validation ##
4893
+ d_head = self .find_hparam (["d_head" ], optional = True ) or 64
4894
+ assert self .hparams .get ("hidden_act" ) in [None , "silu" ], "Only SILU activation supported"
4895
+ assert self .d_inner % d_head == 0 , f"SSM inner size { self .d_inner } not a multiple of head dim { d_head } "
4896
+
4897
+ def modify_tensors (
4898
+ self , data_torch : Tensor , name : str , bid : int | None
4899
+ ) -> Iterable [tuple [str , Tensor ]]:
4900
+
4901
+ # Determine whether this is a mamaba layer or an attention layer
4902
+ if bid in self ._ssm_layers :
4903
+ for mamba_new_name , data_torch in super ().modify_tensors (
4904
+ data_torch , name , bid
4905
+ ):
4906
+ yield mamba_new_name , data_torch
4907
+ elif bid in self ._attn_layers :
4908
+ for llama_new_name , data_torch in self ._transformer_model_class .modify_tensors (
4909
+ self , data_torch , name , bid
4910
+ ):
4911
+ yield llama_new_name , data_torch
4912
+ else :
4913
+ yield self .map_tensor_name (name ), data_torch
4914
+
4915
+
4815
4916
@ModelBase .register ("CohereForCausalLM" )
4816
4917
class CommandR2Model (TextModel ):
4817
4918
model_arch = gguf .MODEL_ARCH .COMMAND_R
0 commit comments