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 ,logger 11 12 13@ ModelBase . register ( "GptOssForCausalLM" ) 14@ ModelBase . example ( "openai/gpt-oss-20b" ) 15class GptOssModel (TextModel ): 16model_arch = gguf .MODEL_ARCH .GPT_OSS 17 18# TODO: remove once MXFP4 is supported more generally 19def dequant_model (self ): 20if self ._is_mxfp4 : 21return 22return super ().dequant_model () 23 24def transform_nibble_layout (self ,tensor ): 25assert tensor .dtype == torch .uint8 26assert tensor .shape [- 1 ]== 16 27# swap nibbles 28t_lo = tensor & 0x0F 29t_hi = tensor & 0xF0 30t_swapped = (t_lo << 4 )| (t_hi >> 4 ) 31tensor = t_swapped 32# transform aaaa...bbbb... to abababab... 33blk_a ,blk_b = tensor .chunk (2 ,dim =- 1 ) 34# get a_ 35blk_a0 = (blk_a & 0xF0 ).view (- 1 ,1 ) 36blk_a1 = (blk_a << 4 ).view (- 1 ,1 ) 37blk_a = torch .stack ((blk_a0 ,blk_a1 ),dim = 2 ).view (tensor .shape ) 38# get _b 39blk_b0 = (blk_b >> 4 ).view (- 1 ,1 ) 40blk_b1 = (blk_b & 0x0F ).view (- 1 ,1 ) 41blk_b = torch .stack ((blk_b0 ,blk_b1 ),dim = 2 ).view (tensor .shape ) 42# swap once more 43out = blk_a | blk_b 44out_h = out & 0xF0 45out_l = out & 0x0F 46out = (out_h >> 4 )| (out_l << 4 ) 47return out 48 49def repack_mxfp4 (self ,new_name :str ,blocks :Tensor ,scales :Tensor ): 50assert blocks .dtype == torch .uint8 51assert scales .dtype == torch .uint8 52scales = scales .unsqueeze (- 1 ) 53assert len (blocks .shape )== 4 54assert len (scales .shape )== 4 55blocks = self .transform_nibble_layout (blocks ) 56new_data = torch .concat ((scales ,blocks ),dim =- 1 ) 57new_shape = [new_data .shape [0 ],new_data .shape [1 ],new_data .shape [2 ]* 32 ] 58logger .info (f"Repacked { new_name } with shape { new_shape } and quantization MXFP4" ) 59# flatten last dim 60new_data = new_data .view (new_data .shape [0 ],new_data .shape [1 ],new_data .shape [2 ]* new_data .shape [3 ]) 61new_data = new_data .numpy () 62self .gguf_writer .add_tensor (new_name ,new_data ,raw_dtype = gguf .GGMLQuantizationType .MXFP4 ) 63 64def generate_extra_tensors (self )-> Iterable [tuple [str ,Tensor ]]: 65blocks0 :Tensor = torch .zeros (1 ) 66blocks1 :Tensor = torch .zeros (1 ) 67# we assume that tensors are loaded in the correct order 68for name ,data_torch in self .get_tensors (): 69if "mlp.experts.down_proj_blocks" in name : 70blocks0 = data_torch 71elif "mlp.experts.down_proj_scales" in name : 72new_name = self .map_tensor_name (name .replace ("_scales" ,".weight" )) 73self .repack_mxfp4 (new_name ,blocks0 ,data_torch ) 74elif "mlp.experts.gate_up_proj_blocks" in name : 75blocks0 ,blocks1 = data_torch [:, ::2 , :, :],data_torch [:,1 ::2 , :, :] 76elif "mlp.experts.gate_up_proj_scales" in name : 77scales0 ,scales1 = data_torch [:, ::2 , :],data_torch [:,1 ::2 , :] 78new_name_gate = self .map_tensor_name (name .replace ("gate_up_proj_scales" ,"gate_proj.weight" )) 79new_name_up = self .map_tensor_name (name .replace ("gate_up_proj_scales" ,"up_proj.weight" )) 80self .repack_mxfp4 (new_name_gate ,blocks0 ,scales0 ) 81self .repack_mxfp4 (new_name_up ,blocks1 ,scales1 ) 82return [] 83 84@classmethod 85def filter_tensors (cls ,item :tuple [str ,Callable [[],Tensor ]])-> tuple [str ,Callable [[],Tensor ]]| None : 86name ,gen = item 87 88if "sinks" in name : 89name += ".weight" 90 91return super ().filter_tensors ((name ,gen )) 92 93def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 94# correct naming for down_proj 95if "down_proj" in name : 96if name .endswith ("_bias" ): 97name = name .replace ("down_proj_bias" ,"down_proj.bias" ) 98elif "_blocks" not in name and "_scales" not in name : 99logger .warning (f" { name } is not in MXFP4, performance may be degraded" ) 100name = name .replace ("down_proj" ,"down_proj.weight" ) 101data_torch = data_torch .transpose (- 1 ,- 2 ) 102else : 103# otherwise, it should already be repacked to ggml MXFP4 format 104return 105 106# split the gate_up into gate and up 107if "gate_up_proj" in name : 108if name .endswith ("_bias" ): 109name_up = name .replace ("gate_up_proj_bias" ,"up_proj.bias" ) 110name_gate = name .replace ("gate_up_proj_bias" ,"gate_proj.bias" ) 111gate_proj_bias ,up_proj_bias = data_torch [..., ::2 ],data_torch [...,1 ::2 ] 112yield from super ().modify_tensors (gate_proj_bias ,name_gate ,bid ) 113yield from super ().modify_tensors (up_proj_bias ,name_up ,bid ) 114elif "_blocks" not in name and "_scales" not in name : 115logger .warning (f" { name } is not in MXFP4, performance may be degraded" ) 116name_up = name .replace ("gate_up_proj" ,"up_proj.weight" ) 117name_gate = name .replace ("gate_up_proj" ,"gate_proj.weight" ) 118data_torch = data_torch .transpose (- 1 ,- 2 ) 119gate_proj_weight ,up_proj_weight = data_torch [:, ::2 , :],data_torch [:,1 ::2 , :] 120yield from super ().modify_tensors (gate_proj_weight ,name_gate ,bid ) 121yield from super ().modify_tensors (up_proj_weight ,name_up ,bid ) 122else : 123yield from super ().modify_tensors (data_torch ,name ,bid ) 124 125def set_vocab (self ): 126self ._set_vocab_gpt2 () 127 128def set_gguf_parameters (self ): 129super ().set_gguf_parameters () 130self .gguf_writer .add_sliding_window (self .hparams ["sliding_window" ]) 131self .gguf_writer .add_expert_feed_forward_length (self .hparams ["intermediate_size" ])