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 Callable ,Iterable ,TYPE_CHECKING 4 5import torch 6 7if TYPE_CHECKING : 8from torch import Tensor 9 10from .base import ModelBase ,TextModel ,gguf 11 12 13@ ModelBase . register ( "BailingMoeForCausalLM" ) 14@ ModelBase . example ( "inclusionAI/Ling-lite" ) 15class BailingMoeModel (TextModel ): 16model_arch = gguf .MODEL_ARCH .BAILINGMOE 17 18def set_vocab (self ): 19self ._set_vocab_gpt2 () 20 21def set_gguf_parameters (self ): 22super ().set_gguf_parameters () 23hparams = self .hparams 24if (rope_dim := hparams .get ("head_dim" ))is None : 25rope_dim = hparams ["hidden_size" ]// hparams ["num_attention_heads" ] 26 27self .gguf_writer .add_rope_dimension_count (rope_dim ) 28self .gguf_writer .add_leading_dense_block_count (hparams ["first_k_dense_replace" ]) 29self .gguf_writer .add_vocab_size (hparams ["vocab_size" ]) 30self .gguf_writer .add_expert_feed_forward_length (hparams ["moe_intermediate_size" ]) 31self .gguf_writer .add_expert_weights_scale (1.0 ) 32self .gguf_writer .add_expert_shared_count (hparams ["num_shared_experts" ]) 33self .gguf_writer .add_expert_weights_norm (hparams ["norm_topk_prob" ]) 34 35_experts :list [dict [str ,Tensor ]]| None = None 36 37@staticmethod 38def permute (weights :Tensor ,n_head :int ,n_head_kv :int | None ): 39if n_head_kv is not None and n_head != n_head_kv : 40n_head = n_head_kv 41return (weights .reshape (n_head ,2 ,weights .shape [0 ]// n_head // 2 ,* weights .shape [1 :]) 42 .swapaxes (1 ,2 ) 43 .reshape (weights .shape )) 44 45def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 46n_head = self .hparams ["num_attention_heads" ] 47n_kv_head = self .hparams .get ("num_key_value_heads" ) 48n_embd = self .hparams ["hidden_size" ] 49if (head_dim := self .hparams .get ("head_dim" ))is None : 50head_dim = n_embd // n_head 51 52output_name = self .format_tensor_name (gguf .MODEL_TENSOR .OUTPUT ) 53 54if name .endswith ("attention.dense.weight" ): 55yield from super ().modify_tensors (data_torch ,self .format_tensor_name (gguf .MODEL_TENSOR .ATTN_OUT ,bid ),bid ) 56return 57elif name .endswith ("query_key_value.weight" ): 58q ,k ,v = data_torch .split ([n_head * head_dim ,n_kv_head * head_dim ,n_kv_head * head_dim ],dim =- 2 ) 59 60yield from super ().modify_tensors (BailingMoeModel .permute (q ,n_head ,n_head ),self .format_tensor_name (gguf .MODEL_TENSOR .ATTN_Q ,bid ),bid ) 61yield from super ().modify_tensors (BailingMoeModel .permute (k ,n_head ,n_kv_head ),self .format_tensor_name (gguf .MODEL_TENSOR .ATTN_K ,bid ),bid ) 62yield from super ().modify_tensors (v ,self .format_tensor_name (gguf .MODEL_TENSOR .ATTN_V ,bid ),bid ) 63return 64elif name .find ("mlp.experts" )!= - 1 : 65n_experts = self .find_hparam (["num_local_experts" ,"num_experts" ]) 66assert bid is not None 67 68if self ._experts is None : 69self ._experts = [{}for _ in range (self .block_count )] 70 71self ._experts [bid ][name ]= data_torch 72 73if len (self ._experts [bid ])>= n_experts * 3 : 74# merge the experts into a single 3d tensor 75for w_name in ["down_proj" ,"gate_proj" ,"up_proj" ]: 76datas :list [Tensor ]= [] 77 78for xid in range (n_experts ): 79ename = f"model.layers. { bid } .mlp.experts. { xid } . { w_name } .weight" 80datas .append (self ._experts [bid ][ename ]) 81del self ._experts [bid ][ename ] 82 83data_torch = torch .stack (datas ,dim = 0 ) 84 85merged_name = f"model.layers. { bid } .mlp.experts. { w_name } .weight" 86 87new_name = self .map_tensor_name (merged_name ) 88 89yield from super ().modify_tensors (data_torch ,new_name ,bid ) 90 91return 92 93new_name = self .map_tensor_name (name ) 94 95if new_name == output_name and self .hparams .get ("norm_head" ): 96data_torch = data_torch .float () 97data_torch /= torch .norm (data_torch ,p = 2 ,dim = 0 ,keepdim = True )+ 1e-7 98 99yield from super ().modify_tensors (data_torch ,new_name ,bid ) 100 101def prepare_tensors (self ): 102super ().prepare_tensors () 103 104if self ._experts is not None : 105# flatten `list[dict[str, Tensor]]` into `list[str]` 106experts = [k for d in self ._experts for k in d .keys ()] 107if len (experts )> 0 : 108raise ValueError (f"Unprocessed experts: { experts } " ) 109 110 111@ ModelBase . register ( "BailingMoeV2ForCausalLM" ) 112@ ModelBase . example ( "inclusionAI/Ling-mini-2.0" ) 113class BailingMoeV2Model (TextModel ): 114model_arch = gguf .MODEL_ARCH .BAILINGMOE2 115 116def __init__ (self ,* args ,** kwargs ): 117super ().__init__ (* args ,** kwargs ) 118if nextn_layers := self .hparams .get ("num_nextn_predict_layers" ,0 ): 119self .block_count = self .hparams ["num_hidden_layers" ]+ nextn_layers 120self .tensor_map = gguf .get_tensor_name_map (self .model_arch ,self .block_count ) 121 122def set_vocab (self ): 123self ._set_vocab_gpt2 () 124 125def set_gguf_parameters (self ): 126super ().set_gguf_parameters () 127hparams = self .hparams 128if (rope_dim := hparams .get ("head_dim" ))is None : 129rope_dim = hparams ["hidden_size" ]// hparams ["num_attention_heads" ] 130 131self .gguf_writer .add_rope_dimension_count (int (rope_dim * self .rope_parameters .get ("partial_rotary_factor" ,0.5 ))) 132self .gguf_writer .add_leading_dense_block_count (hparams ["first_k_dense_replace" ]) 133self .gguf_writer .add_vocab_size (hparams ["vocab_size" ]) 134self .gguf_writer .add_expert_feed_forward_length (hparams ["moe_intermediate_size" ]) 135self .gguf_writer .add_expert_shared_feed_forward_length (hparams .get ("moe_shared_expert_intermediate_size" ,hparams ["moe_intermediate_size" ]* hparams ["num_shared_experts" ])) 136self .gguf_writer .add_expert_weights_scale (hparams ["routed_scaling_factor" ]) 137self .gguf_writer .add_expert_shared_count (hparams ["num_shared_experts" ]) 138self .gguf_writer .add_expert_weights_norm (hparams ["norm_topk_prob" ]) 139 140if (nextn_layers := self .hparams .get ("num_nextn_predict_layers" ))is not None : 141self .gguf_writer .add_nextn_predict_layers (nextn_layers ) 142 143_experts :list [dict [str ,Tensor ]]| None = None 144 145@classmethod 146def filter_tensors (cls ,item :tuple [str ,Callable [[],Tensor ]])-> tuple [str ,Callable [[],Tensor ]]| None : 147name ,gen = item 148 149if name .endswith (".expert_bias" ): 150name = name .replace (".expert_bias" ,".expert_bias.bias" ) 151 152return super ().filter_tensors ((name ,gen )) 153 154def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 155if "mlp.experts" in name : 156n_experts = self .find_hparam (["num_local_experts" ,"num_experts" ]) 157assert bid is not None 158 159if self ._experts is None : 160self ._experts = [{}for _ in range (self .block_count )] 161 162self ._experts [bid ][name ]= data_torch 163 164if len (self ._experts [bid ])>= n_experts * 3 : 165# merge the experts into a single 3d tensor 166for w_name in ["down_proj" ,"gate_proj" ,"up_proj" ]: 167datas :list [Tensor ]= [] 168 169for xid in range (n_experts ): 170ename = f"model.layers. { bid } .mlp.experts. { xid } . { w_name } .weight" 171datas .append (self ._experts [bid ][ename ]) 172del self ._experts [bid ][ename ] 173 174data_torch = torch .stack (datas ,dim = 0 ) 175 176merged_name = f"model.layers. { bid } .mlp.experts. { w_name } .weight" 177 178yield from super ().modify_tensors (data_torch ,merged_name ,bid ) 179return 180 181yield from super ().modify_tensors (data_torch ,name ,bid ) 182 183def prepare_tensors (self ): 184super ().prepare_tensors () 185 186if self ._experts is not None : 187# flatten `list[dict[str, Tensor]]` into `list[str]` 188experts = [k for d in self ._experts for k in d .keys ()] 189if len (experts )> 0 : 190raise ValueError (f"Unprocessed experts: { experts } " ) 191 192 193@ ModelBase . register ( "SarvamMoEForCausalLM" , "modeling_sarvam_moe.SarvamMoEForCausalLM" ) 194@ ModelBase . example ( "sarvamai/sarvam-30b" ) 195class SarvamMoEModel (BailingMoeV2Model ): 196model_arch = gguf .MODEL_ARCH .BAILINGMOE2 197# Sarvam-MoE shares the BailingMoeV2 architecture; only differences: 198# - full rotary (no partial_rotary_factor) 199# - expert bias is zero-mean normalized at load time 200 201def set_gguf_parameters (self ): 202super ().set_gguf_parameters () 203hparams = self .hparams 204if (rope_dim := hparams .get ("head_dim" ))is None : 205rope_dim = hparams ["hidden_size" ]// hparams ["num_attention_heads" ] 206# Override the partial-rotary value written by BailingMoeV2 with the full rotary dim 207self .gguf_writer .add_rope_dimension_count (rope_dim ) 208 209@classmethod 210def filter_tensors (cls ,item :tuple [str ,Callable [[],Tensor ]])-> tuple [str ,Callable [[],Tensor ]]| None : 211name ,gen = item 212if name .endswith (".expert_bias" ): 213# Sarvam normalizes expert bias to zero mean 214inner = gen 215 216def gen (): 217t = inner () 218return t - t .mean () 219return super ().filter_tensors ((name ,gen ))