char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
fa88ae936
char/aliceai-t5-moe
1from __future__import annotations 2 3import re 4 5from typing import Callable ,Iterable ,TYPE_CHECKING 6 7import torch 8 9if TYPE_CHECKING : 10from torch import Tensor 11 12from .base import ModelBase ,TextModel ,gguf 13 14 15@ ModelBase . register ( "BailingMoeV3ForCausalLM" ) 16@ ModelBase . example ( "inclusionAI/Ling-3.0-tiny" , "inclusionAI/Ling-3.0-flash" ) 17class BailingMoeV3Model (TextModel ): 18model_arch = gguf .MODEL_ARCH .BAILINGMOE3 19supports_mtp_export = True 20 21_experts :list [dict [str ,Tensor ]]| None = None 22_main_layers :int | None = None 23 24def __init__ (self ,* args ,** kwargs ): 25super ().__init__ (* args ,** kwargs ) 26nextn_layers = self .hparams .get ("num_nextn_predict_layers" ,0 )or 0 27if self .no_mtp : 28nextn_layers = 0 29self .block_count = self .hparams ["num_hidden_layers" ]+ nextn_layers 30self .tensor_map = gguf .get_tensor_name_map (self .model_arch ,self .block_count ) 31 32def index_tensors (self ,remote_hf_model_id :str | None = None ): 33 type(self )._main_layers = self .hparams ["num_hidden_layers" ] 34return super ().index_tensors (remote_hf_model_id = remote_hf_model_id ) 35 36def set_vocab (self ): 37self ._set_vocab_gpt2 () 38 39def is_full_attention (self ,bid :int )-> bool : 40n_layer = self .hparams ["num_hidden_layers" ] 41layer_group_size = self .hparams ["layer_group_size" ] 42return bid >= n_layer or (bid + 1 )% layer_group_size == 0 or bid >= n_layer // layer_group_size * layer_group_size 43 44def set_gguf_parameters (self ): 45if not self .hparams .get ("no_kda_lora" ,False ): 46raise ValueError ("BailingMoeV3 KDA LoRA projections are not supported" ) 47if not self .hparams .get ("kda_safe_gate" ,False ): 48raise ValueError ("BailingMoeV3 non-safe KDA gates are not supported" ) 49if self .hparams .get ("gated_attention_proj_granularity_type" )!= "head_wise" : 50raise ValueError ("BailingMoeV3 requires head-wise attention gates" ) 51 52self .hparams ["num_key_value_heads" ]= 1 53super ().set_gguf_parameters () 54 55n_head_kv = [1 if self .is_full_attention (il )else 0 for il in range (self .block_count )] 56self .gguf_writer .add_head_count_kv (n_head_kv ) 57 58self .gguf_writer .add_vocab_size (self .hparams ["vocab_size" ]) 59self .gguf_writer .add_ssm_conv_kernel (self .hparams ["short_conv_kernel_size" ]) 60self .gguf_writer .add_kda_head_dim (self .hparams ["head_dim" ]) 61self .gguf_writer .add_kda_safe_gate (self .hparams ["kda_safe_gate" ]) 62self .gguf_writer .add_kda_gate_lower_bound (self .hparams ["kda_lower_bound" ]) 63 64kv_lora_rank = self .hparams ["kv_lora_rank" ] 65qk_nope_head_dim = self .hparams ["qk_nope_head_dim" ] 66qk_rope_head_dim = self .hparams ["qk_rope_head_dim" ] 67if (q_lora_rank := self .hparams .get ("q_lora_rank" ))is not None : 68self .gguf_writer .add_q_lora_rank (q_lora_rank ) 69self .gguf_writer .add_kv_lora_rank (kv_lora_rank ) 70self .gguf_writer .add_rope_dimension_count (qk_rope_head_dim ) 71self .gguf_writer .add_key_length (kv_lora_rank + qk_rope_head_dim ) 72self .gguf_writer .add_key_length_mla (qk_nope_head_dim + qk_rope_head_dim ) 73self .gguf_writer .add_value_length_mla (self .hparams ["v_head_dim" ]) 74 75self .gguf_writer .add_expert_feed_forward_length (self .hparams ["moe_intermediate_size" ]) 76self .gguf_writer .add_expert_shared_feed_forward_length (self .hparams ["moe_shared_expert_intermediate_size" ]) 77self .gguf_writer .add_expert_shared_count (self .hparams ["num_shared_experts" ]) 78self .gguf_writer .add_leading_dense_block_count (self .hparams ["first_k_dense_replace" ]) 79self .gguf_writer .add_expert_weights_scale (self .hparams ["routed_scaling_factor" ]) 80self .gguf_writer .add_expert_weights_norm (self .hparams ["norm_topk_prob" ]) 81 82def clamp_limits (key :str )-> list [float ]| None : 83values = self .hparams .get (key ) 84if values is None : 85return None 86values = [0.0 if value is None else float (value )for value in values [:self .block_count ]] 87return values + [0.0 ]* (self .block_count - len (values )) 88 89if (values := clamp_limits ("expert_swiglu_limit_list" ))is not None : 90self .gguf_writer .add_swiglu_clamp_exp (values ) 91if (values := clamp_limits ("share_expert_swiglu_limit_list" ))is not None : 92self .gguf_writer .add_swiglu_clamp_shexp (values ) 93 94if not self .no_mtp and (nextn_layers := self .hparams .get ("num_nextn_predict_layers" ,0 )): 95self .gguf_writer .add_nextn_predict_layers (nextn_layers ) 96 97def prepare_metadata (self ,vocab_only :bool ): 98from_dir = self .fname_out .is_dir () 99super ().prepare_metadata (vocab_only = vocab_only ) 100 101if not self .mtp_only or not from_dir : 102return 103 104output_type :str = self .ftype .name .partition ("_" )[2 ] 105fname_default :str = gguf .naming_convention ( 106self .metadata .name ,self .metadata .basename ,self .metadata .finetune , 107self .metadata .version ,size_label = None ,output_type = output_type ,model_type = None ) 108self .fname_out = self .fname_out .parent / f"mtp- { fname_default } .gguf" 109 110@classmethod 111def filter_tensors (cls ,item :tuple [str ,Callable [[],Tensor ]])-> tuple [str ,Callable [[],Tensor ]]| None : 112name ,gen = item 113if name .endswith (".expert_bias" ): 114name += ".bias" 115 116if cls ._main_layers is None : 117return super ().filter_tensors ((name ,gen )) 118 119m = re .match (r"model\.layers\.(\d+)\." ,name ) 120is_mtp = m is not None and int (m .group (1 ))>= cls ._main_layers 121 122if is_mtp and cls .no_mtp : 123return None 124if cls .mtp_only and not is_mtp and name not in ( 125"model.word_embeddings.weight" ,"model.norm.weight" ,"lm_head.weight" , 126 ): 127return None 128 129return super ().filter_tensors ((name ,gen )) 130 131def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 132if name .endswith ((".q_conv1d.weight" ,".k_conv1d.weight" ,".v_conv1d.weight" ))and data_torch .ndim in (2 ,3 ): 133d_inner = data_torch .shape [0 ] 134d_conv = data_torch .shape [- 1 ] 135data_torch = data_torch .reshape (1 ,d_inner ,1 ,d_conv ) 136 137if name .endswith (".A_log" ): 138data_torch = torch .exp (data_torch ).reshape (- 1 ,1 ) 139 140if name .endswith (".dt_bias" ): 141name = name .rpartition (".dt_bias" )[0 ]+ ".dt_proj.bias" 142 143if name .endswith (".attention.f_proj.weight" ): 144assert bid is not None 145if self .is_full_attention (bid ): 146raise ValueError (f"unexpected f_proj on full-attention layer { bid } " ) 147name = self .format_tensor_name (gguf .MODEL_TENSOR .SSM_F_A ,bid ) 148 149if name .endswith (".attention.g_proj.weight" ): 150assert bid is not None 151tensor = gguf .MODEL_TENSOR .ATTN_GATE if self .is_full_attention (bid )else gguf .MODEL_TENSOR .SSM_G_A 152name = self .format_tensor_name (tensor ,bid ) 153 154if ".mlp.experts." in name : 155n_experts = self .hparams ["num_experts" ] 156assert bid is not None 157 158if self ._experts is None : 159self ._experts = [{}for _ in range (self .block_count )] 160 161self ._experts [bid ][name ]= data_torch 162if len (self ._experts [bid ])>= n_experts * 3 : 163for weight_name in ("down_proj" ,"gate_proj" ,"up_proj" ): 164tensors = [] 165for expert_id in range (n_experts ): 166expert_name = f"model.layers. { bid } .mlp.experts. { expert_id } . { weight_name } .weight" 167tensors .append (self ._experts [bid ].pop (expert_name )) 168merged_name = f"model.layers. { bid } .mlp.experts. { weight_name } .weight" 169yield from super ().modify_tensors (torch .stack (tensors ,dim = 0 ),merged_name ,bid ) 170return 171 172if name .endswith (".attention.kv_b_proj.weight" ): 173assert bid is not None 174n_head = self .hparams ["num_attention_heads" ] 175v_head_dim = self .hparams ["v_head_dim" ] 176qk_nope_head_dim = self .hparams ["qk_nope_head_dim" ] 177assert data_torch .shape [0 ]== n_head * (v_head_dim + qk_nope_head_dim ) 178kv_b = data_torch .view (n_head ,v_head_dim + qk_nope_head_dim ,data_torch .shape [- 1 ]) 179k_b ,v_b = torch .split (kv_b , [qk_nope_head_dim ,v_head_dim ],dim = 1 ) 180name_k = self .format_tensor_name (gguf .MODEL_TENSOR .ATTN_K_B ,bid ) 181name_v = self .format_tensor_name (gguf .MODEL_TENSOR .ATTN_V_B ,bid ) 182yield from super ().modify_tensors (k_b .transpose (1 ,2 ),name_k ,bid ) 183yield from super ().modify_tensors (v_b ,name_v ,bid ) 184return 185 186yield from super ().modify_tensors (data_torch ,name ,bid ) 187 188def prepare_tensors (self ): 189super ().prepare_tensors () 190if self ._experts is not None : 191experts = [name for layer in self ._experts for name in layer ] 192if experts : 193raise ValueError (f"Unprocessed experts: { experts } " )