char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
fa88ae936
char/aliceai-t5-moe
1from __future__import annotations 2 3from typing import Iterable ,TYPE_CHECKING 4 5import torch 6 7if TYPE_CHECKING : 8from torch import Tensor 9 10from .base import ModelBase ,TextModel ,gguf ,logger 11 12 13@ ModelBase . register ( "JambaForCausalLM" ) 14@ ModelBase . example ( "ai21labs/Jamba-v0.1" ) 15class JambaModel (TextModel ): 16model_arch = gguf .MODEL_ARCH .JAMBA 17 18def set_vocab (self ): 19if (self .dir_model / "tokenizer.model" ).is_file (): 20self ._set_vocab_sentencepiece () 21else : 22self ._set_vocab_llama_hf () 23self .gguf_writer .add_add_space_prefix (False ) 24 25def set_gguf_parameters (self ): 26d_model = self .find_hparam (["hidden_size" ,"mamba_d_model" ]) 27d_conv = self .find_hparam (["mamba_d_conv" ],optional = True )or 4 28d_inner = self .hparams ["mamba_expand" ]* d_model 29d_state = self .find_hparam (["mamba_d_state" ],optional = True )or 16 30# ceiling division 31# ref: https://stackoverflow.com/a/17511341/22827863 32# ref: https://github.com/state-spaces/mamba/blob/ce59daea3a090d011d6476c6e5b97f6d58ddad8b/mamba_ssm/modules/mamba_simple.py#L58 33dt_rank = self .find_hparam (["mamba_dt_rank" ],optional = True )or - (d_model // - 16 ) 34rms_norm_eps = self .find_hparam (["layer_norm_epsilon" ,"rms_norm_eps" ],optional = True )or 1e-6 35n_kv_head = self .hparams ["num_key_value_heads" ] 36attn_offset = self .hparams ["attn_layer_offset" ] 37attn_period = self .hparams ["attn_layer_period" ] 38n_kv_vec = [0 for _ in range (attn_offset )]+ [ 39n_kv_head if (i - attn_offset )% attn_period == 0 else 0 for i in range (attn_offset ,self .block_count ) 40 ] 41 42self .gguf_writer .add_block_count (self .block_count ) 43self .gguf_writer .add_context_length (self .find_hparam (["max_position_embeddings" ,"n_ctx" ])) 44self .gguf_writer .add_embedding_length (d_model ) 45self .gguf_writer .add_feed_forward_length (self .hparams ["intermediate_size" ]) 46self .gguf_writer .add_head_count (self .hparams ["num_attention_heads" ]) 47self .gguf_writer .add_head_count_kv (n_kv_vec ) 48self .gguf_writer .add_ssm_conv_kernel (d_conv ) 49self .gguf_writer .add_ssm_inner_size (d_inner ) 50self .gguf_writer .add_ssm_state_size (d_state ) 51self .gguf_writer .add_ssm_time_step_rank (dt_rank ) 52self .gguf_writer .add_layer_norm_rms_eps (rms_norm_eps ) 53self .gguf_writer .add_expert_count (self .find_hparam (["num_local_experts" ,"num_experts" ])) 54self .gguf_writer .add_expert_used_count (self .find_hparam (["num_experts_per_tok" ,"num_experts_per_token" ])) 55self .gguf_writer .add_file_type (self .ftype ) 56 57_experts :list [dict [str ,Tensor ]]| None = None 58 59def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 60 61# Mini-Jamba 62name = name .replace (".moe." ,".feed_forward." ) 63if bid is not None : 64moe_offset = self .hparams ["expert_layer_offset" ] 65moe_period = self .hparams ["expert_layer_period" ] 66 67if not (bid >= moe_offset and (bid - moe_offset )% moe_period == 0 ): 68name = name .replace (".experts.0." ,"." ) 69 70# process the experts separately 71if ".feed_forward.experts." in name : 72n_experts = self .find_hparam (["num_local_experts" ,"num_experts" ]) 73 74assert bid is not None 75 76if self ._experts is None : 77self ._experts = [{}for _ in range (self .block_count )] 78 79self ._experts [bid ][name ]= data_torch 80 81if len (self ._experts [bid ])>= n_experts * 3 : 82 83# merge the experts into a single 3d tensor 84for wid in ["down_proj" ,"gate_proj" ,"up_proj" ]: 85datas :list [Tensor ]= [] 86 87for xid in range (n_experts ): 88ename = f"model.layers. { bid } .feed_forward.experts. { xid } . { wid } .weight" 89datas .append (self ._experts [bid ][ename ]) 90del self ._experts [bid ][ename ] 91 92data_torch = torch .stack (datas ,dim = 0 ) 93 94# using the same merged name as qwen2moe 95merged_name = f"model.layers. { bid } .mlp.experts. { wid } .weight" 96 97new_name = self .map_tensor_name (merged_name ) 98 99yield new_name ,data_torch 100return 101 102new_name = self .map_tensor_name (name ) 103 104if self .match_model_tensor_name (new_name ,gguf .MODEL_TENSOR .SSM_CONV1D ,bid ): 105data_torch = data_torch .squeeze () 106 107if name .endswith (".A_log" ): 108logger .debug ("A_log --> A ==> " + new_name ) 109data_torch = - torch .exp (data_torch ) 110 111yield (new_name ,data_torch ) 112 113def prepare_tensors (self ): 114super ().prepare_tensors () 115 116if self ._experts is not None : 117# flatten `list[dict[str, Tensor]]` into `list[str]` 118experts = [k for d in self ._experts for k in d .keys ()] 119if len (experts )> 0 : 120raise ValueError (f"Unprocessed experts: { experts } " )