char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
8300f1411
char/aliceai-t5-moe
1#include "ggml.h" 2#include "gguf.h" 3 4#include "build-info.h" 5#include "common.h" 6#include "fit.h" 7#include "log.h" 8#include "llama.h" 9#include "sampling.h" 10#include "speculative.h" 11#include "unicode.h" 12 13#include <algorithm> 14#include <cinttypes> 15#include <climits> 16#include <cmath> 17#include <chrono> 18#include <cstdarg> 19#include <cstring> 20#include <ctime> 21#include <filesystem> 22#include <fstream> 23#include <iostream> 24#include <iterator> 25#include <regex> 26#include <sstream> 27#include <string> 28#include <thread> 29#include <unordered_set> 30#include <vector> 31 32#if defined(__APPLE__ )&& defined(__MACH__ ) 33#include <sys/types.h> 34#include <sys/sysctl.h> 35#endif 36 37#if defined(_WIN32 ) 38#define WIN32_LEAN_AND_MEAN 39#ifndef NOMINMAX 40# define NOMINMAX 41#endif 42#include <locale> 43#include <windows.h> 44#include <string.h> 45#include <fcntl.h> 46#include <io.h> 47#else 48#include <sys/ioctl.h> 49#include <sys/stat.h> 50#include <unistd.h> 51#endif 52 53#if defined(__linux__ ) 54#include <sys/types.h> 55#include <pwd.h> 56#endif 57 58#if defined(_AIX ) 59#include <sys/systemcfg.h> 60#endif 61 62#if defined(_MSC_VER ) 63#pragma warning(disable: 4244 4267) // possible loss of data 64#endif 65 66common_time_meas::common_time_meas (int64_t & t_acc ,bool disable ) :t_start_us (disable ?-1 :ggml_time_us ()),t_acc (t_acc ) {} 67 68common_time_meas::~common_time_meas () { 69if (t_start_us >=0 ) { 70t_acc += ggml_time_us ()- t_start_us ; 71 } 72} 73 74// 75// CPU utils 76// 77 78int32_t common_cpu_get_num_physical_cores () { 79#if defined(_AIX ) 80int32_t logical_cpus = _system_configuration .ncpus ; 81int32_t smt_threads = _system_configuration .smt_threads ; 82if (smt_threads > 0 ) { 83return static_cast < int32_t > (logical_cpus /smt_threads ); 84 } 85if (logical_cpus > 0 ) { 86return static_cast < int32_t > (logical_cpus ); 87 } 88#elif defined(__linux__ ) 89// enumerate the set of thread siblings, num entries is num cores 90 std::unordered_set < std::string > siblings ; 91for (uint32_t cpu = 0 ;cpu < UINT32_MAX ;++ cpu ) { 92 std::ifstream thread_siblings ("/sys/devices/system/cpu/cpu" 93+ std::to_string (cpu )+ "/topology/thread_siblings" ); 94if (!thread_siblings .is_open ()) { 95break ;// no more cpus 96 } 97 std::string line ; 98if (std::getline (thread_siblings ,line )) { 99siblings .insert (line ); 100 } 101 } 102if (!siblings .empty ()) { 103return static_cast < int32_t > (siblings .size ()); 104 } 105#elif defined(__APPLE__ )&& defined(__MACH__ ) 106int32_t num_physical_cores ; 107size_t len = sizeof (num_physical_cores ); 108int result = sysctlbyname ("hw.perflevel0.physicalcpu" ,& num_physical_cores ,& len ,NULL ,0 ); 109if (result == 0 ) { 110return num_physical_cores ; 111 } 112result = sysctlbyname ("hw.physicalcpu" ,& num_physical_cores ,& len ,NULL ,0 ); 113if (result == 0 ) { 114return num_physical_cores ; 115 } 116#elif defined(_WIN32 )&& (_WIN32_WINNT >=0x0601 )&& !defined(__MINGW64__ )// windows 7 and later 117// TODO: windows + arm64 + mingw64 118unsigned int n_threads_win = std::thread::hardware_concurrency (); 119unsigned int default_threads = n_threads_win > 0 ? (n_threads_win <=4 ?n_threads_win :n_threads_win /2 ) :4 ; 120 121DWORD buffer_size = 0 ; 122if (!GetLogicalProcessorInformationEx (RelationProcessorCore ,nullptr ,& buffer_size )) { 123if (GetLastError ()!= ERROR_INSUFFICIENT_BUFFER ) { 124return default_threads ; 125 } 126 } 127 128 std::vector < char > buffer (buffer_size ); 129if (!GetLogicalProcessorInformationEx (RelationProcessorCore ,reinterpret_cast < PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX > (buffer .data ()),& buffer_size )) { 130return default_threads ; 131 } 132 133int32_t num_physical_cores = 0 ; 134PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX info = reinterpret_cast < PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX > (buffer .data ()); 135while (buffer_size > 0 ) { 136if (info -> Relationship == RelationProcessorCore ) { 137num_physical_cores += info -> Processor .GroupCount ; 138 } 139buffer_size -= info -> Size ; 140info = reinterpret_cast < PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX > (reinterpret_cast < char *> (info )+ info -> Size ); 141 } 142 143return num_physical_cores > 0 ?num_physical_cores :default_threads ; 144#endif 145unsigned int n_threads = std::thread::hardware_concurrency (); 146return n_threads > 0 ? (n_threads <=4 ?n_threads :n_threads /2 ) :4 ; 147} 148 149#if defined(__x86_64__ )&& defined(__linux__ )&& !defined(__ANDROID__ ) 150#include <pthread.h> 151 152static void cpuid (unsigned leaf ,unsigned subleaf , 153unsigned * eax ,unsigned * ebx ,unsigned * ecx ,unsigned * edx ) { 154 __asm__("movq\t%%rbx,%%rsi\n\t" 155"cpuid\n\t" 156"xchgq\t%%rbx,%%rsi" 157 :"=a" (* eax ),"=S" (* ebx ),"=c" (* ecx ),"=d" (* edx ) 158 :"0" (leaf ),"2" (subleaf )); 159} 160 161static int pin_cpu (int cpu ) { 162cpu_set_t mask ; 163CPU_ZERO (& mask ); 164CPU_SET (cpu ,& mask ); 165return pthread_setaffinity_np (pthread_self (),sizeof (mask ),& mask ); 166} 167 168static bool is_hybrid_cpu (void ) { 169unsigned eax ,ebx ,ecx ,edx ; 170cpuid (7 ,0 ,& eax ,& ebx ,& ecx ,& edx ); 171return !!(edx & (1u <<15 )); 172} 173 174static bool is_running_on_efficiency_core (void ) { 175unsigned eax ,ebx ,ecx ,edx ; 176cpuid (0x1a ,0 ,& eax ,& ebx ,& ecx ,& edx ); 177int intel_atom = 0x20 ; 178int core_type = (eax & 0xff000000u ) >>24 ; 179return core_type == intel_atom ; 180} 181 182static int cpu_count_math_cpus (int n_cpu ) { 183int result = 0 ; 184for (int cpu = 0 ;cpu < n_cpu ;++ cpu ) { 185if (pin_cpu (cpu )) { 186return -1 ; 187 } 188if (is_running_on_efficiency_core ()) { 189continue ;// efficiency cores harm lockstep threading 190 } 191++ cpu ;// hyperthreading isn't useful for linear algebra 192++ result ; 193 } 194return result ; 195} 196 197#endif // __x86_64__ && __linux__ 198 199/** 200* Returns number of CPUs on system that are useful for math. 201*/ 202int32_t common_cpu_get_num_math () { 203#if defined(__x86_64__ )&& defined(__linux__ )&& !defined(__ANDROID__ ) 204int n_cpu = sysconf (_SC_NPROCESSORS_ONLN ); 205if (n_cpu < 1 ) { 206return common_cpu_get_num_physical_cores (); 207 } 208if (is_hybrid_cpu ()) { 209cpu_set_t affinity ; 210if (!pthread_getaffinity_np (pthread_self (),sizeof (affinity ),& affinity )) { 211int result = cpu_count_math_cpus (n_cpu ); 212pthread_setaffinity_np (pthread_self (),sizeof (affinity ),& affinity ); 213if (result > 0 ) { 214return result ; 215 } 216 } 217 } 218#elif defined(__powerpc64__ )|| defined(__powerpc__ ) 219int32_t smt_factor = 1 ; 220int phy_cpus = common_cpu_get_num_physical_cores (); 221int logical_cpus = sysconf (_SC_NPROCESSORS_ONLN ); 222if (phy_cpus > 0 && logical_cpus > phy_cpus ) { 223smt_factor = logical_cpus /phy_cpus ; 224 } 225return phy_cpus * std::min (smt_factor ,2 ); 226#endif 227return common_cpu_get_num_physical_cores (); 228} 229 230// Helper for setting process priority 231 232#if defined(_WIN32 ) 233 234bool set_process_priority (enum ggml_sched_priority prio ) { 235if (prio == GGML_SCHED_PRIO_NORMAL ) { 236return true; 237 } 238 239DWORD p = NORMAL_PRIORITY_CLASS ; 240switch (prio ) { 241case GGML_SCHED_PRIO_LOW :p = BELOW_NORMAL_PRIORITY_CLASS ;break ; 242case GGML_SCHED_PRIO_NORMAL :p = NORMAL_PRIORITY_CLASS ;break ; 243case GGML_SCHED_PRIO_MEDIUM :p = ABOVE_NORMAL_PRIORITY_CLASS ;break ; 244case GGML_SCHED_PRIO_HIGH :p = HIGH_PRIORITY_CLASS ;break ; 245case GGML_SCHED_PRIO_REALTIME :p = REALTIME_PRIORITY_CLASS ;break ; 246 } 247 248if (!SetPriorityClass (GetCurrentProcess (),p )) { 249COM_WRN ("failed to set process priority class %d : (%d)\n" ,prio , (int )GetLastError ()); 250return false; 251 } 252 253return true; 254} 255 256#else // MacOS and POSIX 257#include <sys/types.h> 258#include <sys/resource.h> 259 260bool set_process_priority (enum ggml_sched_priority prio ) { 261if (prio == GGML_SCHED_PRIO_NORMAL ) { 262return true; 263 } 264 265int p = 0 ; 266switch (prio ) { 267case GGML_SCHED_PRIO_LOW :p = 5 ;break ; 268case GGML_SCHED_PRIO_NORMAL :p = 0 ;break ; 269case GGML_SCHED_PRIO_MEDIUM :p = -5 ;break ; 270case GGML_SCHED_PRIO_HIGH :p = -10 ;break ; 271case GGML_SCHED_PRIO_REALTIME :p = -20 ;break ; 272 } 273 274if (setpriority (PRIO_PROCESS ,0 ,p )!= 0 ) { 275COM_WRN ("failed to set process priority %d : %s (%d)\n" ,prio ,strerror (errno ),errno ); 276return false; 277 } 278return true; 279} 280 281#endif 282 283// 284// CLI argument parsing 285// 286 287 288void postprocess_cpu_params (common_cpu_params & cpuparams ,const common_cpu_params * role_model ) { 289int32_t n_set = 0 ; 290 291if (cpuparams .n_threads < 0 ) { 292// Assuming everything about cpuparams is invalid 293if (role_model != nullptr ) { 294cpuparams = * role_model ; 295 }else { 296cpuparams .n_threads = common_cpu_get_num_math (); 297 } 298 } 299 300for (int32_t i = 0 ;i < GGML_MAX_N_THREADS ;i ++ ) { 301if (cpuparams .cpumask [i ]) { 302n_set ++ ; 303 } 304 } 305 306if (n_set && n_set < cpuparams .n_threads ) { 307// Not enough set bits, may experience performance issues. 308COM_WRN ("Not enough set bits in CPU mask (%d) to satisfy requested thread count: %d\n" ,n_set ,cpuparams .n_threads ); 309 } 310} 311 312bool parse_cpu_range (const std::string & range ,bool (& boolmask )[GGML_MAX_N_THREADS ]) { 313size_t dash_loc = range .find ('-' ); 314if (dash_loc == std::string::npos ) { 315COM_ERR ("%s" ,"Format of CPU range is invalid! Expected [<start>]-[<end>].\n" ); 316return false; 317 } 318 319size_t start_i ; 320size_t end_i ; 321 322if (dash_loc == 0 ) { 323start_i = 0 ; 324 }else { 325start_i = std::stoull (range .substr (0 ,dash_loc )); 326if (start_i >=GGML_MAX_N_THREADS ) { 327COM_ERR ("%s" ,"Start index out of bounds!\n" ); 328return false; 329 } 330 } 331 332if (dash_loc == range .length ()- 1 ) { 333end_i = GGML_MAX_N_THREADS - 1 ; 334 }else { 335end_i = std::stoull (range .substr (dash_loc + 1 )); 336if (end_i >=GGML_MAX_N_THREADS ) { 337COM_ERR ("%s" ,"End index out of bounds!\n" ); 338return false; 339 } 340 } 341 342for (size_t i = start_i ;i <=end_i ;i ++ ) { 343boolmask [i ]= true; 344 } 345 346return true; 347} 348 349bool parse_cpu_mask (const std::string & mask ,bool (& boolmask )[GGML_MAX_N_THREADS ]) { 350// Discard potential 0x prefix 351size_t start_i = 0 ; 352if (mask .length () >=2 && mask .substr (0 ,2 )== "0x" ) { 353start_i = 2 ; 354 } 355 356size_t num_digits = mask .length ()- start_i ; 357num_digits = std::min < size_t > (num_digits ,128 ); 358 359size_t end_i = num_digits + start_i ; 360 361for (size_t i = start_i ,n = (num_digits * 4 - 1 );i < end_i ;i ++ ,n -= 4 ) { 362char c = mask .at (i ); 363int8_t id = c ; 364 365if ((c >='0' && c <='9' )) { 366id -= '0' ; 367 }else if (c >='a' && c <='f' ) { 368id -= 'a' - 10 ; 369 }else if (c >='A' && c <='F' ) { 370id -= 'A' - 10 ; 371 }else { 372COM_ERR ("Invalid hex character '%c' at position %d\n" ,c ,int32_t (i )); 373return false; 374 } 375 376boolmask [n ]= boolmask [n ]|| ((id & 8 )!= 0 ); 377boolmask [n - 1 ]= boolmask [n - 1 ]|| ((id & 4 )!= 0 ); 378boolmask [n - 2 ]= boolmask [n - 2 ]|| ((id & 2 )!= 0 ); 379boolmask [n - 3 ]= boolmask [n - 3 ]|| ((id & 1 )!= 0 ); 380 } 381 382return true; 383} 384 385void common_init () { 386#if defined(_WIN32 ) 387SetConsoleOutputCP (CP_UTF8 ); 388SetConsoleCP (CP_UTF8 ); 389#endif 390 391common_log_set_prefix (common_log_main (), true); 392common_log_set_timestamps (common_log_main (), true); 393 394llama_log_set (common_log_default_callback ,NULL ); 395} 396 397void common_params_print_info (const common_params & params ,bool print_devices ) { 398#ifdef NDEBUG 399const char * build_type = "" ; 400#else 401const char * build_type = " (debug)" ; 402#endif 403COM_TRC ("%s: build %d (%s) with %s for %s%s\n" ,__func__ ,llama_build_number (),llama_commit (),llama_compiler (),llama_build_target (),build_type ); 404 405const int verbosity = common_log_get_verbosity_thold (); 406COM_INF ("%s: verbosity = %d (adjust with the `-lv N` CLI arg)\n" ,__func__ ,verbosity ); 407 408// device enumeration creates a primary context on CUDA backends, skip it when the caller does not own any device 409if (print_devices && verbosity >=LOG_LEVEL_TRACE ) { 410COM_TRC ("%s" ,"device_info:\n" ); 411for (size_t i = 0 ;i < ggml_backend_dev_count ();++ i ) { 412auto * dev = ggml_backend_dev_get (i ); 413size_t free ,total ; 414ggml_backend_dev_memory (dev ,& free ,& total ); 415COM_TRC (" - %-8s: %s (%zu MiB, %zu MiB free)\n" ,ggml_backend_dev_name (dev ),ggml_backend_dev_description (dev ),total /1024 /1024 ,free /1024 /1024 ); 416 } 417 } 418COM_TRC ("%s\n" ,common_params_get_system_info (params ).c_str ()); 419} 420 421std::string common_params_get_system_info (const common_params & params ) { 422 std::ostringstream os ; 423 424os <<"system_info: n_threads = " <<params .cpuparams .n_threads ; 425if (params .cpuparams_batch .n_threads != -1 ) { 426os <<" (n_threads_batch = " <<params .cpuparams_batch .n_threads <<")" ; 427 } 428#if defined(_WIN32 )&& (_WIN32_WINNT >=0x0601 )&& !defined(__MINGW64__ )// windows 7 and later 429// TODO: windows + arm64 + mingw64 430DWORD logicalProcessorCount = GetActiveProcessorCount (ALL_PROCESSOR_GROUPS ); 431os <<" / " <<logicalProcessorCount <<" | " <<llama_print_system_info (); 432#else 433os <<" / " << std::thread::hardware_concurrency () <<" | " <<llama_print_system_info (); 434#endif 435 436return os .str (); 437} 438 439// 440// String utils 441// 442 443std::string string_format (const char * fmt , ...) { 444va_list ap ; 445va_list ap2 ; 446va_start (ap ,fmt ); 447va_copy (ap2 ,ap ); 448int size = vsnprintf (NULL ,0 ,fmt ,ap ); 449GGML_ASSERT (size >=0 && size < INT_MAX );// NOLINT 450 std::vector < char > buf (size + 1 ); 451int size2 = vsnprintf (buf .data (),size + 1 ,fmt ,ap2 ); 452GGML_ASSERT (size2 == size ); 453va_end (ap2 ); 454va_end (ap ); 455return std::string (buf .data (),size ); 456} 457 458std::string string_strip (const std::string & str ) { 459size_t start = 0 ; 460size_t end = str .size (); 461while (start < end && std::isspace (str [start ])) { 462start ++ ; 463 } 464while (end > start && std::isspace (str [end - 1 ])) { 465end -- ; 466 } 467return str .substr (start ,end - start ); 468} 469 470std::string string_lcs (std::string_view a , std::string_view b ) { 471if (a .empty ()|| b .empty ())return {}; 472 473 std::vector < std::vector < size_t >> dp (a .size ()+ 1 , std::vector < size_t > (b .size ()+ 1 ,0 )); 474size_t best_len = 0 ; 475size_t best_end_a = 0 ; 476 477for (size_t i = 1 ;i <=a .size ();++ i ) { 478for (size_t j = 1 ;j <=b .size ();++ j ) { 479if (a [i - 1 ]== b [j - 1 ]) { 480dp [i ][j ]= dp [i - 1 ][j - 1 ]+ 1 ; 481if (dp [i ][j ]> best_len ) { 482best_len = dp [i ][j ]; 483best_end_a = i ; 484 } 485 } 486 } 487 } 488return std::string (a .substr (best_end_a - best_len ,best_len )); 489} 490 491std::string string_get_sortable_timestamp () { 492using clock = std::chrono::system_clock ; 493 494const clock::time_point current_time = clock::now (); 495const time_t as_time_t = clock::to_time_t (current_time ); 496char timestamp_no_ns [100 ]; 497 std::strftime (timestamp_no_ns ,100 ,"%Y_%m_%d-%H_%M_%S" , std::localtime (& as_time_t )); 498 499const int64_t ns = std::chrono::duration_cast < std::chrono::nanoseconds > ( 500current_time .time_since_epoch () %1000000000 ).count (); 501char timestamp_ns [11 ]; 502snprintf (timestamp_ns ,11 ,"%09" PRId64 ,ns ); 503 504return std::string (timestamp_no_ns )+ "." + std::string (timestamp_ns ); 505} 506 507void string_replace_all (std::string & s ,const std::string & search ,const std::string & replace ) { 508if (search .empty ()) { 509return ; 510 } 511 std::string builder ; 512builder .reserve (s .length ()); 513size_t pos = 0 ; 514size_t last_pos = 0 ; 515while ((pos = s .find (search ,last_pos ))!= std::string::npos ) { 516builder .append (s ,last_pos ,pos - last_pos ); 517builder .append (replace ); 518last_pos = pos + search .length (); 519 } 520builder .append (s ,last_pos , std::string::npos ); 521s = std::move (builder ); 522} 523 524std::string regex_escape (const std::string & s ) { 525static const std::regex special_chars ("[.^$|()*+?\\[\\]{}\\\\]" ); 526return std::regex_replace (s ,special_chars ,"\\$&" ); 527} 528 529std::string string_join (const std::vector < std::string > & values ,const std::string & separator ) { 530 std::ostringstream result ; 531for (size_t i = 0 ;i < values .size ();++ i ) { 532if (i > 0 ) { 533result <<separator ; 534 } 535result <<values [i ]; 536 } 537return result .str (); 538} 539 540std::vector < std::string > string_split (const std::string & str ,const std::string & delimiter ) { 541 std::vector < std::string > parts ; 542size_t start = 0 ; 543size_t end = str .find (delimiter ); 544 545while (end != std::string::npos ) { 546parts .push_back (str .substr (start ,end - start )); 547start = end + delimiter .length (); 548end = str .find (delimiter ,start ); 549 } 550 551parts .push_back (str .substr (start )); 552 553return parts ; 554} 555 556std::string string_repeat (const std::string & str ,size_t n ) { 557if (n == 0 ) { 558return "" ; 559 } 560 561 std::string result ; 562result .reserve (str .length ()* n ); 563 564for (size_t i = 0 ;i < n ;++ i ) { 565result += str ; 566 } 567 568return result ; 569} 570 571std::string string_from (bool value ) { 572return value ?"true" :"false" ; 573} 574 575std::string string_from (const std::vector < int > & values ) { 576 std::stringstream buf ; 577 578buf <<"[ " ; 579bool first = true; 580for (auto e :values ) { 581if (first ) { 582first = false; 583 }else { 584buf <<", " ; 585 } 586buf << std::to_string (e ); 587 } 588buf <<" ]" ; 589 590return buf .str (); 591} 592 593std::string string_from (const struct llama_context * ctx ,const std::vector < llama_token > & tokens ) { 594 std::stringstream buf ; 595 596buf <<"[ " ; 597 598bool first = true; 599for (const auto & token :tokens ) { 600if (!first ) { 601buf <<", " ; 602 }else { 603first = false; 604 } 605 606auto detokenized = common_token_to_piece (ctx ,token ); 607 608buf <<"'" <<detokenized <<"'" 609 <<":" << std::to_string (token ); 610 } 611 612buf <<" ]" ; 613 614return buf .str (); 615} 616 617std::string string_from (const struct llama_context * ctx ,const struct llama_batch & batch ) { 618 std::stringstream buf ; 619 620buf <<"[ " ; 621 622bool first = true; 623for (int i = 0 ;i < batch .n_tokens ;++ i ) { 624if (!first ) { 625buf <<", " ; 626 }else { 627first = false; 628 } 629 630auto detokenized = common_token_to_piece (ctx ,batch .token [i ]); 631 632buf <<"\n" << std::to_string (i ) 633 <<", token '" <<detokenized <<"'" 634 <<", pos " << std::to_string (batch .pos [i ]) 635 <<", n_seq_id " << std::to_string (batch .n_seq_id [i ]) 636 <<", seq_id " << std::to_string (batch .seq_id [i ][0 ]) 637 <<", logits " << std::to_string (batch .logits [i ]); 638 } 639 640buf <<" ]" ; 641 642return buf .str (); 643} 644 645void string_process_escapes (std::string & input ) { 646 std::size_t input_len = input .length (); 647 std::size_t output_idx = 0 ; 648 649for (std::size_t input_idx = 0 ;input_idx < input_len ;++ input_idx ) { 650if (input [input_idx ]== '\\' && input_idx + 1 < input_len ) { 651switch (input [++ input_idx ]) { 652case 'n' :input [output_idx ++ ]= '\n' ;break ; 653case 'r' :input [output_idx ++ ]= '\r' ;break ; 654case 't' :input [output_idx ++ ]= '\t' ;break ; 655case '\'' :input [output_idx ++ ]= '\'' ;break ; 656case '\"' :input [output_idx ++ ]= '\"' ;break ; 657case '\\' :input [output_idx ++ ]= '\\' ;break ; 658case 'x' : 659// Handle \x12, etc 660if (input_idx + 2 < input_len ) { 661const char x [3 ]= {input [input_idx + 1 ],input [input_idx + 2 ],0 }; 662char * err_p = nullptr ; 663const long val = std::strtol (x ,& err_p ,16 ); 664if (err_p == x + 2 ) { 665input_idx += 2 ; 666input [output_idx ++ ]= char (val ); 667break ; 668 } 669 } 670// fall through 671default :input [output_idx ++ ]= '\\' ; 672input [output_idx ++ ]= input [input_idx ];break ; 673 } 674 }else { 675input [output_idx ++ ]= input [input_idx ]; 676 } 677 } 678 679input .resize (output_idx ); 680} 681 682bool string_parse_kv_override (const char * data , std::vector < llama_model_kv_override > & overrides ) { 683const char * sep = strchr (data ,'=' ); 684if (sep == nullptr || sep - data >=128 ) { 685COM_ERR ("%s: malformed KV override '%s'\n" ,__func__ ,data ); 686return false; 687 } 688llama_model_kv_override kvo ; 689 std::strncpy (kvo .key ,data ,sep - data ); 690kvo .key [sep - data ]= 0 ; 691sep ++ ; 692if (strncmp (sep ,"int:" ,4 )== 0 ) { 693sep += 4 ; 694kvo .tag = LLAMA_KV_OVERRIDE_TYPE_INT ; 695kvo .val_i64 = std::atol (sep ); 696 }else if (strncmp (sep ,"float:" ,6 )== 0 ) { 697sep += 6 ; 698kvo .tag = LLAMA_KV_OVERRIDE_TYPE_FLOAT ; 699kvo .val_f64 = std::atof (sep ); 700 }else if (strncmp (sep ,"bool:" ,5 )== 0 ) { 701sep += 5 ; 702kvo .tag = LLAMA_KV_OVERRIDE_TYPE_BOOL ; 703if (std::strcmp (sep ,"true" )== 0 ) { 704kvo .val_bool = true; 705 }else if (std::strcmp (sep ,"false" )== 0 ) { 706kvo .val_bool = false; 707 }else { 708COM_ERR ("%s: invalid boolean value for KV override '%s'\n" ,__func__ ,data ); 709return false; 710 } 711 }else if (strncmp (sep ,"str:" ,4 )== 0 ) { 712sep += 4 ; 713kvo .tag = LLAMA_KV_OVERRIDE_TYPE_STR ; 714if (strlen (sep )> 127 ) { 715COM_ERR ("%s: malformed KV override '%s', value cannot exceed 127 chars\n" ,__func__ ,data ); 716return false; 717 } 718strncpy (kvo .val_str ,sep ,127 ); 719kvo .val_str [127 ]= '\0' ; 720 }else { 721COM_ERR ("%s: invalid type for KV override '%s'\n" ,__func__ ,data ); 722return false; 723 } 724overrides .emplace_back (std::move (kvo )); 725return true; 726} 727 728static inline bool glob_class_match (const char c ,const char * pattern ,const char * class_end ) { 729const char * class_start = pattern ; 730bool negated = false; 731 732if (* class_start == '!' ) { 733negated = true; 734class_start ++ ; 735 } 736 737// If first character after negation is ']' or '-', treat it as literal 738if (* class_start == ']' || * class_start == '-' ) { 739if (class_start < class_end && * class_start == c ) { 740return !negated ; 741 } 742class_start ++ ; 743 } 744 745bool matched = false; 746 747while (class_start < class_end ) { 748if (class_start + 2 < class_end && class_start [1 ]== '-' && class_start [2 ]!= ']' ) { 749char start_char = * class_start ; 750char end_char = class_start [2 ]; 751if (c >=start_char && c <=end_char ) { 752matched = true; 753break ; 754 } 755class_start += 3 ; 756 }else { 757if (* class_start == c ) { 758matched = true; 759break ; 760 } 761class_start ++ ; 762 } 763 } 764 765return negated ? !matched :matched ; 766} 767 768// simple glob: * matches non-/ chars, ** matches anything including /, [] matches character class 769static inline bool glob_match (const char * pattern ,const char * str ) { 770if (* pattern == '\0' ) { 771return * str == '\0' ; 772 } 773if (pattern [0 ]== '*' && pattern [1 ]== '*' ) { 774const char * p = pattern + 2 ; 775if (glob_match (p ,str ))return true; 776if (* str != '\0' )return glob_match (pattern ,str + 1 ); 777return false; 778 } 779if (* pattern == '*' ) { 780const char * p = pattern + 1 ; 781for (;* str != '\0' && * str != '/' ;str ++ ) { 782if (glob_match (p ,str ))return true; 783 } 784return glob_match (p ,str ); 785 } 786if (* pattern == '?' && * str != '\0' && * str != '/' ) { 787return glob_match (pattern + 1 ,str + 1 ); 788 } 789if (* pattern == '[' ) { 790const char * class_end = pattern + 1 ; 791// If first character after '[' is ']' or '-', treat it as literal 792if (* class_end == ']' || * class_end == '-' ) { 793class_end ++ ; 794 } 795while (* class_end != '\0' && * class_end != ']' ) { 796class_end ++ ; 797 } 798if (* class_end == ']' ) { 799if (* str == '\0' )return false; 800bool matched = glob_class_match (* str ,pattern + 1 ,class_end ); 801return matched && glob_match (class_end + 1 ,str + 1 ); 802 }else { 803if (* str == '[' ) { 804return glob_match (pattern + 1 ,str + 1 ); 805 } 806return false; 807 } 808 } 809if (* pattern == * str ) { 810return glob_match (pattern + 1 ,str + 1 ); 811 } 812return false; 813} 814 815bool glob_match (const std::string & pattern ,const std::string & str ) { 816return glob_match (pattern .c_str (),str .c_str ()); 817} 818 819// 820// Filesystem utils 821// 822 823// Validate if a filename is safe to use 824// To validate a full path, split the path by the OS-specific path separator, and validate each part with this function 825bool fs_validate_filename (const std::string & filename ,bool allow_subdirs ) { 826if (!filename .length ()) { 827// Empty filename invalid 828return false; 829 } 830if (filename .length ()> 255 ) { 831// Limit at common largest possible filename on Linux filesystems 832// to avoid unnecessary further validation 833// (On systems with smaller limits it will be caught by the OS) 834return false; 835 } 836 837size_t offset = 0 ; 838while (offset < filename .size ()) { 839utf8_parse_result result = common_parse_utf8_codepoint (filename ,offset ); 840 841if (result .status != utf8_parse_result::SUCCESS ) { 842return false; 843 } 844uint32_t c = result .codepoint ; 845 846if ((result .bytes_consumed == 2 && c < 0x80 )|| 847 (result .bytes_consumed == 3 && c < 0x800 )|| 848 (result .bytes_consumed == 4 && c < 0x10000 )) { 849return false; 850 } 851 852// Check for forbidden codepoints: 853// - Control characters 854// - Unicode equivalents of illegal characters 855// - UTF-16 surrogate pairs 856// - UTF-8 replacement character 857// - Byte order mark (BOM) 858// - Illegal characters: / \ : * ? " < > | 859if (c <=0x1F // Control characters (C0) 860|| c == 0x7F // Control characters (DEL) 861|| (c >=0x80 && c <=0x9F )// Control characters (C1) 862|| c == 0xFF0E // Fullwidth Full Stop (period equivalent) 863|| c == 0x2215 // Division Slash (forward slash equivalent) 864|| c == 0x2216 // Set Minus (backslash equivalent) 865|| (c >=0xD800 && c <=0xDFFF )// UTF-16 surrogate pairs 866|| c > 0x10FFFF // Max Unicode limit 867|| c == 0xFFFD // Replacement Character (UTF-8) 868|| c == 0xFEFF // Byte Order Mark (BOM) 869|| c == ':' || c == '*' // Illegal characters 870|| c == '?' || c == '"' || c == '<' || c == '>' || c == '|' ) { 871return false; 872 } 873if (!allow_subdirs && (c == '/' || c == '\\' )) { 874// Subdirectories not allowed, reject path separators 875return false; 876 } 877offset += result .bytes_consumed ; 878 } 879 880// Reject any leading or trailing ' ', or any trailing '.', these are stripped on Windows and will cause a different filename 881// Unicode and other whitespace is not affected, only 0x20 space 882if (filename .front ()== ' ' || filename .back ()== ' ' || filename .back ()== '.' ) { 883return false; 884 } 885 886// Reject any ".." (currently stricter than necessary, it should be fine to just check for == ".." instead) 887if (filename .find (".." )!= std::string::npos ) { 888return false; 889 } 890 891// Reject "." 892if (filename == "." ) { 893return false; 894 } 895 896return true; 897} 898 899#include <iostream> 900 901 902#ifdef _WIN32 903static std::wstring utf8_to_wstring (const std::string & str ) { 904if (str .empty ()) { 905return std::wstring (); 906 } 907 908int size = MultiByteToWideChar (CP_UTF8 ,0 ,str .c_str (), (int )str .size (),NULL ,0 ); 909 910if (size <=0 ) { 911return std::wstring (); 912 } 913 914 std::wstring wstr (size ,0 ); 915MultiByteToWideChar (CP_UTF8 ,0 ,str .c_str (), (int )str .size (),& wstr [0 ],size ); 916 917return wstr ; 918} 919#endif 920 921// returns true if successful, false otherwise 922bool fs_create_directory_with_parents (const std::string & path ) { 923#ifdef _WIN32 924 std::wstring wpath = utf8_to_wstring (path ); 925 926// if the path already exists, check whether it's a directory 927const DWORD attributes = GetFileAttributesW (wpath .c_str ()); 928if ((attributes != INVALID_FILE_ATTRIBUTES )&& (attributes & FILE_ATTRIBUTE_DIRECTORY )) { 929return true; 930 } 931 932size_t pos_slash = 0 ; 933 934// process path from front to back, procedurally creating directories 935while ((pos_slash = path .find ('\\' ,pos_slash ))!= std::string::npos ) { 936const std::wstring subpath = wpath .substr (0 ,pos_slash ); 937 938pos_slash += 1 ; 939 940// skip the drive letter, in some systems it can return an access denied error 941if (subpath .length ()== 2 && subpath [1 ]== ':' ) { 942continue ; 943 } 944 945const bool success = CreateDirectoryW (subpath .c_str (),NULL ); 946 947if (!success ) { 948const DWORD error = GetLastError (); 949 950// if the path already exists, ensure that it's a directory 951if (error == ERROR_ALREADY_EXISTS ) { 952const DWORD attributes = GetFileAttributesW (subpath .c_str ()); 953if (attributes == INVALID_FILE_ATTRIBUTES || !(attributes & FILE_ATTRIBUTE_DIRECTORY )) { 954return false; 955 } 956 }else { 957return false; 958 } 959 } 960 } 961 962return true; 963#else 964// if the path already exists, check whether it's a directory 965struct stat info ; 966if (stat (path .c_str (),& info )== 0 ) { 967return S_ISDIR (info .st_mode ); 968 } 969 970size_t pos_slash = 1 ;// skip leading slashes for directory creation 971 972// process path from front to back, procedurally creating directories 973while ((pos_slash = path .find ('/' ,pos_slash ))!= std::string::npos ) { 974const std::string subpath = path .substr (0 ,pos_slash ); 975struct stat info ; 976 977// if the path already exists, ensure that it's a directory 978if (stat (subpath .c_str (),& info )== 0 ) { 979if (!S_ISDIR (info .st_mode )) { 980return false; 981 } 982 }else { 983// create parent directories 984const int ret = mkdir (subpath .c_str (),0755 ); 985if (ret != 0 ) { 986return false; 987 } 988 } 989 990pos_slash += 1 ; 991 } 992 993return true; 994#endif // _WIN32 995} 996 997bool fs_is_directory (const std::string & path ) { 998 std::filesystem::path dir (path ); 999return std::filesystem::exists (dir )&& std::filesystem::is_directory (dir ); 1000} 1001 1002std::string common_get_env (const std::string & name ) { 1003const char * value = std::getenv (name .c_str ()); 1004return value == nullptr ?"" :value ; 1005} 1006 1007void common_set_env (const std::string & name ,const std::string & value ) { 1008#if defined(_WIN32 ) 1009_putenv_s (name .c_str (),value .c_str ()); 1010#else 1011if (value .empty ()) { 1012unsetenv (name .c_str ()); 1013 }else { 1014setenv (name .c_str (),value .c_str (),1 ); 1015 } 1016#endif 1017} 1018 1019std::string fs_get_cache_directory () { 1020 std::string cache_directory = "" ; 1021auto ensure_trailing_slash = [](std::string p ) { 1022// Make sure to add trailing slash 1023if (p .empty ()|| p .back ()!= DIRECTORY_SEPARATOR ) { 1024p += DIRECTORY_SEPARATOR ; 1025 } 1026return p ; 1027 }; 1028cache_directory = common_get_env ("LLAMA_CACHE" ); 1029if (cache_directory .empty ()) { 1030#if defined(__linux__ )|| defined(__FreeBSD__ )|| defined(_AIX )|| \ 1031 defined(__OpenBSD__ )|| defined(__NetBSD__ ) 1032const std::string xdg_cache_home = common_get_env ("XDG_CACHE_HOME" ); 1033const std::string home = common_get_env ("HOME" ); 1034if (!xdg_cache_home .empty ()) { 1035cache_directory = xdg_cache_home ; 1036 }else if (!home .empty ()) { 1037cache_directory = home + "/.cache/" ; 1038 }else { 1039#if defined(__linux__ ) 1040/* no $HOME is defined, fallback to getpwuid */ 1041struct passwd * pw = getpwuid (getuid ()); 1042if ((!pw )|| (!pw -> pw_dir )) { 1043throw std::runtime_error ("Failed to find $HOME directory" ); 1044 } 1045 1046cache_directory = std::string (pw -> pw_dir )+ std::string ("/.cache/" ); 1047#else /* defined(__linux__) */ 1048throw std::runtime_error ("Failed to find $HOME directory" ); 1049#endif /* defined(__linux__) */ 1050 } 1051#elif defined(__APPLE__ ) 1052cache_directory = common_get_env ("HOME" ); 1053if (cache_directory .empty ()) { 1054throw std::runtime_error ("Failed to find $HOME directory" ); 1055 } 1056cache_directory += "/Library/Caches/" ; 1057#elif defined(_WIN32 ) 1058cache_directory = common_get_env ("LOCALAPPDATA" ); 1059if (cache_directory .empty ()) { 1060throw std::runtime_error ("Failed to find %LOCALAPPDATA% directory" ); 1061 } 1062#elif defined(__EMSCRIPTEN__ ) 1063GGML_ABORT ("not implemented on this platform" ); 1064#else 1065# error Unknown architecture 1066#endif 1067cache_directory = ensure_trailing_slash (cache_directory ); 1068cache_directory += "llama.cpp" ; 1069 } 1070return ensure_trailing_slash (cache_directory ); 1071} 1072 1073std::string fs_get_config_directory () { 1074 std::string config_directory = "" ; 1075auto ensure_trailing_slash = [](std::string p ) { 1076if (p .empty ()|| p .back ()!= DIRECTORY_SEPARATOR ) { 1077p += DIRECTORY_SEPARATOR ; 1078 } 1079return p ; 1080 }; 1081#if defined(__linux__ )|| defined(__FreeBSD__ )|| defined(_AIX )|| \ 1082 defined(__OpenBSD__ )|| defined(__NetBSD__ )|| defined(__APPLE__ ) 1083const std::string xdg_config_home = common_get_env ("XDG_CONFIG_HOME" ); 1084const std::string home = common_get_env ("HOME" ); 1085if (!xdg_config_home .empty ()) { 1086config_directory = xdg_config_home ; 1087 }else if (!home .empty ()) { 1088config_directory = home + "/.config/" ; 1089 }else { 1090#if defined(__linux__ ) 1091/* no $HOME is defined, fallback to getpwuid */ 1092struct passwd * pw = getpwuid (getuid ()); 1093if ((!pw )|| (!pw -> pw_dir )) { 1094throw std::runtime_error ("Failed to find $HOME directory" ); 1095 } 1096 1097config_directory = std::string (pw -> pw_dir )+ std::string ("/.config/" ); 1098#else 1099throw std::runtime_error ("Failed to find $HOME directory" ); 1100#endif 1101 } 1102#elif defined(_WIN32 ) 1103config_directory = common_get_env ("APPDATA" ); 1104if (config_directory .empty ()) { 1105throw std::runtime_error ("Failed to find %APPDATA% directory" ); 1106 } 1107#elif defined(__EMSCRIPTEN__ ) 1108// caller decides what to do when there is no config directory 1109throw std::runtime_error ("not implemented on this platform" ); 1110#else 1111# error Unknown architecture 1112#endif 1113config_directory = ensure_trailing_slash (config_directory ); 1114config_directory += "llama.cpp" ; 1115return ensure_trailing_slash (config_directory ); 1116} 1117 1118std::string fs_get_cache_file (const std::string & filename ) { 1119GGML_ASSERT (filename .find (DIRECTORY_SEPARATOR )== std::string::npos ); 1120 std::string cache_directory = fs_get_cache_directory (); 1121const bool success = fs_create_directory_with_parents (cache_directory ); 1122if (!success ) { 1123throw std::runtime_error ("failed to create cache directory: " + cache_directory ); 1124 } 1125return cache_directory + filename ; 1126} 1127 1128std::vector < common_file_info > fs_list (const std::string & path ,bool include_directories ) { 1129 std::vector < common_file_info > files ; 1130if (path .empty ())return files ; 1131 1132 std::filesystem::path dir (path ); 1133if (!std::filesystem::exists (dir )|| !std::filesystem::is_directory (dir )) { 1134return files ; 1135 } 1136 1137for (const auto & entry : std::filesystem::directory_iterator (dir )) { 1138try { 1139// Only include regular files (skip directories) 1140const auto & p = entry .path (); 1141if (std::filesystem::is_regular_file (p )) { 1142common_file_info info ; 1143info .path = p .string (); 1144info .name = p .filename ().string (); 1145info .is_dir = false; 1146try { 1147info .size = static_cast < size_t > (std::filesystem::file_size (p )); 1148 }catch (const std::filesystem::filesystem_error & ) { 1149info .size = 0 ; 1150 } 1151files .push_back (std::move (info )); 1152 }else if (include_directories && std::filesystem::is_directory (p )) { 1153common_file_info info ; 1154info .path = p .string (); 1155info .name = p .filename ().string (); 1156info .size = 0 ;// Directories have no size 1157info .is_dir = true; 1158files .push_back (std::move (info )); 1159 } 1160 }catch (const std::filesystem::filesystem_error & ) { 1161// skip entries we cannot inspect 1162continue ; 1163 } 1164 } 1165 1166return files ; 1167} 1168 1169std::ifstream fs_open_ifstream (const std::string & fname , std::ios_base::openmode mode ) { 1170#ifdef _WIN32 1171int wlen = MultiByteToWideChar (CP_UTF8 ,0 ,fname .c_str (),-1 ,NULL ,0 ); 1172if (!wlen ) {return std::ifstream (); } 1173 std::vector < wchar_t > wfname (wlen ); 1174 (void )MultiByteToWideChar (CP_UTF8 ,0 ,fname .c_str (),-1 ,wfname .data (),wlen ); 1175return std::ifstream (wfname .data (),mode ); 1176#else 1177return std::ifstream (fname ,mode ); 1178#endif 1179} 1180 1181// 1182// TTY utils 1183// 1184 1185bool tty_can_use_colors () { 1186// Check NO_COLOR environment variable (https://no-color.org/) 1187if (const char * no_color = std::getenv ("NO_COLOR" )) { 1188if (no_color [0 ]!= '\0' ) { 1189return false; 1190 } 1191 } 1192 1193// Check TERM environment variable 1194if (const char * term = std::getenv ("TERM" )) { 1195if (std::strcmp (term ,"dumb" )== 0 ) { 1196return false; 1197 } 1198 } 1199 1200// Check if stdout and stderr are connected to a terminal 1201// We check both because log messages can go to either 1202bool stdout_is_tty = isatty (fileno (stdout )); 1203bool stderr_is_tty = isatty (fileno (stderr )); 1204 1205return stdout_is_tty || stderr_is_tty ; 1206} 1207 1208// 1209// Model utils 1210// 1211 1212// TODO: move to common/sampling 1213static void common_init_sampler_from_model ( 1214const llama_model * model , 1215common_params_sampling & sparams ) { 1216 1217const uint64_t config = sparams .user_sampling_config ; 1218 1219auto get_int32 = [& ](const char * key ,int32_t & dst ,uint64_t user_config ) { 1220if (config & user_config ) { 1221return ; 1222 } 1223 1224char buf [64 ]= {0 }; 1225if (llama_model_meta_val_str (model ,key ,buf ,sizeof (buf ))> 0 ) { 1226char * end = nullptr ; 1227int32_t v = strtol (buf ,& end ,10 ); 1228if (end && end != buf ) { 1229dst = v ; 1230 } 1231 } 1232 }; 1233 1234auto get_float = [& ](const char * key ,float & dst ,uint64_t user_config ) { 1235if (config & user_config ) { 1236return ; 1237 } 1238 1239char buf [128 ]= {0 }; 1240if (llama_model_meta_val_str (model ,key ,buf ,sizeof (buf ))> 0 ) { 1241char * end = nullptr ; 1242float v = strtof (buf ,& end ); 1243if (end && end != buf ) { 1244dst = v ; 1245 } 1246 } 1247 }; 1248 1249// Sampling sequence 1250if (!(config & common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_SAMPLERS )) { 1251char buf [512 ]= {0 }; 1252if (llama_model_meta_val_str (model ,llama_model_meta_key_str (LLAMA_MODEL_META_KEY_SAMPLING_SEQUENCE ),buf ,sizeof (buf ))> 0 ) { 1253const std::vector < std::string > sampler_names = string_split < std::string > (std::string (buf ),';' ); 1254if (!sampler_names .empty ()) { 1255sparams .samplers = common_sampler_types_from_names (sampler_names ); 1256 } 1257 } 1258 } 1259 1260get_int32 (llama_model_meta_key_str (LLAMA_MODEL_META_KEY_SAMPLING_TOP_K ),sparams .top_k , common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_TOP_K ); 1261get_float (llama_model_meta_key_str (LLAMA_MODEL_META_KEY_SAMPLING_TOP_P ),sparams .top_p , common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_TOP_P ); 1262get_float (llama_model_meta_key_str (LLAMA_MODEL_META_KEY_SAMPLING_MIN_P ),sparams .min_p , common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_MIN_P ); 1263get_float (llama_model_meta_key_str (LLAMA_MODEL_META_KEY_SAMPLING_XTC_PROBABILITY ),sparams .xtc_probability , common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_XTC_PROBABILITY ); 1264get_float (llama_model_meta_key_str (LLAMA_MODEL_META_KEY_SAMPLING_XTC_THRESHOLD ),sparams .xtc_threshold , common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_XTC_THRESHOLD ); 1265get_float (llama_model_meta_key_str (LLAMA_MODEL_META_KEY_SAMPLING_TEMP ),sparams .temp , common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_TEMP ); 1266get_int32 (llama_model_meta_key_str (LLAMA_MODEL_META_KEY_SAMPLING_PENALTY_LAST_N ),sparams .penalty_last_n , common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_PENALTY_LAST_N ); 1267get_float (llama_model_meta_key_str (LLAMA_MODEL_META_KEY_SAMPLING_PENALTY_REPEAT ),sparams .penalty_repeat , common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_PENALTY_REPEAT ); 1268get_int32 (llama_model_meta_key_str (LLAMA_MODEL_META_KEY_SAMPLING_MIROSTAT ),sparams .mirostat , common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_MIROSTAT ); 1269get_float (llama_model_meta_key_str (LLAMA_MODEL_META_KEY_SAMPLING_MIROSTAT_TAU ),sparams .mirostat_tau , common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_MIROSTAT_TAU ); 1270get_float (llama_model_meta_key_str (LLAMA_MODEL_META_KEY_SAMPLING_MIROSTAT_ETA ),sparams .mirostat_eta , common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_MIROSTAT_ETA ); 1271} 1272 1273struct common_init_result::impl { 1274impl ()= default ; 1275 ~impl ()= default ; 1276 1277// note: the order in which model, context, etc. are declared matters because their destructors will be called bottom-to-top 1278 1279common_threadpools threadpools ; 1280 1281llama_model_ptr model ; 1282llama_context_ptr context ; 1283 1284 std::vector < llama_adapter_lora_ptr > lora ; 1285 1286 std::vector < common_sampler_ptr > samplers ; 1287 std::vector < llama_sampler_seq_config > samplers_seq_config ; 1288}; 1289 1290common_init_result::common_init_result (common_params & params ,bool model_only ) : 1291pimpl (new impl {}) { 1292auto mparams = common_model_params_to_llama (params ); 1293auto cparams = common_context_params_to_llama (params ); 1294 1295if (params .fit_params ) { 1296COM_TRC ("%s" ,"fitting params to device memory ...\n" ); 1297COM_TRC ("%s" ,"(for bugs during this step try to reproduce them with -fit off, or provide --verbose logs if the bug only occurs with -fit on)\n" ); 1298 1299// the draft context is created from the same base params and follows the main context, fit both together 1300const bool has_draft = params .speculative .has_dft (); 1301const bool spec_mtp = std::find (params .speculative .types .begin (),params .speculative .types .end (), 1302COMMON_SPECULATIVE_TYPE_DRAFT_MTP )!= params .speculative .types .end (); 1303 1304common_params params_dft = common_base_params_to_speculative (params ); 1305 1306auto mparams_dft = common_model_params_to_llama (params_dft ); 1307auto cparams_dft = common_context_params_to_llama (params_dft ); 1308if (spec_mtp ) { 1309cparams_dft .ctx_type = LLAMA_CONTEXT_TYPE_MTP ; 1310 } 1311cparams_dft .n_rs_seq = 0 ; 1312 1313const common_fit_extra_model extra = { 1314/*.path_model =*/ params_dft .model .path .c_str (), 1315/*.mparams =*/ & mparams_dft , 1316/*.cparams =*/ & cparams_dft , 1317/*.shares_model =*/ !has_draft ,// an MTP context runs on the weights of the main model 1318 }; 1319 1320common_fit_params (params .model .path .c_str (),& mparams ,& cparams , 1321params .tensor_split , 1322params .tensor_buft_overrides .data (), 1323params .fit_params_target .data (), 1324params .fit_params_min_ctx , 1325has_draft || spec_mtp ?& extra :nullptr , 1326params .verbosity >=LOG_LEVEL_DEBUG ?GGML_LOG_LEVEL_DEBUG :GGML_LOG_LEVEL_ERROR ); 1327 } 1328 1329llama_model * model = llama_model_load_from_file (params .model .path .c_str (),mparams ); 1330if (model == NULL ) { 1331return ; 1332 } 1333 1334pimpl -> model .reset (model ); 1335 1336if (model_only ) { 1337return ; 1338 } 1339 1340const llama_vocab * vocab = llama_model_get_vocab (model ); 1341 1342// load and optionally apply lora adapters 1343for (auto & la :params .lora_adapters ) { 1344llama_adapter_lora_ptr lora ; 1345lora .reset (llama_adapter_lora_init (model ,la .path .c_str ())); 1346if (lora == nullptr ) { 1347COM_ERR ("failed to load lora adapter '%s'\n" ,la .path .c_str ()); 1348return ; 1349 } 1350 1351char buf [1024 ]; 1352la .ptr = lora .get (); 1353llama_adapter_meta_val_str (la .ptr ,"adapter.lora.task_name" ,buf ,sizeof (buf )); 1354la .task_name = buf ; 1355llama_adapter_meta_val_str (la .ptr ,"adapter.lora.prompt_prefix" ,buf ,sizeof (buf )); 1356la .prompt_prefix = buf ; 1357pimpl -> lora .emplace_back (std::move (lora ));// copy to list of loaded adapters 1358 } 1359 1360// updates params.sampling 1361// TODO: fix naming 1362common_init_sampler_from_model (model ,params .sampling ); 1363 1364if (params .sampling .ignore_eos && llama_vocab_eos (vocab )== LLAMA_TOKEN_NULL ) { 1365COM_WRN ("%s" ,"vocab does not have an EOS token, ignoring --ignore-eos\n" ); 1366params .sampling .ignore_eos = false; 1367 } 1368 1369// initialize once 1370for (llama_token i = 0 ;i < llama_vocab_n_tokens (vocab );i ++ ) { 1371if (llama_vocab_is_eog (vocab ,i )) { 1372COM_TRC ("added %s logit bias = %f\n" ,common_token_to_piece (vocab ,i ).c_str (),- INFINITY ); 1373params .sampling .logit_bias_eog .push_back ({i ,- INFINITY }); 1374 } 1375 } 1376 1377if (params .sampling .ignore_eos ) { 1378// add EOG biases to the active set of logit biases 1379params .sampling .logit_bias .insert ( 1380params .sampling .logit_bias .end (), 1381params .sampling .logit_bias_eog .begin (),params .sampling .logit_bias_eog .end ()); 1382 } 1383 1384if (llama_model_has_encoder (model )&& llama_model_has_decoder (model )) { 1385// Cross-attention state is shared by the whole context. 1386params .n_parallel = 1 ; 1387cparams .n_seq_max = 1 ; 1388params .sampling .backend_sampling = false; 1389 } 1390 1391// init the backend samplers as part of the context creation 1392pimpl -> samplers .resize (cparams .n_seq_max ); 1393pimpl -> samplers_seq_config .resize (cparams .n_seq_max ); 1394 1395for (int i = 0 ;i < (int )cparams .n_seq_max ;++ i ) { 1396pimpl -> samplers [i ].reset (common_sampler_init (model ,params .sampling )); 1397pimpl -> samplers_seq_config [i ]= {i ,common_sampler_get (pimpl -> samplers [i ].get ()) }; 1398 } 1399 1400if (params .sampling .backend_sampling ) { 1401cparams .samplers = pimpl -> samplers_seq_config .data (); 1402cparams .n_samplers = pimpl -> samplers_seq_config .size (); 1403 } 1404 1405llama_context * lctx = llama_init_from_model (model ,cparams ); 1406if (lctx == NULL ) { 1407COM_ERR ("failed to create context with model '%s'\n" ,params .model .path .c_str ()); 1408return ; 1409 } 1410 1411pimpl -> context .reset (lctx ); 1412 1413set_process_priority (params .cpuparams .priority ); 1414 1415pimpl -> threadpools .init (lctx ,params ); 1416} 1417 1418llama_model * common_init_result::model () { 1419return pimpl -> model .get (); 1420} 1421 1422llama_context * common_init_result::context () { 1423return pimpl -> context .get (); 1424} 1425 1426common_sampler * common_init_result::sampler (llama_seq_id seq_id ) { 1427if (seq_id < 0 || seq_id >= (int )pimpl -> samplers .size ()) { 1428return nullptr ; 1429 } 1430return pimpl -> samplers [seq_id ].get (); 1431} 1432 1433void common_init_result::reset_samplers () { 1434for (int i = 0 ;i < (int )pimpl -> samplers .size ();++ i ) { 1435llama_sampler_reset (common_sampler_get (pimpl -> samplers [i ].get ())); 1436 } 1437} 1438 1439std::vector < llama_adapter_lora_ptr > & common_init_result::lora () { 1440return pimpl -> lora ; 1441} 1442 1443common_init_result_ptr common_init_from_params (common_params & params ,bool model_only ) { 1444common_init_result_ptr res (new common_init_result (params ,model_only )); 1445 1446llama_model * model = res -> model (); 1447if (model == NULL ) { 1448COM_ERR ("failed to load model '%s'\n" ,params .model .path .c_str ()); 1449return res ; 1450 } 1451 1452if (model_only ) { 1453return res ; 1454 } 1455 1456llama_context * lctx = res -> context (); 1457if (lctx == NULL ) { 1458COM_ERR ("failed to create context with model '%s'\n" ,params .model .path .c_str ()); 1459return res ; 1460 } 1461 1462const llama_vocab * vocab = llama_model_get_vocab (model ); 1463 1464if (params .ctx_shift && !llama_memory_can_shift (llama_get_memory (lctx ))) { 1465COM_WRN ("%s" ,"KV cache shifting is not supported for this context, disabling KV cache shifting\n" ); 1466params .ctx_shift = false; 1467 } 1468 1469if (!params .control_vectors .empty ()) { 1470if (params .control_vector_layer_start <=0 )params .control_vector_layer_start = 1 ; 1471if (params .control_vector_layer_end <=0 )params .control_vector_layer_end = llama_model_n_layer (model ); 1472 1473const auto cvec = common_control_vector_load (params .control_vectors ); 1474if (cvec .n_embd == -1 ) { 1475return res ; 1476 } 1477 1478int err = llama_set_adapter_cvec ( 1479lctx , 1480cvec .data .data (), 1481cvec .data .size (), 1482cvec .n_embd , 1483params .control_vector_layer_start , 1484params .control_vector_layer_end ); 1485if (err ) { 1486return res ; 1487 } 1488 } 1489 1490if (llama_pooling_type (lctx )== LLAMA_POOLING_TYPE_RANK ) { 1491bool ok = true; 1492 1493if (llama_vocab_bos (vocab )== LLAMA_TOKEN_NULL ) { 1494COM_WRN ("%s" ,"vocab does not have a BOS token, reranking will not work\n" ); 1495ok = false; 1496 } 1497 1498bool has_eos = llama_vocab_eos (vocab )!= LLAMA_TOKEN_NULL ; 1499bool has_sep = llama_vocab_sep (vocab )!= LLAMA_TOKEN_NULL ; 1500bool has_rerank_prompt = llama_model_chat_template (model ,"rerank" )!= NULL ; 1501 1502if (!has_eos && !has_sep && !has_rerank_prompt ) { 1503COM_WRN ("%s" ,"vocab does not have an EOS token, SEP token, or rerank prompt. Reranking will not work\n" ); 1504ok = false; 1505 }else if (!has_eos ) { 1506COM_WRN ("%s" ,"vocab does not have an EOS token, using SEP token as fallback\n" ); 1507 } 1508 1509if (!ok ) { 1510return res ; 1511 } 1512 } 1513 1514if (!params .lora_init_without_apply ) { 1515common_set_adapter_lora (lctx ,params .lora_adapters ); 1516 } 1517 1518if (params .warmup ) { 1519COM_TRC ("%s" ,"warming up the model with an empty run - please wait ... (--no-warmup to disable)\n" ); 1520 1521 std::vector < llama_token > tmp ; 1522llama_token bos = llama_vocab_bos (vocab ); 1523llama_token eos = llama_vocab_eos (vocab ); 1524 1525// some models (e.g. T5) don't have a BOS token 1526if (bos != LLAMA_TOKEN_NULL ) { 1527tmp .push_back (bos ); 1528 } 1529if (eos != LLAMA_TOKEN_NULL ) { 1530tmp .push_back (eos ); 1531 } 1532if (tmp .empty ()) { 1533tmp .push_back (0 ); 1534 } 1535 1536if (llama_model_has_encoder (model )) { 1537llama_encode (lctx ,llama_batch_get_one (tmp .data (),tmp .size ())); 1538llama_token decoder_start_token_id = llama_model_decoder_start_token (model ); 1539if (decoder_start_token_id == LLAMA_TOKEN_NULL ) { 1540decoder_start_token_id = bos ; 1541 } 1542tmp .clear (); 1543tmp .push_back (decoder_start_token_id ); 1544 } 1545if (llama_model_has_decoder (model )) { 1546llama_decode (lctx ,llama_batch_get_one (tmp .data (), std::min (tmp .size (), (size_t )params .n_batch ))); 1547 } 1548llama_memory_clear (llama_get_memory (lctx ), true); 1549llama_synchronize (lctx ); 1550llama_perf_context_reset (lctx ); 1551 1552// reset samplers to reset RNG state after warmup to the seeded state 1553res -> reset_samplers (); 1554 } 1555 1556return res ; 1557} 1558 1559common_init_result::~common_init_result ()= default ; 1560 1561std::string common_get_model_endpoint () { 1562 std::string endpoint = common_get_env ("MODEL_ENDPOINT" ); 1563if (endpoint .empty ()) { 1564// the HF_ENDPOINT variable is respected for backward compatibility 1565endpoint = common_get_env ("HF_ENDPOINT" ); 1566 } 1567if (endpoint .empty ()) { 1568return "https://huggingface.co/" ; 1569 } 1570if (endpoint .back ()!= '/' ) { 1571endpoint += '/' ; 1572 } 1573return endpoint ; 1574} 1575 1576char * common_get_model_or_exit (int argc ,char * argv []) { 1577if (argc > 1 ) { 1578return argv [1 ]; 1579 } 1580 1581char * path = getenv ("LLAMACPP_TEST_MODELFILE" ); 1582if (!path || strlen (path )== 0 ) { 1583fprintf (stderr ,"\033[33mWARNING: No model file provided. Skipping this test. Set LLAMACPP_TEST_MODELFILE=<gguf_model_path> to silence this warning and run this test.\n\033[0m" ); 1584exit (EXIT_SUCCESS ); 1585 } 1586 1587return path ; 1588} 1589 1590common_context_seq_rm_type common_context_can_seq_rm (llama_context * ctx ) { 1591auto * mem = llama_get_memory (ctx ); 1592if (mem == nullptr ) { 1593return COMMON_CONTEXT_SEQ_RM_TYPE_NO ; 1594 } 1595 1596if (llama_n_rs_seq (ctx )> 0 ) { 1597COM_TRC ("%s" ,"the context supports bounded partial sequence removal\n" ); 1598return COMMON_CONTEXT_SEQ_RM_TYPE_RS ; 1599 } 1600 1601common_context_seq_rm_type res = COMMON_CONTEXT_SEQ_RM_TYPE_PART ; 1602 1603llama_memory_clear (mem , true); 1604 1605// eval 2 tokens to check if the context is compatible 1606 std::vector < llama_token > tmp ; 1607tmp .push_back (0 ); 1608tmp .push_back (0 ); 1609 1610int ret = llama_decode (ctx ,llama_batch_get_one (tmp .data (),tmp .size ())); 1611if (ret != 0 ) { 1612COM_ERR ("llama_decode() failed: %d\n" ,ret ); 1613res = COMMON_CONTEXT_SEQ_RM_TYPE_NO ; 1614 gotodone ; 1615 } 1616 1617// try to remove the last tokens 1618if (!llama_memory_seq_rm (mem ,0 ,1 ,-1 )) { 1619COM_TRC ("%s" ,"the context does not support partial sequence removal\n" ); 1620res = COMMON_CONTEXT_SEQ_RM_TYPE_FULL ; 1621 gotodone ; 1622 } 1623 1624done : 1625llama_memory_clear (mem , true); 1626llama_synchronize (ctx ); 1627 1628return res ; 1629} 1630 1631static void common_context_seq_rm (llama_context * ctx ,llama_seq_id seq_id ,llama_pos p0 ,llama_pos p1 ) { 1632auto * mem = llama_get_memory (ctx ); 1633if (!llama_memory_seq_rm (mem ,seq_id ,p0 ,p1 )) { 1634GGML_ABORT ("%s" ,string_format ("failed to remove sequence %d with p0=%d, p1=%d\n" ,seq_id ,p0 ,p1 ).c_str ()); 1635 } 1636} 1637 1638static void common_context_seq_cp (llama_context * ctx ,llama_seq_id seq_id_src ,llama_seq_id seq_id_dst ,llama_pos p0 ,llama_pos p1 ) { 1639auto * mem = llama_get_memory (ctx ); 1640llama_memory_seq_cp (mem ,seq_id_src ,seq_id_dst ,p0 ,p1 ); 1641} 1642 1643static void common_context_seq_add (llama_context * ctx ,llama_seq_id seq_id ,llama_pos p0 ,llama_pos p1 ,llama_pos delta ) { 1644auto * mem = llama_get_memory (ctx ); 1645llama_memory_seq_add (mem ,seq_id ,p0 ,p1 ,delta ); 1646} 1647 1648void common_memory::init (llama_context * ctx_tgt ,llama_context * ctx_dft ) { 1649this -> ctx_tgt = ctx_tgt ; 1650this -> ctx_dft = ctx_dft ; 1651} 1652 1653void common_memory::seq_rm (llama_seq_id seq_id ,llama_pos p0 ,llama_pos p1 )const { 1654common_context_seq_rm (ctx_tgt ,seq_id ,p0 ,p1 ); 1655if (ctx_dft ) { 1656common_context_seq_rm (ctx_dft ,seq_id ,p0 ,p1 ); 1657 } 1658} 1659 1660void common_memory::seq_cp (llama_seq_id seq_id_src ,llama_seq_id seq_id_dst ,llama_pos p0 ,llama_pos p1 )const { 1661common_context_seq_cp (ctx_tgt ,seq_id_src ,seq_id_dst ,p0 ,p1 ); 1662if (ctx_dft ) { 1663common_context_seq_cp (ctx_dft ,seq_id_src ,seq_id_dst ,p0 ,p1 ); 1664 } 1665} 1666 1667void common_memory::seq_add (llama_seq_id seq_id ,llama_pos p0 ,llama_pos p1 ,llama_pos delta )const { 1668common_context_seq_add (ctx_tgt ,seq_id ,p0 ,p1 ,delta ); 1669if (ctx_dft ) { 1670common_context_seq_add (ctx_dft ,seq_id ,p0 ,p1 ,delta ); 1671 } 1672} 1673 1674void common_set_adapter_lora (struct llama_context * ctx , std::vector < common_adapter_lora_info > & lora ) { 1675 std::vector < llama_adapter_lora *> loras ; 1676 std::vector < float > scales ; 1677 1678for (auto & la :lora ) { 1679loras .push_back (la .ptr ); 1680scales .push_back (la .scale ); 1681 } 1682 1683llama_set_adapters_lora (ctx ,loras .data (),loras .size (),scales .data ()); 1684} 1685 1686struct llama_model_params common_model_params_to_llama (common_params & params ) { 1687auto mparams = llama_model_default_params (); 1688 1689if (!params .devices .empty ()) { 1690mparams .devices = params .devices .data (); 1691 } 1692 1693mparams .n_gpu_layers = params .n_gpu_layers ; 1694mparams .main_gpu = params .main_gpu ; 1695mparams .split_mode = params .split_mode ; 1696mparams .load_mode = params .load_mode ; 1697mparams .lazy_mode = params .lazy_mode ; 1698mparams .tensor_split = params .tensor_split ; 1699mparams .check_tensors = params .check_tensors ; 1700mparams .use_extra_bufts = !params .no_extra_bufts ; 1701mparams .no_host = params .no_host ; 1702 1703if (params .kv_overrides .empty ()) { 1704mparams .kv_overrides = NULL ; 1705 }else { 1706GGML_ASSERT (params .kv_overrides .back ().key [0 ]== 0 && "KV overrides not terminated with empty key" ); 1707mparams .kv_overrides = params .kv_overrides .data (); 1708 } 1709 1710if (params .tensor_buft_overrides .empty ()) { 1711mparams .tensor_buft_overrides = NULL ; 1712 }else { 1713GGML_ASSERT (params .tensor_buft_overrides .back ().pattern == nullptr && "Tensor buffer overrides not terminated with empty pattern" ); 1714mparams .tensor_buft_overrides = params .tensor_buft_overrides .data (); 1715 } 1716 1717mparams .progress_callback = params .load_progress_callback ; 1718mparams .progress_callback_user_data = params .load_progress_callback_user_data ; 1719mparams .no_alloc = params .no_alloc ; 1720mparams .load_mtp = std::find (params .speculative .types .begin (),params .speculative .types .end (),COMMON_SPECULATIVE_TYPE_DRAFT_MTP )!= params .speculative .types .end (); 1721 1722return mparams ; 1723} 1724 1725struct llama_context_params common_context_params_to_llama (const common_params & params ) { 1726auto cparams = llama_context_default_params (); 1727 1728cparams .n_ctx = params .n_ctx ; 1729cparams .n_seq_max = params .n_parallel ; 1730cparams .n_rs_seq = params .speculative .need_n_rs_seq (); 1731cparams .n_outputs_max = std::max (params .n_outputs_max ,0 ); 1732cparams .n_outputs_max_per_seq = std::max (params .n_outputs_max_per_seq ,0 ); 1733cparams .n_batch = params .n_batch ; 1734cparams .n_ubatch = params .n_ubatch ; 1735cparams .n_threads = params .cpuparams .n_threads ; 1736cparams .n_threads_batch = params .cpuparams_batch .n_threads == -1 ? 1737params .cpuparams .n_threads :params .cpuparams_batch .n_threads ; 1738cparams .embeddings = params .embedding ; 1739cparams .rope_scaling_type = params .rope_scaling_type ; 1740cparams .rope_freq_base = params .rope_freq_base ; 1741cparams .rope_freq_scale = params .rope_freq_scale ; 1742cparams .yarn_ext_factor = params .yarn_ext_factor ; 1743cparams .yarn_attn_factor = params .yarn_attn_factor ; 1744cparams .yarn_beta_fast = params .yarn_beta_fast ; 1745cparams .yarn_beta_slow = params .yarn_beta_slow ; 1746cparams .yarn_orig_ctx = params .yarn_orig_ctx ; 1747cparams .pooling_type = params .pooling_type ; 1748cparams .attention_type = params .attention_type ; 1749cparams .flash_attn_type = params .flash_attn_type ; 1750cparams .cb_eval = params .cb_eval ; 1751cparams .cb_eval_user_data = params .cb_eval_user_data ; 1752cparams .offload_kqv = !params .no_kv_offload ; 1753cparams .no_perf = params .no_perf ; 1754cparams .op_offload = !params .no_op_offload ; 1755cparams .swa_full = params .swa_full ; 1756cparams .kv_unified = params .kv_unified ; 1757 1758cparams .type_k = params .cache_type_k ; 1759cparams .type_v = params .cache_type_v ; 1760 1761return cparams ; 1762} 1763 1764// 1765// Threadpool utils 1766// 1767 1768struct ggml_threadpool_params ggml_threadpool_params_from_cpu_params (const common_cpu_params & params ) { 1769struct ggml_threadpool_params tpp ; 1770 1771ggml_threadpool_params_init (& tpp ,params .n_threads );// setup the defaults 1772 1773if (params .mask_valid ) { 1774 std::memcpy (& tpp .cpumask ,& params .cpumask ,GGML_MAX_N_THREADS ); 1775 } 1776 1777tpp .prio = params .priority ; 1778tpp .poll = params .poll ; 1779tpp .strict_cpu = params .strict_cpu ; 1780 1781return tpp ; 1782} 1783 1784common_threadpools::~common_threadpools () { 1785if (!free_fn ) { 1786return ; 1787 } 1788free_fn (threadpool ); 1789free_fn (threadpool_batch ); 1790} 1791 1792void common_threadpools::init (llama_context * ctx ,const common_params & params ) { 1793GGML_ASSERT (!threadpool ); 1794GGML_ASSERT (!threadpool_batch ); 1795 1796COM_INF ("llama threadpool init, n_threads = %d\n" , (int )params .cpuparams .n_threads ); 1797 1798auto * cpu_dev = ggml_backend_dev_by_type (GGML_BACKEND_DEVICE_TYPE_CPU ); 1799if (!cpu_dev ) { 1800COM_WRN ("%s" ,"no CPU backend found\n" ); 1801return ; 1802 } 1803auto * reg = ggml_backend_dev_backend_reg (cpu_dev ); 1804auto * ggml_threadpool_new_fn = (decltype(ggml_threadpool_new )* )ggml_backend_reg_get_proc_address (reg ,"ggml_threadpool_new" ); 1805free_fn = (decltype(ggml_threadpool_free )* )ggml_backend_reg_get_proc_address (reg ,"ggml_threadpool_free" ); 1806 1807struct ggml_threadpool_params tpp_batch = 1808ggml_threadpool_params_from_cpu_params (params .cpuparams_batch ); 1809struct ggml_threadpool_params tpp = 1810ggml_threadpool_params_from_cpu_params (params .cpuparams ); 1811 1812// each pool needs to match the respective n_threads exactly 1813// see: https://github.com/ggml-org/llama.cpp/pull/27138#issuecomment-5332307332 1814if (!ggml_threadpool_params_match (& tpp ,& tpp_batch )) { 1815threadpool_batch = ggml_threadpool_new_fn (& tpp_batch ); 1816if (!threadpool_batch ) { 1817COM_WRN ("batch threadpool create failed : n_threads %d\n" ,tpp_batch .n_threads ); 1818return ; 1819 } 1820 1821// start the non-batch threadpool in the paused state 1822tpp .paused = true; 1823 } 1824 1825threadpool = ggml_threadpool_new_fn (& tpp ); 1826if (!threadpool ) { 1827COM_WRN ("threadpool create failed : n_threads %d\n" ,tpp .n_threads ); 1828free_fn (threadpool_batch ); 1829threadpool_batch = nullptr ; 1830return ; 1831 } 1832 1833llama_attach_threadpool (ctx ,threadpool ,threadpool_batch ); 1834} 1835 1836// 1837// Batch utils 1838// 1839 1840void common_batch_clear (struct llama_batch & batch ) { 1841batch .n_tokens = 0 ; 1842} 1843 1844void common_batch_add ( 1845struct llama_batch & batch , 1846llama_token id , 1847llama_pos pos , 1848const std::vector < llama_seq_id > & seq_ids , 1849bool logits ) { 1850GGML_ASSERT (batch .seq_id [batch .n_tokens ]&& "llama_batch size exceeded" ); 1851 1852batch .token [batch .n_tokens ]= id ; 1853batch .pos [batch .n_tokens ]= pos ; 1854batch .n_seq_id [batch .n_tokens ]= seq_ids .size (); 1855for (size_t i = 0 ;i < seq_ids .size ();++ i ) { 1856batch .seq_id [batch .n_tokens ][i ]= seq_ids [i ]; 1857 } 1858batch .logits [batch .n_tokens ]= logits ; 1859 1860batch .n_tokens ++ ; 1861} 1862 1863// 1864// Vocab utils 1865// 1866 1867std::vector < llama_token > common_tokenize ( 1868const struct llama_context * ctx , 1869const std::string & text , 1870bool add_special , 1871bool parse_special ) { 1872const llama_model * model = llama_get_model (ctx ); 1873const llama_vocab * vocab = llama_model_get_vocab (model ); 1874return common_tokenize (vocab ,text ,add_special ,parse_special ); 1875} 1876 1877std::vector < llama_token > common_tokenize ( 1878const struct llama_vocab * vocab , 1879const std::string & text , 1880bool add_special , 1881bool parse_special ) { 1882// upper limit for the number of tokens 1883int n_tokens = text .length ()+ 2 * add_special ; 1884 std::vector < llama_token > result (n_tokens ); 1885n_tokens = llama_tokenize (vocab ,text .data (),text .length (),result .data (),result .size (),add_special ,parse_special ); 1886if (n_tokens == std::numeric_limits < int32_t > ::min ()) { 1887throw std::runtime_error ("Tokenization failed: input text too large, tokenization result exceeds int32_t limit" ); 1888 } 1889if (n_tokens < 0 ) { 1890result .resize (- n_tokens ); 1891int check = llama_tokenize (vocab ,text .data (),text .length (),result .data (),result .size (),add_special ,parse_special ); 1892GGML_ASSERT (check == - n_tokens ); 1893 }else { 1894result .resize (n_tokens ); 1895 } 1896return result ; 1897} 1898 1899std::string common_token_to_piece (const struct llama_context * ctx ,llama_token token ,bool special ) { 1900const llama_model * model = llama_get_model (ctx ); 1901const llama_vocab * vocab = llama_model_get_vocab (model ); 1902return common_token_to_piece (vocab ,token ,special ); 1903} 1904 1905std::string common_token_to_piece (const struct llama_vocab * vocab ,llama_token token ,bool special ) { 1906 std::string piece ; 1907piece .resize (piece .capacity ());// using string internal cache, 15 bytes + '\n' 1908const int n_chars = llama_token_to_piece (vocab ,token ,& piece [0 ],piece .size (),0 ,special ); 1909if (n_chars < 0 ) { 1910piece .resize (- n_chars ); 1911int check = llama_token_to_piece (vocab ,token ,& piece [0 ],piece .size (),0 ,special ); 1912GGML_ASSERT (check == - n_chars ); 1913 } 1914else { 1915piece .resize (n_chars ); 1916 } 1917 1918return piece ; 1919} 1920 1921std::string common_detokenize (const struct llama_context * ctx ,const std::vector < llama_token > & tokens ,bool special ) { 1922const llama_model * model = llama_get_model (ctx ); 1923const llama_vocab * vocab = llama_model_get_vocab (model ); 1924return common_detokenize (vocab ,tokens ,special ); 1925} 1926 1927std::string common_detokenize (const struct llama_vocab * vocab ,const std::vector < llama_token > & tokens ,bool special ) { 1928 std::string text ; 1929text .resize (std::max (text .capacity (),tokens .size ())); 1930int32_t n_chars = llama_detokenize (vocab ,tokens .data (), (int32_t )tokens .size (),& text [0 ], (int32_t )text .size (), false,special ); 1931if (n_chars < 0 ) { 1932text .resize (- n_chars ); 1933n_chars = llama_detokenize (vocab ,tokens .data (), (int32_t )tokens .size (),& text [0 ], (int32_t )text .size (), false,special ); 1934GGML_ASSERT (n_chars <= (int32_t )text .size ());// whitespace trimming is performed after per-token detokenization 1935 } 1936 1937text .resize (n_chars ); 1938 1939// NOTE: the original tokenizer decodes bytes after collecting the pieces. 1940return text ; 1941} 1942 1943// 1944// Embedding utils 1945// 1946 1947void common_embd_normalize (const float * inp ,float * out ,int n ,int embd_norm ) { 1948double sum = 0.0 ; 1949 1950switch (embd_norm ) { 1951case -1 :// no normalisation 1952sum = 1.0 ; 1953break ; 1954case 0 :// max absolute 1955for (int i = 0 ;i < n ;i ++ ) { 1956if (sum < std::abs (inp [i ])) { 1957sum = std::abs (inp [i ]); 1958 } 1959 } 1960sum /=32760.0 ;// make an int16 range 1961break ; 1962case 2 :// euclidean 1963for (int i = 0 ;i < n ;i ++ ) { 1964sum += inp [i ]* inp [i ]; 1965 } 1966sum = std::sqrt (sum ); 1967break ; 1968default :// p-norm (euclidean is p-norm p=2) 1969for (int i = 0 ;i < n ;i ++ ) { 1970sum += std::pow (std::abs (inp [i ]),embd_norm ); 1971 } 1972sum = std::pow (sum ,1.0 /embd_norm ); 1973break ; 1974 } 1975 1976const float norm = sum > 0.0 ?1.0 /sum :0.0f ; 1977 1978for (int i = 0 ;i < n ;i ++ ) { 1979out [i ]= inp [i ]* norm ; 1980 } 1981} 1982 1983float common_embd_similarity_cos (const float * embd1 ,const float * embd2 ,int n ){ 1984double sum = 0.0 ; 1985double sum1 = 0.0 ; 1986double sum2 = 0.0 ; 1987 1988for (int i = 0 ;i < n ;i ++ ) { 1989sum += embd1 [i ]* embd2 [i ]; 1990sum1 += embd1 [i ]* embd1 [i ]; 1991sum2 += embd2 [i ]* embd2 [i ]; 1992 } 1993 1994// Handle the case where one or both vectors are zero vectors 1995if (sum1 == 0.0 || sum2 == 0.0 ) { 1996if (sum1 == 0.0 && sum2 == 0.0 ) { 1997return 1.0f ;// two zero vectors are similar 1998 } 1999return 0.0f ; 2000 } 2001 2002return sum / (sqrt (sum1 )* sqrt (sum2 )); 2003} 2004 2005// 2006// Control vector utils 2007// 2008 2009static common_control_vector_data common_control_vector_load_one (const common_control_vector_load_info & load_info ) { 2010common_control_vector_data result = {-1 , {} }; 2011 2012ggml_context * ctx = nullptr ; 2013struct gguf_init_params meta_gguf_params = { 2014/* .no_alloc = */ false, 2015/* .ctx = */ & ctx , 2016 }; 2017struct gguf_context * ctx_gguf = gguf_init_from_file (load_info .fname .c_str (),meta_gguf_params ); 2018if (!ctx_gguf ) { 2019COM_ERR ("failed to load control vector file from %s\n" ,load_info .fname .c_str ()); 2020return result ; 2021 } 2022 2023int32_t n_tensors = gguf_get_n_tensors (ctx_gguf ); 2024if (n_tensors == 0 ) { 2025COM_WRN ("no direction tensors found in %s\n" ,load_info .fname .c_str ()); 2026 } 2027 2028for (int i = 0 ;i < n_tensors ;i ++ ) { 2029 std::string name = gguf_get_tensor_name (ctx_gguf ,i ); 2030 2031int layer_idx = -1 ; 2032 2033// split on '.' 2034size_t dotpos = name .find ('.' ); 2035if (dotpos != std::string::npos && name .substr (0 ,dotpos )== "direction" ) { 2036try { 2037layer_idx = std::stoi (name .substr (dotpos + 1 )); 2038 }catch (...) { 2039layer_idx = -1 ; 2040 } 2041 } 2042if (layer_idx < 0 ) { 2043COM_ERR ("invalid/unparsable direction tensor layer index in %s\n" ,load_info .fname .c_str ()); 2044result .n_embd = -1 ; 2045break ; 2046 }else if (layer_idx == 0 ) { 2047COM_ERR ("invalid (zero) direction tensor layer index in %s\n" ,load_info .fname .c_str ()); 2048result .n_embd = -1 ; 2049break ; 2050 } 2051 2052struct ggml_tensor * tensor = ggml_get_tensor (ctx ,name .c_str ()); 2053if (tensor -> type != GGML_TYPE_F32 ) { 2054COM_ERR ("invalid (non-F32) direction tensor type in %s\n" ,load_info .fname .c_str ()); 2055result .n_embd = -1 ; 2056break ; 2057 } 2058if (ggml_n_dims (tensor )!= 1 ) { 2059COM_ERR ("invalid (non-1D) direction tensor shape in %s\n" ,load_info .fname .c_str ()); 2060result .n_embd = -1 ; 2061break ; 2062 } 2063 2064if (result .n_embd == -1 ) { 2065result .n_embd = ggml_nelements (tensor ); 2066 }else if (ggml_nelements (tensor )!= result .n_embd ) { 2067COM_ERR ("direction tensor in %s does not match previous dimensions\n" ,load_info .fname .c_str ()); 2068result .n_embd = -1 ; 2069break ; 2070 } 2071 2072// extend if necessary - do not store data for layer 0 (it's not used) 2073result .data .resize (std::max (result .data .size (),static_cast < size_t > (result .n_embd * layer_idx )),0.0f ); 2074 2075const float * src = (const float * )tensor -> data ; 2076float * dst = result .data .data ()+ result .n_embd * (layer_idx - 1 );// layer 1 at [0] 2077for (int j = 0 ;j < result .n_embd ;j ++ ) { 2078dst [j ]+= src [j ]* load_info .strength ;// allows multiple directions for same layer in same file 2079 } 2080 2081 } 2082 2083if (result .n_embd == -1 ) { 2084COM_WRN ("skipping %s due to invalid direction tensors\n" ,load_info .fname .c_str ()); 2085result .data .clear (); 2086 } 2087 2088gguf_free (ctx_gguf ); 2089ggml_free (ctx ); 2090 2091return result ; 2092} 2093 2094common_control_vector_data common_control_vector_load (const std::vector < common_control_vector_load_info > & load_infos ) { 2095common_control_vector_data result = {-1 , {} }; 2096 2097for (const auto & info :load_infos ) { 2098auto cur = common_control_vector_load_one (info ); 2099 2100if (cur .n_embd == -1 ) { 2101result .n_embd = -1 ; 2102break ; 2103 } 2104if (result .n_embd != -1 && result .n_embd != cur .n_embd ) { 2105COM_ERR ("control vectors in %s does not match previous dimensions\n" ,info .fname .c_str ()); 2106result .n_embd = -1 ; 2107break ; 2108 } 2109 2110if (result .n_embd == -1 ) { 2111result = std::move (cur ); 2112 }else { 2113result .data .resize (std::max (result .data .size (),cur .data .size ()),0.0f );// extend if necessary 2114for (size_t i = 0 ;i < cur .data .size ();i ++ ) { 2115result .data [i ]+= cur .data [i ]; 2116 } 2117 } 2118 } 2119 2120if (result .n_embd == -1 ) { 2121COM_ERR ("%s" ,"no valid control vector files passed\n" ); 2122result .data .clear (); 2123 } 2124 2125return result ; 2126} 2127 2128ggml_opt_dataset_t common_opt_dataset_init (struct llama_context * ctx ,const std::vector < llama_token > & tokens ,int64_t stride ) { 2129const int64_t ne_datapoint = llama_n_ctx (ctx ); 2130const int64_t ndata = (tokens .size ()- ne_datapoint - 1 ) /stride ; 2131ggml_opt_dataset_t result = ggml_opt_dataset_init ( 2132GGML_TYPE_I32 ,GGML_TYPE_I32 ,ne_datapoint ,ne_datapoint ,ndata ,/*ndata_shard =*/ 1 ); 2133 2134llama_token * data = (llama_token * )ggml_opt_dataset_data (result )-> data ; 2135llama_token * labels = (llama_token * )ggml_opt_dataset_labels (result )-> data ; 2136 2137for (int64_t idata = 0 ;idata < ndata ;++ idata ) { 2138memcpy (data + idata * ne_datapoint ,tokens .data ()+ idata * stride + 0 ,ne_datapoint * sizeof (llama_token )); 2139memcpy (labels + idata * ne_datapoint ,tokens .data ()+ idata * stride + 1 ,ne_datapoint * sizeof (llama_token )); 2140 } 2141 2142return result ; 2143} 2144 2145ggml_opt_optimizer_params common_opt_lr_pars (void * userdata ) { 2146ggml_opt_optimizer_params result = ggml_opt_get_default_optimizer_params (nullptr ); 2147const lr_opt & d = * (lr_opt * )userdata ; 2148result .adamw .alpha = result .sgd .alpha = d .get_lr (d .epoch ); 2149result .sgd .wd = result .adamw .wd = d .wd ; 2150return result ; 2151} 2152 2153// TODO make all command line args case-insensitive 2154static inline bool eq_case_insensitive (char const * a ,char const * b ) { 2155return ! 2156#if defined(_MSC_VER ) 2157_stricmp 2158#else 2159strcasecmp 2160#endif // defined(_MSC_VER) 2161 (a ,b ); 2162} 2163 2164enum ggml_opt_optimizer_type common_opt_get_optimizer (const char * n ) { 2165if (eq_case_insensitive ("adamw" ,n )) { 2166return GGML_OPT_OPTIMIZER_TYPE_ADAMW ; 2167 } 2168if (eq_case_insensitive ("sgd" ,n )) { 2169return GGML_OPT_OPTIMIZER_TYPE_SGD ; 2170 } 2171return GGML_OPT_OPTIMIZER_TYPE_COUNT ; 2172} 2173 2174// TODO simplify to use just log and exp 2175static float const k_log_2 = std::log (2.f ); 2176 2177void lr_opt::init () { 2178if (lr_min > 0 && lr_min < lr0 ) { 2179float nhalf = std::log (lr0 /lr_min ) /k_log_2 ; 2180float e = epochs ; 2181if (decay_epochs > 0 && decay_epochs < e ) { 2182e = decay_epochs ; 2183 }else { 2184decay_epochs = e ; 2185 } 2186scale_epoch = nhalf /e ; 2187 } 2188} 2189 2190float lr_opt::get_lr (float epoch )const { 2191float r = lr_min <=0 ?lr0 : 2192epoch >=decay_epochs ?lr_min : 2193lr0 * std::pow (0.5f ,epoch * scale_epoch ); 2194LOG_INF ("epoch %.2g lr=%.2g\n" ,epoch ,r ); 2195return r ; 2196} 2197 2198bool common_replay_last_token (struct llama_context * ctx ,llama_token last_token ,int32_t pos ) { 2199llama_batch batch = llama_batch_get_one (& last_token ,1 ); 2200batch .pos = & pos ; 2201if (llama_decode (ctx ,batch )) { 2202LOG_ERR ("%s: failed to replay last token\n" ,__func__ ); 2203return false; 2204 } 2205return true; 2206} 2207 2208bool common_prompt_batch_decode ( 2209struct llama_context * ctx , 2210const std::vector < llama_token > & all_tokens , 2211int n_new , 2212int & n_past , 2213int n_batch , 2214 std::string_view state_path , 2215bool save_state ) { 2216if (n_new == 0 ) { 2217return true; 2218 } 2219const int offset = all_tokens .size ()- n_new ; 2220 2221if (save_state && n_new > 1 ) { 2222const int n_tokens_before_last = n_new - 1 ; 2223 2224GGML_ASSERT (n_new <=n_batch ); 2225 2226// Decode all but the last token so we can save the memory state before decoding the last token. 2227// This is done so we can restore the session state later and replay the last token. 2228// Memory implementations in recurrent/hybrid models don't support removing tokens from their 2229// memory, so we can't just remove the last token from the memory and replay the last token which 2230// is the reason for this logic. 2231if (llama_decode (ctx ,llama_batch_get_one (const_cast < llama_token *> (all_tokens .data ()+ offset ),n_tokens_before_last ))) { 2232COM_ERR ("%s" ,"failed to eval\n" ); 2233return false; 2234 } 2235n_past += n_tokens_before_last ; 2236 2237llama_state_save_file (ctx ,state_path .data (),all_tokens .data (),all_tokens .size ()); 2238COM_INF ("saved session before last token to %s, n_new = %zu\n" ,state_path .data (),all_tokens .size ()); 2239 2240llama_token last_token = all_tokens .back (); 2241llama_batch batch = llama_batch_get_one (& last_token ,1 ); 2242int32_t pos = n_past ; 2243batch .pos = & pos ; 2244 2245if (llama_decode (ctx ,batch )) { 2246COM_ERR ("%s" ,"failed to eval last token\n" ); 2247return false; 2248 } 2249n_past ++ ; 2250 }else { 2251if (llama_decode (ctx ,llama_batch_get_one (const_cast < llama_token *> (all_tokens .data ()+ offset ),n_new ))) { 2252COM_ERR ("%s" ,"failed to eval\n" ); 2253return false; 2254 } 2255n_past += n_new ; 2256 } 2257 2258return true; 2259} 2260 2261size_t common_prompt_checkpoint::size ()const { 2262return data_tgt .size ()+ data_dft .size ()+ data_spec .size (); 2263} 2264 2265bool common_prompt_checkpoint::empty ()const { 2266return data_tgt .empty (); 2267} 2268 2269void common_prompt_checkpoint::clear () { 2270n_tokens = 0 ; 2271 2272pos_min = 0 ; 2273pos_max = 0 ; 2274 2275data_tgt .clear (); 2276data_dft .clear (); 2277data_spec .clear (); 2278} 2279 2280void common_prompt_checkpoint::update_pos ( 2281int64_t n_tokens , 2282llama_pos pos_min , 2283llama_pos pos_max ) { 2284this -> n_tokens = n_tokens ; 2285this -> pos_min = pos_min ; 2286this -> pos_max = pos_max ; 2287} 2288 2289void common_prompt_checkpoint::update_tgt ( 2290llama_context * ctx , 2291llama_seq_id seq_id , 2292llama_state_seq_flags flags ) { 2293if (ctx == nullptr ) { 2294return ; 2295 } 2296 2297const size_t ckpt_size = llama_state_seq_get_size_ext (ctx ,seq_id ,flags ); 2298 2299data_tgt .resize (ckpt_size ); 2300 2301const size_t n = llama_state_seq_get_data_ext (ctx ,data_tgt .data (),ckpt_size ,seq_id ,flags ); 2302if (n != ckpt_size ) { 2303GGML_ABORT ("checkpoint size mismatch: expected %zu, got %zu\n" ,ckpt_size ,n ); 2304 } 2305} 2306 2307void common_prompt_checkpoint::update_dft ( 2308llama_context * ctx , 2309llama_seq_id seq_id , 2310llama_state_seq_flags flags ) { 2311if (ctx == nullptr ) { 2312return ; 2313 } 2314 2315const size_t ckpt_size = llama_state_seq_get_size_ext (ctx ,seq_id ,flags ); 2316 2317data_dft .resize (ckpt_size ); 2318 2319const size_t n = llama_state_seq_get_data_ext (ctx ,data_dft .data (),ckpt_size ,seq_id ,flags ); 2320if (n != ckpt_size ) { 2321GGML_ABORT ("checkpoint size mismatch: expected %zu, got %zu\n" ,ckpt_size ,n ); 2322 } 2323} 2324 2325void common_prompt_checkpoint::load_tgt ( 2326llama_context * ctx , 2327llama_seq_id seq_id , 2328llama_state_seq_flags flags )const { 2329if (ctx == nullptr ) { 2330return ; 2331 } 2332 2333if (data_tgt .empty ()) { 2334return ; 2335 } 2336 2337const size_t n = llama_state_seq_set_data_ext (ctx ,data_tgt .data (),data_tgt .size (),seq_id ,flags ); 2338if (n != data_tgt .size ()) { 2339GGML_ABORT ("checkpoint size mismatch: expected %zu, got %zu\n" ,data_tgt .size (),n ); 2340 } 2341} 2342 2343void common_prompt_checkpoint::load_dft ( 2344llama_context * ctx , 2345llama_seq_id seq_id , 2346llama_state_seq_flags flags )const { 2347if (ctx == nullptr ) { 2348return ; 2349 } 2350 2351if (data_dft .empty ()) { 2352return ; 2353 } 2354 2355const size_t n = llama_state_seq_set_data_ext (ctx ,data_dft .data (),data_dft .size (),seq_id ,flags ); 2356if (n != data_dft .size ()) { 2357GGML_ABORT ("checkpoint size mismatch: expected %zu, got %zu\n" ,data_dft .size (),n ); 2358 } 2359} 2360 2361void common_prompt_checkpoint::clear_tgt () { 2362data_tgt .clear (); 2363} 2364 2365void common_prompt_checkpoint::clear_dft () { 2366data_dft .clear (); 2367data_spec .clear (); 2368}