char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Charlotte Somenc/dec in server context8300f1411

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