char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
732707dff
char/aliceai-t5-moe
1#include "llama.h" 2 3#include "build-info.h" 4#include "common.h" 5#include "imatrix-loader.h" 6 7#include "gguf.h" 8 9#include <algorithm> 10#include <cctype> 11#include <clocale> 12#include <cmath> 13#include <cstdio> 14#include <cstring> 15#include <vector> 16#include <string> 17#include <unordered_map> 18#include <fstream> 19#include <filesystem> 20 21// result of parsing --tensor-type option 22// changes to this struct must also be reflected in src/llama-quant.cpp 23struct tensor_type_option { 24 std::string name ; 25ggml_type type = GGML_TYPE_COUNT ; 26}; 27 28struct quant_option { 29 std::string name ; 30llama_ftype ftype ; 31 std::string desc ; 32}; 33 34static const std::vector < quant_option > QUANT_OPTIONS = { 35 {"Q1_0" ,LLAMA_FTYPE_MOSTLY_Q1_0 ," 1.125 bpw quantization" , }, 36 {"Q2_0" ,LLAMA_FTYPE_MOSTLY_Q2_0 ," 2.25 bpw quantization (group 64)" , }, 37 {"Q4_0" ,LLAMA_FTYPE_MOSTLY_Q4_0 ," 4.34G, +0.4685 ppl @ Llama-3-8B" , }, 38 {"Q4_1" ,LLAMA_FTYPE_MOSTLY_Q4_1 ," 4.78G, +0.4511 ppl @ Llama-3-8B" , }, 39 {"MXFP4_MOE" ,LLAMA_FTYPE_MOSTLY_MXFP4_MOE ," MXFP4 MoE" , }, 40 {"Q5_0" ,LLAMA_FTYPE_MOSTLY_Q5_0 ," 5.21G, +0.1316 ppl @ Llama-3-8B" , }, 41 {"Q5_1" ,LLAMA_FTYPE_MOSTLY_Q5_1 ," 5.65G, +0.1062 ppl @ Llama-3-8B" , }, 42 {"IQ2_XXS" ,LLAMA_FTYPE_MOSTLY_IQ2_XXS ," 2.06 bpw quantization" , }, 43 {"IQ2_XS" ,LLAMA_FTYPE_MOSTLY_IQ2_XS ," 2.31 bpw quantization" , }, 44 {"IQ2_S" ,LLAMA_FTYPE_MOSTLY_IQ2_S ," 2.5 bpw quantization" , }, 45 {"IQ2_M" ,LLAMA_FTYPE_MOSTLY_IQ2_M ," 2.7 bpw quantization" , }, 46 {"IQ1_S" ,LLAMA_FTYPE_MOSTLY_IQ1_S ," 1.56 bpw quantization" , }, 47 {"IQ1_M" ,LLAMA_FTYPE_MOSTLY_IQ1_M ," 1.75 bpw quantization" , }, 48 {"TQ1_0" ,LLAMA_FTYPE_MOSTLY_TQ1_0 ," 1.69 bpw ternarization" , }, 49 {"TQ2_0" ,LLAMA_FTYPE_MOSTLY_TQ2_0 ," 2.06 bpw ternarization" , }, 50 {"Q2_K" ,LLAMA_FTYPE_MOSTLY_Q2_K ," 2.96G, +3.5199 ppl @ Llama-3-8B" , }, 51 {"Q2_K_S" ,LLAMA_FTYPE_MOSTLY_Q2_K_S ," 2.96G, +3.1836 ppl @ Llama-3-8B" , }, 52 {"IQ3_XXS" ,LLAMA_FTYPE_MOSTLY_IQ3_XXS ," 3.06 bpw quantization" , }, 53 {"IQ3_S" ,LLAMA_FTYPE_MOSTLY_IQ3_S ," 3.44 bpw quantization" , }, 54 {"IQ3_M" ,LLAMA_FTYPE_MOSTLY_IQ3_M ," 3.66 bpw quantization mix" , }, 55 {"Q3_K" ,LLAMA_FTYPE_MOSTLY_Q3_K_M ,"alias for Q3_K_M" }, 56 {"IQ3_XS" ,LLAMA_FTYPE_MOSTLY_IQ3_XS ," 3.3 bpw quantization" , }, 57 {"Q3_K_S" ,LLAMA_FTYPE_MOSTLY_Q3_K_S ," 3.41G, +1.6321 ppl @ Llama-3-8B" , }, 58 {"Q3_K_M" ,LLAMA_FTYPE_MOSTLY_Q3_K_M ," 3.74G, +0.6569 ppl @ Llama-3-8B" , }, 59 {"Q3_K_L" ,LLAMA_FTYPE_MOSTLY_Q3_K_L ," 4.03G, +0.5562 ppl @ Llama-3-8B" , }, 60 {"IQ4_NL" ,LLAMA_FTYPE_MOSTLY_IQ4_NL ," 4.50 bpw non-linear quantization" , }, 61 {"IQ4_XS" ,LLAMA_FTYPE_MOSTLY_IQ4_XS ," 4.25 bpw non-linear quantization" , }, 62 {"Q4_K" ,LLAMA_FTYPE_MOSTLY_Q4_K_M ,"alias for Q4_K_M" , }, 63 {"Q4_K_S" ,LLAMA_FTYPE_MOSTLY_Q4_K_S ," 4.37G, +0.2689 ppl @ Llama-3-8B" , }, 64 {"Q4_K_M" ,LLAMA_FTYPE_MOSTLY_Q4_K_M ," 4.58G, +0.1754 ppl @ Llama-3-8B" , }, 65 {"Q5_K" ,LLAMA_FTYPE_MOSTLY_Q5_K_M ,"alias for Q5_K_M" , }, 66 {"Q5_K_S" ,LLAMA_FTYPE_MOSTLY_Q5_K_S ," 5.21G, +0.1049 ppl @ Llama-3-8B" , }, 67 {"Q5_K_M" ,LLAMA_FTYPE_MOSTLY_Q5_K_M ," 5.33G, +0.0569 ppl @ Llama-3-8B" , }, 68 {"Q6_K" ,LLAMA_FTYPE_MOSTLY_Q6_K ," 6.14G, +0.0217 ppl @ Llama-3-8B" , }, 69 {"Q8_0" ,LLAMA_FTYPE_MOSTLY_Q8_0 ," 7.96G, +0.0026 ppl @ Llama-3-8B" , }, 70 {"F16" ,LLAMA_FTYPE_MOSTLY_F16 ,"14.00G, +0.0020 ppl @ Mistral-7B" , }, 71 {"BF16" ,LLAMA_FTYPE_MOSTLY_BF16 ,"14.00G, -0.0050 ppl @ Mistral-7B" , }, 72 {"F32" ,LLAMA_FTYPE_ALL_F32 ,"26.00G @ 7B" , }, 73// Note: Ensure COPY comes after F32 to avoid ftype 0 from matching. 74 {"COPY" ,LLAMA_FTYPE_ALL_F32 ,"only copy tensors, no quantizing" , }, 75}; 76 77static const char * const LLM_KV_QUANTIZE_IMATRIX_FILE = "quantize.imatrix.file" ; 78static const char * const LLM_KV_QUANTIZE_IMATRIX_DATASET = "quantize.imatrix.dataset" ; 79static const char * const LLM_KV_QUANTIZE_IMATRIX_N_ENTRIES = "quantize.imatrix.entries_count" ; 80static const char * const LLM_KV_QUANTIZE_IMATRIX_N_CHUNKS = "quantize.imatrix.chunks_count" ; 81 82static bool striequals (const char * a ,const char * b ) { 83while (* a && * b ) { 84if (std::tolower (* a )!= std::tolower (* b )) { 85return false; 86 } 87a ++ ;b ++ ; 88 } 89return * a == * b ; 90} 91 92static bool try_parse_ftype (const std::string & ftype_str_in ,llama_ftype & ftype , std::string & ftype_str_out ) { 93 std::string ftype_str ; 94 95for (auto ch :ftype_str_in ) { 96ftype_str .push_back (std::toupper (ch )); 97 } 98for (const auto & it :QUANT_OPTIONS ) { 99if (striequals (it .name .c_str (),ftype_str .c_str ())) { 100ftype = it .ftype ; 101ftype_str_out = it .name ; 102return true; 103 } 104 } 105try { 106int ftype_int = std::stoi (ftype_str ); 107for (const auto & it :QUANT_OPTIONS ) { 108if (it .ftype == ftype_int ) { 109ftype = it .ftype ; 110ftype_str_out = it .name ; 111return true; 112 } 113 } 114 } 115catch (...) { 116// stoi failed 117 } 118return false; 119} 120 121[[noreturn ]] 122static void usage (const char * executable ) { 123printf ("usage: %s [--help] [--allow-requantize] [--leave-output-tensor] [--pure] [--imatrix] [--include-weights]\n" ,executable ); 124printf (" [--exclude-weights] [--output-tensor-type] [--token-embedding-type] [--tensor-type] [--tensor-type-file]\n" ); 125printf (" [--prune-layers] [--keep-split] [--override-kv] [--dry-run] [--max-buffer-size]\n" ); 126printf (" model-f32.gguf [model-quant.gguf] type [nthreads]\n\n" ); 127printf (" --allow-requantize\n" ); 128printf (" allow requantizing tensors that have already been quantized\n" ); 129printf (" WARNING: this can severely reduce quality compared to quantizing\n" ); 130printf (" from 16bit or 32bit!\n" ); 131printf (" --leave-output-tensor\n" ); 132printf (" leave output.weight un(re)quantized\n" ); 133printf (" increases model size but may also increase quality, especially when requantizing\n" ); 134printf (" --pure\n" ); 135printf (" disable k-quant mixtures and quantize all tensors to the same type\n" ); 136printf (" --imatrix file_name\n" ); 137printf (" use data in file_name as importance matrix for quant optimizations\n" ); 138printf (" --include-weights tensor_name\n" ); 139printf (" use importance matrix for this/these tensor(s)\n" ); 140printf (" --exclude-weights tensor_name\n" ); 141printf (" do not use importance matrix for this/these tensor(s)\n" ); 142printf (" --output-tensor-type ggml_type\n" ); 143printf (" use this ggml_type for the output.weight tensor\n" ); 144printf (" --token-embedding-type ggml_type\n" ); 145printf (" use this ggml_type for the token embeddings tensor\n" ); 146printf (" --tensor-type tensor_name=ggml_type\n" ); 147printf (" quantize this tensor to this ggml_type\n" ); 148printf (" this is an advanced option to selectively quantize tensors. may be specified multiple times.\n" ); 149printf (" example: --tensor-type attn_q=q8_0\n" ); 150printf (" --tensor-type-file tensor_types.txt\n" ); 151printf (" list of tensors to quantize to a specific ggml_type\n" ); 152printf (" this is an advanced option to selectively quantize a long list of tensors.\n" ); 153printf (" the file should use the same format as above, separated by spaces or newlines.\n" ); 154printf (" --prune-layers L0,L1,L2...\n" ); 155printf (" comma-separated list of layer numbers to prune from the model\n" ); 156printf (" WARNING: this is an advanced option, use with care.\n" ); 157printf (" --keep-split\n" ); 158printf (" generate quantized model in the same shards as input\n" ); 159printf (" --override-kv KEY=TYPE:VALUE\n" ); 160printf (" override model metadata by key in the quantized model. may be specified multiple times.\n" ); 161printf (" WARNING: this is an advanced option, use with care.\n" ); 162printf (" --dry-run\n" ); 163printf (" calculate and show the final quantization size without performing quantization\n" ); 164printf (" example: llama-quantize --dry-run model-f32.gguf Q4_K\n" ); 165printf (" --max-buffer-size MiB\n" ); 166printf (" max amount of tensor rows kept in memory while quantizing one tensor (default: 8192)\n" ); 167printf (" lower it to quantize models with very large tensors on a machine with little RAM\n\n" ); 168printf ("note: --include-weights and --exclude-weights cannot be used together\n\n" ); 169printf ("-----------------------------------------------------------------------------\n" ); 170printf (" allowed quantization types\n" ); 171printf ("-----------------------------------------------------------------------------\n\n" ); 172for (const auto & it :QUANT_OPTIONS ) { 173if (it .name != "COPY" ) { 174printf (" %2d or " ,it .ftype ); 175 }else { 176printf (" " ); 177 } 178printf ("%-7s : %s\n" ,it .name .c_str (),it .desc .c_str ()); 179 } 180exit (1 ); 181} 182 183static int load_imatrix (const std::string & imatrix_file , std::vector < std::string > & imatrix_datasets , std::unordered_map < std::string , std::vector < float >> & imatrix_data ) { 184common_imatrix loaded ; 185if (!common_imatrix_load (imatrix_file ,loaded )) { 186fprintf (stderr ,"%s: failed to load imatrix from '%s'\n" ,__func__ ,imatrix_file .c_str ()); 187exit (1 ); 188 } 189 190if (!loaded .is_legacy && !loaded .has_metadata ) { 191fprintf (stderr ,"%s: missing imatrix metadata in file %s\n" ,__func__ ,imatrix_file .c_str ()); 192exit (1 ); 193 } 194 195for (const auto & [name ,entry ] :loaded .entries ) { 196auto & e = imatrix_data [name ]; 197e .resize (entry .sums .size ()); 198 199if (!loaded .is_legacy ) { 200// GGUF format: normalize by per-expert counts 201const int64_t ncounts = entry .counts .size (); 202const int64_t ne0 = (int64_t )entry .sums .size () /ncounts ; 203 204for (int64_t j = 0 ;j < ncounts ;++ j ) { 205const float count = (float )entry .counts [j ]; 206if (count > 0.0f ) { 207for (int64_t i = 0 ;i < ne0 ;++ i ) { 208e [j * ne0 + i ]= entry .sums [j * ne0 + i ] /count ; 209 } 210 }else { 211for (int64_t i = 0 ;i < ne0 ;++ i ) { 212e [j * ne0 + i ]= 1 ; 213 } 214 } 215 } 216 217if (getenv ("LLAMA_TRACE" )) { 218float max_count = 0.0f ; 219for (int64_t j = 0 ;j < ncounts ;++ j ) { 220const float count = (float )entry .counts [j ]; 221if (count > max_count ) { 222max_count = count ; 223 } 224 } 225printf ("%s: loaded data (size = %6d, n_tokens = %6d, n_chunks = %6d) for '%s'\n" , 226__func__ ,int (e .size ()),int (max_count ),int (max_count /loaded .chunk_size ),name .c_str ()); 227 } 228 }else { 229// Legacy format: sums contain (raw/count)*ncall, divide by ncall 230const int64_t ncall = entry .counts .empty () ?0 :entry .counts [0 ]; 231if (ncall > 0 ) { 232for (size_t i = 0 ;i < entry .sums .size ();++ i ) { 233e [i ]= entry .sums [i ] /ncall ; 234 } 235 }else { 236for (size_t i = 0 ;i < entry .sums .size ();++ i ) { 237e [i ]= entry .sums [i ]; 238 } 239 } 240 241if (getenv ("LLAMA_TRACE" )) { 242printf ("%s: loaded data (size = %6d, ncall = %6d) for '%s'\n" , 243__func__ ,int (e .size ()),int (ncall ),name .c_str ()); 244 } 245 } 246 } 247 248imatrix_datasets = std::move (loaded .datasets ); 249 250if (!imatrix_datasets .empty ()) { 251printf ("%s: imatrix datasets=['%s'" ,__func__ ,imatrix_datasets [0 ].c_str ()); 252for (size_t i = 1 ;i < imatrix_datasets .size ();++ i ) { 253printf (", '%s'" ,imatrix_datasets [i ].c_str ()); 254 } 255printf ("]\n" ); 256 } 257 258printf ("%s: loaded %d importance matrix entries from %s computed on %d chunks\n" ,__func__ ,int (imatrix_data .size ()),imatrix_file .c_str (),loaded .chunk_count ); 259 260return loaded .chunk_count ; 261} 262 263static int prepare_imatrix (const std::string & imatrix_file , 264 std::vector < std::string > & imatrix_dataset , 265const std::vector < std::string > & included_weights , 266const std::vector < std::string > & excluded_weights , 267 std::unordered_map < std::string , std::vector < float >> & imatrix_data ) { 268int m_last_call = -1 ; 269if (!imatrix_file .empty ()) { 270m_last_call = load_imatrix (imatrix_file ,imatrix_dataset ,imatrix_data ); 271 } 272if (imatrix_data .empty ()) { 273return m_last_call ; 274 } 275if (!excluded_weights .empty ()) { 276for (const auto & name :excluded_weights ) { 277for (auto it = imatrix_data .begin ();it != imatrix_data .end ();) { 278auto pos = it -> first .find (name ); 279if (pos != std::string::npos ) { 280it = imatrix_data .erase (it ); 281 }else { 282++ it ; 283 } 284 } 285 } 286 } 287if (!included_weights .empty ()) { 288 std::unordered_map < std::string , std::vector < float >> tmp ; 289for (const auto & name :included_weights ) { 290for (auto & e :imatrix_data ) { 291auto pos = e .first .find (name ); 292if (pos != std::string::npos ) { 293tmp .emplace (std::move (e )); 294 } 295 } 296 } 297imatrix_data = std::move (tmp ); 298 } 299if (!imatrix_data .empty ()) { 300printf ("%s: have %d importance matrix entries\n" ,__func__ ,int (imatrix_data .size ())); 301 } 302return m_last_call ; 303} 304 305static ggml_type parse_ggml_type (const char * arg ) { 306for (int i = 0 ;i < GGML_TYPE_COUNT ;++ i ) { 307auto type = (ggml_type )i ; 308const auto * name = ggml_type_name (type ); 309if (name && striequals (name ,arg )) { 310return type ; 311 } 312 } 313fprintf (stderr ,"\n%s: invalid ggml_type '%s'\n\n" ,__func__ ,arg ); 314return GGML_TYPE_COUNT ; 315} 316 317static bool parse_tensor_type (const char * data , std::vector < tensor_type_option > & tensor_type ) { 318const char * sep = strchr (data ,'=' ); 319if (sep == nullptr ) { 320printf ("\n%s: malformed tensor type '%s'\n\n" ,__func__ ,data ); 321return false; 322 } 323 324const size_t tn_len = sep - data ; 325if (tn_len == 0 ) { 326printf ("\n%s: missing tensor name\n\n" ,__func__ ); 327return false; 328 } 329if (const size_t qt_len = strlen (sep );qt_len == 1 ) { 330printf ("\n%s: missing quantization type\n\n" ,__func__ ); 331return false; 332 } 333 334 std::string tn (data ,tn_len ); 335 std::transform (tn .begin (),tn .end (),tn .begin (),tolower ); 336sep ++ ; 337tensor_type_option tensor_type_opt ; 338tensor_type_opt .name = tn ; 339tensor_type_opt .type = parse_ggml_type (sep ); 340tensor_type .emplace_back (std::move (tensor_type_opt )); 341if (tensor_type_opt .type == GGML_TYPE_COUNT ) { 342printf ("\n%s: invalid quantization type '%s'\n\n" ,__func__ ,sep ); 343return false; 344 } 345 346return true; 347} 348 349static bool parse_tensor_type_file (const char * filename , std::vector < tensor_type_option > & tensor_type ) { 350 std::ifstream file (filename ); 351if (!file ) { 352printf ("\n%s: failed to open file '%s': %s\n\n" ,__func__ ,filename , std::strerror (errno )); 353return false; 354 } 355 356 std::string arg ; 357while (file >>arg ) { 358if (!parse_tensor_type (arg .c_str (),tensor_type )) { 359return false; 360 } 361 } 362 363return true; 364} 365 366static bool parse_layer_prune (const char * data , std::vector < int > & prune_layers ) { 367if (!data ) { 368printf ("\n%s: no layer pruning ids provided\n\n" ,__func__ ); 369return false; 370 } 371 372const auto block_ids = string_split < std::string > (data ,',' ); 373for (const auto & block_id :block_ids ) { 374int id ; 375try { 376id = std::stoi (block_id ); 377 }catch (...) { 378id = -1 ; 379 } 380if (id < 0 ) { 381printf ("\n%s: invalid layer id '%s'\n\n" ,__func__ ,block_id .c_str ()); 382return false; 383 } 384prune_layers .emplace_back (id ); 385 } 386 387sort (prune_layers .begin (),prune_layers .end ()); 388prune_layers .erase (std::unique (prune_layers .begin (),prune_layers .end ()),prune_layers .end ()); 389return true; 390} 391 392// satisfies -Wmissing-declarations 393int llama_quantize (int argc ,char ** argv ); 394 395int llama_quantize (int argc ,char ** argv ) { 396 std::setlocale (LC_NUMERIC ,"C" ); 397if (argc < 3 ) { 398usage (argv [0 ]); 399 } 400 401llama_model_quantize_params params = llama_model_quantize_default_params (); 402 403int arg_idx = 1 ; 404 std::string imatrix_file ; 405 std::vector < std::string > included_weights ,excluded_weights ; 406 std::vector < llama_model_kv_override > kv_overrides ; 407 std::vector < tensor_type_option > tensor_type_opts ; 408 std::vector < int > prune_layers ; 409 410for (;arg_idx < argc && strncmp (argv [arg_idx ],"--" ,2 )== 0 ;arg_idx ++ ) { 411if (strcmp (argv [arg_idx ],"--leave-output-tensor" )== 0 ) { 412params .quantize_output_tensor = false; 413 }else if (strcmp (argv [arg_idx ],"--output-tensor-type" )== 0 ) { 414if (arg_idx < argc - 1 ) { 415params .output_tensor_type = parse_ggml_type (argv [++ arg_idx ]); 416if (params .output_tensor_type == GGML_TYPE_COUNT ) { 417usage (argv [0 ]); 418 } 419 }else { 420usage (argv [0 ]); 421 } 422 }else if (strcmp (argv [arg_idx ],"--token-embedding-type" )== 0 ) { 423if (arg_idx < argc - 1 ) { 424params .token_embedding_type = parse_ggml_type (argv [++ arg_idx ]); 425if (params .token_embedding_type == GGML_TYPE_COUNT ) { 426usage (argv [0 ]); 427 } 428 }else { 429usage (argv [0 ]); 430 } 431 }else if (strcmp (argv [arg_idx ],"--tensor-type" )== 0 ) { 432if (arg_idx == argc - 1 || !parse_tensor_type (argv [++ arg_idx ],tensor_type_opts )) { 433usage (argv [0 ]); 434 } 435 }else if (strcmp (argv [arg_idx ],"--tensor-type-file" )== 0 ) { 436if (arg_idx == argc - 1 || !parse_tensor_type_file (argv [++ arg_idx ],tensor_type_opts )) { 437usage (argv [0 ]); 438 } 439 }else if (strcmp (argv [arg_idx ],"--prune-layers" )== 0 ) { 440if (arg_idx == argc - 1 || !parse_layer_prune (argv [++ arg_idx ],prune_layers )) { 441usage (argv [0 ]); 442 } 443 }else if (strcmp (argv [arg_idx ],"--override-kv" )== 0 ) { 444if (arg_idx == argc - 1 || !string_parse_kv_override (argv [++ arg_idx ],kv_overrides )) { 445usage (argv [0 ]); 446 } 447 }else if (strcmp (argv [arg_idx ],"--dry-run" )== 0 ) { 448params .dry_run = true; 449 }else if (strcmp (argv [arg_idx ],"--allow-requantize" )== 0 ) { 450params .allow_requantize = true; 451 }else if (strcmp (argv [arg_idx ],"--pure" )== 0 ) { 452params .pure = true; 453 }else if (strcmp (argv [arg_idx ],"--imatrix" )== 0 ) { 454if (arg_idx < argc - 1 ) { 455imatrix_file = argv [++ arg_idx ]; 456 }else { 457usage (argv [0 ]); 458 } 459 }else if (strcmp (argv [arg_idx ],"--include-weights" )== 0 ) { 460if (arg_idx < argc - 1 ) { 461included_weights .emplace_back (argv [++ arg_idx ]); 462 }else { 463usage (argv [0 ]); 464 } 465 }else if (strcmp (argv [arg_idx ],"--exclude-weights" )== 0 ) { 466if (arg_idx < argc - 1 ) { 467excluded_weights .emplace_back (argv [++ arg_idx ]); 468 }else { 469usage (argv [0 ]); 470 } 471 }else if (strcmp (argv [arg_idx ],"--keep-split" )== 0 ) { 472params .keep_split = true; 473 }else if (strcmp (argv [arg_idx ],"--max-buffer-size" )== 0 ) { 474if (arg_idx == argc - 1 ) { 475usage (argv [0 ]); 476 } 477const int mib = atoi (argv [++ arg_idx ]); 478if (mib <=0 ) { 479fprintf (stderr ,"%s: invalid --max-buffer-size '%s'\n" ,__func__ ,argv [arg_idx ]); 480return 1 ; 481 } 482params .max_buf_size = (size_t )mib * 1024 * 1024 ; 483 }else { 484usage (argv [0 ]); 485 } 486 } 487 488if (argc - arg_idx < 2 ) { 489printf ("%s: bad arguments\n" ,argv [0 ]); 490usage (argv [0 ]); 491 } 492if (!included_weights .empty ()&& !excluded_weights .empty ()) { 493usage (argv [0 ]); 494 } 495 496 std::vector < std::string > imatrix_datasets ; 497 std::unordered_map < std::string , std::vector < float >> imatrix_data ; 498int m_last_call = prepare_imatrix (imatrix_file ,imatrix_datasets ,included_weights ,excluded_weights ,imatrix_data ); 499 500 std::vector < llama_model_imatrix_data > i_data ; 501 std::vector < llama_model_tensor_override > t_override ; 502if (!imatrix_data .empty ()) { 503i_data .reserve (imatrix_data .size ()+ 1 ); 504for (const auto & kv :imatrix_data ) { 505i_data .push_back ({kv .first .c_str (),kv .second .data (),kv .second .size ()}); 506 } 507i_data .push_back ({nullptr ,nullptr ,0 });// array terminator 508params .imatrix = i_data .data (); 509 { 510llama_model_kv_override kvo ; 511 std::strcpy (kvo .key ,LLM_KV_QUANTIZE_IMATRIX_FILE ); 512kvo .tag = LLAMA_KV_OVERRIDE_TYPE_STR ; 513strncpy (kvo .val_str ,imatrix_file .c_str (),127 ); 514kvo .val_str [127 ]= '\0' ; 515kv_overrides .emplace_back (std::move (kvo )); 516 } 517if (!imatrix_datasets .empty ()) { 518llama_model_kv_override kvo ; 519// TODO: list multiple datasets when there are more than one 520 std::strcpy (kvo .key ,LLM_KV_QUANTIZE_IMATRIX_DATASET ); 521kvo .tag = LLAMA_KV_OVERRIDE_TYPE_STR ; 522strncpy (kvo .val_str ,imatrix_datasets [0 ].c_str (),127 ); 523kvo .val_str [127 ]= '\0' ; 524kv_overrides .emplace_back (std::move (kvo )); 525 } 526 { 527llama_model_kv_override kvo ; 528 std::strcpy (kvo .key ,LLM_KV_QUANTIZE_IMATRIX_N_ENTRIES ); 529kvo .tag = LLAMA_KV_OVERRIDE_TYPE_INT ; 530kvo .val_i64 = imatrix_data .size (); 531kv_overrides .emplace_back (std::move (kvo )); 532 } 533if (m_last_call > 0 ) { 534llama_model_kv_override kvo ; 535 std::strcpy (kvo .key ,LLM_KV_QUANTIZE_IMATRIX_N_CHUNKS ); 536kvo .tag = LLAMA_KV_OVERRIDE_TYPE_INT ; 537kvo .val_i64 = m_last_call ; 538kv_overrides .emplace_back (std::move (kvo )); 539 } 540 } 541if (!kv_overrides .empty ()) { 542kv_overrides .emplace_back (); 543kv_overrides .back ().key [0 ]= 0 ; 544params .kv_overrides = kv_overrides .data (); 545 } 546if (!tensor_type_opts .empty ()) { 547t_override .reserve (tensor_type_opts .size ()+ 1 ); 548for (const auto & tt :tensor_type_opts ) { 549t_override .push_back ({tt .name .c_str (),tt .type }); 550 } 551t_override .push_back ({nullptr ,GGML_TYPE_COUNT });// array terminator 552params .tt_overrides = t_override .data (); 553 } 554if (!prune_layers .empty ()) { 555prune_layers .push_back (-1 );// array terminator 556params .prune_layers = prune_layers .data (); 557 } 558 559llama_backend_init (); 560 561// parse command line arguments 562const std::string fname_inp = argv [arg_idx ]; 563arg_idx ++ ; 564 std::string fname_out ; 565 566 std::string ftype_str ; 567 std::string suffix = ".gguf" ; 568if (try_parse_ftype (argv [arg_idx ],params .ftype ,ftype_str )) { 569// argv[arg_idx] is the ftype directly: <input> <ftype> 570if (!params .dry_run ) { 571 std::string fpath ; 572const size_t pos = fname_inp .find_last_of ("/\\" ); 573if (pos != std::string::npos ) { 574fpath = fname_inp .substr (0 ,pos + 1 ); 575 } 576 577// export as [inp path]/ggml-model-[ftype]. Only add extension if there is no splitting 578fname_out = fpath + "ggml-model-" + ftype_str ; 579if (!params .keep_split ) { 580fname_out += suffix ; 581 } 582 } 583arg_idx ++ ; 584if (ftype_str == "COPY" ) { 585params .only_copy = true; 586 } 587 }else { 588// argv[arg_idx] is not a valid ftype, so treat it as output path: <input> <output> <ftype> 589fname_out = argv [arg_idx ]; 590if (params .keep_split && fname_out .find (suffix )!= std::string::npos ) { 591fname_out = fname_out .substr (0 ,fname_out .length ()- suffix .length ()); 592 } 593arg_idx ++ ; 594 595if (argc <=arg_idx ) { 596fprintf (stderr ,"%s: missing ftype\n" ,__func__ ); 597return 1 ; 598 } 599if (!try_parse_ftype (argv [arg_idx ],params .ftype ,ftype_str )) { 600fprintf (stderr ,"%s: invalid ftype '%s'\n" ,__func__ ,argv [arg_idx ]); 601return 1 ; 602 } 603if (ftype_str == "COPY" ) { 604params .only_copy = true; 605 } 606arg_idx ++ ; 607 } 608 609// parse nthreads 610if (argc > arg_idx ) { 611try { 612params .nthread = std::stoi (argv [arg_idx ]); 613 } 614catch (const std::exception & e ) { 615fprintf (stderr ,"%s: invalid nthread '%s' (%s)\n" ,__func__ ,argv [arg_idx ],e .what ()); 616return 1 ; 617 } 618 } 619 620if (!params .dry_run ) { 621if (std::error_code ec ; std::filesystem::equivalent (fname_inp ,fname_out ,ec )) { 622fprintf (stderr ,"%s: error: input and output files are the same: '%s'\n" ,__func__ ,fname_inp .c_str ()); 623return 1 ; 624 } 625 } 626 627llama_print_build_info (llama_version ()); 628 629if (params .dry_run ) { 630fprintf (stderr ,"%s: calculating quantization size for '%s' as %s" ,__func__ ,fname_inp .c_str (),ftype_str .c_str ()); 631 }else { 632fprintf (stderr ,"%s: quantizing '%s' to '%s' as %s" ,__func__ ,fname_inp .c_str (),fname_out .c_str (),ftype_str .c_str ()); 633 } 634 635if (params .nthread > 0 ) { 636fprintf (stderr ," using %d threads" ,params .nthread ); 637 } 638fprintf (stderr ,"\n" ); 639 640const int64_t t_main_start_us = llama_time_us (); 641 642int64_t t_quantize_us = 0 ; 643 644// load the model 645 { 646const int64_t t_start_us = llama_time_us (); 647 648if (llama_model_quantize (fname_inp .c_str (),fname_out .c_str (),& params )) { 649fprintf (stderr ,"%s: failed to quantize model from '%s'\n" ,__func__ ,fname_inp .c_str ()); 650return 1 ; 651 } 652 653t_quantize_us = llama_time_us ()- t_start_us ; 654 } 655 656// report timing 657 { 658const int64_t t_main_end_us = llama_time_us (); 659 660printf ("\n" ); 661printf ("%s: quantize time = %8.2f ms\n" ,__func__ ,t_quantize_us /1000.0 ); 662printf ("%s: total time = %8.2f ms\n" ,__func__ , (t_main_end_us - t_main_start_us )/1000.0 ); 663 } 664 665llama_backend_free (); 666 667return 0 ; 668}