char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
98a01afd9
char/aliceai-t5-moe
1#include "common.h" 2#include "log.h" 3#include "ggml-backend.h" 4#include "ggml.h" 5#include "gguf.h" 6#include "ggml-cpp.h" 7#include "llama.h" 8#include "llama-cpp.h" 9 10// TODO: replace with #include "llama-ext.h" in the future 11#include "../src/llama-arch.h" 12#include "../src/llama-model-saver.h" 13 14#include <cinttypes> 15#include <cstddef> 16#include <cstdio> 17#include <cstring> 18#include <cstdint> 19#include <random> 20#include <stdexcept> 21#include <string> 22#include <utility> 23#include <vector> 24 25// normalized mean squared error = mse(a, b) / mse(a, 0) 26static double nmse (const std::vector < float > & a ,const std::vector < float > & b ) { 27GGML_ASSERT (a .size ()== b .size ()); 28double mse_a_b = 0.0 ; 29double mse_a_0 = 0.0 ; 30 31for (size_t i = 0 ;i < a .size ();i ++ ) { 32float a_i = a [i ]; 33float b_i = b [i ]; 34 35mse_a_b += (a_i - b_i )* (a_i - b_i ); 36mse_a_0 += a_i * a_i ; 37 } 38 39return mse_a_b /mse_a_0 ; 40} 41 42static void set_tensor_data (struct ggml_tensor * tensor ,void * userdata ) { 43size_t seed = * (const size_t * )userdata ; 44 std::hash < std::string > hasher ; 45seed ^=hasher (tensor -> name ); 46 std::mt19937 gen (seed ); 47 std::normal_distribution < float > dis (0.0f ,1.0e-2f ); 48 49const int64_t ne = ggml_nelements (tensor ); 50if (tensor -> type == GGML_TYPE_F32 ) { 51 std::vector < float > tmp (ne ); 52for (int64_t i = 0 ;i < ne ;i ++ ) { 53tmp [i ]= dis (gen ); 54 } 55ggml_backend_tensor_set (tensor ,tmp .data (),0 ,ggml_nbytes (tensor )); 56 }else if (tensor -> type == GGML_TYPE_F16 ) { 57 std::vector < ggml_fp16_t > tmp (ne ); 58for (int64_t i = 0 ;i < ne ;i ++ ) { 59tmp [i ]= ggml_fp32_to_fp16 (dis (gen )); 60 } 61ggml_backend_tensor_set (tensor ,tmp .data (),0 ,ggml_nbytes (tensor )); 62 }else { 63GGML_ABORT ("fatal error" ); 64 } 65} 66 67static void usage (char ** argv ) { 68printf ("Usage: %s [-a/--arch arch] [-s/--seed seed] [-o/--out dir] [-v N] [-h/--help]\n" ,argv [0 ]); 69} 70 71static std::vector < llama_token > get_tokens (const uint32_t n_tokens ,const uint32_t n_vocab ,const size_t seed ){ 72 std::mt19937 gen (seed ); 73 std::uniform_int_distribution <> dis (0 ,n_vocab - 1 ); 74 std::vector < llama_token > ret ; 75ret .reserve (n_tokens ); 76for (uint32_t i = 0 ;i < n_tokens ;i ++ ) { 77ret .push_back (dis (gen )); 78 } 79return ret ; 80} 81 82static gguf_context_ptr get_gguf_ctx (const llm_arch arch ,const bool moe ) { 83gguf_context_ptr ret (gguf_init_empty ()); 84llama_model_saver ms (arch ,ret .get ()); 85const uint32_t n_ctx = 256 ; 86 87uint32_t n_vocab = 128 ; 88uint32_t n_embd = 256 ; 89uint32_t n_head = 2 ; 90uint32_t n_ff = 384 ; 91uint32_t n_layer = 2 ; 92if (arch == LLM_ARCH_LLAMA4 ) { 93n_layer = 4 ;// hparams.n_no_rope_layer_step is hard-coded to 4 94 }else if (arch == LLM_ARCH_GEMMA4 ) { 95n_embd = 128 ; 96n_head = 2 ; 97n_ff = 192 ; 98n_layer = 5 ;// need at least 5 for swa_pattern (every 5th is full_attention) 99 }else if (arch == LLM_ARCH_GEMMA3N ) { 100n_embd = 64 ; 101n_head = 1 ; 102n_ff = 96 ; 103n_layer = 22 ;// hparams.n_layer_kv_from_start = 20 is hardcoded 104 }else if (arch == LLM_ARCH_DEEPSEEK4 ) { 105// head size 64 so that GPU flash attention kernels support the model 106n_embd = 512 ; 107n_head = 8 ; 108n_ff = 1024 ; 109n_layer = 4 ; 110 }else if (arch == LLM_ARCH_STEP35 || arch == LLM_ARCH_LAGUNA ) { 111n_embd = 160 ;// exercise per-head tensor split granularity with head size 80 112 }else if (arch == LLM_ARCH_QWEN3 || arch == LLM_ARCH_MUSE_GLIMMER || arch == LLM_ARCH_AFMOE ) { 113n_head = 4 ; 114 }else if (arch == LLM_ARCH_DEEPSEEK2 115|| arch == LLM_ARCH_DEEPSEEK32 116|| arch == LLM_ARCH_GLM_DSA 117|| arch == LLM_ARCH_DOTS3NOTE 118|| arch == LLM_ARCH_KIMI_LINEAR 119|| arch == LLM_ARCH_BAILINGMOE3 120|| arch == LLM_ARCH_KIMI_K3 121|| arch == LLM_ARCH_MISTRAL4 122|| arch == LLM_ARCH_HY_V4 ) { 123n_embd = 128 ; 124n_head = 1 ; 125n_ff = 192 ; 126 }else if (arch == LLM_ARCH_NEMOTRON_H || arch == LLM_ARCH_NEMOTRON_H_MOE ) { 127n_layer = 3 ; 128 }else if (arch == LLM_ARCH_CHAMELEON ) { 129n_vocab = 10240 ; 130 }else if (arch == LLM_ARCH_QWEN3TTS ) { 131//n_vocab = 4096; // must be >= the hard-coded codec head size (3072) 132n_vocab = 3072 ;// TODO: should be 4096, but user code cannot get `n_vocab_out` yet [TAG_LLAMA_N_VOCAB_OUT] 133 } 134 135uint32_t n_head_kv = n_head ; 136if (arch == LLM_ARCH_QWEN3 ) { 137n_head_kv = 1 ;// MQA coverage 138 }else if (arch == LLM_ARCH_MUSE_GLIMMER || arch == LLM_ARCH_AFMOE ) { 139n_head_kv = 2 ;// GQA coverage 140 } 141const uint32_t n_embd_head = n_embd /n_head ; 142 143ms .add_kv (LLM_KV_GENERAL_ARCHITECTURE ,llm_arch_name (arch )); 144ms .add_kv (LLM_KV_VOCAB_SIZE ,n_vocab ); 145ms .add_kv (LLM_KV_CONTEXT_LENGTH ,n_ctx ); 146ms .add_kv (LLM_KV_EMBEDDING_LENGTH ,n_embd ); 147ms .add_kv (LLM_KV_FEATURES_LENGTH ,n_embd ); 148ms .add_kv (LLM_KV_BLOCK_COUNT ,n_layer ); 149ms .add_kv (LLM_KV_LEADING_DENSE_BLOCK_COUNT ,uint32_t (1 )); 150 151if (arch == LLM_ARCH_NEMOTRON_H || arch == LLM_ARCH_NEMOTRON_H_MOE ) { 152 std::vector < uint32_t > n_ff_per_layer ; 153n_ff_per_layer .reserve (n_layer ); 154for (uint32_t il = 0 ;il < n_layer ;il ++ ) { 155n_ff_per_layer .push_back (il <=1 ?0 :n_ff ); 156 } 157ms .add_kv (LLM_KV_FEED_FORWARD_LENGTH ,n_ff_per_layer ); 158 }else { 159ms .add_kv (LLM_KV_FEED_FORWARD_LENGTH ,n_ff ); 160 } 161 162ms .add_kv (LLM_KV_USE_PARALLEL_RESIDUAL , false); 163ms .add_kv (LLM_KV_LOGIT_SCALE ,1.0f ); 164ms .add_kv (LLM_KV_TIME_MIX_EXTRA_DIM ,uint32_t (64 )); 165ms .add_kv (LLM_KV_TIME_DECAY_EXTRA_DIM ,uint32_t (128 )); 166ms .add_kv (LLM_KV_FULL_ATTENTION_INTERVAL ,uint32_t (2 )); 167 168if (arch == LLM_ARCH_PLAMO2 || arch == LLM_ARCH_JAMBA || arch == LLM_ARCH_NEMOTRON_H || arch == LLM_ARCH_NEMOTRON_H_MOE || 169arch == LLM_ARCH_GRANITE_HYBRID || arch == LLM_ARCH_LFM2 || arch == LLM_ARCH_LFM2MOE || arch == LLM_ARCH_KIMI_LINEAR || 170arch == LLM_ARCH_BAILINGMOE3 || arch == LLM_ARCH_KIMI_K3 ) { 171GGML_ASSERT (n_layer >=2 ); 172 std::vector < uint32_t > n_head_per_layer ; 173n_head_per_layer .reserve (n_layer ); 174for (uint32_t il = 0 ;il < n_layer ;il ++ ) { 175n_head_per_layer .push_back (il == 1 ?0 :n_head ); 176 } 177ms .add_kv (LLM_KV_ATTENTION_HEAD_COUNT ,n_head_per_layer ); 178ms .add_kv (LLM_KV_ATTENTION_HEAD_COUNT_KV ,n_head_per_layer ); 179 }else { 180ms .add_kv (LLM_KV_ATTENTION_HEAD_COUNT ,n_head ); 181ms .add_kv (LLM_KV_ATTENTION_HEAD_COUNT_KV ,arch == LLM_ARCH_DEEPSEEK4 ?uint32_t (1 ) :n_head_kv ); 182 } 183 184ms .add_kv (LLM_KV_ATTENTION_MAX_ALIBI_BIAS ,8.0f ); 185if (arch == LLM_ARCH_DEEPSEEK4 ) { 186ms .add_kv (LLM_KV_ATTENTION_KEY_LENGTH ,n_embd_head ); 187ms .add_kv (LLM_KV_ATTENTION_VALUE_LENGTH ,n_embd_head ); 188ms .add_kv (LLM_KV_ROPE_DIMENSION_COUNT ,n_embd_head /2 ); 189 }else if (arch == LLM_ARCH_DEEPSEEK2 190|| arch == LLM_ARCH_DEEPSEEK32 191|| arch == LLM_ARCH_GLM_DSA 192|| arch == LLM_ARCH_DOTS3NOTE 193|| arch == LLM_ARCH_KIMI_LINEAR 194|| arch == LLM_ARCH_BAILINGMOE3 195|| arch == LLM_ARCH_KIMI_K3 196|| arch == LLM_ARCH_MISTRAL4 197|| arch == LLM_ARCH_HY_V4 ) { 198ms .add_kv (LLM_KV_ATTENTION_KEY_LENGTH ,uint32_t (576 )); 199ms .add_kv (LLM_KV_ATTENTION_VALUE_LENGTH ,uint32_t (512 )); 200ms .add_kv (LLM_KV_ROPE_DIMENSION_COUNT ,uint32_t (64 )); 201ms .add_kv (LLM_KV_ATTENTION_KEY_LENGTH_MLA ,uint32_t (192 )); 202ms .add_kv (LLM_KV_ATTENTION_VALUE_LENGTH_MLA ,uint32_t (128 )); 203if (arch == LLM_ARCH_DOTS3NOTE ) { 204// SWA layers reuse the same MLA geometry as the full layers in this fixture 205ms .add_kv (LLM_KV_ATTENTION_KV_LORA_RANK_SWA ,uint32_t (512 )); 206ms .add_kv (LLM_KV_ATTENTION_KEY_LENGTH_SWA ,uint32_t (576 )); 207ms .add_kv (LLM_KV_ATTENTION_VALUE_LENGTH_SWA ,uint32_t (512 )); 208ms .add_kv (LLM_KV_ATTENTION_KEY_LENGTH_MLA_SWA ,uint32_t (192 )); 209ms .add_kv (LLM_KV_ATTENTION_VALUE_LENGTH_MLA_SWA ,uint32_t (128 )); 210ms .add_kv (LLM_KV_ROPE_FREQ_BASE_SWA ,10000.0f ); 211// indexer on the full-attention layers (inverse of the swa pattern) 212 std::vector < uint32_t > indexer_types ; 213indexer_types .reserve (n_layer ); 214for (uint32_t il = 0 ;il < n_layer ;il ++ ) { 215indexer_types .push_back (il %2 ?0 :1 ); 216 } 217ms .add_kv (LLM_KV_ATTENTION_INDEXER_TYPES ,indexer_types ); 218 } 219 }else if (arch == LLM_ARCH_MINIMAX_M3 ) { 220// partial rotary: n_rot must not exceed the indexer key length (64) 221ms .add_kv (LLM_KV_ROPE_DIMENSION_COUNT ,uint32_t (64 )); 222 } 223ms .add_kv (LLM_KV_ATTENTION_CLAMP_KQV ,1.0f ); 224ms .add_kv (LLM_KV_ATTENTION_LAYERNORM_EPS ,1e-5f ); 225ms .add_kv (LLM_KV_ATTENTION_LAYERNORM_RMS_EPS ,1e-5f ); 226ms .add_kv (LLM_KV_ATTENTION_GROUPNORM_EPS ,1e-5f ); 227ms .add_kv (LLM_KV_ATTENTION_GROUPNORM_GROUPS ,uint32_t (8 )); 228ms .add_kv (LLM_KV_ATTENTION_Q_LORA_RANK ,arch == LLM_ARCH_DEEPSEEK4 ?uint32_t (64 ) :uint32_t (512 )); 229ms .add_kv (LLM_KV_ATTENTION_KV_LORA_RANK ,uint32_t (512 )); 230ms .add_kv (LLM_KV_ATTENTION_RELATIVE_BUCKETS_COUNT ,uint32_t (8 )); 231ms .add_kv (LLM_KV_ATTENTION_SLIDING_WINDOW ,n_ctx /8 ); 232 233if (arch == LLM_ARCH_GEMMA4 ) { 234ms .add_kv (LLM_KV_EMBEDDING_LENGTH_PER_LAYER ,n_embd /2 ); 235ms .add_kv (LLM_KV_ATTENTION_SHARED_KV_LAYERS ,uint32_t (0 )); 236ms .add_kv (LLM_KV_ATTENTION_KEY_LENGTH_SWA ,n_embd_head ); 237ms .add_kv (LLM_KV_ATTENTION_VALUE_LENGTH_SWA ,n_embd_head ); 238ms .add_kv (LLM_KV_ROPE_FREQ_BASE_SWA ,10000.0f ); 239// SWA pattern: every 5th layer is full attention (matches E2B layer_types) 240ms .add_kv (LLM_KV_ATTENTION_SLIDING_WINDOW_PATTERN ,uint32_t (5 )); 241 }else if (arch == LLM_ARCH_COHERE2MOE || arch == LLM_ARCH_MIMO2 || arch == LLM_ARCH_STEP35 || arch == LLM_ARCH_SPARK2_5 || 242arch == LLM_ARCH_MUSE_GLIMMER || arch == LLM_ARCH_GRANITE_SWA || arch == LLM_ARCH_DOTS3NOTE || 243arch == LLM_ARCH_MAPLE ) { 244 std::vector < uint32_t > pattern ; 245pattern .reserve (n_layer ); 246for (uint32_t il = 0 ;il < n_layer ;il ++ ) { 247pattern .push_back (il %2 ); 248 } 249ms .add_kv (LLM_KV_ATTENTION_SLIDING_WINDOW_PATTERN ,pattern ); 250 }else { 251ms .add_kv (LLM_KV_ATTENTION_SLIDING_WINDOW_PATTERN ,uint32_t (2 )); 252 } 253 254// MSA requires one indexer head per GQA (KV) head, unlike the DSA archs where the 255// indexer head count is independent of the main attention head count. 256if (arch == LLM_ARCH_QWEN4EXP ) { 257ms .add_kv (LLM_KV_HYPER_CONNECTION_COUNT ,uint32_t (4 )); 258ms .add_kv (LLM_KV_HYPER_CONNECTION_LOW_RANK ,uint32_t (8 )); 259// without this the QSA layers fall back to dense and go uncovered 260ms .add_kv (LLM_KV_ATTENTION_COMPRESS_RATIOS , std::vector < uint32_t > (n_layer ,4 )); 261 262// has_cell_ext() needs ple_n_heads here: the indexer cache serializes no ext without it 263const uint32_t ple_ngram_size = 3 ; 264const uint32_t ple_heads_per_ngram = 2 ; 265const uint32_t ple_n_heads = (ple_ngram_size - 1 )* ple_heads_per_ngram ; 266GGML_ASSERT (n_embd %ple_n_heads == 0 ); 267const uint32_t ple_head_dim = n_embd /ple_n_heads ; 268 269 std::vector < uint64_t > ple_head_offsets (ple_n_heads ); 270 std::vector < uint64_t > ple_head_vocab_sizes (ple_n_heads ,n_vocab ); 271for (uint32_t h = 0 ;h < ple_n_heads ;h ++ ) { 272ple_head_offsets [h ]= uint64_t (h )* n_vocab ; 273 } 274 275// the PLE history lives in the recurrent cache, so it must sit on a linear attention layer 276ms .add_kv (LLM_KV_PLE_LAYERS , std::vector < uint32_t > ({0 })); 277ms .add_kv (LLM_KV_PLE_NGRAM_SIZE ,ple_ngram_size ); 278ms .add_kv (LLM_KV_PLE_HEADS_PER_NGRAM ,ple_heads_per_ngram ); 279ms .add_kv (LLM_KV_PLE_CONV_KERNEL ,uint32_t (4 )); 280ms .add_kv (LLM_KV_PLE_EOS_TOKEN_ID ,uint32_t (0 )); 281ms .add_kv (LLM_KV_EMBEDDING_LENGTH_PER_LAYER ,ple_head_dim ); 282ms .add_kv (LLM_KV_PLE_LAYER_MULTIPLIERS , std::vector < uint64_t > ({1 ,3 ,5 })); 283ms .add_kv (LLM_KV_PLE_HEAD_OFFSETS ,ple_head_offsets ); 284ms .add_kv (LLM_KV_PLE_HEAD_VOCAB_SIZES ,ple_head_vocab_sizes ); 285 } 286 287// minimax-m3 keeps one indexer head per GQA head; the rest use a fixed 64 to match the fused 288ms .add_kv (LLM_KV_ATTENTION_INDEXER_HEAD_COUNT ,arch == LLM_ARCH_MINIMAX_M3 ?n_head :uint32_t (64 )); 289// qwen4exp ropes indexer keys with the main rotary width, so its head can't be < n_rot 290ms .add_kv (LLM_KV_ATTENTION_INDEXER_KEY_LENGTH , 291arch == LLM_ARCH_QWEN4EXP ?n_embd_head :uint32_t (128 )); 292 293ms .add_kv (LLM_KV_ATTENTION_INDEXER_TOP_K ,uint32_t (8 )); 294ms .add_kv (LLM_KV_ATTENTION_INDEXER_BLOCK_SIZE ,uint32_t (4 )); 295ms .add_kv (LLM_KV_ATTENTION_INDEXER_LOCAL_BLOCKS ,uint32_t (1 )); 296ms .add_kv (LLM_KV_ROPE_DIMENSION_SECTIONS , std::vector < uint32_t > ({n_embd_head /4 ,n_embd_head /4 ,n_embd_head /4 ,n_embd_head /4 })); 297 298if (arch == LLM_ARCH_HY_V4 ) { 299ms .add_kv (LLM_KV_HYPER_CONNECTION_COUNT ,uint32_t (4 )); 300ms .add_kv (LLM_KV_HYPER_CONNECTION_EPSILON ,1.0e-6f ); 301ms .add_kv (LLM_KV_HYPER_CONNECTION_MAGNITUDE ,2.0f ); 302ms .add_kv (LLM_KV_SWIGLU_CLAMP_EXP ,10.0f ); 303ms .add_kv (LLM_KV_EXPERT_WEIGHTS_SCALE ,1.0f ); 304ms .add_kv (LLM_KV_EXPERT_WEIGHTS_NORM , true); 305// layer 0 must own an indexer, the odd layers share it 306 std::vector < uint32_t > indexer_types ; 307indexer_types .reserve (n_layer ); 308for (uint32_t il = 0 ;il < n_layer ;il ++ ) { 309indexer_types .push_back (il %2 ?0 :1 ); 310 } 311ms .add_kv (LLM_KV_ATTENTION_INDEXER_TYPES ,indexer_types ); 312 } 313 314if (arch == LLM_ARCH_DEEPSEEK4 ) { 315ms .add_kv (LLM_KV_ATTENTION_OUTPUT_GROUP_COUNT ,uint32_t (8 )); 316ms .add_kv (LLM_KV_ATTENTION_OUTPUT_LORA_RANK ,uint32_t (32 )); 317ms .add_kv (LLM_KV_ATTENTION_COMPRESS_RATIOS , std::vector < uint32_t > ({0 ,0 ,4 ,128 })); 318ms .add_kv (LLM_KV_ATTENTION_COMPRESS_ROPE_FREQ_BASE ,160000.0f ); 319ms .add_kv (LLM_KV_HYPER_CONNECTION_COUNT ,uint32_t (4 )); 320ms .add_kv (LLM_KV_HYPER_CONNECTION_SINKHORN_ITERATIONS ,uint32_t (2 )); 321ms .add_kv (LLM_KV_HYPER_CONNECTION_EPSILON ,1.0e-6f ); 322ms .add_kv (LLM_KV_HASH_LAYER_COUNT ,uint32_t (0 )); 323ms .add_kv (LLM_KV_SWIGLU_CLAMP_EXP ,10.0f ); 324ms .add_kv (LLM_KV_EXPERT_WEIGHTS_SCALE ,1.0f ); 325ms .add_kv (LLM_KV_EXPERT_WEIGHTS_NORM , true); 326 } 327 328if (arch == LLM_ARCH_MAPLE ) { 329ms .add_kv (LLM_KV_SWIGLU_CLAMP_EXP ,7.0f ); 330 } 331 332if (arch == LLM_ARCH_ALICEAI_T5_MOE ) { 333ms .add_kv (LLM_KV_DECODER_BLOCK_COUNT ,n_layer - 1 ); 334ms .add_kv (LLM_KV_DECODER_START_TOKEN_ID ,uint32_t (1 )); 335ms .add_kv (LLM_KV_ENCODER_ATTENTION_HEAD_COUNT_KV ,n_head ); 336ms .add_kv (LLM_KV_ATTENTION_HEAD_COUNT_KV ,uint32_t (1 )); 337ms .add_kv (LLM_KV_EXPERT_WEIGHTS_SCALE ,1.0f ); 338ms .add_kv (LLM_KV_EXPERT_WEIGHTS_NORM , true); 339 } 340 341ms .add_kv (LLM_KV_TOKENIZER_MODEL ,"no_vocab" ); 342// ms.add_kv(LLM_KV_DENSE_2_FEAT_OUT, n_embd); 343// ms.add_kv(LLM_KV_DENSE_3_FEAT_IN, n_embd); 344 345if (moe ) { 346ms .add_kv (LLM_KV_EXPERT_FEED_FORWARD_LENGTH ,n_ff ); 347ms .add_kv (LLM_KV_EXPERT_SHARED_FEED_FORWARD_LENGTH ,n_ff /2 );// distinct from n_ff so a saver key-clobber surfaces on reload 348ms .add_kv (LLM_KV_EXPERT_LATENT_LENGTH ,n_ff ); 349ms .add_kv (LLM_KV_INTERLEAVE_MOE_LAYER_STEP ,uint32_t (2 )); 350ms .add_kv (LLM_KV_EXPERT_COUNT ,uint32_t (2 )); 351ms .add_kv (LLM_KV_EXPERT_USED_COUNT ,uint32_t (1 )); 352ms .add_kv (LLM_KV_EXPERT_SHARED_COUNT ,uint32_t (1 )); 353ms .add_kv (LLM_KV_EXPERT_GATING_FUNC ,arch == LLM_ARCH_DEEPSEEK4 ?uint32_t (4 ) :uint32_t (2 ));// sqrtsoftplus : sigmoid 354ms .add_kv (LLM_KV_EXPERT_GROUP_SCALE ,1.0f ); 355ms .add_kv (LLM_KV_EXPERTS_PER_GROUP ,uint32_t (1 )); 356 } 357 358ms .add_kv (LLM_KV_POSNET_EMBEDDING_LENGTH ,n_embd ); 359ms .add_kv (LLM_KV_POSNET_BLOCK_COUNT ,n_layer ); 360ms .add_kv (LLM_KV_CONVNEXT_EMBEDDING_LENGTH ,n_embd ); 361ms .add_kv (LLM_KV_CONVNEXT_BLOCK_COUNT ,n_layer ); 362ms .add_kv (LLM_KV_XIELU_ALPHA_N ,1.0f ); 363ms .add_kv (LLM_KV_XIELU_ALPHA_P ,1.0f ); 364ms .add_kv (LLM_KV_XIELU_BETA ,1.0f ); 365ms .add_kv (LLM_KV_XIELU_EPS ,1.0e-7f ); 366ms .add_kv (LLM_KV_SSM_INNER_SIZE ,arch == LLM_ARCH_QWEN3NEXT || arch == LLM_ARCH_QWEN35 || arch == LLM_ARCH_QWEN35MOE || arch == LLM_ARCH_QWEN4EXP ?256 :2 * n_embd ); 367ms .add_kv (LLM_KV_SSM_CONV_KERNEL ,uint32_t (4 )); 368ms .add_kv (LLM_KV_SSM_STATE_SIZE ,uint32_t (128 )); 369ms .add_kv (LLM_KV_SSM_TIME_STEP_RANK ,n_head ); 370ms .add_kv (LLM_KV_SSM_GROUP_COUNT ,arch == LLM_ARCH_PLAMO2 ?0 :uint32_t (2 )); 371ms .add_kv (LLM_KV_KDA_HEAD_DIM ,uint32_t (128 )); 372ms .add_kv (LLM_KV_KDA_SAFE_GATE , true); 373ms .add_kv (LLM_KV_KDA_GATE_LOWER_BOUND ,-5.0f ); 374if (arch == LLM_ARCH_BAILINGMOE3 ) { 375ms .add_kv (LLM_KV_SWIGLU_CLAMP_EXP , std::vector < float > ({0.0f ,4.0f })); 376ms .add_kv (LLM_KV_SWIGLU_CLAMP_SHEXP , std::vector < float > ({0.0f ,5.0f })); 377 } 378ms .add_kv (LLM_KV_WKV_HEAD_SIZE ,n_embd /n_head ); 379ms .add_kv (LLM_KV_SHORTCONV_L_CACHE ,uint32_t (3 )); 380ms .add_kv (LLM_KV_RESIDUAL_SCALE ,3.5565588200778455f ); 381ms .add_kv (LLM_KV_ATTN_RES_BLOCK_SIZE ,uint32_t (12 )); 382ms .add_kv (LLM_KV_ACTIVATION_SITU_BETA ,4.0f ); 383ms .add_kv (LLM_KV_ACTIVATION_SITU_LINEAR_BETA ,25.0f ); 384ms .add_kv (LLM_KV_KDA_GATE_LOWER_BOUND ,-5.0f ); 385 386for (uint32_t il = 0 ;il < n_layer ;il ++ ) { 387ggml_tensor t ; 388memset (& t ,0 ,sizeof (ggml_tensor )); 389t .type = GGML_TYPE_F16 ; 390ggml_format_name (& t ,"conv%" PRIu32 "d.weight" ,il ); 391gguf_add_tensor (ms .gguf_ctx ,& t ); 392ggml_format_name (& t ,"posnet.%" PRIu32 ".conv1.weight" ,il ); 393gguf_add_tensor (ms .gguf_ctx ,& t ); 394ggml_format_name (& t ,"posnet.%" PRIu32 ".conv2.weight" ,il ); 395gguf_add_tensor (ms .gguf_ctx ,& t ); 396ggml_format_name (& t ,"convnext.%" PRIu32 ".dw.weight" ,il ); 397gguf_add_tensor (ms .gguf_ctx ,& t ); 398 } 399return ret ; 400} 401 402static bool silent_model_load_progress (float /*progress*/ ,void * /*user_data*/ ) { 403return true; 404} 405 406static std::pair < llama_model_ptr ,llama_context_ptr > get_model_and_ctx ( 407struct gguf_context * gguf_ctx ,FILE * file ,const size_t seed ,const std::vector < ggml_backend_dev_t > & devs , 408const llama_split_mode split_mode = LLAMA_SPLIT_MODE_LAYER ,bool encode = false) { 409GGML_ASSERT ((gguf_ctx == nullptr )!= (file == nullptr )); 410llama_model_params model_params = llama_model_default_params (); 411model_params .progress_callback = silent_model_load_progress ; 412 std::vector < ggml_backend_dev_t > devs_copy = devs ; 413devs_copy .push_back (nullptr ); 414model_params .devices = devs_copy .data (); 415model_params .split_mode = split_mode ; 416 417llama_context_params ctx_params = llama_context_default_params (); 418ctx_params .n_ctx = 0 ; 419ctx_params .n_threads = 4 ; 420ctx_params .n_threads_batch = 4 ; 421if (!encode ) { 422ctx_params .n_ubatch = 64 ; 423 } 424 425size_t tmp = seed ; 426llama_model_ptr model (gguf_ctx != nullptr ? 427llama_model_init_from_user (gguf_ctx ,set_tensor_data ,& tmp ,model_params ) : 428llama_model_load_from_file_ptr (file ,model_params )); 429if (!model ) { 430throw std::runtime_error ("failed to create llama model" ); 431 } 432llama_context_ptr lctx (llama_init_from_model (model .get (),ctx_params )); 433if (!lctx ) { 434throw std::runtime_error ("failed to create llama context" ); 435 } 436return std::make_pair (std::move (model ), std::move (lctx )); 437} 438 439static std::vector < float > get_logits ( 440llama_model * model ,llama_context * lctx ,const std::vector < llama_token > & tokens ,bool encode = false) { 441const uint32_t n_vocab = llama_vocab_n_tokens (llama_model_get_vocab (model )); 442const uint32_t n_ctx = llama_n_ctx (lctx ); 443const uint32_t n_tokens = tokens .size (); 444llama_batch batch = llama_batch_init (n_ctx ,0 ,1 ); 445GGML_ASSERT (n_tokens <=n_ctx ); 446for (uint32_t pos = 0 ;pos < n_tokens ;pos ++ ) { 447common_batch_add (batch ,tokens [pos ],pos , {0 }, true); 448 } 449batch .n_tokens = n_tokens ; 450if (encode ) { 451if (llama_encode (lctx ,batch )) { 452llama_batch_free (batch ); 453throw std::runtime_error ("failed to encode batch" ); 454 } 455 } 456if (llama_decode (lctx ,batch )) { 457llama_batch_free (batch ); 458throw std::runtime_error ("failed to decode batch" ); 459 } 460 461 std::vector < float > ret ; 462ret .reserve (n_tokens * n_vocab ); 463for (uint32_t i = 0 ;i < n_tokens ;i ++ ) { 464const float * logits_ith = llama_get_logits_ith (lctx ,i ); 465for (uint32_t j = 0 ;j < n_vocab ;j ++ ) { 466ret .push_back (logits_ith [j ]); 467 } 468 } 469llama_batch_free (batch ); 470return ret ; 471} 472 473static void test_encoder_decoder_batches (llama_model * model ,llama_context * ctx ,size_t seed ) { 474if (!llama_model_has_encoder (model )|| !llama_model_has_decoder (model )) { 475return ; 476 } 477 478const uint32_t n_vocab = llama_vocab_n_tokens (llama_model_get_vocab (model )); 479auto decoder = get_tokens (8 ,n_vocab ,seed ); 480for (uint32_t n_enc : {16u ,16u ,7u ,32u }) { 481auto encoder = get_tokens (n_enc ,n_vocab ,++ seed ); 482llama_memory_clear (llama_get_memory (ctx ), true); 483GGML_ASSERT (llama_encode (ctx ,llama_batch_get_one (encoder .data (),encoder .size ()))== 0 ); 484const auto expected = get_logits (model ,ctx ,decoder ); 485 486llama_memory_clear (llama_get_memory (ctx ), true); 487 std::vector < float > actual ; 488int8_t outputs []= {1 ,1 }; 489uint32_t pos = 0 ; 490for (uint32_t count : {1u ,1u ,2u ,2u ,1u ,1u }) { 491auto batch = llama_batch_get_one (decoder .data ()+ pos ,count ); 492batch .logits = outputs ; 493GGML_ASSERT (llama_decode (ctx ,batch )== 0 ); 494for (uint32_t i = 0 ;i < count ;++ i ) { 495const float * logits = llama_get_logits_ith (ctx ,i ); 496actual .insert (actual .end (),logits ,logits + n_vocab ); 497 } 498pos += count ; 499 } 500GGML_ASSERT (nmse (expected ,actual )< 1e-4 ); 501 } 502} 503 504static bool moe_mandatory (const llm_arch arch ) { 505switch (arch ) { 506case LLM_ARCH_LLAMA4 : 507case LLM_ARCH_COHERE2MOE : 508case LLM_ARCH_GROK : 509case LLM_ARCH_QWEN2MOE : 510case LLM_ARCH_QWEN3MOE : 511case LLM_ARCH_QWEN3NEXT : 512case LLM_ARCH_QWEN3VLMOE : 513case LLM_ARCH_QWEN35MOE : 514case LLM_ARCH_QWEN4EXP : 515case LLM_ARCH_PHIMOE : 516case LLM_ARCH_DBRX : 517case LLM_ARCH_OLMOE : 518case LLM_ARCH_ARCTIC : 519case LLM_ARCH_DEEPSEEK : 520case LLM_ARCH_DEEPSEEK2 : 521case LLM_ARCH_DEEPSEEK32 : 522case LLM_ARCH_DOTS3NOTE : 523case LLM_ARCH_DEEPSEEK4 : 524case LLM_ARCH_GLM4_MOE : 525case LLM_ARCH_GLM_DSA : 526case LLM_ARCH_EXAONE_MOE : 527case LLM_ARCH_BAILINGMOE : 528case LLM_ARCH_BAILINGMOE2 : 529case LLM_ARCH_BAILINGMOE3 : 530case LLM_ARCH_DOTS1 : 531case LLM_ARCH_AFMOE : 532case LLM_ARCH_ERNIE4_5 : 533case LLM_ARCH_ERNIE4_5_MOE : 534case LLM_ARCH_HUNYUAN_MOE : 535case LLM_ARCH_HY_V3 : 536case LLM_ARCH_HY_V4 : 537case LLM_ARCH_OPENAI_MOE : 538case LLM_ARCH_LFM2MOE : 539case LLM_ARCH_SMALLTHINKER : 540case LLM_ARCH_LLADA_MOE : 541case LLM_ARCH_GROVEMOE : 542case LLM_ARCH_MINIMAX_01 : 543case LLM_ARCH_MINIMAX_M2 : 544case LLM_ARCH_MINIMAX_M3 : 545case LLM_ARCH_RND1 : 546case LLM_ARCH_PADDLEOCR : 547case LLM_ARCH_MIMO2 : 548case LLM_ARCH_KIMI_LINEAR : 549case LLM_ARCH_KIMI_K3 : 550case LLM_ARCH_STEP35 : 551case LLM_ARCH_MISTRAL4 : 552case LLM_ARCH_MELLUM : 553case LLM_ARCH_LAGUNA : 554case LLM_ARCH_MAPLE : 555case LLM_ARCH_ALICEAI_T5_MOE : 556return true; 557default : 558return false; 559 } 560} 561 562static bool moe_implemented (const llm_arch arch ) { 563if (moe_mandatory (arch )) { 564return true; 565 } 566switch (arch ) { 567case LLM_ARCH_LLAMA : 568case LLM_ARCH_REFACT : 569case LLM_ARCH_MINICPM : 570case LLM_ARCH_GRANITE : 571case LLM_ARCH_GRANITE_MOE : 572case LLM_ARCH_MISTRAL3 : 573case LLM_ARCH_LLAMA_EMBED : 574return true; 575default : 576return false; 577 } 578} 579 580static bool arch_supported (const llm_arch arch ) { 581if (arch == LLM_ARCH_CLIP || arch == LLM_ARCH_GPTJ || arch == LLM_ARCH_UNKNOWN ) { 582return false;// These models don't have usable implementations. 583 } 584if (arch == LLM_ARCH_CHAMELEON ) { 585return false;// Only half-implemented and to be removed in the future. 586 } 587if (arch == LLM_ARCH_WAVTOKENIZER_DEC ) { 588return false;// FIXME CUDA backend crashes. 589 } 590if (arch == LLM_ARCH_GEMMA4 || arch == LLM_ARCH_GEMMA4_ASSISTANT ) { 591return false;// FIXME @ngxson 592 } 593if (arch == LLM_ARCH_GRANITE_SWITCH ) { 594return false;// FIXME adapter fixture 595 } 596if (arch == LLM_ARCH_LLAMA_EMBED || arch == LLM_ARCH_GEMMA_EMBEDDING || arch == LLM_ARCH_T5ENCODER ) { 597return false;// FIXME Embedding (?) models produce inconsistent results. 598 } 599if (arch == LLM_ARCH_RWKV6 || arch == LLM_ARCH_RWKV6QWEN2 || arch == LLM_ARCH_RWKV7 || arch == LLM_ARCH_ARWKV7 ) { 600return false;// FIXME RWKV models hang indefinitely. 601 } 602if (arch == LLM_ARCH_BERT || arch == LLM_ARCH_MODERN_BERT || arch == LLM_ARCH_NOMIC_BERT || arch == LLM_ARCH_NOMIC_BERT_MOE || 603arch == LLM_ARCH_NEO_BERT || arch == LLM_ARCH_JINA_BERT_V2 || arch == LLM_ARCH_JINA_BERT_V3 || arch == LLM_ARCH_EUROBERT ) { 604return false;// TODO vocab 605 } 606if (arch == LLM_ARCH_PLM ) { 607return false;// TODO tensor shapes 608 } 609if (arch == LLM_ARCH_DEEPSEEK2OCR ) { 610return false; 611 } 612// FIXME: these hit scheduler/view-backed-output issues with WebGPU on CI. 613#ifdef GGML_USE_WEBGPU 614if (arch == LLM_ARCH_DEEPSEEK32 || arch == LLM_ARCH_GLM_DSA || arch == LLM_ARCH_DOTS3NOTE || arch == LLM_ARCH_QWEN4EXP || 615arch == LLM_ARCH_HY_V4 ) { 616return false; 617 } 618#endif // GGML_USE_WEBGPU 619 620// FIXME: jamba produces incorrect output (~0.55 NMSE vs CPU) on the HIP 621// backend on RDNA3.5 (gfx1151); the SSM kernels need investigation. 622#ifdef GGML_USE_HIP 623if (arch == LLM_ARCH_JAMBA ) { 624return false; 625 } 626#endif // GGML_USE_HIP 627 628return true; 629} 630 631static int save_models (const llm_arch target_arch ,const size_t seed ,const int verbosity ,const std::string & dir ) { 632struct user_data_t { 633struct { 634ggml_log_callback callback ; 635void * user_data ; 636 }log_old ; 637 638int verbosity ; 639 640user_data_t (int verbosity ) :verbosity (verbosity ) { 641llama_log_get (& log_old .callback ,& log_old .user_data ); 642 } 643 }; 644user_data_t ud (verbosity ); 645 646llama_log_set ([](ggml_log_level level ,const char * text ,void * user_data ) { 647const user_data_t * ud = (const user_data_t * )user_data ; 648int verbosity = common_log_get_verbosity (level ); 649if (verbosity <=ud -> verbosity ) { 650ud -> log_old .callback (level ,text ,ud -> log_old .user_data ); 651 } 652 },& ud ); 653 654for (const llm_arch & arch :llm_arch_all ()) { 655if (arch == LLM_ARCH_UNKNOWN ) { 656continue ; 657 } 658if (target_arch != LLM_ARCH_UNKNOWN && arch != target_arch ) { 659continue ; 660 } 661if (arch == LLM_ARCH_GEMMA4 || arch == LLM_ARCH_GEMMA4_ASSISTANT ) { 662continue ;// FIXME: ISWA KV cache initialization needs more fixture params 663 } 664if (arch == LLM_ARCH_EAGLE3 || arch == LLM_ARCH_DFLASH ) { 665continue ; 666 } 667for (bool moe : {false, true}) { 668if (moe && !moe_implemented (arch )) { 669continue ; 670 } 671if (!moe && moe_mandatory (arch )) { 672continue ; 673 } 674if (!llama_model_saver_supports_arch (arch )|| !arch_supported (arch )) { 675LOG_INF ("%s: %s model (%s) is unsupported, skipping\n" ,__func__ ,llm_arch_name (arch ),moe ?"MoE" :"dense" ); 676continue ; 677 } 678gguf_context_ptr gguf_ctx = get_gguf_ctx (arch ,moe ); 679auto model_and_ctx = get_model_and_ctx (gguf_ctx .get (),nullptr ,seed , {}); 680const std::string path = dir + "/" + llm_arch_name (arch )+ (moe ?"-moe.gguf" :"-dense.gguf" ); 681LOG_INF ("%s: Saving %s model (%s) to %s...\n" ,__func__ ,llm_arch_name (arch ),moe ?"MoE" :"dense" ,path .c_str ()); 682llama_model_save_to_file (model_and_ctx .first .get (),path .c_str ()); 683 } 684 } 685llama_log_set (ud .log_old .callback ,ud .log_old .user_data ); 686return 0 ; 687} 688 689static int test_backends (const llm_arch target_arch ,const size_t seed ,const int verbosity ) { 690struct user_data_t { 691struct { 692ggml_log_callback callback ; 693void * user_data ; 694 }log_old ; 695 696int verbosity ; 697 698user_data_t (int verbosity ) :verbosity (verbosity ) { 699llama_log_get (& log_old .callback ,& log_old .user_data ); 700 } 701 }; 702user_data_t ud (verbosity ); 703 704llama_log_set ([](ggml_log_level level ,const char * text ,void * user_data ) { 705const user_data_t * ud = (const user_data_t * )user_data ; 706int verbosity = common_log_get_verbosity (level ); 707if (verbosity <=ud -> verbosity ) { 708ud -> log_old .callback (level ,text ,ud -> log_old .user_data ); 709 } 710 },& ud ); 711 712const std::vector < llama_token > tokens = get_tokens (128 ,128 ,seed ); 713 714struct device_config { 715 std::vector < ggml_backend_dev_t > devs ; 716 std::string label ; 717llama_split_mode split_mode ; 718 719device_config (std::vector < ggml_backend_dev_t > devs , std::string name ,llama_split_mode split_mode ) 720 :devs (std::move (devs )),label (std::move (name )),split_mode (split_mode ) {} 721 }; 722 723 std::vector < device_config > dev_configs ; 724size_t max_device_label_length = 4 ; 725 { 726 std::vector < ggml_backend_dev_t > devices_meta ; 727 { 728const size_t device_count = ggml_backend_dev_count (); 729for (size_t i = 0 ;i < device_count ;i ++ ) { 730ggml_backend_dev_t dev = ggml_backend_dev_get (i ); 731dev_configs .emplace_back (std::vector < ggml_backend_dev_t > {dev },ggml_backend_dev_description (dev ),LLAMA_SPLIT_MODE_LAYER ); 732max_device_label_length = std::max (max_device_label_length ,dev_configs .back ().label .length ()); 733 734// cpu-based devices cannot be used in tensor split mode 735if (ggml_backend_dev_buffer_type (dev )!= ggml_backend_cpu_buffer_type ()) { 736devices_meta .push_back (dev ); 737 } 738 } 739 } 740 741dev_configs .emplace_back (devices_meta ,"Meta" ,LLAMA_SPLIT_MODE_TENSOR ); 742 } 743 744size_t max_arch_name_length = 0 ; 745for (const llm_arch & arch :llm_arch_all ()) { 746max_arch_name_length = std::max (max_arch_name_length ,strlen (llm_arch_name (arch ))); 747 } 748 749const std::string template_header = std::string ("|%" + std::to_string (max_arch_name_length )+ "s|%" )+ std::to_string (max_device_label_length )+ "s|%6s|%15s|%9s|\n" ; 750const std::string template_row_cfg = std::string ("|%" + std::to_string (max_arch_name_length )+ "s|%" )+ std::to_string (max_device_label_length )+ "s|%6s|" ; 751const std::string template_row_res = "%15s %10s|%20s|\n" ; 752 753bool all_ok = true; 754common_log_flush (common_log_main ()); 755printf (template_header .c_str (),"Model arch." ,"Device" ,"Config" ,"NMSE vs. CPU" ,"Roundtrip" ); 756printf ("|" ); 757for (size_t i = 0 ;i < max_arch_name_length ;i ++ ) { 758printf ("-" ); 759 } 760printf ("|" ); 761for (size_t i = 0 ;i < max_device_label_length ;i ++ ) { 762printf ("-" ); 763 } 764printf ("|------|---------------|---------|\n" ); 765for (const llm_arch & arch :llm_arch_all ()) { 766if (arch == LLM_ARCH_UNKNOWN ) { 767continue ; 768 } 769if (target_arch != LLM_ARCH_UNKNOWN && arch != target_arch ) { 770continue ; 771 } 772if (arch == LLM_ARCH_GEMMA4 || arch == LLM_ARCH_GEMMA4_ASSISTANT ) { 773continue ;// FIXME: ISWA KV cache initialization needs more fixture params 774 } 775if (arch == LLM_ARCH_EAGLE3 || arch == LLM_ARCH_DFLASH ) { 776continue ; 777 } 778 779const bool encode = arch == LLM_ARCH_T5 || arch == LLM_ARCH_ALICEAI_T5_MOE || arch == LLM_ARCH_DREAM || arch == LLM_ARCH_LLADA || arch == LLM_ARCH_LLADA_MOE || arch == LLM_ARCH_RND1 ; 780for (bool moe : {false, true}) { 781if (moe && !moe_implemented (arch )) { 782continue ; 783 } 784if (!moe && moe_mandatory (arch )) { 785continue ; 786 } 787const std::string config_name = moe ?"MoE" :"Dense" ; 788gguf_context_ptr gguf_ctx = get_gguf_ctx (arch ,moe ); 789if (arch == LLM_ARCH_BAILINGMOE3 ) { 790GGML_ASSERT (gguf_remove_key (gguf_ctx .get (),"bailingmoe3.kda.safe_gate" ) >=0 ); 791 } 792 std::pair < llama_model_ptr ,llama_context_ptr > model_and_ctx_cpu ; 793 std::vector < float > logits_cpu ; 794for (device_config & dc :dev_configs ) { 795// print test config first; should anything fail during model loading or inference, at least we know which test case caused it 796printf (template_row_cfg .c_str (), 797llm_arch_name (arch ),dc .label .c_str (),config_name .c_str ()); 798fflush (stdout ); 799 800 std::pair < llama_model_ptr ,llama_context_ptr > model_and_ctx_dev ; 801 std::vector < float > logits_dev ; 802 std::string status_nmse = "\033[1;33mSKIP\033[0m" ; 803 std::string status_roundtrip = "\033[1;33mSKIP\033[0m" ; 804char nmse_str [12 ]= {0 }; 805 806bool skip = !arch_supported (arch )|| (dc .split_mode == LLAMA_SPLIT_MODE_TENSOR && dc .devs .empty ()); 807if (!skip ) { 808if (logits_cpu .empty ()) { 809model_and_ctx_cpu = get_model_and_ctx (gguf_ctx .get (),nullptr ,seed , {},LLAMA_SPLIT_MODE_LAYER ,encode ); 810logits_cpu = get_logits (model_and_ctx_cpu .first .get (),model_and_ctx_cpu .second .get (),tokens ,encode ); 811 } 812if (dc .split_mode != LLAMA_SPLIT_MODE_TENSOR || llm_arch_supports_sm_tensor (arch )) { 813model_and_ctx_dev = get_model_and_ctx (gguf_ctx .get (),nullptr ,seed ,dc .devs ,dc .split_mode ,encode ); 814logits_dev = get_logits (model_and_ctx_dev .first .get (),model_and_ctx_dev .second .get (),tokens ,encode ); 815test_encoder_decoder_batches (model_and_ctx_dev .first .get (),model_and_ctx_dev .second .get (),seed ); 816const double nmse_val = nmse (logits_cpu ,logits_dev ); 817snprintf (nmse_str ,sizeof (nmse_str ),"(%.2e)" ,nmse_val ); 818status_nmse = "\033[1;32mOK\033[0m" ; 819if (nmse_val > 1e-4 ) { 820all_ok = false; 821status_nmse = "\033[1;31mFAIL\033[0m" ; 822 } 823 } 824 825FILE * file = tmpfile ();// Can be null on Windows without administrator privileges. 826// FIXME: when adding a tensor to a gguf_context a copy is made, this changes the pointer which the meta backend 827// in turn uses to map the tensors to their simple equivalents - this is fundamentally incompatible 828if (file != nullptr && llama_model_saver_supports_arch (arch )&& dc .split_mode != LLAMA_SPLIT_MODE_TENSOR ) { 829GGML_ASSERT (model_and_ctx_dev .first && model_and_ctx_dev .second ); 830llama_model_saver ms = llama_model_saver (model_and_ctx_dev .first .get ()); 831ms .add_kv_from_model (); 832ms .add_tensors_from_model (); 833ms .save (file ); 834rewind (file ); 835 836auto model_and_ctx_roundtrip = get_model_and_ctx (nullptr ,file ,seed ,dc .devs ,dc .split_mode ,encode ); 837const std::vector < float > logits_roundtrip = get_logits ( 838model_and_ctx_roundtrip .first .get (),model_and_ctx_roundtrip .second .get (),tokens ,encode ); 839status_roundtrip = "\033[1;32mOK\033[0m" ; 840GGML_ASSERT (logits_roundtrip .size ()== logits_dev .size ()); 841for (size_t i = 0 ;i < logits_roundtrip .size ();i ++ ) { 842if (logits_roundtrip [i ]!= logits_dev [i ]) { 843all_ok = false; 844status_roundtrip = "\033[1;31mFAIL\033[0m" ; 845break ; 846 } 847 } 848 } 849 } 850 851// log the results for this test case 852printf (template_row_res .c_str (), 853status_nmse .c_str (),nmse_str ,status_roundtrip .c_str ()); 854 } 855 } 856 } 857llama_log_set (ud .log_old .callback ,ud .log_old .user_data ); 858return all_ok ?0 :1 ; 859} 860 861int main (int argc ,char ** argv ) { 862// init the logger at max verbosity. filter with a custom callback respecting the user-configure verbosity 863common_log_set_verbosity_thold (LOG_LEVEL_DEBUG ); 864common_init (); 865 866 std::random_device rd ; 867 868llm_arch arch = LLM_ARCH_UNKNOWN ; 869size_t seed = rd (); 870 std::string out ; 871 872int verbosity = LOG_LEVEL_ERROR ; 873 874for (int i = 1 ;i < argc ;i ++ ) { 875if (strcmp (argv [i ],"-h" )== 0 || strcmp (argv [i ],"--help" )== 0 ) { 876usage (argv ); 877return 0 ; 878 } 879if (strcmp (argv [i ],"-a" )== 0 || strcmp (argv [i ],"--arch" )== 0 ) { 880if (i + 1 < argc ) { 881const std::string arch_name = argv [++ i ]; 882arch = llm_arch_from_string (arch_name ); 883if (arch == LLM_ARCH_UNKNOWN ) { 884LOG_ERR ("%s: unkown LLM architecture: %s\n" ,__func__ ,arch_name .c_str ()); 885return 1 ; 886 } 887 }else { 888usage (argv ); 889return 1 ; 890 } 891 } 892if (strcmp (argv [i ],"-s" )== 0 || strcmp (argv [i ],"--seed" )== 0 ) { 893if (i + 1 < argc ) { 894seed = std::stoull (argv [++ i ]); 895 }else { 896usage (argv ); 897return 1 ; 898 } 899 } 900if (strcmp (argv [i ],"-v" )== 0 ) { 901if (i + 1 < argc ) { 902verbosity = std::stoull (argv [++ i ]); 903 }else { 904usage (argv ); 905return 1 ; 906 } 907 } 908if (strcmp (argv [i ],"-o" )== 0 || strcmp (argv [i ],"--out" )== 0 ) { 909if (i + 1 < argc ) { 910out = argv [++ i ]; 911 }else { 912usage (argv ); 913return 1 ; 914 } 915 } 916 } 917printf ("%s: using seed %zu\n" ,__func__ ,seed ); 918 919try { 920if (!out .empty ()) { 921return save_models (arch ,seed ,verbosity ,out ); 922 } 923return test_backends (arch ,seed ,verbosity ); 924 }catch (const std::exception & err ) { 925fprintf (stderr ,"encountered runtime error: %s\n" ,err .what ()); 926return -1 ; 927 } 928}