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 Any ,Callable ,Iterable ,TYPE_CHECKING 4 5import torch 6 7if TYPE_CHECKING : 8from torch import Tensor 9 10from .base import MmprojModel ,ModelBase ,TextModel ,gguf 11 12from .gemma import ConformerAudioModel 13 14 15@ ModelBase . register ( "Lfm2ForCausalLM" , "LFM2ForCausalLM" ) 16@ ModelBase . example ( "LiquidAI/LFM2-1.2B" , "LiquidAI/LFM2.5-350M" ) 17class LFM2Model (TextModel ): 18model_arch = gguf .MODEL_ARCH .LFM2 19 20def _add_feed_forward_length (self ): 21ff_dim = self .find_hparam (["block_ff_dim" ,"intermediate_size" ]) 22auto_adjust_ff_dim = self .hparams ["block_auto_adjust_ff_dim" ] 23ffn_dim_multiplier = self .hparams ["block_ffn_dim_multiplier" ] 24multiple_of = self .hparams ["block_multiple_of" ] 25 26if auto_adjust_ff_dim : 27ff_dim = int (2 * ff_dim / 3 ) 28# custom dim factor multiplier 29if ffn_dim_multiplier is not None : 30ff_dim = int (ffn_dim_multiplier * ff_dim ) 31ff_dim = multiple_of * ((ff_dim + multiple_of - 1 )// multiple_of ) 32 33self .gguf_writer .add_feed_forward_length (ff_dim ) 34 35def set_gguf_parameters (self ): 36# set num_key_value_heads only for attention layers 37self .hparams ["num_key_value_heads" ]= [ 38self .hparams ["num_key_value_heads" ]if layer_type != "conv" else 0 39for layer_type in self .hparams ["layer_types" ] 40 ] 41 42super ().set_gguf_parameters () 43self .gguf_writer .add_vocab_size (self .hparams ["vocab_size" ]) 44self .gguf_writer .add_shortconv_l_cache (self .hparams ["conv_L_cache" ]) 45self .gguf_writer .add_layer_norm_rms_eps (self .hparams ["norm_eps" ]) 46self ._add_feed_forward_length () 47 48@classmethod 49def filter_tensors (cls ,item :tuple [str ,Callable [[],Tensor ]])-> tuple [str ,Callable [[],Tensor ]]| None : 50name ,gen = item 51 52if ConformerAudioModel .is_audio_tensor (name ): 53# skip multimodal tensors 54return None 55 56name = name .replace ("lfm." ,"model." )# audio 57 58return super ().filter_tensors ((name ,gen )) 59 60def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 61# conv op requires 2d tensor 62if 'conv.conv' in name : 63data_torch = data_torch .squeeze (1 ) 64 65yield from super ().modify_tensors (data_torch ,name ,bid ) 66 67 68@ ModelBase . register ( "Lfm2Model" , "Lfm2BidirectionalModel" ) 69@ ModelBase . example ( "LiquidAI/LFM2.5-ColBERT-350M" , "LiquidAI/LFM2.5-Embedding-350M" ) 70class LFM2ColBertModel (LFM2Model ): 71model_arch = gguf .MODEL_ARCH .LFM2 72dense_tensor_name = "dense_2" 73 74def set_gguf_parameters (self ): 75super ().set_gguf_parameters () 76if self .hf_arch == "Lfm2BidirectionalModel" : 77self .gguf_writer .add_causal_attention (False ) 78self ._try_set_pooling_type () 79 80def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 81if not name .startswith (self .dense_tensor_name ): 82name = "model." + name 83 84yield from super ().modify_tensors (data_torch ,name ,bid ) 85 86def generate_extra_tensors (self )-> Iterable [tuple [str ,Tensor ]]: 87# optional dense tensor is stored in a separate safetensors file 88from safetensors .torch import load_file 89tensors_file = self .dir_model / "1_Dense" / "model.safetensors" 90if not tensors_file .is_file (): 91return 92tensor = load_file (tensors_file )["linear.weight" ] 93self .gguf_writer .add_embedding_length_out (tensor .shape [0 ]) 94yield f" { self . dense_tensor_name } .weight" ,tensor .clone () 95 96 97@ ModelBase . register ( "Lfm2MoeForCausalLM" ) 98@ ModelBase . example ( "LiquidAI/LFM2-8B-A1B" ) 99class LFM2MoeModel (TextModel ): 100model_arch = gguf .MODEL_ARCH .LFM2MOE 101 102def set_gguf_parameters (self ): 103# set num_key_value_heads only for attention layers 104self .hparams ["num_key_value_heads" ]= [ 105self .hparams ["num_key_value_heads" ]if layer_type == "full_attention" else 0 106for layer_type in self .hparams ["layer_types" ] 107 ] 108 109super ().set_gguf_parameters () 110 111self .gguf_writer .add_expert_feed_forward_length (self .hparams ["moe_intermediate_size" ]) 112self .gguf_writer .add_leading_dense_block_count (self .hparams ["num_dense_layers" ]) 113self .gguf_writer .add_expert_gating_func (gguf .ExpertGatingFuncType .SIGMOID ) 114 115self .gguf_writer .add_vocab_size (self .hparams ["vocab_size" ]) 116self .gguf_writer .add_shortconv_l_cache (self .hparams ["conv_L_cache" ]) 117 118# cache for experts weights for merging 119_experts_cache :dict [int ,dict [str ,Tensor ]]= {} 120 121@classmethod 122def filter_tensors (cls ,item :tuple [str ,Callable [[],Tensor ]])-> tuple [str ,Callable [[],Tensor ]]| None : 123name ,gen = item 124 125if name .endswith (".expert_bias" ): 126name = name .replace (".expert_bias" ,".expert_bias.bias" ) 127 128return super ().filter_tensors ((name ,gen )) 129 130def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 131# conv op requires 2d tensor 132if 'conv.conv' in name : 133data_torch = data_torch .squeeze (1 ) 134 135# merge expert weights 136if 'experts' in name : 137n_experts = self .find_hparam (["num_local_experts" ,"num_experts" ]) 138assert bid is not None 139 140expert_cache = self ._experts_cache .setdefault (bid , {}) 141expert_cache [name ]= data_torch 142expert_weights = ["w1" ,"w2" ,"w3" ] 143 144# not enough expert weights to merge 145if len (expert_cache )< n_experts * len (expert_weights ): 146return 147 148for w_name in expert_weights : 149datas :list [Tensor ]= [] 150 151for xid in range (n_experts ): 152ename = f"model.layers. { bid } .feed_forward.experts. { xid } . { w_name } .weight" 153datas .append (expert_cache [ename ]) 154del expert_cache [ename ] 155 156data_torch = torch .stack (datas ,dim = 0 ) 157merged_name = f"layers. { bid } .feed_forward.experts. { w_name } .weight" 158 159yield from super ().modify_tensors (data_torch ,merged_name ,bid ) 160 161del self ._experts_cache [bid ] 162return 163 164yield from super ().modify_tensors (data_torch ,name ,bid ) 165 166def prepare_tensors (self ): 167super ().prepare_tensors () 168assert not self ._experts_cache 169 170 171@ ModelBase . register ( "Lfm2VlForConditionalGeneration" ) 172@ ModelBase . example ( "LiquidAI/LFM2-VL-450M" ) 173class LFM2VLModel (MmprojModel ): 174def __init__ (self ,* args ,** kwargs ): 175super ().__init__ (* args ,** kwargs ) 176assert self .hparams_vision is not None 177# TODO(tarek): for dynamic resolution image_size is not specified, setting here for compatibility 178self .hparams_vision ["image_size" ]= 256 179 180def set_gguf_parameters (self ): 181super ().set_gguf_parameters () 182self .gguf_writer .add_clip_projector_type (gguf .VisionProjectorType .LFM2 ) 183self .gguf_writer .add_vision_attention_layernorm_eps (self .find_vparam (["layer_norm_eps" ])) 184self .gguf_writer .add_vision_projector_scale_factor (self .global_config .get ("downsample_factor" ,2 )) 185self .gguf_writer .add_vision_use_gelu (True ) 186# python notation, e.g. for vision_feature_layer == -1, we pick last layer -> vision_feature_layers_to_drop = 0 187vision_feature_layers_to_drop = - (self .global_config .get ("vision_feature_layer" ,- 1 )+ 1 ) 188self .gguf_writer .add_vision_block_count (self .find_vparam (self .n_block_keys )- vision_feature_layers_to_drop ) 189 190@classmethod 191def filter_tensors (cls ,item :tuple [str ,Callable [[],Tensor ]])-> tuple [str ,Callable [[],Tensor ]]| None : 192name ,gen = item 193 194name = name .replace ("model.vision_tower." ,"vision_tower." ) 195name = name .replace ("model.multi_modal_projector." ,"multi_modal_projector." ) 196 197return super ().filter_tensors ((name ,gen )) 198 199def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 200if "patch_embedding.weight" in name : 201data_torch = data_torch .view (data_torch .shape [0 ],16 ,16 ,3 ).permute (0 ,3 ,1 ,2 ) 202 203yield from super ().modify_tensors (data_torch ,name ,bid ) 204 205 206@ ModelBase . register ( "Lfm2AudioForConditionalGeneration" ) 207@ ModelBase . example ( "LiquidAI/LFM2.5-Audio-1.5B" , "LiquidAI/LFM2-Audio-1.5B" ) 208class LFM2AudioModel (ConformerAudioModel ): 209has_vision_encoder = False 210has_audio_encoder = True 211model_name = "Lfm2AudioEncoder" 212 213def get_audio_config (self )-> dict [str ,Any ]| None : 214return self .global_config .get ("encoder" ) 215 216def set_gguf_parameters (self ): 217assert self .hparams_audio is not None 218self .hparams_audio ["hidden_size" ]= self .hparams_audio ["d_model" ] 219self .hparams_audio ["intermediate_size" ]= self .hparams_audio ["d_model" ] 220self .hparams_audio ["num_attention_heads" ]= self .hparams_audio ["n_heads" ] 221super ().set_gguf_parameters () 222self .gguf_writer .add_clip_projector_type (gguf .VisionProjectorType .LFM2A ) 223self .gguf_writer .add_audio_num_mel_bins (self .hparams_audio ["feat_in" ]) 224self .gguf_writer .add_audio_attention_layernorm_eps (1e-5 ) 225 226@classmethod 227def filter_tensors (cls ,item :tuple [str ,Callable [[],Tensor ]])-> tuple [str ,Callable [[],Tensor ]]| None : 228name ,gen = item 229 230# skip language model tensors 231if name .startswith ("lfm." ): 232return None 233 234# for training only 235if any (p in name for p in ["audio_loss_weight" ]): 236return None 237 238# for audio output 239if any (p in name for p in ["codebook_offsets" ,"depth_embeddings" ,"depth_linear" ,"depthformer" ]): 240return None 241 242return super ().filter_tensors (item ) 243 244 245@ ModelBase . register ( "Lfm25AudioTokenizer" ) 246@ ModelBase . example ( "LiquidAI/LFM2.5-Audio-1.5B" ) 247class LFM25AudioTokenizer (LFM2Model ): 248model_arch = gguf .MODEL_ARCH .LFM2 249 250def set_vocab (self ): 251self ._set_vocab_none () 252 253def set_gguf_parameters (self ): 254super ().set_gguf_parameters () 255self .gguf_writer .add_sliding_window (self .hparams ["sliding_window" ]) 256self .gguf_writer .add_embedding_length_out (self .hparams ["output_size" ]) 257 258@classmethod 259def filter_tensors (cls ,item :tuple [str ,Callable [[],Tensor ]])-> tuple [str ,Callable [[],Tensor ]]| None : 260name ,gen = item 261 262# skip language model tensors 263if name == "istft.window" or name .startswith ("emb.emb" ): 264return None 265 266if name .startswith ("lin" ): 267name = name .replace ("lin" ,"dense_2_out" ) 268 269return super ().filter_tensors ((name ,gen ))