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 Iterable ,TYPE_CHECKING 4 5import torch 6 7if TYPE_CHECKING : 8from torch import Tensor 9 10from .base import ModelBase ,TextModel ,gguf 11 12 13@ ModelBase . register ( "LLaDAModelLM" ) 14@ ModelBase . example ( "GSAI-ML/LLaDA-8B-Instruct" ) 15class LLaDAModel (TextModel ): 16model_arch = gguf .MODEL_ARCH .LLADA 17undo_permute = True 18 19def get_vocab_base (self )-> tuple [list [str ],list [int ],str ]: 20tokens :list [str ]= [] 21toktypes :list [int ]= [] 22 23from transformers import AutoTokenizer 24tokenizer = AutoTokenizer .from_pretrained (self .dir_model ,trust_remote_code = True ) 25 26vocab_dict = tokenizer .get_vocab ()# ty: ignore[unresolved-attribute] 27vocab_size = self .hparams .get ("vocab_size" ,len (vocab_dict )) 28assert max (vocab_dict .values ())< vocab_size 29 30tokpre = self .get_vocab_base_pre (tokenizer ) 31 32reverse_vocab = {id_ :encoded_tok for encoded_tok ,id_ in vocab_dict .items ()} 33added_vocab = tokenizer .get_added_vocab ()# ty: ignore[unresolved-attribute] 34 35for i in range (vocab_size ): 36if i not in reverse_vocab : 37tokens .append (f"[PAD { i } ]" ) 38toktypes .append (gguf .TokenType .UNUSED ) 39elif reverse_vocab [i ]in added_vocab : 40tokens .append (reverse_vocab [i ]) 41# Check if it's a special token - treat special tokens as CONTROL tokens 42if hasattr (tokenizer ,'added_tokens_decoder' )and i in tokenizer .added_tokens_decoder : 43if tokenizer .added_tokens_decoder [i ].special : 44toktypes .append (gguf .TokenType .CONTROL ) 45else : 46toktypes .append (gguf .TokenType .USER_DEFINED ) 47else : 48# Fallback: treat all added vocab as control tokens for special tokens like <|im_start|> 49toktypes .append (gguf .TokenType .CONTROL ) 50else : 51tokens .append (reverse_vocab [i ]) 52toktypes .append (gguf .TokenType .NORMAL ) 53 54return tokens ,toktypes ,tokpre 55 56def set_vocab (self ): 57self ._set_vocab_gpt2 () 58 59# LLaDA specific parameters 60self .gguf_writer .add_add_bos_token (True ) 61 62def set_gguf_parameters (self ): 63super ().set_gguf_parameters () 64self ._try_set_pooling_type () 65 66# Add parameters similar to LlamaModel 67hparams = self .hparams 68self .gguf_writer .add_vocab_size (hparams ["vocab_size" ]) 69 70if (rope_dim := hparams .get ("head_dim" ))is None : 71n_heads = hparams .get ("num_attention_heads" ,hparams .get ("n_heads" )) 72assert n_heads is not None 73rope_dim = hparams .get ("hidden_size" ,hparams .get ("d_model" ))// n_heads 74self .gguf_writer .add_rope_dimension_count (rope_dim ) 75 76# Set context length for LLaDA 77context_length = self .hparams .get ("max_sequence_length" ,4096 ) 78self .gguf_writer .add_context_length (context_length ) 79 80# Set embedding length (dimension size) 81embedding_length = self .hparams .get ("d_model" ,4096 ) 82self .gguf_writer .add_embedding_length (embedding_length ) 83 84# Set feed forward length (MLP hidden size) 85feed_forward_length = self .hparams .get ("mlp_hidden_size" ,12288 ) 86self .gguf_writer .add_feed_forward_length (feed_forward_length ) 87 88# LLaDA models use non-causal attention for diffusion, similar to Dream 89self .gguf_writer .add_causal_attention (False ) 90 91# LLaDA models don't shift their logits 92self .gguf_writer .add_diffusion_shift_logits (False ) 93 94@staticmethod 95def permute (weights :Tensor ,n_head :int ,n_head_kv :int | None ): 96if n_head_kv is not None and n_head != n_head_kv : 97n_head = n_head_kv 98return (weights .reshape (n_head ,2 ,weights .shape [0 ]// n_head // 2 ,* weights .shape [1 :]) 99 .swapaxes (1 ,2 ) 100 .reshape (weights .shape )) 101 102def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 103n_head = self .hparams .get ("num_attention_heads" ,self .hparams .get ("n_heads" )) 104assert n_head is not None 105n_kv_head = self .hparams .get ("num_key_value_heads" ,self .hparams .get ("n_kv_heads" )) 106 107if self .undo_permute : 108if name .endswith (("q_proj.weight" ,"q_proj.bias" )): 109data_torch = LLaDAModel .permute (data_torch ,n_head ,n_head ) 110if name .endswith (("k_proj.weight" ,"k_proj.bias" )): 111data_torch = LLaDAModel .permute (data_torch ,n_head ,n_kv_head ) 112 113# LLaDA model tensors should be mapped directly since it's the base model 114yield from super ().modify_tensors (data_torch ,name ,bid ) 115 116 117@ ModelBase . register ( "LLaDAMoEModel" , "LLaDAMoEModelLM" ) 118@ ModelBase . example ( "inclusionAI/LLaDA-MoE-7B-A1B-Instruct" ) 119class LLaDAMoEModel (TextModel ): 120model_arch = gguf .MODEL_ARCH .LLADA_MOE 121 122def set_gguf_parameters (self ): 123super ().set_gguf_parameters () 124if (expert_intermediate_size := self .hparams .get ("expert_intermediate_size" ))is not None : 125self .gguf_writer .add_expert_feed_forward_length (expert_intermediate_size ) 126 127self .gguf_writer .add_mask_token_id (156895 ) 128self .gguf_writer .add_causal_attention (False ) 129self .gguf_writer .add_diffusion_shift_logits (False ) 130 131_experts :list [dict [str ,Tensor ]]| None = None 132 133# Copied from: Qwen2MoeModel 134def modify_tensors (self ,data_torch :Tensor ,name :str ,bid :int | None )-> Iterable [tuple [str ,Tensor ]]: 135# process the experts separately 136if name .find ("experts" )!= - 1 : 137n_experts = self .find_hparam (["num_local_experts" ,"num_experts" ]) 138assert bid is not None 139 140if self ._experts is None : 141self ._experts = [{}for _ in range (self .block_count )] 142 143self ._experts [bid ][name ]= data_torch 144 145if len (self ._experts [bid ])>= n_experts * 3 : 146# merge the experts into a single 3d tensor 147for w_name in ["down_proj" ,"gate_proj" ,"up_proj" ]: 148datas :list [Tensor ]= [] 149 150for xid in range (n_experts ): 151ename = f"model.layers. { bid } .mlp.experts. { xid } . { w_name } .weight" 152datas .append (self ._experts [bid ][ename ]) 153del self ._experts [bid ][ename ] 154 155data_torch = torch .stack (datas ,dim = 0 ) 156 157merged_name = f"model.layers. { bid } .mlp.experts. { w_name } .weight" 158 159yield from super ().modify_tensors (data_torch ,merged_name ,bid ) 160return 161else : 162return 163 164yield from super ().modify_tensors (data_torch ,name ,bid ) 165 166# Copied from: Qwen2MoeModel 167def prepare_tensors (self ): 168super ().prepare_tensors () 169 170if self ._experts is not None : 171# flatten `list[dict[str, Tensor]]` into `list[str]` 172experts = [k for d in self ._experts for k in d .keys ()] 173if len (experts )> 0 : 174raise ValueError (f"Unprocessed experts: { experts } " )