char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
67672dc5b
char/aliceai-t5-moe
1from __future__import annotations 2 3import json 4from typing import Any ,Iterable ,TYPE_CHECKING 5 6import torch 7 8if TYPE_CHECKING : 9from torch import Tensor 10 11from .base import MmprojModel ,ModelBase ,TextModel ,gguf 12 13 14def _unpermute_for_rope (tensor :"Tensor" ,n_heads :int )-> "Tensor" : 15"""Invert transformers' `_permute_for_rope`: HF stores Q/K in rotate_half layout, 16llama.cpp consumes the interleaved (NORM) layout.""" 17if tensor .ndim == 2 : 18dim1 ,dim2 = tensor .shape 19return tensor .view (n_heads ,2 ,dim1 // n_heads // 2 ,dim2 ).transpose (1 ,2 ).reshape (dim1 ,dim2 ) 20if tensor .ndim == 1 : 21 (dim1 ,)= tensor .shape 22return tensor .view (n_heads ,2 ,dim1 // n_heads // 2 ).transpose (1 ,2 ).reshape (dim1 ) 23raise ValueError (f"_unpermute_for_rope: unexpected shape { tuple ( tensor . shape ) } " ) 24 25 26@ ModelBase . register ( "MuseGlimmerForConditionalGeneration" ) 27@ ModelBase . example ( "meta-models/Muse-Glimmer-30B" ) 28class MuseGlimmerModel (TextModel ): 29model_arch = gguf .MODEL_ARCH .MUSE_GLIMMER 30 31def norm_shift (self ,name :str )-> float : 32# All four layer norms use 1, the final norm uses 0. 33return 1.0 if name .endswith ("layernorm.weight" )else 0.0 34 35def set_vocab (self ): 36self ._set_vocab_gpt2 () 37 38from transformers import AutoTokenizer 39tok = AutoTokenizer .from_pretrained (self .dir_model ) 40eot_id = tok .convert_tokens_to_ids ("<|eot|>" )# ty: ignore[unresolved-attribute] 41if isinstance (eot_id ,int )and eot_id >= 0 : 42self .gguf_writer .add_eot_token_id (eot_id ) 43 44def set_gguf_parameters (self ): 45super ().set_gguf_parameters () 46hparams = self .hparams 47 48self .gguf_writer .add_final_logit_softcapping (hparams ["final_logit_softcapping" ]) 49self .gguf_writer .add_logit_scale (hparams ["output_multiplier" ]) 50self .gguf_writer .add_sliding_window (hparams ["sliding_window" ]) 51self .gguf_writer .add_sliding_window_pattern ([t == "sliding_attention" for t in hparams ["layer_types" ]]) 52 53def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 54shift = self .norm_shift (name ) 55if shift != 0.0 : 56data_torch = data_torch + shift 57 58# Invert transformers' `_permute_for_rope` on Q/K, we keep ggml's NORM (interleaved) rope 59if ".self_attn.q_proj." in name : 60data_torch = _unpermute_for_rope (data_torch ,int (self .hparams ["num_attention_heads" ])) 61elif ".self_attn.k_proj." in name : 62data_torch = _unpermute_for_rope (data_torch ,int (self .hparams ["num_key_value_heads" ])) 63 64# Synthesize QK-norm weights to absorb qk_scale_factor. 65# MuseGlimmer implementation: scaleless RMSNorm followed by qk_scale_factor.. 66if bid is not None and name .endswith (f"model.layers. { bid } .self_attn.q_proj.weight" ): 67head_dim = self .hparams ["head_dim" ] 68q_scale = float (self .hparams ["qk_scale_factor" ]) 69yield ( 70self .map_tensor_name (f"model.layers. { bid } .self_attn.q_norm.weight" ), 71torch .full ((head_dim ,),q_scale ,dtype = torch .float32 ), 72 ) 73yield ( 74self .map_tensor_name (f"model.layers. { bid } .self_attn.k_norm.weight" ), 75torch .ones ((head_dim ,),dtype = torch .float32 ), 76 ) 77 78yield from super ().modify_tensors (data_torch ,name ,bid ) 79 80 81@ ModelBase . register ( "MuseGlimmerForConditionalGeneration" ) 82@ ModelBase . example ( "meta-models/Muse-Glimmer-30B" ) 83class MuseGlimmerVisionModel (MmprojModel ): 84def get_vision_config (self )-> dict [str ,Any ]| None : 85c = self .global_config .get ("vision_config" ) 86if not c : 87return None 88# MuseGlimmer actually uses dynamic size, initialize with nominal size 89image_size = c ["pos_emb_height" ]* c ["patch_size" ]* c ["merge_size" ] 90return {** c ,"image_size" :image_size } 91 92def set_gguf_parameters (self ): 93super ().set_gguf_parameters () 94assert self .hparams_vision is not None 95c = self .hparams_vision # enriched vision_config from get_vision_config() 96 97self .gguf_writer .add_clip_projector_type (gguf .VisionProjectorType .MUSE_GLIMMER ) 98self .gguf_writer .add_vision_attention_layernorm_eps (float (c ["layer_norm_eps" ])) 99self .gguf_writer .add_vision_spatial_merge_size (int (c ["merge_size" ])) 100 101@classmethod 102def filter_tensors (cls ,item ): 103name ,gen = item 104keep = ("model.vision_tower." ,"model.vision_adapter." ,"model.vision_projection." ) 105if not any (name .startswith (k )for k in keep ): 106return None 107return super ().filter_tensors ((name ,gen )) 108 109# 3-layer projector MLP 110_MM_MLP_MAP = { 111"model.vision_adapter.fc1" : (gguf .MODEL_TENSOR .V_MMPROJ ,0 ), 112"model.vision_adapter.fc2" : (gguf .MODEL_TENSOR .V_MMPROJ ,1 ), 113"model.vision_projection" : (gguf .MODEL_TENSOR .V_MMPROJ ,2 ), 114 } 115 116def modify_tensors (self ,data_torch ,name ,bid ): 117assert self .hparams_vision is not None 118if ".attn.q_proj." in name or ".attn.k_proj." in name : 119n_heads = int (self .hparams_vision ["num_attention_heads" ]) 120data_torch = _unpermute_for_rope (data_torch ,n_heads ) 121# Lay out the pt=2 temporal slabs of the patch embedding as a conv2d for build_inp() 122if name .endswith ("patch_embedder.patch_embedding.weight" ): 123n_embd = data_torch .shape [0 ] 124pt = int (self .hparams_vision ["patch_temporal" ]) 125ps = int (self .hparams_vision ["patch_size" ]) 126data_torch = data_torch .view (n_embd ,pt ,3 ,ps ,ps ).sum (dim = 1 )# (n_embd, 3, ps, ps) 127stem ,_ ,suffix = name .rpartition ("." ) 128if stem in self ._MM_MLP_MAP : 129tensor_key ,idx = self ._MM_MLP_MAP [stem ] 130yield (self .format_tensor_name (tensor_key ,bid = idx ,suffix = "." + suffix ),data_torch ) 131return 132yield (self .map_tensor_name (name ),data_torch ) 133 134 135@ ModelBase . register ( "MuseGlimmerAssistantModel" ) 136@ ModelBase . example ( "meta-models/Muse-Glimmer-30B-assistant" ) 137class MuseGlimmerAssistantModel (TextModel ): 138model_arch = gguf .MODEL_ARCH .DFLASH 139 140def set_vocab (self ): 141if self .target_model_dir is None : 142raise ValueError ( 143"MuseGlimmerAssistant (DFlash drafter) requires --target-model-dir pointing to the " 144"target MuseGlimmer HF directory" 145 ) 146 147original_dir = self .dir_model 148self .dir_model = self .target_model_dir 149 150from .import get_model_class 151with open (self .target_model_dir / "config.json" ,"r" ,encoding = "utf-8" )as f : 152target_arch = json .load (f )["architectures" ][0 ] 153target_cls = get_model_class (target_arch ) 154if target_cls is not type (self ): 155target_cls .set_vocab (self )# ty: ignore[unresolved-attribute] 156else : 157super ().set_vocab () 158 159self .dir_model = original_dir 160 161mask_token_id = self .hparams .get ("mask_token_id" ) 162if mask_token_id is not None : 163self .gguf_writer .add_mask_token_id (int (mask_token_id )) 164 165def set_gguf_parameters (self ): 166super ().set_gguf_parameters () 167h = self .hparams 168 169self .gguf_writer .add_block_size (int (h ["block_size" ])) 170 171# dflash.target_layers[k] refers to the inputs going into the ith layer, which come from the (i-1)th layer's output. 172# The transformers configuration refers to the outputs being recorded. 173self .gguf_writer .add_target_layers ([int (x )+ 1 for x in h ["target_layer_ids" ]]) 174 175if h .get ("sliding_window" )and h .get ("layer_types" ): 176self .gguf_writer .add_sliding_window (int (h ["sliding_window" ])) 177self .gguf_writer .add_sliding_window_pattern ([t == "sliding_attention" for t in h ["layer_types" ]]) 178 179def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 180# DFlash defaults to NEOX (rotate_half) rope, matching transformers HF layout for Q/K, QK-norms 181# no permutation needed. 182yield (self .map_tensor_name (name ),data_torch )