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 json 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 ModelBase ,TextModel ,gguf ,logger 14 15 16@ ModelBase . register ( "MambaForCausalLM" , "MambaLMHeadModel" , "FalconMambaForCausalLM" ) 17@ ModelBase . example ( "state-spaces/mamba-130m-hf" , "tiiuae/falcon-mamba-7b" ) 18class MambaModel (TextModel ): 19model_arch = gguf .MODEL_ARCH .MAMBA 20 21def __init__ (self ,dir_model :Path ,* args ,** kwargs ): 22# Avoid using AutoConfig for hparams 23hparams = kwargs .pop ("hparams" ,None ) 24if hparams is None : 25with open (dir_model / "config.json" ,"r" ,encoding = "utf-8" )as f : 26hparams = json .load (f ) 27super ().__init__ (dir_model ,* args ,hparams = hparams ,** kwargs ) 28 29def set_vocab (self ): 30vocab_size = self .hparams ["vocab_size" ] 31# Round vocab size to next multiple of 8 32pad_vocab = self .hparams .get ("pad_vocab_size_multiple" ,8 ) 33# pad using ceiling division 34# ref: https://stackoverflow.com/a/17511341/22827863 35vocab_size = - (vocab_size // - pad_vocab )* pad_vocab 36self .hparams ["vocab_size" ]= vocab_size 37 38if (self .dir_model / "tokenizer.json" ).is_file (): 39self ._set_vocab_gpt2 () 40elif (self .dir_model / "tokenizer.model" ).is_file (): 41self ._set_vocab_sentencepiece () 42else : 43# Use the GPT-NeoX tokenizer when no tokenizer files are present 44self ._set_vocab_builtin ("gpt-neox" ,vocab_size ) 45 46def set_gguf_parameters (self ): 47d_model = self .find_hparam (["hidden_size" ,"d_model" ]) 48d_conv = self .find_hparam (["conv_kernel" ,"d_conv" ],optional = True )or 4 49d_inner = self .find_hparam (["intermediate_size" ,"d_inner" ],optional = True )or 2 * d_model 50d_state = self .find_hparam (["state_size" ,"d_state" ],optional = True )or 16 51# ceiling division 52# ref: https://stackoverflow.com/a/17511341/22827863 53# ref: https://github.com/state-spaces/mamba/blob/ce59daea3a090d011d6476c6e5b97f6d58ddad8b/mamba_ssm/modules/mamba_simple.py#L58 54dt_rank = self .find_hparam (["time_step_rank" ,"dt_rank" ],optional = True )or - (d_model // - 16 ) 55rms_norm_eps = self .find_hparam (["layer_norm_epsilon" ,"rms_norm_eps" ],optional = True )or 1e-5 56use_dt_b_c_norm = False 57# For falconmamba we do apply RMS norm on B / DT and C layers 58if self .find_hparam (["model_type" ],optional = True )in ("falcon_mamba" ,): 59use_dt_b_c_norm = True 60# Fail early for models which don't have a block expansion factor of 2 61assert d_inner == 2 * d_model 62 63self .gguf_writer .add_context_length (2 ** 20 )# arbitrary value; for those who use the default 64self .gguf_writer .add_embedding_length (d_model ) 65self .gguf_writer .add_feed_forward_length (0 )# unused, but seemingly required when loading 66self .gguf_writer .add_head_count (0 )# unused, but seemingly required when loading 67self .gguf_writer .add_block_count (self .block_count ) 68self .gguf_writer .add_ssm_conv_kernel (d_conv ) 69self .gguf_writer .add_ssm_inner_size (d_inner ) 70self .gguf_writer .add_ssm_state_size (d_state ) 71self .gguf_writer .add_ssm_time_step_rank (dt_rank ) 72self .gguf_writer .add_layer_norm_rms_eps (rms_norm_eps ) 73self .gguf_writer .add_ssm_dt_b_c_rms (use_dt_b_c_norm )# For classic Mamba we don't apply rms norm on B / DT layers 74self .gguf_writer .add_file_type (self .ftype ) 75 76_tok_embd = None 77 78def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 79output_name = self .format_tensor_name (gguf .MODEL_TENSOR .OUTPUT ) 80tok_embd_name = self .format_tensor_name (gguf .MODEL_TENSOR .TOKEN_EMBD ) 81 82new_name = self .map_tensor_name (name ) 83 84if name .endswith (".A_log" ): 85logger .debug ("A_log --> A ==> " + new_name ) 86data_torch = - torch .exp (data_torch ) 87 88# [4 1 8192 1] -> [4 8192 1 1] 89if self .match_model_tensor_name (new_name ,gguf .MODEL_TENSOR .SSM_CONV1D ,bid ): 90data_torch = data_torch .squeeze () 91 92# assuming token_embd.weight is seen before output.weight 93if self ._tok_embd is not None and new_name == output_name : 94if torch .equal (self ._tok_embd ,data_torch ): 95logger .debug (f" { output_name } is equivalent to { tok_embd_name } , omitting" ) 96return 97elif new_name == tok_embd_name : 98self ._tok_embd = data_torch 99 100yield from super ().modify_tensors (data_torch ,new_name ,bid ) 101 102 103@ ModelBase . register ( "Mamba2ForCausalLM" ) 104@ ModelBase . example ( "mistralai/Mamba-Codestral-7B-v0.1" ) 105class Mamba2Model (TextModel ): 106model_arch = gguf .MODEL_ARCH .MAMBA2 107 108def __init__ (self ,dir_model :Path ,* args ,** kwargs ): 109# Avoid using AutoConfig for hparams 110# It wrongly assumes all Mamba2 models are Mamba-Codestral-7B-v0.1 111hparams = kwargs .pop ("hparams" ,None ) 112if hparams is None : 113with open (dir_model / "config.json" ,"r" ,encoding = "utf-8" )as f : 114hparams = json .load (f ) 115if "llm_config" in hparams : 116hparams ["text_config" ]= hparams ["llm_config" ] 117super ().__init__ (dir_model ,* args ,hparams = hparams ,** kwargs ) 118self .d_model = self .find_hparam (["hidden_size" ,"d_model" ,"dim" ]) 119self .expand = self .find_hparam (["mamba_expand" ,"expand" ],optional = True )or 2 120self .d_inner = self .find_hparam (["mamba_d_ssm" ,"intermediate_size" ,"d_inner" ],optional = True )or self .expand * self .d_model 121self .n_group = self .find_hparam (["n_groups" ],optional = True )or 1 122 123def set_vocab (self ): 124vocab_size = self .hparams ["vocab_size" ] 125# Round vocab size to next multiple of 16 126pad_vocab = self .hparams .get ("pad_vocab_size_multiple" ,16 ) 127# pad using ceiling division 128# ref: https://stackoverflow.com/a/17511341/22827863 129vocab_size = - (vocab_size // - pad_vocab )* pad_vocab 130self .hparams ["vocab_size" ]= vocab_size 131 132if (self .dir_model / "tokenizer.model" ).is_file (): 133self ._set_vocab_sentencepiece () 134elif (self .dir_model / "tokenizer.model.v3" ).is_file (): 135# mamba-codestral 136raise NotImplementedError (f"Please rename { self . dir_model / 'tokenizer.model.v3' } to { self . dir_model / 'tokenizer.model' } " ) 137elif (self .dir_model / "tokenizer.json" ).is_file (): 138self ._set_vocab_gpt2 () 139else : 140# Use the GPT-NeoX tokenizer when no tokenizer files are present 141self ._set_vocab_builtin ("gpt-neox" ,vocab_size ) 142 143def set_gguf_parameters (self ): 144d_conv = self .find_hparam (["conv_kernel" ,"d_conv" ],optional = True )or 4 145d_state = self .find_hparam (["state_size" ,"d_state" ],optional = True )or 128 146head_dim = self .find_hparam (["mamba_d_head" ,"head_dim" ],optional = True )or 64 147 148rms_norm_eps = self .find_hparam (["layer_norm_epsilon" ,"rms_norm_eps" ],optional = True )or 1e-5 149 150# skip the assertion for FalconH1 Model 151if self .model_arch != gguf .MODEL_ARCH .FALCON_H1 : 152assert self .d_inner == self .expand * self .d_model 153assert self .d_inner % head_dim == 0 154 155self .gguf_writer .add_context_length (2 ** 20 )# arbitrary value; for those who use the default 156self .gguf_writer .add_embedding_length (self .d_model ) 157self .gguf_writer .add_feed_forward_length (0 )# unused, but seemingly required when loading 158self .gguf_writer .add_head_count (0 )# unused, but seemingly required when loading 159self .gguf_writer .add_block_count (self .block_count ) 160self .gguf_writer .add_ssm_conv_kernel (d_conv ) 161self .gguf_writer .add_ssm_inner_size (self .d_inner ) 162self .gguf_writer .add_ssm_state_size (d_state ) 163self .gguf_writer .add_ssm_time_step_rank (self .d_inner // head_dim ) 164self .gguf_writer .add_ssm_group_count (self .n_group ) 165self .gguf_writer .add_layer_norm_rms_eps (rms_norm_eps ) 166self .gguf_writer .add_file_type (self .ftype ) 167 168@classmethod 169def filter_tensors (cls ,item :tuple [str ,Callable [[],Tensor ]])-> tuple [str ,Callable [[],Tensor ]]| None : 170name ,gen = item 171 172if name .startswith (("model.backbone" ,"model.lm_head" )): 173# map Mamba-Codestral-7B-v0.1 tensor names to the names used by Mamba-2 174name = name .removeprefix ("model." ) 175 176if name .endswith (".dt_bias" ): 177name = name .rpartition (".dt_bias" )[0 ]+ ".dt_proj.bias" 178 179return super ().filter_tensors ((name ,gen )) 180 181def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 182new_name = self .map_tensor_name (name ) 183 184if self .match_model_tensor_name (new_name ,gguf .MODEL_TENSOR .SSM_CONV1D ,bid ): 185data_torch = data_torch .squeeze () 186elif any (self .match_model_tensor_name (new_name ,t ,bid ,suffix = "" )for t in [ 187gguf .MODEL_TENSOR .SSM_A , 188gguf .MODEL_TENSOR .SSM_D , 189 ]): 190# unsqueeze A to use similar shape semantics as Mamba-1 191# (D is also unsqueezed, but for more straightforward broadcast internally) 192data_torch = data_torch .reshape ((* data_torch .shape ,1 )) 193elif self .match_model_tensor_name (new_name ,gguf .MODEL_TENSOR .SSM_NORM ,bid ): 194data_torch = data_torch .reshape ((self .n_group ,self .d_inner // self .n_group )) 195 196if name .endswith (".A_log" ): 197logger .debug ("A_log --> A ==> " + new_name ) 198data_torch = - torch .exp (data_torch ) 199 200yield (new_name ,data_torch )