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 math 4 5from pathlib import Path 6from typing import Callable ,Iterable ,TYPE_CHECKING 7 8import torch 9 10if TYPE_CHECKING : 11from torch import Tensor 12 13from .base import MmprojModel ,ModelBase ,TextModel ,gguf 14from .qwenvl import Qwen2VLVisionModel 15 16 17@ ModelBase . register ( "ExaoneForCausalLM" ) 18@ ModelBase . example ( "LGAI-EXAONE/EXAONE-3.5-2.4B-Instruct" ) 19class ExaoneModel (TextModel ): 20model_arch = gguf .MODEL_ARCH .EXAONE 21 22def set_gguf_parameters (self ): 23super ().set_gguf_parameters () 24hparams = self .hparams 25 26assert (hparams ["activation_function" ]== "silu" ) 27 28rotary_factor = self .rope_parameters .get ("partial_rotary_factor" ) 29rotary_factor = rotary_factor if rotary_factor is not None else 1.0 30self .gguf_writer .add_rope_dimension_count (int (rotary_factor * (hparams ["hidden_size" ]// hparams ["num_attention_heads" ]))) 31 32def generate_extra_tensors (self )-> Iterable [tuple [str ,Tensor ]]: 33if rope_params := self .rope_parameters .get ("full_attention" ,self .rope_parameters ): 34if rope_params .get ("rope_type" ,'' ).lower ()== "llama3" : 35base = self .rope_parameters .get ("rope_theta" ,10000.0 ) 36if (dim := self .hparams .get ("head_dim" ))is None : 37dim = self .hparams ["hidden_size" ]// self .hparams ["num_attention_heads" ] 38freqs = 1.0 / (base ** (torch .arange (0 ,dim ,2 ,dtype = torch .float32 )/ dim )) 39 40factor = rope_params .get ("factor" ,8.0 ) 41low_freq_factor = rope_params .get ("low_freq_factor" ,1.0 ) 42high_freq_factor = rope_params .get ("high_freq_factor" ,4.0 ) 43old_context_len = rope_params .get ("original_max_position_embeddings" ,8192 ) 44 45low_freq_wavelen = old_context_len / low_freq_factor 46high_freq_wavelen = old_context_len / high_freq_factor 47assert low_freq_wavelen != high_freq_wavelen 48 49rope_factors = [] 50for freq in freqs : 51wavelen = 2 * math .pi / freq 52if wavelen < high_freq_wavelen : 53rope_factors .append (1 ) 54elif wavelen > low_freq_wavelen : 55rope_factors .append (factor ) 56else : 57smooth = (old_context_len / wavelen - low_freq_factor )/ (high_freq_factor - low_freq_factor ) 58rope_factors .append (1 / ((1 - smooth )/ factor + smooth )) 59 60yield (self .format_tensor_name (gguf .MODEL_TENSOR .ROPE_FREQS ),torch .tensor (rope_factors ,dtype = torch .float32 )) 61 62 63@ ModelBase . register ( "Exaone4ForCausalLM" ) 64@ ModelBase . example ( "LGAI-EXAONE/EXAONE-4.0-32B" ) 65class Exaone4Model (TextModel ): 66model_arch = gguf .MODEL_ARCH .EXAONE4 67 68def set_vocab (self ): 69tokens ,toktypes ,tokpre = self .get_vocab_base () 70self .gguf_writer .add_tokenizer_model ("gpt2" ) 71self .gguf_writer .add_tokenizer_pre (tokpre ) 72self .gguf_writer .add_token_list (tokens ) 73self .gguf_writer .add_token_types (toktypes ) 74 75special_vocab = gguf .SpecialVocab (self .dir_model ,load_merges = True ) 76special_vocab .add_to_gguf (self .gguf_writer ) 77 78def set_gguf_parameters (self ): 79super ().set_gguf_parameters () 80hparams = self .hparams 81self .gguf_writer .add_vocab_size (hparams ["vocab_size" ]) 82 83if hparams .get ("sliding_window" )is not None : 84self .gguf_writer .add_sliding_window (hparams ["sliding_window" ]) 85if "layer_types" in hparams : 86self .gguf_writer .add_sliding_window_pattern ([t == "sliding_attention" for t in hparams ["layer_types" ]]) 87elif "sliding_window_pattern" in hparams : 88sliding_window_pattern = [] 89if isinstance (hparams ["sliding_window_pattern" ],str ):# e.g. LLLG 90for i in range (hparams ["num_hidden_layers" ]): 91sliding_window_pattern .append (hparams ["sliding_window_pattern" ][i % len (hparams ["sliding_window_pattern" ])]== "L" ) 92if isinstance (hparams ["sliding_window_pattern" ],int ):# e.g. 4 93for i in range (hparams ["num_hidden_layers" ]): 94sliding_window_pattern .append ((i + 1 )% hparams ["sliding_window_pattern" ]!= 0 ) 95if len (sliding_window_pattern )== hparams ["num_hidden_layers" ]: 96self .gguf_writer .add_sliding_window_pattern (sliding_window_pattern ) 97 98def generate_extra_tensors (self )-> Iterable [tuple [str ,Tensor ]]: 99if rope_params := self .rope_parameters .get ("full_attention" ,self .rope_parameters ): 100if rope_params .get ("rope_type" ,'' ).lower ()== "llama3" : 101base = rope_params .get ("rope_theta" ,10_000.0 ) 102if (dim := self .hparams .get ("head_dim" ))is None : 103dim = self .hparams ["hidden_size" ]// self .hparams ["num_attention_heads" ] 104freqs = 1.0 / (base ** (torch .arange (0 ,dim ,2 ,dtype = torch .float32 )/ dim )) 105 106factor = rope_params .get ("factor" ,16.0 ) 107low_freq_factor = rope_params .get ("low_freq_factor" ,1.0 ) 108high_freq_factor = rope_params .get ("high_freq_factor" ,4.0 ) 109old_context_len = rope_params .get ("original_max_position_embeddings" ,8192 ) 110 111low_freq_wavelen = old_context_len / low_freq_factor 112high_freq_wavelen = old_context_len / high_freq_factor 113 114rope_factors = [] 115for freq in freqs : 116wavelen = 2 * math .pi / freq 117if wavelen < high_freq_wavelen : 118rope_factors .append (1 ) 119elif wavelen > low_freq_wavelen : 120rope_factors .append (factor ) 121else : 122smooth = (old_context_len / wavelen - low_freq_factor )/ (high_freq_factor - low_freq_factor ) 123rope_factors .append (1 / ((1 - smooth )/ factor + smooth )) 124 125yield (self .format_tensor_name (gguf .MODEL_TENSOR .ROPE_FREQS ),torch .tensor (rope_factors ,dtype = torch .float32 )) 126 127 128# note: transformers >= 5.1 renamed the class to "ExaoneMoeForCausalLM" (lowercase 'e'), 129# so accept both spellings - LG AI have updated the configs of already-released models 130@ ModelBase . register ( "ExaoneMoEForCausalLM" , "ExaoneMoeForCausalLM" ) 131@ ModelBase . example ( "LGAI-EXAONE/K-EXAONE-236B-A23B" ) 132class ExaoneMoEModel (Exaone4Model ): 133model_arch = gguf .MODEL_ARCH .EXAONE_MOE 134 135def __init__ (self ,* args ,** kwargs ): 136super ().__init__ (* args ,** kwargs ) 137self .block_count = self .hparams ["num_hidden_layers" ]+ self .hparams .get ("num_nextn_predict_layers" ,0 ) 138self .tensor_map = gguf .get_tensor_name_map (self .model_arch ,self .block_count ) 139 140def set_gguf_parameters (self ): 141super ().set_gguf_parameters () 142moe_intermediate_size = self .hparams ["moe_intermediate_size" ] 143num_shared_experts = self .hparams ["num_shared_experts" ] 144self .gguf_writer .add_expert_feed_forward_length (moe_intermediate_size ) 145self .gguf_writer .add_expert_shared_count (num_shared_experts ) 146self .gguf_writer .add_expert_shared_feed_forward_length (moe_intermediate_size * num_shared_experts ) 147self .gguf_writer .add_expert_weights_scale (self .hparams ["routed_scaling_factor" ]) 148self .gguf_writer .add_expert_weights_norm (self .hparams ["norm_topk_prob" ]) 149n_dense_layer = self .hparams .get ("first_k_dense_replace" ,self .hparams .get ("first_last_k_dense_replace" ,0 )) 150self .gguf_writer .add_leading_dense_block_count (n_dense_layer ) 151self .gguf_writer .add_nextn_predict_layers (self .hparams .get ("num_nextn_predict_layers" ,0 )) 152 153self .gguf_writer .add_rope_scaling_type (gguf .RopeScalingType .NONE ) 154 155_experts :list [dict [str ,Tensor ]]| None = None 156 157def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 158if name .startswith ("mtp." ): 159if name .find ("layers." )!= - 1 : 160# `mtp.layers.0.[module_name]` format 161name = name .replace (f"mtp.layers. { bid } " ,f"model.layers. { bid + self . hparams [ 'num_hidden_layers' ] } " ) 162else : 163# mtp fc/norm weights 164remapper = { 165"mtp.fc" :"model.layers.{bid}.eh_proj" , 166"mtp.pre_fc_norm_embedding" :"model.layers.{bid}.enorm" , 167"mtp.pre_fc_norm_hidden" :"model.layers.{bid}.hnorm" , 168"mtp.norm" :"model.layers.{bid}.shared_head.norm" , 169 } 170_n = Path (name ) 171new_name = remapper [_n .stem ]+ _n .suffix 172 173# set shared weights for all NextN/MTP layers 174for bid in range (self .hparams ['num_hidden_layers' ],self .block_count ): 175yield from super ().modify_tensors (data_torch ,new_name .format (bid = bid ),bid ) 176return 177 178if name .find ("mlp.experts" )!= - 1 : 179n_experts = self .find_hparam (["num_local_experts" ,"num_experts" ]) 180assert bid is not None 181 182if self ._experts is None : 183self ._experts = [{}for _ in range (self .block_count )] 184 185self ._experts [bid ][name ]= data_torch 186 187if len (self ._experts [bid ])>= n_experts * 3 : 188# merge the experts into a single 3d tensor 189for w_name in ["down_proj" ,"gate_proj" ,"up_proj" ]: 190datas :list [Tensor ]= [] 191 192for xid in range (n_experts ): 193ename = f"model.layers. { bid } .mlp.experts. { xid } . { w_name } .weight" 194datas .append (self ._experts [bid ][ename ]) 195del self ._experts [bid ][ename ] 196 197data_torch = torch .stack (datas ,dim = 0 ) 198 199merged_name = f"model.layers. { bid } .mlp.experts. { w_name } .weight" 200 201new_name = self .map_tensor_name (merged_name ) 202 203yield from super ().modify_tensors (data_torch ,new_name ,bid ) 204return 205else : 206return 207 208yield from super ().modify_tensors (data_torch ,name ,bid ) 209 210def prepare_tensors (self ): 211super ().prepare_tensors () 212if self ._experts is not None : 213# flatten `list[dict[str, Tensor]]` into `list[str]` 214experts = [k for d in self ._experts for k in d .keys ()] 215if len (experts )> 0 : 216raise ValueError (f"Unprocessed experts: { experts } " ) 217 218 219@ ModelBase . register ( "Exaone4_5_ForConditionalGeneration" ) 220@ ModelBase . example ( "LGAI-EXAONE/EXAONE-4.5-33B" ) 221class Exaone4_5_TextModel (Exaone4Model ): 222"""Text tower of EXAONE 4.5; Tensors match EXAONE4""" 223 224model_arch = gguf .MODEL_ARCH .EXAONE4 225 226def __init__ (self ,* args ,** kwargs ): 227super ().__init__ (* args ,** kwargs ) 228n_nextn = int (self .hparams .get ("num_nextn_predict_layers" ,0 )or 0 ) 229if n_nextn > 0 : 230self .block_count = self .hparams ["num_hidden_layers" ]+ n_nextn 231self .tensor_map = gguf .get_tensor_name_map (self .model_arch ,self .block_count ) 232 233def set_gguf_parameters (self ): 234super ().set_gguf_parameters () 235n_nextn = int (self .hparams .get ("num_nextn_predict_layers" ,0 )or 0 ) 236if n_nextn > 0 : 237self .gguf_writer .add_nextn_predict_layers (n_nextn ) 238 239def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 240if name .startswith ("mtp." ): 241n_nextn = int (self .hparams .get ("num_nextn_predict_layers" ,0 )or 0 ) 242if n_nextn <= 0 : 243return 244nh = self .hparams ["num_hidden_layers" ] 245if ".layers." in name : 246share = self .hparams .get ("mtp_share_layers" ,False ) 247mtp_bid = bid if bid is not None else 0 248if share : 249for k in range (n_nextn ): 250nn = name .replace (f"mtp.layers. { mtp_bid } " ,f"model.layers. { nh + k } " ) 251yield from super ().modify_tensors (data_torch ,nn ,nh + k ) 252return 253name = name .replace (f"mtp.layers. { mtp_bid } " ,f"model.layers. { mtp_bid + nh } " ) 254else : 255remapper = { 256"mtp.fc" :gguf .MODEL_TENSOR .NEXTN_EH_PROJ , 257"mtp.pre_fc_norm_embedding" :gguf .MODEL_TENSOR .NEXTN_ENORM , 258"mtp.pre_fc_norm_hidden" :gguf .MODEL_TENSOR .NEXTN_HNORM , 259"mtp.norm" :gguf .MODEL_TENSOR .NEXTN_SHARED_HEAD_NORM , 260 } 261_n = Path (name ) 262key = _n .stem 263if key not in remapper : 264return 265for bid_mtp in range (nh ,self .block_count ): 266mapped_name = self .format_tensor_name (remapper [key ],bid_mtp ,suffix = _n .suffix ) 267yield from ModelBase .modify_tensors (self ,data_torch ,mapped_name ,bid_mtp ) 268return 269 270yield from super ().modify_tensors (data_torch ,name ,bid ) 271 272 273@ ModelBase . register ( "Exaone4_5_ForConditionalGeneration" ) 274@ ModelBase . example ( "LGAI-EXAONE/EXAONE-4.5-33B" ) 275class Exaone4_5VisionModel (Qwen2VLVisionModel ): 276"""Vision tower for EXAONE 4.5; Qwen2-VL-style ViT (GQA) + patch merger""" 277 278@classmethod 279def filter_tensors (cls ,item :tuple [str ,Callable [[],Tensor ]])-> tuple [str ,Callable [[],Tensor ]]| None : 280name ,gen = item 281name = name .replace ("model.visual." ,"visual." ,1 ) 282return super ().filter_tensors ((name ,gen )) 283 284def set_gguf_parameters (self ): 285MmprojModel .set_gguf_parameters (self ) 286assert self .hparams_vision is not None 287hparams = self .hparams_vision 288self .gguf_writer .add_clip_projector_type (gguf .VisionProjectorType .EXAONE4_5 ) 289self .gguf_writer .add_vision_use_silu (True ) 290self .gguf_writer .add_vision_min_pixels (self .preprocessor_config ["min_pixels" ]) 291self .gguf_writer .add_vision_max_pixels (self .preprocessor_config ["max_pixels" ]) 292num_kv_head = self .find_vparam (["num_key_value_heads" ],optional = True ) 293if num_kv_head is not None : 294self .gguf_writer .add_vision_head_count_kv (num_kv_head ) 295eps = hparams .get ("rms_norm_eps" ,self .global_config .get ("rms_norm_eps" ,1e-6 )) 296self .gguf_writer .add_vision_attention_layernorm_eps (eps ) 297if (window_size := hparams .get ("window_size" ))is not None : 298self .gguf_writer .add_vision_window_size (window_size ) 299fullatt_block_indexes = hparams .get ("fullatt_block_indexes" ) 300if fullatt_block_indexes : 301n_wa_pattern = fullatt_block_indexes [0 ]+ 1 302for i in range (1 ,len (fullatt_block_indexes )): 303if fullatt_block_indexes [i ]- fullatt_block_indexes [i - 1 ]!= n_wa_pattern : 304raise ValueError (f"Invalid EXAONE4.5 fullatt_block_indexes: { fullatt_block_indexes } " ) 305self .gguf_writer .add_vision_n_wa_pattern (n_wa_pattern ) 306 307def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 308if ".qkv." in name : 309yield from ModelBase .modify_tensors (self ,data_torch ,name ,bid ) 310return 311 312yield from Qwen2VLVisionModel .modify_tensors (self ,data_torch ,name ,bid )