char-fork/llama.cpp

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

Xuan-Son Nguyencommon: add LOG_JSON macro to log structured data (#28586)8e330954a

char/aliceai-t5-moe
215.0 KiB4754 linesraw
1#include "arg.h"
2
3#include "build-info.h"
4#include "chat.h"
5#include "common.h"
6#include "download.h"
7#include "json-schema-to-grammar.h"
8#include "json.h"
9#include "llama.h"
10#include "log.h"
11#include "sampling.h"
12#include "speculative.h"
13#include "preset.h"
14
15// fix problem with std::min and std::max
16#if defined(_WIN32)
17#define WIN32_LEAN_AND_MEAN
18#ifndef NOMINMAX
19#   define NOMINMAX
20#endif
21#include <windows.h>
22#include <shellapi.h>
23#endif
24
25#include <algorithm>
26#include <cinttypes>
27#include <climits>
28#include <cmath>
29#include <cstdarg>
30#include <filesystem>
31#include <fstream>
32#include <list>
33#include <numeric>
34#include <regex>
35#include <set>
36#include <string>
37#include <system_error>
38#include <thread> // for hardware_concurrency
39#include <vector>
40
41#ifndef __EMSCRIPTEN__
42#ifdef __linux__
43#include <linux/limits.h>
44#elif defined(_WIN32)
45#   if !defined(PATH_MAX)
46#   define PATH_MAX MAX_PATH
47#   endif
48#elif defined(_AIX)
49#include <sys/limits.h>
50#else
51#include <sys/syslimits.h>
52#endif
53#endif
54
55#define LLAMA_MAX_URL_LENGTH 2084 // Maximum URL Length in Chrome: 2083
56
57using json = common_json;
58using namespace common_arg_utils;
59
60static std::initializer_list<enum llama_example> mmproj_examples = {
61    LLAMA_EXAMPLE_MTMD,
62    LLAMA_EXAMPLE_SERVER,
63    LLAMA_EXAMPLE_CLI,
64    LLAMA_EXAMPLE_TTS,
65};
66
67static std::string read_file(const std::string & fname) {
68    std::ifstream file(fname);
69    if (!file) {
70        throw std::runtime_error(string_format("error: failed to open file '%s'\n", fname.c_str()));
71    }
72    std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
73    file.close();
74    return content;
75}
76
77static const std::vector<common_arg> & get_common_arg_defs() {
78    static const std::vector<common_arg> options = [] {
79        common_params params;
80        auto ctx = common_params_parser_init(params, LLAMA_EXAMPLE_SERVER, nullptr);
81        return ctx.options;
82    }();
83    return options;
84}
85
86common_arg & common_arg::set_examples(std::initializer_list<enum llama_example> examples) {
87    this->examples = examples;
88    return *this;
89}
90
91common_arg & common_arg::set_excludes(std::initializer_list<enum llama_example> excludes) {
92    this->excludes = excludes;
93    return *this;
94}
95
96common_arg & common_arg::set_env(const char * env) {
97    help = help + "\n(env: " + env + ")";
98    this->env = env;
99    return *this;
100}
101
102common_arg & common_arg::set_sampling() {
103    is_sampling = true;
104    return *this;
105}
106
107common_arg & common_arg::set_spec() {
108    is_spec = true;
109    return *this;
110}
111
112common_arg & common_arg::set_preset_only() {
113    is_preset_only = true;
114    return *this;
115}
116
117bool common_arg::in_example(enum llama_example ex) {
118    return examples.find(ex) != examples.end();
119}
120
121bool common_arg::is_exclude(enum llama_example ex) {
122    return excludes.find(ex) != excludes.end();
123}
124
125bool common_arg::get_value_from_env(std::string & output) const {
126    if (env == nullptr) return false;
127    if (!args_neg.empty()) {
128        // for compatibility, we need to check LLAMA_ARG_NO_ env as well
129        std::string neg_env = env;
130        string_replace_all(neg_env, "LLAMA_ARG_", "LLAMA_ARG_NO_");
131        char * neg_value = std::getenv(neg_env.c_str());
132        if (neg_value) {
133            output = "0"; // falsey
134            return true;
135        }
136    }
137    char * value = std::getenv(env);
138    if (value) {
139        output = value;
140        return true;
141    }
142    return false;
143}
144
145bool common_arg::has_value_from_env() const {
146    if (env != nullptr && !args_neg.empty()) {
147        // for compatibility, we need to check LLAMA_ARG_NO_ env as well
148        std::string neg_env = env;
149        string_replace_all(neg_env, "LLAMA_ARG_", "LLAMA_ARG_NO_");
150        if (std::getenv(neg_env.c_str())) {
151            return true;
152        }
153    }
154    return env != nullptr && std::getenv(env);
155}
156
157static std::vector<std::string> break_str_into_lines(std::string input, size_t max_char_per_line) {
158    std::vector<std::string> result;
159    std::istringstream iss(input);
160    std::string line;
161    auto add_line = [&](const std::string& l) {
162        if (l.length() <= max_char_per_line) {
163            result.push_back(l);
164        } else {
165            std::istringstream line_stream(l);
166            std::string word, current_line;
167            while (line_stream >> word) {
168                if (current_line.length() + !current_line.empty() + word.length() > max_char_per_line) {
169                    if (!current_line.empty()) result.push_back(current_line);
170                    current_line = word;
171                } else {
172                    current_line += (!current_line.empty() ? " " : "") + word;
173                }
174            }
175            if (!current_line.empty()) result.push_back(current_line);
176        }
177    };
178    while (std::getline(iss, line)) {
179        add_line(line);
180    }
181    return result;
182}
183
184std::string common_arg::to_string() const {
185    // params for printing to console
186    const static int n_leading_spaces = 40;
187    const static int n_char_per_line_help = 70; // TODO: detect this based on current console
188    std::string leading_spaces(n_leading_spaces, ' ');
189
190    std::ostringstream ss;
191    auto all_args = get_args(); // also contains args_neg
192    for (const auto & arg : all_args) {
193        if (arg == all_args.front()) {
194            if (all_args.size() == 1) {
195                ss << arg;
196            } else {
197                // first arg is usually abbreviation, we need padding to make it more beautiful
198                auto tmp = std::string(arg) + ", ";
199                auto spaces = std::string(std::max(0, 7 - (int)tmp.size()), ' ');
200                ss << tmp << spaces;
201            }
202        } else {
203            ss << arg << (arg != all_args.back() ? ", " : "");
204        }
205    }
206    if (value_hint) ss << " " << value_hint;
207    if (value_hint_2) ss << " " << value_hint_2;
208    if (ss.tellp() > n_leading_spaces - 3) {
209        // current line is too long, add new line
210        ss << "\n" << leading_spaces;
211    } else {
212        // padding between arg and help, same line
213        ss << std::string(leading_spaces.size() - ss.tellp(), ' ');
214    }
215    const auto help_lines = break_str_into_lines(help, n_char_per_line_help);
216    for (const auto & line : help_lines) {
217        ss << (&line == &help_lines.front() ? "" : leading_spaces) << line << "\n";
218    }
219    return ss.str();
220}
221
222std::vector<std::string> common_arg::get_args() const {
223    std::vector<std::string> result;
224    for (const auto & arg : args) {
225        result.push_back(std::string(arg));
226    }
227    for (const auto & arg : args_neg) {
228        result.push_back(std::string(arg));
229    }
230    return result;
231}
232
233std::vector<std::string> common_arg::get_env() const {
234    std::vector<std::string> result;
235    if (env) {
236        result.push_back(std::string(env));
237    }
238    if (!args_neg.empty() && env) {
239        // for compatibility, we need to add LLAMA_ARG_NO_ variant
240        std::string neg_env = env;
241        string_replace_all(neg_env, "LLAMA_ARG_", "LLAMA_ARG_NO_");
242        result.push_back(neg_env);
243    }
244    return result;
245}
246
247//
248// utils
249//
250
251// Helper function to parse tensor buffer override strings
252static void parse_tensor_buffer_overrides(const std::string & value, std::vector<llama_model_tensor_buft_override> & overrides) {
253    ggml_backend_load_all();
254
255    std::map<std::string, ggml_backend_buffer_type_t> buft_list;
256    for (size_t i = 0; i < ggml_backend_dev_count(); ++i) {
257        auto * dev = ggml_backend_dev_get(i);
258        auto * buft = ggml_backend_dev_buffer_type(dev);
259        if (buft) {
260            buft_list[ggml_backend_buft_name(buft)] = buft;
261        }
262    }
263
264    for (const auto & override : string_split<std::string>(value, ',')) {
265        std::string::size_type pos = override.find('=');
266        if (pos == std::string::npos) {
267            throw std::invalid_argument("invalid value");
268        }
269        std::string tensor_name = override.substr(0, pos);
270        std::string buffer_type = override.substr(pos + 1);
271
272        if (buft_list.find(buffer_type) == buft_list.end()) {
273            printf("Available buffer types:\n");
274            for (const auto & it : buft_list) {
275                printf("  %s\n", ggml_backend_buft_name(it.second));
276            }
277            throw std::invalid_argument("unknown buffer type");
278        }
279        // keep strings alive and avoid leaking memory by storing them in a static vector
280        static std::list<std::string> buft_overrides;
281        buft_overrides.push_back(tensor_name);
282        overrides.push_back({buft_overrides.back().c_str(), buft_list.at(buffer_type)});
283    }
284}
285
286static std::string clean_file_name(const std::string & fname) {
287    std::string clean_fname = fname;
288    string_replace_all(clean_fname, "\\", "_");
289    string_replace_all(clean_fname, "/", "_");
290    return clean_fname;
291}
292
293struct handle_model_result {
294    bool found_mmproj = false;
295    common_params_model mmproj;
296
297    bool found_mtp = false;
298    common_params_model mtp;
299
300    bool found_preset = false;
301    std::string preset_path;
302};
303
304const std::vector<ggml_type> kv_cache_types = {
305    GGML_TYPE_F32,
306    GGML_TYPE_F16,
307    GGML_TYPE_BF16,
308    GGML_TYPE_Q8_0,
309    GGML_TYPE_Q4_0,
310    GGML_TYPE_Q4_1,
311    GGML_TYPE_IQ4_NL,
312    GGML_TYPE_Q5_0,
313    GGML_TYPE_Q5_1,
314};
315
316static ggml_type kv_cache_type_from_str(const std::string & s) {
317    for (const auto & type : kv_cache_types) {
318        if (ggml_type_name(type) == s) {
319            return type;
320        }
321    }
322    throw std::runtime_error("Unsupported cache type: " + s);
323}
324
325static std::string get_all_kv_cache_types() {
326    std::ostringstream msg;
327    for (const auto & type : kv_cache_types) {
328        msg << ggml_type_name(type) << (&type == &kv_cache_types.back() ? "" : ", ");
329    }
330    return msg.str();
331}
332
333static bool parse_bool_value(const std::string & value) {
334    if (is_truthy(value)) {
335        return true;
336    } else if (is_falsey(value)) {
337        return false;
338    } else {
339        throw std::invalid_argument("invalid boolean value");
340    }
341}
342
343[[noreturn]] static void arg_removed(const std::string & msg) {
344    throw std::invalid_argument("the argument has been removed. " + msg);
345}
346
347//
348// common_models_handler
349//
350
351static std::string get_default_local_path(const std::string & url) {
352    auto f = string_split<std::string>(url, '#').front();
353    f = string_split<std::string>(f, '?').front();
354    return fs_get_cache_file(string_split<std::string>(f, '/').back());
355}
356
357static bool spec_types_is_default(const common_params & params) {
358    return params.speculative.types == std::vector<enum common_speculative_type>{COMMON_SPECULATIVE_TYPE_NONE};
359}
360
361common_models_handler common_models_handler_init(const common_params & params, llama_example curr_ex) {
362    common_download_hf_plan plan;
363    common_download_hf_plan plan_spec;
364    common_download_opts opts;
365
366    const bool spec_type_draft_mtp = std::find(params.speculative.types.begin(),
367                                        params.speculative.types.end(),
368                                        COMMON_SPECULATIVE_TYPE_DRAFT_MTP) != params.speculative.types.end();
369
370    const bool spec_type_draft_dflash = std::find(params.speculative.types.begin(),
371                                           params.speculative.types.end(),
372                                           COMMON_SPECULATIVE_TYPE_DRAFT_DFLASH) != params.speculative.types.end();
373
374    const bool spec_type_draft_eagle3 = std::find(params.speculative.types.begin(),
375                                           params.speculative.types.end(),
376                                           COMMON_SPECULATIVE_TYPE_DRAFT_EAGLE3) != params.speculative.types.end();
377
378    const bool spec_type_draft_dspark = std::find(params.speculative.types.begin(),
379                                           params.speculative.types.end(),
380                                           COMMON_SPECULATIVE_TYPE_DRAFT_DSPARK) != params.speculative.types.end();
381
382    // only download mmproj if the current example is using it
383    bool use_mmproj = false;
384    for (const auto & ex : mmproj_examples) {
385        if (curr_ex == ex) {
386            use_mmproj = true;
387            break;
388        }
389    }
390
391    opts.bearer_token    = params.hf_token;
392    opts.offline         = params.offline;
393    opts.download_mtp    = spec_type_draft_mtp;
394    opts.download_eagle3 = spec_type_draft_eagle3;
395    opts.download_dflash = spec_type_draft_dflash;
396    opts.download_dspark = spec_type_draft_dspark;
397    opts.download_mmproj = use_mmproj && !params.no_mmproj
398                        && params.mmproj.path.empty() && params.mmproj.url.empty();
399
400    if (!params.model.hf_repo.empty()) {
401        plan = common_download_get_hf_plan(params.model, opts);
402    }
403
404    if (!params.speculative.draft.mparams.hf_repo.empty()) {
405        // without a requested type, discover every sidecar the draft repo ships to infer the type later
406        auto opts_spec = opts;
407        if (spec_types_is_default(params)) {
408            opts_spec.download_mtp    = true;
409            opts_spec.download_dflash = true;
410            opts_spec.download_eagle3 = true;
411            opts_spec.download_dspark = true;
412        }
413        plan_spec = common_download_get_hf_plan(params.speculative.draft.mparams, opts_spec);
414    }
415
416    return common_models_handler{plan, plan_spec, opts};
417}
418
419bool common_models_handler_is_preset_repo(const common_models_handler & handler) {
420    return !handler.plan.preset.url.empty();
421}
422
423static std::vector<common_download_task> build_url_tasks(const common_params_model & model, common_download_opts opts) {
424    auto parts = common_download_get_all_parts(model.url);
425    std::vector<common_download_task> tasks;
426
427    // single-part: download straight to model.path if the user gave one (-m), else the cache default
428    if (parts.size() == 1) {
429        common_download_task task;
430        task.url        = parts[0];
431        task.local_path = model.path.empty() ? get_default_local_path(parts[0]) : model.path;
432        task.opts       = opts;
433        tasks.push_back(std::move(task));
434        return tasks;
435    }
436
437    // multi-part: place each part under the user's -m directory (if given), else the cache default
438    std::string base_dir;
439    if (!model.path.empty()) {
440        auto pos = model.path.rfind('/');
441        base_dir = pos == std::string::npos ? std::string(".") : model.path.substr(0, pos);
442    }
443
444    for (const auto & part : parts) {
445        common_download_task task;
446        task.url  = part;
447        task.opts = opts;
448
449        std::string local = get_default_local_path(part);
450        if (!base_dir.empty()) {
451            auto pos = local.rfind('/');
452            std::string name = pos == std::string::npos ? local : local.substr(pos + 1);
453            local = base_dir + "/" + name;
454        }
455        task.local_path = local;
456        tasks.push_back(std::move(task));
457    }
458    return tasks;
459}
460
461void common_models_handler_apply(common_models_handler & handler, common_params & params, common_download_callback * callback) {
462    std::vector<common_download_task> tasks;
463
464    auto & plan      = handler.plan;
465    auto & plan_spec = handler.plan_spec;
466
467    auto opts = handler.opts; // copy
468    opts.callback = callback;
469
470    // handle plain "url" if needed
471    auto handle_url = [&](common_params_model & model) {
472        if (!model.url.empty()) {
473            if (model.path.empty()) {
474                model.path = get_default_local_path(model.url);
475            }
476        }
477    };
478    handle_url(params.model);
479    handle_url(params.mmproj);
480    handle_url(params.speculative.draft.mparams);
481
482    // optionally, if docker repo is set, resolve it
483    if (!params.model.docker_repo.empty()) {
484        params.model.url  = common_docker_resolve_model(params.model.docker_repo);
485        params.model.path = get_default_local_path(params.model.url);
486    }
487
488    // handle plain "url" tasks (non-hf)
489    if (!params.model.url.empty()) {
490        auto url_tasks = build_url_tasks(params.model, opts);
491        // the first part is what gets loaded, so point params.model.path at it
492        if (!url_tasks.empty()) {
493            std::string first_path = url_tasks.front().local_path;
494            url_tasks.front().on_done = [&, first_path]() { params.model.path = first_path; };
495        }
496        for (auto & task : url_tasks) {
497            tasks.push_back(std::move(task));
498        }
499    }
500    if (!params.mmproj.url.empty()) {
501        common_download_task task;
502        task.url        = params.mmproj.url;
503        task.local_path = params.mmproj.path;
504        task.opts       = opts;
505        tasks.push_back(task);
506    }
507    bool had_spec_url = false;
508    if (!params.speculative.draft.mparams.url.empty()) {
509        common_download_task task;
510        task.url        = params.speculative.draft.mparams.url;
511        task.local_path = params.speculative.draft.mparams.path;
512        task.opts       = opts;
513        tasks.push_back(task);
514        had_spec_url = true;
515    }
516
517    // handle hf_plan tasks
518    auto add_tasks = [&opts, &tasks](const hf_cache::hf_files  & model_files,
519                                    const hf_cache::hf_file    & primary,
520                                    common_params_model        & model) {
521        for (size_t i = 0; i < model_files.size(); ++i) {
522            auto & model_file = model_files[i];
523            bool is_primary = (model_file.path == primary.path);
524            tasks.emplace_back(model_file, opts, [&, is_primary]() {
525                if (is_primary) {
526                    // the primary file is the first split (00001-of), use it as model path
527                    model.path = hf_cache::finalize_file(model_file);
528                } else {
529                    hf_cache::finalize_file(model_file);
530                }
531            });
532        }
533    };
534
535    // an explicit draft file selection (e.g. -md with -hfd) disables the sidecar resolution of the draft repo
536    if (!params.speculative.draft.mparams.hf_file.empty()) {
537        plan_spec.mtp    = {};
538        plan_spec.dflash = {};
539        plan_spec.eagle3 = {};
540        plan_spec.dspark = {};
541    }
542
543    // infer the speculative type from the sidecar shipped by the draft repo when none is requested
544    if (spec_types_is_default(params)) {
545        if (!plan_spec.mtp.local_path.empty()) {
546            params.speculative.types = { COMMON_SPECULATIVE_TYPE_DRAFT_MTP };
547            plan_spec.dspark = {};
548            plan_spec.dflash = {};
549            plan_spec.eagle3 = {};
550        } else if (!plan_spec.dspark.local_path.empty()) {
551            // dspark outranks dflash, its sidecar carries the extra Markov head
552            params.speculative.types = { COMMON_SPECULATIVE_TYPE_DRAFT_DSPARK };
553            plan_spec.dflash = {};
554            plan_spec.eagle3 = {};
555        } else if (!plan_spec.dflash.local_path.empty()) {
556            params.speculative.types = { COMMON_SPECULATIVE_TYPE_DRAFT_DFLASH };
557            plan_spec.eagle3 = {};
558        } else if (!plan_spec.eagle3.local_path.empty()) {
559            params.speculative.types = { COMMON_SPECULATIVE_TYPE_DRAFT_EAGLE3 };
560        }
561    }
562
563    // infer the speculative type from the draft GGUF metadata when none is requested
564    // note: reads only the first split - sharded drafts need an explicit --spec-type
565    if (spec_types_is_default(params) && !params.speculative.draft.mparams.path.empty()) {
566        const auto types_gguf = common_speculative_types_from_gguf(params.speculative.draft.mparams.path);
567        if (!types_gguf.empty()) {
568            params.speculative.types = types_gguf;
569        }
570    }
571
572    // when a sidecar type is requested, the draft repo resolves to its sidecar instead of a full model
573    const bool spec_sidecar_found = !plan_spec.mtp.local_path.empty() ||
574                                    !plan_spec.dflash.local_path.empty() ||
575                                    !plan_spec.eagle3.local_path.empty() ||
576                                    !plan_spec.dspark.local_path.empty();
577    if (!plan_spec.mtp.local_path.empty() && !had_spec_url) {
578        tasks.emplace_back(plan_spec.mtp, opts, [&]() {
579            // only use the discovered MTP head when no draft path is set yet
580            if (params.speculative.draft.mparams.path.empty()) {
581                params.speculative.draft.mparams.path = hf_cache::finalize_file(plan_spec.mtp);
582            } else {
583                hf_cache::finalize_file(plan_spec.mtp);
584            }
585        });
586    }
587    if (!plan_spec.dflash.local_path.empty() && !had_spec_url) {
588        tasks.emplace_back(plan_spec.dflash, opts, [&]() {
589            // only use the discovered DFlash sidecar when no draft path is set yet
590            if (params.speculative.draft.mparams.path.empty()) {
591                params.speculative.draft.mparams.path = hf_cache::finalize_file(plan_spec.dflash);
592            } else {
593                hf_cache::finalize_file(plan_spec.dflash);
594            }
595        });
596    }
597    if (!plan_spec.eagle3.local_path.empty() && !had_spec_url) {
598        tasks.emplace_back(plan_spec.eagle3, opts, [&]() {
599            // only use the discovered Eagle3 sidecar when no draft path is set yet
600            if (params.speculative.draft.mparams.path.empty()) {
601                params.speculative.draft.mparams.path = hf_cache::finalize_file(plan_spec.eagle3);
602            } else {
603                hf_cache::finalize_file(plan_spec.eagle3);
604            }
605        });
606    }
607    if (!plan_spec.dspark.local_path.empty() && !had_spec_url) {
608        tasks.emplace_back(plan_spec.dspark, opts, [&]() {
609            // only use the discovered DSpark sidecar when no draft path is set yet
610            if (params.speculative.draft.mparams.path.empty()) {
611                params.speculative.draft.mparams.path = hf_cache::finalize_file(plan_spec.dspark);
612            } else {
613                hf_cache::finalize_file(plan_spec.dspark);
614            }
615        });
616    }
617
618    // a wired draft sidecar counts as an explicit draft for the main plan fallback below
619    if (spec_sidecar_found) {
620        had_spec_url = true;
621    }
622
623    // handle plan_spec (e.g. --spec-draft-hf)
624    if (!plan_spec.model_files.empty() && !had_spec_url && !spec_sidecar_found) {
625        add_tasks(plan_spec.model_files, plan_spec.primary, params.speculative.draft.mparams);
626        had_spec_url = true;
627    }
628
629    if (!plan.model_files.empty()) {
630        add_tasks(plan.model_files, plan.primary, params.model);
631    }
632    if (!plan.mmproj.local_path.empty()) {
633        tasks.emplace_back(plan.mmproj, opts, [&]() {
634            params.mmproj.path = hf_cache::finalize_file(plan.mmproj);
635        });
636    }
637    if (!plan.mtp.local_path.empty() && !had_spec_url) {
638        tasks.emplace_back(plan.mtp, opts, [&]() {
639            // only fall back to the discovered MTP head when no draft was explicitly provided
640            if (params.speculative.draft.mparams.empty()) {
641                params.speculative.draft.mparams.path = hf_cache::finalize_file(plan.mtp);
642            } else {
643                hf_cache::finalize_file(plan.mtp);
644            }
645        });
646    }
647    if (!plan.dflash.local_path.empty() && !had_spec_url) {
648        tasks.emplace_back(plan.dflash, opts, [&]() {
649            // only fall back to the discovered DFlash sidecar when no draft was explicitly provided
650            if (params.speculative.draft.mparams.empty()) {
651                params.speculative.draft.mparams.path = hf_cache::finalize_file(plan.dflash);
652            } else {
653                hf_cache::finalize_file(plan.dflash);
654            }
655        });
656    }
657    if (!plan.eagle3.local_path.empty() && !had_spec_url) {
658        tasks.emplace_back(plan.eagle3, opts, [&]() {
659            // only fall back to the discovered Eagle3 sidecar when no draft was explicitly provided
660            if (params.speculative.draft.mparams.empty()) {
661                params.speculative.draft.mparams.path = hf_cache::finalize_file(plan.eagle3);
662            } else {
663                hf_cache::finalize_file(plan.eagle3);
664            }
665        });
666    }
667    if (!plan.dspark.local_path.empty() && !had_spec_url) {
668        tasks.emplace_back(plan.dspark, opts, [&]() {
669            // only fall back to the discovered DSpark sidecar when no draft was explicitly provided
670            if (params.speculative.draft.mparams.empty()) {
671                params.speculative.draft.mparams.path = hf_cache::finalize_file(plan.dspark);
672            } else {
673                hf_cache::finalize_file(plan.dspark);
674            }
675        });
676    }
677    if (!plan.preset.local_path.empty()) {
678        tasks.emplace_back(plan.preset, opts, [&]() {
679            // if HF repo is a preset repo, we simply run server in router mode with the preset.ini file
680            params.models_preset_hf = params.model.hf_repo; // only for showing a warning
681            params.models_preset    = hf_cache::finalize_file(plan.preset);
682            params.model = common_params_model{}; // make sure to clear model, so server starts in router mode
683        });
684    }
685
686    // run all tasks in parallel
687    if (!params.offline) {
688        // if duplicated files are found, only download once (but still call on_done for each task)
689        std::unordered_map<std::string, common_download_task *> unique_tasks;
690        for (auto & task : tasks) {
691            auto it = unique_tasks.find(task.local_path);
692            if (it == unique_tasks.end()) {
693                unique_tasks[task.local_path] = &task;
694            }
695        }
696        std::vector<common_download_task> unique_tasks_vec;
697        for (auto & pair : unique_tasks) {
698            LOG_DBG("download task: %s -> %s\n", pair.second->url.c_str(), pair.second->local_path.c_str());
699            unique_tasks_vec.push_back(*pair.second);
700        }
701        common_download_run_tasks(unique_tasks_vec);
702    }
703
704    // download successful, update params with the downloaded paths
705    for (const auto & task : tasks) {
706        if (task.on_done) {
707            task.on_done();
708        }
709    }
710}
711
712//
713// CLI argument parsing functions
714//
715
716// apply config files (if present), a later file overrides an earlier one:
717// 1. system-wide: /etc/llama.cpp/config.ini (%PROGRAMDATA%\llama.cpp\config.ini on windows)
718// 2. user-level: ${XDG_CONFIG_HOME:-~/.config}/llama.cpp/config.ini (%APPDATA%\llama.cpp\config.ini on windows)
719static void common_params_apply_system_config(common_params & params, llama_example ex) {
720    std::vector<std::string> paths;
721
722#if defined(_WIN32)
723    const std::string program_data = common_get_env("PROGRAMDATA");
724    if (!program_data.empty()) {
725        paths.push_back(program_data + "\\llama.cpp\\config.ini");
726    }
727#else
728    paths.push_back("/etc/llama.cpp/config.ini");
729#endif
730
731    try {
732        paths.push_back(fs_get_config_directory() + "config.ini");
733    } catch (const std::exception & e) {
734        LOG_DBG("cannot read user-level config file, skipping: %s\n", e.what());
735    }
736
737    std::vector<std::string> found;
738    for (const auto & path : paths) {
739        std::error_code ec;
740        if (std::filesystem::exists(path, ec)) {
741            found.push_back(path);
742        }
743    }
744    if (found.empty()) {
745        return;
746    }
747
748    common_preset_context ctx(ex);
749    ctx.ignore_unknown_keys = true; // the same config file is shared by all programs
750    for (const auto & path : found) {
751        LOG_INF("using config file: %s\n", path.c_str());
752        common_preset global;
753        common_presets presets = ctx.load_from_ini(path, global);
754        global.apply_to_params(params);
755        auto it = presets.find(COMMON_PRESET_DEFAULT_NAME);
756        if (it != presets.end()) {
757            it->second.apply_to_params(params);
758        }
759    }
760}
761
762static bool common_params_parse_ex(int argc, char ** argv, common_params_context & ctx_arg) {
763    common_params & params = ctx_arg.params;
764
765    // setup log directly from params.verbosity: see tools/cli/cli.cpp
766    common_log_set_verbosity_thold(params.verbosity);
767
768    // config file applies first, so env variables and CLI arguments override it
769    common_params_apply_system_config(params, ctx_arg.ex);
770
771    std::unordered_map<std::string, std::pair<common_arg *, bool>> arg_to_options;
772    for (auto & opt : ctx_arg.options) {
773        for (const auto & arg : opt.args) {
774            arg_to_options[arg] = {&opt, /* is_positive */ true};
775        }
776        for (const auto & arg : opt.args_neg) {
777            arg_to_options[arg] = {&opt, /* is_positive */ false};
778        }
779    }
780
781    // handle environment variables
782    for (auto & opt : ctx_arg.options) {
783        std::string value;
784        if (opt.get_value_from_env(value)) {
785            try {
786                if (opt.handler_void && is_truthy(value)) {
787                    opt.handler_void(params);
788                }
789                if (opt.handler_int) {
790                    opt.handler_int(params, std::stoi(value));
791                }
792                if (opt.handler_bool) {
793                    opt.handler_bool(params, parse_bool_value(value));
794                }
795                if (opt.handler_string) {
796                    opt.handler_string(params, value);
797                    continue;
798                }
799            } catch (std::exception & e) {
800                throw std::invalid_argument(string_format(
801                    "error while handling environment variable \"%s\": %s\n\n", opt.env, e.what()));
802            }
803        }
804    }
805
806    // handle command line arguments
807    auto check_arg = [&](int i) {
808        if (i+1 >= argc) {
809            throw std::invalid_argument("expected value for argument");
810        }
811    };
812
813    auto parse_cli_args = [&]() {
814        std::set<std::string> seen_args;
815
816        for (int i = 1; i < argc; i++) {
817            const std::string arg_prefix = "--";
818
819            std::string arg = argv[i];
820            if (arg.compare(0, arg_prefix.size(), arg_prefix) == 0) {
821                std::replace(arg.begin(), arg.end(), '_', '-');
822            }
823            if (arg_to_options.find(arg) == arg_to_options.end()) {
824                throw std::invalid_argument(string_format("error: invalid argument: %s", arg.c_str()));
825            }
826            if (!seen_args.insert(arg).second) {
827                const bool skip = (arg == "--spec-type");
828
829                if (!skip) {
830                    LOG_WRN("DEPRECATED: argument '%s' specified multiple times, use comma-separated values instead (only last value will be used)\n", arg.c_str());
831                }
832            }
833            auto & tmp = arg_to_options[arg];
834            auto opt = *tmp.first;
835            bool is_positive = tmp.second;
836            if (opt.has_value_from_env()) {
837                fprintf(stderr, "warn: %s environment variable is set, but will be overwritten by command line argument %s\n", opt.env, arg.c_str());
838            }
839            try {
840                if (opt.handler_void) {
841                    opt.handler_void(params);
842                    continue;
843                }
844                if (opt.handler_bool) {
845                    opt.handler_bool(params, is_positive);
846                    continue;
847                }
848
849                // arg with single value
850                check_arg(i);
851                std::string val = argv[++i];
852                if (opt.handler_int) {
853                    opt.handler_int(params, std::stoi(val));
854                    continue;
855                }
856                if (opt.handler_string) {
857                    opt.handler_string(params, val);
858                    continue;
859                }
860
861                // arg with 2 values
862                check_arg(i);
863                std::string val2 = argv[++i];
864                if (opt.handler_str_str) {
865                    opt.handler_str_str(params, val, val2);
866                    continue;
867                }
868            } catch (std::exception & e) {
869                throw std::invalid_argument(string_format(
870                    "error while handling argument \"%s\": %s\n\n"
871                    "usage:\n%s\n\nto show complete usage, run with -h",
872                    arg.c_str(), e.what(), opt.to_string().c_str()));
873            }
874        }
875    };
876
877    // parse all CLI args now, so that -hf is available below for remote preset resolution
878    parse_cli_args();
879
880    postprocess_cpu_params(params.cpuparams,       nullptr);
881    postprocess_cpu_params(params.cpuparams_batch, &params.cpuparams);
882
883    postprocess_cpu_params(params.speculative.draft.cpuparams,       &params.cpuparams);
884    postprocess_cpu_params(params.speculative.draft.cpuparams_batch, &params.cpuparams_batch);
885
886    // default the mmproj device to the global device selection if not set explicitly with -mmdev
887    if (params.mmproj_use_gpu && params.mmproj_device == nullptr && !params.devices.empty()) {
888        params.mmproj_device = params.devices.front();
889        params.mmproj_use_gpu = params.mmproj_device != nullptr;
890    }
891
892    if (params.prompt_cache_all && (params.interactive || params.interactive_first)) {
893        throw std::invalid_argument("error: --prompt-cache-all not supported in interactive mode yet\n");
894    }
895
896    const bool skip_model_download =
897        // server will call common_params_handle_models() later, so we skip it here
898        ctx_arg.ex == LLAMA_EXAMPLE_SERVER ||
899        // download calls common_params_handle_models() itself and prints the paths
900        ctx_arg.ex == LLAMA_EXAMPLE_DOWNLOAD ||
901        // export_graph_ops loads only metadata
902        ctx_arg.ex == LLAMA_EXAMPLE_EXPORT_GRAPH_OPS;
903
904    if (!skip_model_download) {
905        // handle model and download
906        common_models_handler handler = common_models_handler_init(params, ctx_arg.ex);
907        common_models_handler_apply(handler, params);
908
909        // model is required (except for server)
910        // TODO @ngxson : maybe show a list of available models in CLI in this case
911        bool can_skip_model = params.usage || params.completion || !params.server_base.empty();
912        if (!can_skip_model && params.model.path.empty()) {
913            throw std::invalid_argument("error: --model is required\n");
914        }
915    }
916
917    if (params.escape) {
918        string_process_escapes(params.prompt);
919        string_process_escapes(params.input_prefix);
920        string_process_escapes(params.input_suffix);
921        for (auto & antiprompt : params.antiprompt) {
922            string_process_escapes(antiprompt);
923        }
924        for (auto & seq_breaker : params.sampling.dry_sequence_breakers) {
925            string_process_escapes(seq_breaker);
926        }
927    }
928
929    if (!params.kv_overrides.empty()) {
930        params.kv_overrides.emplace_back();
931        params.kv_overrides.back().key[0] = 0;
932    }
933
934    const bool mcp_enabled = !params.mcp_servers_config.empty() || !params.mcp_servers_json.empty();
935    if ((!params.server_tools.empty() || mcp_enabled) && !params.cors_origins_explicit) {
936        LOG_WRN("server tools or MCP servers are enabled, using localhost as default CORS origin (change via --cors-origins)\n");
937        params.cors_origins = "localhost";
938    }
939
940    // pad tensor_buft_overrides for llama_params_fit:
941    const size_t ntbo = llama_max_tensor_buft_overrides();
942    while (params.tensor_buft_overrides.size() < ntbo) {
943        params.tensor_buft_overrides.push_back({nullptr, nullptr});
944    }
945
946    if (!params.speculative.draft.tensor_buft_overrides.empty()) {
947        params.speculative.draft.tensor_buft_overrides.push_back({nullptr, nullptr});
948    }
949
950    if (!params.chat_template.empty() && !common_chat_verify_template(params.chat_template, params.use_jinja)) {
951        throw std::runtime_error(string_format(
952            "error: the supplied chat template is not supported: %s%s\n",
953            params.chat_template.c_str(),
954            params.use_jinja ? "" : "\nnote: llama.cpp was started without --jinja, we only support commonly used templates"
955        ));
956    }
957
958    // if the preserve_reasoning kwarg was not specified explicitly, enable it by default
959    if (!params.default_template_kwargs.count("preserve_reasoning")) {
960        params.default_template_kwargs["preserve_reasoning"] = "true";
961    }
962
963    return true;
964}
965
966static void common_params_print_usage(common_params_context & ctx_arg) {
967    auto print_options = [](std::vector<common_arg *> & options) {
968        for (common_arg * opt : options) {
969            printf("%s", opt->to_string().c_str());
970        }
971    };
972
973    std::vector<common_arg *> common_options;
974    std::vector<common_arg *> sampling_options;
975    std::vector<common_arg *> spec_options;
976    std::vector<common_arg *> specific_options;
977    for (auto & opt : ctx_arg.options) {
978        // in case multiple LLAMA_EXAMPLE_* are set, we prioritize the LLAMA_EXAMPLE_* matching current example
979        if (opt.is_sampling) {
980            sampling_options.push_back(&opt);
981        } else if (opt.is_spec) {
982            spec_options.push_back(&opt);
983        } else if (opt.in_example(ctx_arg.ex)) {
984            specific_options.push_back(&opt);
985        } else {
986            common_options.push_back(&opt);
987        }
988    }
989    bool first = true;
990    auto print_section = [&](const char * header, std::vector<common_arg *> & options) {
991        if (options.empty()) {
992            return;
993        }
994        printf("%s----- %s -----\n\n", first ? "" : "\n\n", header);
995        first = false;
996        print_options(options);
997    };
998    print_section("common params",           common_options);
999    print_section("sampling params",         sampling_options);
1000    print_section("speculative params",      spec_options);
1001    print_section("example-specific params", specific_options);
1002}
1003
1004static void common_params_print_completion(common_params_context & ctx_arg) {
1005    std::vector<common_arg *> common_options;
1006    std::vector<common_arg *> sampling_options;
1007    std::vector<common_arg *> spec_options;
1008    std::vector<common_arg *> specific_options;
1009
1010    for (auto & opt : ctx_arg.options) {
1011        if (opt.is_sampling) {
1012            sampling_options.push_back(&opt);
1013        } else if (opt.is_spec) {
1014            spec_options.push_back(&opt);
1015        } else if (opt.in_example(ctx_arg.ex)) {
1016            specific_options.push_back(&opt);
1017        } else {
1018            common_options.push_back(&opt);
1019        }
1020    }
1021
1022    printf("_llama_completions() {\n");
1023    printf("    local cur prev opts\n");
1024    printf("    COMPREPLY=()\n");
1025    printf("    cur=\"${COMP_WORDS[COMP_CWORD]}\"\n");
1026    printf("    prev=\"${COMP_WORDS[COMP_CWORD-1]}\"\n\n");
1027
1028    printf("    opts=\"");
1029    auto print_options = [](const std::vector<common_arg *> & options) {
1030        for (const common_arg * opt : options) {
1031            for (const char * arg : opt->args) {
1032                printf("%s ", arg);
1033            }
1034        }
1035    };
1036
1037    print_options(common_options);
1038    print_options(sampling_options);
1039    print_options(spec_options);
1040    print_options(specific_options);
1041    printf("\"\n\n");
1042
1043    printf("    case \"$prev\" in\n");
1044    printf("        --model|-m)\n");
1045    printf("            COMPREPLY=( $(compgen -f -X '!*.gguf' -- \"$cur\") $(compgen -d -- \"$cur\") )\n");
1046    printf("            return 0\n");
1047    printf("            ;;\n");
1048    printf("        --grammar-file)\n");
1049    printf("            COMPREPLY=( $(compgen -f -X '!*.gbnf' -- \"$cur\") $(compgen -d -- \"$cur\") )\n");
1050    printf("            return 0\n");
1051    printf("            ;;\n");
1052    printf("        --chat-template-file)\n");
1053    printf("            COMPREPLY=( $(compgen -f -X '!*.jinja' -- \"$cur\") $(compgen -d -- \"$cur\") )\n");
1054    printf("            return 0\n");
1055    printf("            ;;\n");
1056    printf("        *)\n");
1057    printf("            COMPREPLY=( $(compgen -W \"${opts}\" -- \"$cur\") )\n");
1058    printf("            return 0\n");
1059    printf("            ;;\n");
1060    printf("    esac\n");
1061    printf("}\n\n");
1062
1063    std::set<std::string> executables = {
1064        "llama-batched",
1065        "llama-batched-bench",
1066        "llama-bench",
1067        "llama-cli",
1068        "llama-completion",
1069        "llama-convert-llama2c-to-ggml",
1070        "llama-cvector-generator",
1071        "llama-debug",
1072        "llama-diffusion-cli",
1073        "llama-embedding",
1074        "llama-eval-callback",
1075        "llama-export-lora",
1076        "llama-finetune",
1077        "llama-fit-params",
1078        "llama-gemma3-cli",
1079        "llama-gen-docs",
1080        "llama-gguf",
1081        "llama-gguf-hash",
1082        "llama-gguf-split",
1083        "llama-idle",
1084        "llama-imatrix",
1085        "llama-llava-cli",
1086        "llama-lookahead",
1087        "llama-lookup",
1088        "llama-lookup-create",
1089        "llama-lookup-merge",
1090        "llama-lookup-stats",
1091        "llama-minicpmv-cli",
1092        "llama-mtmd-cli",
1093        "llama-parallel",
1094        "llama-passkey",
1095        "llama-perplexity",
1096        "llama-q8dot",
1097        "llama-quantize",
1098        "llama-qwen2vl-cli",
1099        "llama-retrieval",
1100        "llama-save-load-state",
1101        "llama-server",
1102        "llama-simple",
1103        "llama-simple-chat",
1104        "llama-speculative",
1105        "llama-speculative-simple",
1106        "llama-tokenize",
1107        "llama-tts",
1108        "llama-vdot"
1109    };
1110
1111    for (const auto& exe : executables) {
1112        printf("complete -F _llama_completions %s\n", exe.c_str());
1113    }
1114}
1115
1116static std::vector<ggml_backend_dev_t> parse_device_list(const std::string & value) {
1117    std::vector<ggml_backend_dev_t> devices;
1118    auto dev_names = string_split<std::string>(value, ',');
1119    if (dev_names.empty()) {
1120        throw std::invalid_argument("no devices specified");
1121    }
1122    if (dev_names.size() == 1 && dev_names[0] == "none") {
1123        devices.push_back(nullptr);
1124    } else {
1125        ggml_backend_load_all();
1126        for (const auto & device : dev_names) {
1127            auto * dev = ggml_backend_dev_by_name(device.c_str());
1128            if (!dev || ggml_backend_dev_type(dev) == GGML_BACKEND_DEVICE_TYPE_CPU) {
1129                throw std::invalid_argument(string_format("invalid device: %s", device.c_str()));
1130            }
1131            devices.push_back(dev);
1132        }
1133        devices.push_back(nullptr);
1134    }
1135    return devices;
1136}
1137
1138void common_print_available_devices() {
1139    constexpr size_t MiB = 1024 * 1024;
1140    std::vector<ggml_backend_dev_t> devices;
1141
1142    ggml_backend_load_all();
1143
1144    for (size_t i = 0; i < ggml_backend_dev_count(); ++i) {
1145        auto * dev = ggml_backend_dev_get(i);
1146        if (ggml_backend_dev_type(dev) != GGML_BACKEND_DEVICE_TYPE_CPU) {
1147            devices.push_back(dev);
1148        }
1149    }
1150    printf("Available devices:\n");
1151
1152    if (devices.empty()) {
1153        printf("  (none)\n");
1154        return;
1155    }
1156    for (auto * dev : devices) {
1157        size_t free, total;
1158        ggml_backend_dev_memory(dev, &free, &total);
1159        printf("  %s: %s (%zu MiB, %zu MiB free)\n", ggml_backend_dev_name(dev), ggml_backend_dev_description(dev), total / MiB, free / MiB);
1160    }
1161}
1162
1163static void add_rpc_devices(const std::string & servers) {
1164    auto rpc_servers = string_split<std::string>(servers, ',');
1165    if (rpc_servers.empty()) {
1166        throw std::invalid_argument("no RPC servers specified");
1167    }
1168    ggml_backend_load_all();
1169    ggml_backend_reg_t rpc_reg = ggml_backend_reg_by_name("RPC");
1170    if (!rpc_reg) {
1171        throw std::invalid_argument("failed to find RPC backend");
1172    }
1173    typedef ggml_backend_reg_t (*ggml_backend_rpc_add_server_t)(const char * endpoint);
1174    ggml_backend_rpc_add_server_t ggml_backend_rpc_add_server_fn = (ggml_backend_rpc_add_server_t) ggml_backend_reg_get_proc_address(rpc_reg, "ggml_backend_rpc_add_server");
1175    if (!ggml_backend_rpc_add_server_fn) {
1176        throw std::invalid_argument("failed to find RPC add server function");
1177    }
1178    for (const auto & server : rpc_servers) {
1179        auto reg = ggml_backend_rpc_add_server_fn(server.c_str());
1180        ggml_backend_register(reg);
1181    }
1182}
1183
1184bool common_params_to_map(int argc, char ** argv, llama_example ex, std::map<common_arg, std::string> & out_map) {
1185    common_params dummy_params;
1186    common_params_context ctx_arg = common_params_parser_init(dummy_params, ex, nullptr);
1187
1188    std::unordered_map<std::string, common_arg *> arg_to_options;
1189    for (auto & opt : ctx_arg.options) {
1190        for (const auto & arg : opt.args) {
1191            arg_to_options[arg] = &opt;
1192        }
1193        for (const auto & arg : opt.args_neg) {
1194            arg_to_options[arg] = &opt;
1195        }
1196    }
1197
1198    // TODO @ngxson : find a way to deduplicate this code
1199
1200    // handle command line arguments
1201    auto check_arg = [&](int i) {
1202        if (i+1 >= argc) {
1203            throw std::invalid_argument("expected value for argument");
1204        }
1205    };
1206
1207    std::set<std::string> seen_args;
1208
1209    for (int i = 1; i < argc; i++) {
1210        const std::string arg_prefix = "--";
1211
1212        std::string arg = argv[i];
1213        if (arg.compare(0, arg_prefix.size(), arg_prefix) == 0) {
1214            std::replace(arg.begin(), arg.end(), '_', '-');
1215        }
1216        if (arg_to_options.find(arg) == arg_to_options.end()) {
1217            throw std::invalid_argument(string_format("error: invalid argument: %s", arg.c_str()));
1218        }
1219        if (!seen_args.insert(arg).second) {
1220            const bool skip = (arg == "--spec-type");
1221
1222            if (!skip) {
1223                LOG_WRN("DEPRECATED: argument '%s' specified multiple times, use comma-separated values instead (only last value will be used)\n", arg.c_str());
1224            }
1225        }
1226        auto opt = *arg_to_options[arg];
1227        std::string val;
1228        if (opt.value_hint == nullptr && opt.value_hint_2 == nullptr) {
1229            // bool arg (need to reverse the meaning for negative args)
1230            bool is_neg = std::find(opt.args_neg.begin(), opt.args_neg.end(), arg) != opt.args_neg.end();
1231            val = is_neg ? "0" : "1";
1232        }
1233        if (opt.value_hint != nullptr) {
1234            // arg with single value
1235            check_arg(i);
1236            val = argv[++i];
1237        }
1238        if (opt.value_hint_2 != nullptr) {
1239            // TODO: support arg with 2 values
1240            throw std::invalid_argument("error: argument with 2 values is not yet supported\n");
1241        }
1242        out_map[opt] = val;
1243    }
1244
1245    return true;
1246}
1247
1248#ifdef _WIN32
1249struct utf8_argv {
1250    std::vector<std::string> buf;
1251    std::vector<char*> ptrs;
1252};
1253
1254static utf8_argv make_utf8_argv() {
1255    utf8_argv out;
1256    int wargc = 0;
1257    LPWSTR* wargv = CommandLineToArgvW(GetCommandLineW(), &wargc);
1258    if (!wargv) return out;
1259
1260    out.buf.reserve(wargc);
1261    for (int i = 0; i < wargc; ++i) {
1262        int n = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, wargv[i], -1, nullptr, 0, nullptr, nullptr);
1263        if (n <= 0) { out.buf.emplace_back(); continue; }
1264        auto& s = out.buf.emplace_back();
1265        s.resize(static_cast<size_t>(n - 1));
1266        (void)WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, s.data(), n, nullptr, nullptr);
1267    }
1268    LocalFree(wargv);
1269
1270    out.ptrs.reserve(out.buf.size() + 1);
1271    for (auto& s : out.buf) out.ptrs.push_back(s.data());
1272    out.ptrs.push_back(nullptr);
1273    return out;
1274}
1275#endif
1276
1277bool common_params_parse(int argc, char ** argv, common_params & params, llama_example ex, void(*print_usage)(int, char **)) {
1278#ifdef _WIN32
1279    auto utf8 = make_utf8_argv();
1280    // repair argv only when it matches the process command line
1281    if (static_cast<int>(utf8.buf.size()) == argc) {
1282        argv = utf8.ptrs.data();
1283    }
1284#endif
1285
1286    auto ctx_arg = common_params_parser_init(params, ex, print_usage);
1287    const common_params params_org = ctx_arg.params; // the example can modify the default params
1288
1289    try {
1290        if (!common_params_parse_ex(argc, argv, ctx_arg)) {
1291            ctx_arg.params = params_org;
1292            return false;
1293        }
1294        if (ctx_arg.params.usage) {
1295            common_params_print_usage(ctx_arg);
1296            if (ctx_arg.print_usage) {
1297                ctx_arg.print_usage(argc, argv);
1298            }
1299            common_log_flush(common_log_main());
1300            exit(0);
1301        }
1302        if (ctx_arg.params.completion) {
1303            common_params_print_completion(ctx_arg);
1304            exit(0);
1305        }
1306        params.lr.init();
1307    } catch (const std::invalid_argument & ex) {
1308        fprintf(stderr, "%s\n", ex.what());
1309        ctx_arg.params = params_org;
1310        return false;
1311    } catch (std::exception & ex) {
1312        fprintf(stderr, "%s\n", ex.what());
1313        exit(1); // for other exceptions, we exit with status code 1
1314    }
1315
1316    return true;
1317}
1318
1319static std::string list_builtin_chat_templates() {
1320    std::vector<const char *> supported_tmpl;
1321    int32_t res = llama_chat_builtin_templates(nullptr, 0);
1322    supported_tmpl.resize(res);
1323    res = llama_chat_builtin_templates(supported_tmpl.data(), supported_tmpl.size());
1324    std::ostringstream msg;
1325    for (auto & tmpl : supported_tmpl) {
1326        msg << tmpl << (&tmpl == &supported_tmpl.back() ? "" : ", ");
1327    }
1328    return msg.str();
1329}
1330
1331bool common_arg_utils::is_truthy(const std::string & value) {
1332    return value == "on" || value == "enabled" || value == "true" || value == "1";
1333}
1334
1335bool common_arg_utils::is_falsey(const std::string & value) {
1336    return value == "off" || value == "disabled" || value == "false" || value == "0";
1337}
1338
1339bool common_arg_utils::is_autoy(const std::string & value) {
1340    return value == "auto" || value == "-1";
1341}
1342
1343// Simple CSV parser that handles quoted fields and escaped quotes
1344// example:
1345//    input:  value1,"value, with, commas","value with ""escaped"" quotes",value4
1346//    output: [value1] [value, with, commas] [value with "escaped" quotes] [value4]
1347static std::vector<std::string> parse_csv_row(const std::string& input) {
1348    std::vector<std::string> fields;
1349    std::string field;
1350    bool in_quotes = false;
1351
1352    for (size_t i = 0; i < input.length(); ++i) {
1353        char ch = input[i];
1354
1355        if (ch == '"') {
1356            if (!in_quotes) {
1357                // start of quoted field (only valid if at beginning of field)
1358                if (!field.empty()) {
1359                    // quote appeared in middle of unquoted field, treat as literal
1360                    field += '"';
1361                } else {
1362                    in_quotes = true; // start
1363                }
1364            } else {
1365                if (i + 1 < input.length() && input[i + 1] == '"') {
1366                    // escaped quote: ""
1367                    field += '"';
1368                    ++i; // skip the next quote
1369                } else {
1370                    in_quotes = false; // end
1371                }
1372            }
1373        } else if (ch == ',') {
1374            if (in_quotes) {
1375                field += ',';
1376            } else {
1377                fields.push_back(std::move(field));
1378                field.clear();
1379            }
1380        } else {
1381            field += ch;
1382        }
1383    }
1384
1385    // Add the last field
1386    fields.push_back(std::move(field));
1387
1388    return fields;
1389}
1390
1391common_params_context common_params_parser_init(common_params & params, llama_example ex, void(*print_usage)(int, char **)) {
1392    // per-example default params
1393    // we define here to make sure it's included in llama-gen-docs
1394    if (ex == LLAMA_EXAMPLE_COMPLETION) {
1395        params.use_jinja = false;   // disable jinja by default
1396    } else if (ex == LLAMA_EXAMPLE_MTMD) {
1397        params.use_jinja = false;   // disable jinja by default
1398        params.sampling.temp = 0.2; // lower temp by default for better quality
1399    } else if (ex == LLAMA_EXAMPLE_SERVER) {
1400        params.n_parallel = -1;     // auto by default
1401    } else if (ex == LLAMA_EXAMPLE_TOKENIZE) {
1402        params.parse_special = true; // parse special tokens by default, like the old tokenize tool
1403    } else if (ex == LLAMA_EXAMPLE_TTS) {
1404        params.out_file = "output.wav";
1405        params.sampling.penalty_repeat = 1.05f;
1406        params.sampling.penalty_last_n = -1;
1407    }
1408
1409    params.use_color = tty_can_use_colors();
1410
1411    common_params_context ctx_arg(params);
1412    ctx_arg.print_usage = print_usage;
1413    ctx_arg.ex          = ex;
1414
1415    std::string sampler_type_chars;
1416    std::string sampler_type_names;
1417    for (const auto & sampler : params.sampling.samplers) {
1418        sampler_type_chars += common_sampler_type_to_chr(sampler);
1419        sampler_type_names += common_sampler_type_to_str(sampler) + ";";
1420    }
1421    if (!sampler_type_names.empty()) {
1422        sampler_type_names.pop_back(); // remove last semicolon
1423    }
1424
1425    /**
1426     * filter options by example
1427     * rules:
1428     * - all examples inherit options from LLAMA_EXAMPLE_COMMON
1429     * - if LLAMA_EXAMPLE_* is set (other than COMMON), we only show the option in the corresponding example
1430     * - if both {LLAMA_EXAMPLE_COMMON, LLAMA_EXAMPLE_*,} are set, we will prioritize the LLAMA_EXAMPLE_* matching current example
1431     */
1432    auto add_opt = [&](common_arg arg) {
1433        // download only exposes the handful of args explicitly tagged for it
1434        const bool inherit_common = ex != LLAMA_EXAMPLE_DOWNLOAD;
1435        if ((arg.in_example(ex) || (inherit_common && arg.in_example(LLAMA_EXAMPLE_COMMON))) && !arg.is_exclude(ex)) {
1436            ctx_arg.options.push_back(std::move(arg));
1437        }
1438    };
1439
1440    add_opt(common_arg(
1441        {"-h", "--help", "--usage"},
1442        "print usage and exit",
1443        [](common_params & params) {
1444            params.usage = true;
1445        }
1446    ).set_examples({LLAMA_EXAMPLE_COMMON, LLAMA_EXAMPLE_DOWNLOAD}));
1447    add_opt(common_arg(
1448        {"--version"},
1449        "show version and build info",
1450        [](common_params &) {
1451            llama_print_build_info(llama_version());
1452            exit(0);
1453        }
1454    ));
1455    add_opt(common_arg(
1456        {"-cl", "--cache-list"},
1457        "show list of models in cache",
1458        [](common_params &) {
1459            auto models = common_list_cached_models();
1460            printf("number of models in cache: %zu\n", models.size());
1461            for (size_t i = 0; i < models.size(); i++) {
1462                printf("%4zu. %s\n", i + 1, models[i].to_string().c_str());
1463            }
1464            exit(0);
1465        }
1466    ));
1467    add_opt(common_arg(
1468        {"--completion-bash"},
1469        "print source-able bash completion script for llama.cpp",
1470        [](common_params & params) {
1471            params.completion = true;
1472        }
1473    ));
1474    add_opt(common_arg(
1475        {"--server-base"}, "URL",
1476        string_format("connect to this server instead of starting a new one, example: 'http://localhost:8080' (default: none)"),
1477        [](common_params & params, const std::string & value) {
1478            params.server_base = value;
1479        }
1480    ).set_examples({LLAMA_EXAMPLE_CLI}));
1481    add_opt(common_arg(
1482        {"--verbose-prompt"},
1483        string_format("print a verbose prompt before generation (default: %s)", params.verbose_prompt ? "true" : "false"),
1484        [](common_params & params) {
1485            params.verbose_prompt = true;
1486        }
1487    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_EMBEDDING, LLAMA_EXAMPLE_RETRIEVAL}));
1488    add_opt(common_arg(
1489        {"--display-prompt"},
1490        {"--no-display-prompt"},
1491        string_format("whether to print prompt at generation (default: %s)", params.display_prompt ? "true" : "false"),
1492        [](common_params & params, bool value) {
1493            params.display_prompt = value;
1494        }
1495    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI}));
1496    add_opt(common_arg(
1497        {"-co", "--color"}, "[on|off|auto]",
1498        "Colorize output to distinguish prompt and user input from generations ('on', 'off', or 'auto', default: 'auto')\n"
1499        "'auto' enables colors when output is to a terminal",
1500        [](common_params & params, const std::string & value) {
1501            if (is_truthy(value)) {
1502                params.use_color = true;
1503            } else if (is_falsey(value)) {
1504                params.use_color = false;
1505            } else if (is_autoy(value)) {
1506                params.use_color = tty_can_use_colors();
1507            } else {
1508                throw std::invalid_argument(
1509                    string_format("error: unknown value for --color: '%s'\n", value.c_str()));
1510            }
1511        }
1512    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_LOOKUP}));
1513    add_opt(common_arg(
1514        {"-t", "--threads"}, "N",
1515        string_format("number of CPU threads to use during generation (default: %d)", params.cpuparams.n_threads),
1516        [](common_params & params, int value) {
1517            params.cpuparams.n_threads = value;
1518            if (params.cpuparams.n_threads <= 0) {
1519                params.cpuparams.n_threads = std::thread::hardware_concurrency();
1520            }
1521        }
1522    ).set_env("LLAMA_ARG_THREADS"));
1523    add_opt(common_arg(
1524        {"-tb", "--threads-batch"}, "N",
1525        "number of threads to use during batch and prompt processing (default: same as --threads)",
1526        [](common_params & params, int value) {
1527            params.cpuparams_batch.n_threads = value;
1528            if (params.cpuparams_batch.n_threads <= 0) {
1529                params.cpuparams_batch.n_threads = std::thread::hardware_concurrency();
1530            }
1531        }
1532    ));
1533    add_opt(common_arg(
1534        {"-C", "--cpu-mask"}, "M",
1535        "CPU affinity mask: arbitrarily long hex. Complements cpu-range (default: \"\")",
1536        [](common_params & params, const std::string & mask) {
1537            params.cpuparams.mask_valid = true;
1538            if (!parse_cpu_mask(mask, params.cpuparams.cpumask)) {
1539                throw std::invalid_argument("invalid cpumask");
1540            }
1541        }
1542    ));
1543    add_opt(common_arg(
1544        {"-Cr", "--cpu-range"}, "lo-hi",
1545        "range of CPUs for affinity. Complements --cpu-mask",
1546        [](common_params & params, const std::string & range) {
1547            params.cpuparams.mask_valid = true;
1548            if (!parse_cpu_range(range, params.cpuparams.cpumask)) {
1549                throw std::invalid_argument("invalid range");
1550            }
1551        }
1552    ));
1553    add_opt(common_arg(
1554        {"--cpu-strict"}, "<0|1>",
1555        string_format("use strict CPU placement (default: %u)\n", (unsigned) params.cpuparams.strict_cpu),
1556        [](common_params & params, const std::string & value) {
1557            params.cpuparams.strict_cpu = std::stoul(value);
1558        }
1559    ));
1560    add_opt(common_arg(
1561        {"--prio"}, "N",
1562        string_format("set process/thread priority : low(-1), normal(0), medium(1), high(2), realtime(3) (default: %d)\n", params.cpuparams.priority),
1563        [](common_params & params, int prio) {
1564            if (prio < GGML_SCHED_PRIO_LOW || prio > GGML_SCHED_PRIO_REALTIME) {
1565                throw std::invalid_argument("invalid value");
1566            }
1567            params.cpuparams.priority = (enum ggml_sched_priority) prio;
1568        }
1569    ));
1570    add_opt(common_arg(
1571        {"--poll"}, "<0...100>",
1572        string_format("use polling level to wait for work (0 - no polling, default: %u)\n", (unsigned) params.cpuparams.poll),
1573        [](common_params & params, const std::string & value) {
1574            params.cpuparams.poll = std::stoul(value);
1575        }
1576    ));
1577    add_opt(common_arg(
1578        {"-Cb", "--cpu-mask-batch"}, "M",
1579        "CPU affinity mask: arbitrarily long hex. Complements cpu-range-batch (default: same as --cpu-mask)",
1580        [](common_params & params, const std::string & mask) {
1581            params.cpuparams_batch.mask_valid = true;
1582            if (!parse_cpu_mask(mask, params.cpuparams_batch.cpumask)) {
1583                throw std::invalid_argument("invalid cpumask");
1584            }
1585        }
1586    ));
1587    add_opt(common_arg(
1588        {"-Crb", "--cpu-range-batch"}, "lo-hi",
1589        "ranges of CPUs for affinity. Complements --cpu-mask-batch",
1590        [](common_params & params, const std::string & range) {
1591            params.cpuparams_batch.mask_valid = true;
1592            if (!parse_cpu_range(range, params.cpuparams_batch.cpumask)) {
1593                throw std::invalid_argument("invalid range");
1594            }
1595        }
1596    ));
1597    add_opt(common_arg(
1598        {"--cpu-strict-batch"}, "<0|1>",
1599        "use strict CPU placement (default: same as --cpu-strict)",
1600        [](common_params & params, int value) {
1601            params.cpuparams_batch.strict_cpu = value;
1602        }
1603    ));
1604    add_opt(common_arg(
1605        {"--prio-batch"}, "N",
1606        string_format("set process/thread priority : 0-normal, 1-medium, 2-high, 3-realtime (default: %d)\n", params.cpuparams_batch.priority),
1607        [](common_params & params, int prio) {
1608            if (prio < 0 || prio > 3) {
1609                throw std::invalid_argument("invalid value");
1610            }
1611            params.cpuparams_batch.priority = (enum ggml_sched_priority) prio;
1612        }
1613    ));
1614    add_opt(common_arg(
1615        {"--poll-batch"}, "<0|1>",
1616        "use polling to wait for work (default: same as --poll)",
1617        [](common_params & params, int value) {
1618            params.cpuparams_batch.poll = value;
1619        }
1620    ));
1621    add_opt(common_arg(
1622        {"-lcs", "--lookup-cache-static"}, "FNAME",
1623        "path to static lookup cache to use for lookup decoding (not updated by generation)",
1624        [](common_params & params, const std::string & value) {
1625            params.speculative.ngram_cache.lookup_cache_static = value;
1626        }
1627    ).set_examples({LLAMA_EXAMPLE_LOOKUP, LLAMA_EXAMPLE_SERVER}));
1628    add_opt(common_arg(
1629        {"-lcd", "--lookup-cache-dynamic"}, "FNAME",
1630        "path to dynamic lookup cache to use for lookup decoding (updated by generation)",
1631        [](common_params & params, const std::string & value) {
1632            params.speculative.ngram_cache.lookup_cache_dynamic = value;
1633        }
1634    ).set_examples({LLAMA_EXAMPLE_LOOKUP, LLAMA_EXAMPLE_SERVER}));
1635    add_opt(common_arg(
1636        {"-c", "--ctx-size"}, "N",
1637        string_format("size of the prompt context (default: %d, 0 = loaded from model)", params.n_ctx),
1638        [](common_params & params, int value) {
1639            params.n_ctx = value;
1640            if (value == 0) {
1641                // disable context reduction in llama_params_fit if the user explicitly requests the full context size:
1642                params.fit_params_min_ctx = UINT32_MAX;
1643            }
1644        }
1645    ).set_env("LLAMA_ARG_CTX_SIZE"));
1646    add_opt(common_arg(
1647        { "--kv-unified-per-slot" }, "N",
1648        "context limit per parallel slot (default: unset, behavior unchanged).\n"
1649        "when set without -c/--ctx-size, the shared KV pool is sized to n_parallel*N",
1650        [](common_params & params, int value) {
1651            params.kv_unified_per_slot = value;
1652        }
1653    ).set_env("LLAMA_ARG_KV_UNIFIED_PER_SLOT").set_examples({ LLAMA_EXAMPLE_SERVER }));
1654    add_opt(common_arg(
1655        {"-n", "--predict", "--n-predict"}, "N",
1656        string_format(
1657            ex == LLAMA_EXAMPLE_COMPLETION
1658                ? "number of tokens to predict (default: %d, -1 = infinity, -2 = until context filled)"
1659                : "number of tokens to predict (default: %d, -1 = infinity)",
1660            params.n_predict),
1661        [](common_params & params, int value) {
1662            params.n_predict = value;
1663        }
1664    ).set_env("LLAMA_ARG_N_PREDICT"));
1665    add_opt(common_arg(
1666        {"-b", "--batch-size"}, "N",
1667        string_format("logical maximum batch size (default: %d)", params.n_batch),
1668        [](common_params & params, int value) {
1669            params.n_batch = value;
1670        }
1671    ).set_env("LLAMA_ARG_BATCH"));
1672    add_opt(common_arg(
1673        {"-ub", "--ubatch-size"}, "N",
1674        string_format("physical maximum batch size (default: %d)", params.n_ubatch),
1675        [](common_params & params, int value) {
1676            params.n_ubatch = value;
1677        }
1678    ).set_env("LLAMA_ARG_UBATCH"));
1679    add_opt(common_arg(
1680        {"--keep"}, "N",
1681        string_format("number of tokens to keep from the initial prompt (default: %d, -1 = all)", params.n_keep),
1682        [](common_params & params, int value) {
1683            params.n_keep = value;
1684        }
1685    ));
1686    add_opt(common_arg(
1687        {"--swa-full"},
1688        string_format("use full-size SWA cache (default: %s)\n"
1689            "[(more info)](https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)", params.swa_full ? "true" : "false"),
1690        [](common_params & params) {
1691            params.swa_full = true;
1692        }
1693    ).set_env("LLAMA_ARG_SWA_FULL"));
1694    add_opt(common_arg(
1695        {"-ctxcp", "--ctx-checkpoints", "--swa-checkpoints"}, "N",
1696        string_format("max number of context checkpoints to create per slot (default: %d)"
1697            "[(more info)](https://github.com/ggml-org/llama.cpp/pull/15293)", params.n_ctx_checkpoints),
1698        [](common_params & params, int value) {
1699            params.n_ctx_checkpoints = value;
1700        }
1701    ).set_env("LLAMA_ARG_CTX_CHECKPOINTS").set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
1702    add_opt(common_arg(
1703        {"-cms", "--checkpoint-min-step"}, "N",
1704        string_format("minimum spacing between context checkpoints in tokens (default: %d, 0 = no minimum)", params.checkpoint_min_step),
1705        [](common_params & params, int value) {
1706            if (value < 0) {
1707                throw std::invalid_argument("checkpoint-min-step must be non-negative");
1708            }
1709            params.checkpoint_min_step = value;
1710        }
1711    ).set_env("LLAMA_ARG_CHECKPOINT_MIN_SPACING_NT").set_examples({LLAMA_EXAMPLE_SERVER}));
1712    add_opt(common_arg(
1713        {"-cram", "--cache-ram"}, "N",
1714        string_format("set the maximum cache size in MiB (default: %d, -1 - no limit, 0 - disable)"
1715            "[(more info)](https://github.com/ggml-org/llama.cpp/pull/16391)", params.cache_ram_mib),
1716        [](common_params & params, int value) {
1717            params.cache_ram_mib = value;
1718        }
1719    ).set_env("LLAMA_ARG_CACHE_RAM").set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
1720    add_opt(common_arg(
1721        {"-kvu", "--kv-unified"},
1722        {"-no-kvu", "--no-kv-unified"},
1723        "use single unified KV buffer shared across all sequences (default: enabled if number of slots is auto)",
1724        [](common_params & params, bool value) {
1725            params.kv_unified = value;
1726        }
1727    ).set_env("LLAMA_ARG_KV_UNIFIED").set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_PERPLEXITY, LLAMA_EXAMPLE_BATCHED, LLAMA_EXAMPLE_BENCH, LLAMA_EXAMPLE_PARALLEL}));
1728    add_opt(common_arg(
1729        {"--cache-idle-slots"},
1730        {"--no-cache-idle-slots"},
1731        "save idle slots to the prompt cache on new task, and clear them when using unified KV (default: enabled, requires cache-ram)",
1732        [](common_params & params, bool value) {
1733            params.cache_idle_slots = value;
1734        }
1735    ).set_env("LLAMA_ARG_CACHE_IDLE_SLOTS").set_examples({LLAMA_EXAMPLE_SERVER}));
1736    add_opt(common_arg(
1737        {"--context-shift"},
1738        {"--no-context-shift"},
1739        string_format("whether to use context shift on infinite text generation (default: %s)", params.ctx_shift ? "enabled" : "disabled"),
1740        [](common_params & params, bool value) {
1741            params.ctx_shift = value;
1742        }
1743    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_IMATRIX, LLAMA_EXAMPLE_PERPLEXITY}).set_env("LLAMA_ARG_CONTEXT_SHIFT"));
1744    add_opt(common_arg(
1745        {"--chunks"}, "N",
1746        string_format("max number of chunks to process (default: %d, -1 = all)", params.n_chunks),
1747        [](common_params & params, int value) {
1748            params.n_chunks = value;
1749        }
1750    ).set_examples({LLAMA_EXAMPLE_IMATRIX, LLAMA_EXAMPLE_PERPLEXITY, LLAMA_EXAMPLE_RETRIEVAL}));
1751    add_opt(common_arg({ "-fa", "--flash-attn" }, "[on|off|auto]",
1752                       string_format("set Flash Attention use ('on', 'off', or 'auto', default: '%s')",
1753                                     llama_flash_attn_type_name(params.flash_attn_type)),
1754                       [](common_params & params, const std::string & value) {
1755                           if (is_truthy(value)) {
1756                               params.flash_attn_type = LLAMA_FLASH_ATTN_TYPE_ENABLED;
1757                           } else if (is_falsey(value)) {
1758                               params.flash_attn_type = LLAMA_FLASH_ATTN_TYPE_DISABLED;
1759                           } else if (is_autoy(value)) {
1760                               params.flash_attn_type = LLAMA_FLASH_ATTN_TYPE_AUTO;
1761                           } else {
1762                               throw std::runtime_error(
1763                                   string_format("error: unknown value for --flash-attn: '%s'\n", value.c_str()));
1764                           }
1765                       }).set_env("LLAMA_ARG_FLASH_ATTN"));
1766    add_opt(common_arg(
1767        {"-p", "--prompt"}, "PROMPT",
1768        "prompt to start generation with; for system message, use -sys",
1769        [](common_params & params, const std::string & value) {
1770            params.prompt = value;
1771        }
1772    ).set_excludes({LLAMA_EXAMPLE_SERVER}));
1773    add_opt(common_arg(
1774        {"-sys", "--system-prompt"}, "PROMPT",
1775        "system prompt to use with model (if applicable, depending on chat template)",
1776        [](common_params & params, const std::string & value) {
1777            params.system_prompt = value;
1778        }
1779    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_DIFFUSION, LLAMA_EXAMPLE_MTMD}));
1780    add_opt(common_arg(
1781        {"--perf"},
1782        {"--no-perf"},
1783        string_format("whether to enable internal libllama performance timings (default: %s)", params.no_perf ? "true" : "false"),
1784        [](common_params & params, bool value) {
1785            params.no_perf = !value;
1786            params.sampling.no_perf = !value;
1787        }
1788    ).set_env("LLAMA_ARG_PERF"));
1789    add_opt(common_arg(
1790        {"--show-timings"},
1791        {"--no-show-timings"},
1792        string_format("whether to show timing information after each response (default: %s)", params.show_timings ? "true" : "false"),
1793        [](common_params & params, bool value) {
1794            params.show_timings = value;
1795        }
1796    ).set_examples({LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SHOW_TIMINGS"));
1797    add_opt(common_arg(
1798        {"-f", "--file"}, "FNAME",
1799        "a file containing the prompt (default: none)",
1800        [](common_params & params, const std::string & value) {
1801            params.prompt = read_file(value);
1802            // store the external file name in params
1803            params.prompt_file = value;
1804            if (!params.prompt.empty() && params.prompt.back() == '\n') {
1805                params.prompt.pop_back();
1806            }
1807        }
1808    ).set_excludes({LLAMA_EXAMPLE_SERVER}));
1809    add_opt(common_arg(
1810        {"-sysf", "--system-prompt-file"}, "FNAME",
1811        "a file containing the system prompt (default: none)",
1812        [](common_params & params, const std::string & value) {
1813            params.system_prompt = read_file(value);
1814            if (!params.system_prompt.empty() && params.system_prompt.back() == '\n') {
1815                params.system_prompt.pop_back();
1816            }
1817        }
1818    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_DIFFUSION}));
1819    add_opt(common_arg(
1820        {"--in-file"}, "FNAME",
1821        "an input file (use comma-separated values to specify multiple files)",
1822        [](common_params & params, const std::string & value) {
1823            for (const auto & item : parse_csv_row(value)) {
1824                std::ifstream file(item);
1825                if (!file) {
1826                    throw std::runtime_error(string_format("error: failed to open file '%s'\n", item.c_str()));
1827                }
1828                params.in_files.push_back(item);
1829            }
1830        }
1831    ).set_examples({LLAMA_EXAMPLE_IMATRIX}));
1832    add_opt(common_arg(
1833        {"-bf", "--binary-file"}, "FNAME",
1834        "binary file containing the prompt (default: none)",
1835        [](common_params & params, const std::string & value) {
1836            std::ifstream file(value, std::ios::binary);
1837            if (!file) {
1838                throw std::runtime_error(string_format("error: failed to open file '%s'\n", value.c_str()));
1839            }
1840            // store the external file name in params
1841            params.prompt_file = value;
1842            std::ostringstream ss;
1843            ss << file.rdbuf();
1844            params.prompt = ss.str();
1845            fprintf(stderr, "Read %zu bytes from binary file %s\n", params.prompt.size(), value.c_str());
1846        }
1847    ).set_excludes({LLAMA_EXAMPLE_SERVER}));
1848    add_opt(common_arg(
1849        {"-e", "--escape"},
1850        {"--no-escape"},
1851        string_format("whether to process escapes sequences (\\n, \\r, \\t, \\', \\\", \\\\) (default: %s)", params.escape ? "true" : "false"),
1852        [](common_params & params, bool value) {
1853            params.escape = value;
1854        }
1855    ));
1856    add_opt(common_arg(
1857        {"-ptc", "--print-token-count"}, "N",
1858        string_format("print token count every N tokens (default: %d)", params.n_print),
1859        [](common_params & params, int value) {
1860            params.n_print = value;
1861        }
1862    ).set_examples({LLAMA_EXAMPLE_COMPLETION}));
1863    add_opt(common_arg(
1864        {"--prompt-cache"}, "FNAME",
1865        "file to cache prompt state for faster startup (default: none)",
1866        [](common_params & params, const std::string & value) {
1867            params.path_prompt_cache = value;
1868        }
1869    ).set_examples({LLAMA_EXAMPLE_COMPLETION}));
1870    add_opt(common_arg(
1871        {"--prompt-cache-all"},
1872        "if specified, saves user input and generations to cache as well\n",
1873        [](common_params & params) {
1874            params.prompt_cache_all = true;
1875        }
1876    ).set_examples({LLAMA_EXAMPLE_COMPLETION}));
1877    add_opt(common_arg(
1878        {"--prompt-cache-ro"},
1879        "if specified, uses the prompt cache but does not update it",
1880        [](common_params & params) {
1881            params.prompt_cache_ro = true;
1882        }
1883    ).set_examples({LLAMA_EXAMPLE_COMPLETION}));
1884    add_opt(common_arg(
1885        {"-r", "--reverse-prompt"}, "PROMPT",
1886        "halt generation at PROMPT, return control in interactive mode\n",
1887        [](common_params & params, const std::string & value) {
1888            params.antiprompt.emplace_back(value);
1889        }
1890    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_SERVER}));
1891    add_opt(common_arg(
1892        {"-sp", "--special"},
1893        string_format("special tokens output enabled (default: %s)", params.special ? "true" : "false"),
1894        [](common_params & params) {
1895            params.special = true;
1896        }
1897    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_SERVER}));
1898    add_opt(common_arg(
1899        {"-cnv", "--conversation"},
1900        {"-no-cnv", "--no-conversation"},
1901        "whether to run in conversation mode:\n"
1902        "- does not print special tokens and suffix/prefix\n"
1903        "- interactive mode is also enabled\n"
1904        "(default: auto enabled if chat template is available)",
1905        [](common_params & params, bool value) {
1906            params.conversation_mode = value ? COMMON_CONVERSATION_MODE_ENABLED : COMMON_CONVERSATION_MODE_DISABLED;
1907        }
1908    ).set_examples({LLAMA_EXAMPLE_COMPLETION}));
1909    add_opt(common_arg(
1910        {"-st", "--single-turn"},
1911        "run conversation for a single turn only, then exit when done\n"
1912        "will not be interactive if first turn is predefined with --prompt\n"
1913        "(default: false)",
1914        [](common_params & params) {
1915            params.single_turn = true;
1916        }
1917    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI}));
1918    add_opt(common_arg(
1919        {"-i", "--interactive"},
1920        string_format("run in interactive mode (default: %s)", params.interactive ? "true" : "false"),
1921        [](common_params & params) {
1922            params.interactive = true;
1923        }
1924    ).set_examples({LLAMA_EXAMPLE_COMPLETION}));
1925    add_opt(common_arg(
1926        {"-if", "--interactive-first"},
1927        string_format("run in interactive mode and wait for input right away (default: %s)", params.interactive_first ? "true" : "false"),
1928        [](common_params & params) {
1929            params.interactive_first = true;
1930        }
1931    ).set_examples({LLAMA_EXAMPLE_COMPLETION}));
1932    add_opt(common_arg(
1933        {"-mli", "--multiline-input"},
1934        "allows you to write or paste multiple lines without ending each in '\\'",
1935        [](common_params & params) {
1936            params.multiline_input = true;
1937        }
1938    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI}));
1939    add_opt(common_arg(
1940        {"--in-prefix-bos"},
1941        "prefix BOS to user inputs, preceding the `--in-prefix` string",
1942        [](common_params & params) {
1943            params.input_prefix_bos = true;
1944            params.enable_chat_template = false;
1945        }
1946    ).set_examples({LLAMA_EXAMPLE_COMPLETION}));
1947    add_opt(common_arg(
1948        {"--in-prefix"}, "STRING",
1949        "string to prefix user inputs with (default: empty)",
1950        [](common_params & params, const std::string & value) {
1951            params.input_prefix = value;
1952            params.enable_chat_template = false;
1953        }
1954    ).set_examples({LLAMA_EXAMPLE_COMPLETION}));
1955    add_opt(common_arg(
1956        {"--in-suffix"}, "STRING",
1957        "string to suffix after user inputs with (default: empty)",
1958        [](common_params & params, const std::string & value) {
1959            params.input_suffix = value;
1960            params.enable_chat_template = false;
1961        }
1962    ).set_examples({LLAMA_EXAMPLE_COMPLETION}));
1963    add_opt(common_arg(
1964        {"--warmup"},
1965        {"--no-warmup"},
1966        string_format("whether to perform warmup with an empty run (default: %s)", params.warmup ? "enabled" : "disabled"),
1967        [](common_params & params, bool value) {
1968            params.warmup = value;
1969        }
1970    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_MTMD, LLAMA_EXAMPLE_EMBEDDING, LLAMA_EXAMPLE_RETRIEVAL, LLAMA_EXAMPLE_PERPLEXITY, LLAMA_EXAMPLE_DEBUG}));
1971    add_opt(common_arg(
1972        {"--spm-infill"},
1973        string_format(
1974            "use Suffix/Prefix/Middle pattern for infill (instead of Prefix/Suffix/Middle) as some models prefer this. (default: %s)",
1975            params.spm_infill ? "enabled" : "disabled"
1976        ),
1977        [](common_params & params) {
1978            params.spm_infill = true;
1979        }
1980    ).set_examples({LLAMA_EXAMPLE_SERVER}));
1981    add_opt(common_arg(
1982        {"--samplers"}, "SAMPLERS",
1983        string_format("samplers that will be used for generation in the order, separated by \';\'\n(default: %s)", sampler_type_names.c_str()),
1984        [](common_params & params, const std::string & value) {
1985            const auto sampler_names = string_split<std::string>(value, ';');
1986            params.sampling.samplers = common_sampler_types_from_names(sampler_names);
1987            params.sampling.user_sampling_config |= common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_SAMPLERS;
1988        }
1989    ).set_sampling());
1990    add_opt(common_arg(
1991        {"-s", "--seed"}, "SEED",
1992        string_format("RNG seed (default: %d, use random seed for %d)", params.sampling.seed, LLAMA_DEFAULT_SEED),
1993        [](common_params & params, const std::string & value) {
1994            params.sampling.seed = std::stoul(value);
1995        }
1996    ).set_sampling());
1997    add_opt(common_arg(
1998        {"--sampler-seq", "--sampling-seq"}, "SEQUENCE",
1999        string_format("simplified sequence for samplers that will be used (default: %s)", sampler_type_chars.c_str()),
2000        [](common_params & params, const std::string & value) {
2001            params.sampling.samplers = common_sampler_types_from_chars(value);
2002        }
2003    ).set_sampling());
2004    add_opt(common_arg(
2005        {"--ignore-eos"},
2006        "ignore end of stream token and continue generating (implies --logit-bias EOS-inf)",
2007        [](common_params & params) {
2008            params.sampling.ignore_eos = true;
2009        }
2010    ).set_sampling());
2011    add_opt(common_arg(
2012        {"--temp", "--temperature"}, "N",
2013        string_format("temperature (default: %.2f)", (double)params.sampling.temp),
2014        [](common_params & params, const std::string & value) {
2015            params.sampling.temp = std::stof(value);
2016            params.sampling.temp = std::max(params.sampling.temp, 0.0f);
2017            params.sampling.user_sampling_config |= common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_TEMP;
2018        }
2019    ).set_sampling());
2020    add_opt(common_arg(
2021        {"--top-k"}, "N",
2022        string_format("top-k sampling (default: %d, 0 = disabled)", params.sampling.top_k),
2023        [](common_params & params, int value) {
2024            params.sampling.top_k = value;
2025            params.sampling.user_sampling_config |= common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_TOP_K;
2026        }
2027    ).set_sampling().set_env("LLAMA_ARG_TOP_K"));
2028    add_opt(common_arg(
2029        {"--top-p"}, "N",
2030        string_format("top-p sampling (default: %.2f, 1.0 = disabled)", (double)params.sampling.top_p),
2031        [](common_params & params, const std::string & value) {
2032            params.sampling.top_p = std::stof(value);
2033            params.sampling.user_sampling_config |= common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_TOP_P;
2034        }
2035    ).set_sampling());
2036    add_opt(common_arg(
2037        {"--min-p"}, "N",
2038        string_format("min-p sampling (default: %.2f, 0.0 = disabled)", (double)params.sampling.min_p),
2039        [](common_params & params, const std::string & value) {
2040            params.sampling.min_p = std::stof(value);
2041            params.sampling.user_sampling_config |= common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_MIN_P;
2042        }
2043    ).set_sampling());
2044    add_opt(common_arg(
2045        {"--top-nsigma", "--top-n-sigma"}, "N",
2046        string_format("top-n-sigma sampling (default: %.2f, -1.0 = disabled)", params.sampling.top_n_sigma),
2047        [](common_params & params, const std::string & value) {
2048            params.sampling.top_n_sigma = std::stof(value);
2049        }
2050    ).set_sampling());
2051    add_opt(common_arg(
2052        {"--xtc-probability"}, "N",
2053        string_format("xtc probability (default: %.2f, 0.0 = disabled)", (double)params.sampling.xtc_probability),
2054        [](common_params & params, const std::string & value) {
2055            params.sampling.xtc_probability = std::stof(value);
2056            params.sampling.user_sampling_config |= common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_XTC_PROBABILITY;
2057        }
2058    ).set_sampling());
2059    add_opt(common_arg(
2060        {"--xtc-threshold"}, "N",
2061        string_format("xtc threshold (default: %.2f, 1.0 = disabled)", (double)params.sampling.xtc_threshold),
2062        [](common_params & params, const std::string & value) {
2063            params.sampling.xtc_threshold = std::stof(value);
2064            params.sampling.user_sampling_config |= common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_XTC_THRESHOLD;
2065        }
2066    ).set_sampling());
2067    add_opt(common_arg(
2068        {"--typical", "--typical-p"}, "N",
2069        string_format("locally typical sampling, parameter p (default: %.2f, 1.0 = disabled)", (double)params.sampling.typ_p),
2070        [](common_params & params, const std::string & value) {
2071            params.sampling.typ_p = std::stof(value);
2072        }
2073    ).set_sampling());
2074    add_opt(common_arg(
2075        {"--repeat-last-n"}, "N",
2076        string_format("last n tokens to consider for penalize (default: %d, 0 = disabled)", params.sampling.penalty_last_n),
2077        [](common_params & params, int value) {
2078            if (value < 0) {
2079                throw std::runtime_error(string_format("error: invalid repeat-last-n = %d\n", value));
2080            }
2081            params.sampling.penalty_last_n = value;
2082            params.sampling.n_prev = std::max(params.sampling.n_prev, params.sampling.penalty_last_n);
2083            params.sampling.user_sampling_config |= common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_PENALTY_LAST_N;
2084        }
2085    ).set_sampling());
2086    add_opt(common_arg(
2087        {"--repeat-penalty"}, "N",
2088        string_format("penalize repeat sequence of tokens (default: %.2f, 1.0 = disabled)", (double)params.sampling.penalty_repeat),
2089        [](common_params & params, const std::string & value) {
2090            const float penalty_repeat = std::stof(value);
2091            if (!std::isfinite(penalty_repeat) ||
2092                penalty_repeat <= 0.0f ||
2093                !std::isfinite(1.0f/penalty_repeat)) {
2094                throw std::runtime_error("error: repeat-penalty must be finite and greater than 0\n");
2095            }
2096            params.sampling.penalty_repeat = penalty_repeat;
2097            params.sampling.user_sampling_config |= common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_PENALTY_REPEAT;
2098        }
2099    ).set_sampling());
2100    add_opt(common_arg(
2101        {"--presence-penalty"}, "N",
2102        string_format("repeat alpha presence penalty (default: %.2f, 0.0 = disabled)", (double)params.sampling.penalty_present),
2103        [](common_params & params, const std::string & value) {
2104            const float penalty_present = std::stof(value);
2105            if (!std::isfinite(penalty_present)) {
2106                throw std::runtime_error("error: presence-penalty must be finite\n");
2107            }
2108            params.sampling.penalty_present = penalty_present;
2109        }
2110    ).set_sampling());
2111    add_opt(common_arg(
2112        {"--frequency-penalty"}, "N",
2113        string_format("repeat alpha frequency penalty (default: %.2f, 0.0 = disabled)", (double)params.sampling.penalty_freq),
2114        [](common_params & params, const std::string & value) {
2115            const float penalty_freq = std::stof(value);
2116            if (!std::isfinite(penalty_freq)) {
2117                throw std::runtime_error("error: frequency-penalty must be finite\n");
2118            }
2119            params.sampling.penalty_freq = penalty_freq;
2120        }
2121    ).set_sampling());
2122    add_opt(common_arg(
2123        {"--dry-multiplier"}, "N",
2124        string_format("set DRY sampling multiplier (default: %.2f, 0.0 = disabled)", (double)params.sampling.dry_multiplier),
2125        [](common_params & params, const std::string & value) {
2126            params.sampling.dry_multiplier = std::stof(value);
2127        }
2128    ).set_sampling());
2129    add_opt(common_arg(
2130        {"--dry-base"}, "N",
2131        string_format("set DRY sampling base value (default: %.2f)", (double)params.sampling.dry_base),
2132        [](common_params & params, const std::string & value) {
2133            float potential_base = std::stof(value);
2134            if (potential_base >= 1.0f)
2135            {
2136                params.sampling.dry_base = potential_base;
2137            }
2138        }
2139    ).set_sampling());
2140    add_opt(common_arg(
2141        {"--dry-allowed-length"}, "N",
2142        string_format("set allowed length for DRY sampling (default: %d)", params.sampling.dry_allowed_length),
2143        [](common_params & params, int value) {
2144            params.sampling.dry_allowed_length = value;
2145        }
2146    ).set_sampling());
2147    add_opt(common_arg(
2148        {"--dry-penalty-last-n"}, "N",
2149        string_format("set DRY penalty for the last n tokens (default: %d, 0 = disable)", params.sampling.dry_penalty_last_n),
2150        [](common_params & params, int value) {
2151            if (value < 0) {
2152                throw std::runtime_error(string_format("error: invalid dry-penalty-last-n = %d\n", value));
2153            }
2154            params.sampling.dry_penalty_last_n = value;
2155        }
2156    ).set_sampling());
2157    add_opt(common_arg(
2158        {"--dry-sequence-breaker"}, "STRING",
2159        string_format("add sequence breaker for DRY sampling, clearing out default breakers (%s) in the process; use \"none\" to not use any sequence breakers\n",
2160            params.sampling.dry_sequence_breakers.empty() ? "none" :
2161            std::accumulate(std::next(params.sampling.dry_sequence_breakers.begin()),
2162                params.sampling.dry_sequence_breakers.end(),
2163                std::string("'") + (params.sampling.dry_sequence_breakers[0] == "\n" ? "\\n" : params.sampling.dry_sequence_breakers[0]) + "'",
2164                [](const std::string& a, const std::string& b) {
2165                    std::string formatted_b = (b == "\n") ? "\\n" : b;
2166                    return a + ", '" + formatted_b + "'";
2167                }).c_str()),
2168        [](common_params & params, const std::string & value) {
2169            static bool defaults_cleared = false;
2170
2171            if (!defaults_cleared) {
2172                params.sampling.dry_sequence_breakers.clear();
2173                defaults_cleared = true;
2174            }
2175
2176            if (value == "none") {
2177                params.sampling.dry_sequence_breakers.clear();
2178            } else {
2179                params.sampling.dry_sequence_breakers.emplace_back(value);
2180            }
2181        }
2182    ).set_sampling());
2183    add_opt(common_arg(
2184        {"--adaptive-target"}, "N",
2185        string_format("adaptive-p: select tokens near this probability (valid range 0.0 "
2186                      "to 1.0; negative = disabled) (default: %.2f)\n"
2187                      "[(more info)](https://github.com/ggml-org/llama.cpp/pull/17927)",
2188                      (double)params.sampling.adaptive_target),
2189        [](common_params & params, const std::string & value) {
2190            params.sampling.adaptive_target = std::stof(value);
2191        }
2192    ).set_sampling());
2193    add_opt(common_arg(
2194        {"--adaptive-decay"}, "N",
2195        string_format("adaptive-p: decay rate for target adaptation over time. lower values "
2196                      "are more reactive, higher values are more stable.\n"
2197                      "(valid range 0.0 to 0.99) (default: %.2f)",
2198                      (double)params.sampling.adaptive_decay),
2199        [](common_params & params, const std::string & value) {
2200            params.sampling.adaptive_decay = std::stof(value);
2201        }
2202    ).set_sampling());
2203    add_opt(common_arg(
2204        {"--dynatemp-range"}, "N",
2205        string_format("dynamic temperature range (default: %.2f, 0.0 = disabled)", (double)params.sampling.dynatemp_range),
2206        [](common_params & params, const std::string & value) {
2207            params.sampling.dynatemp_range = std::stof(value);
2208        }
2209    ).set_sampling());
2210    add_opt(common_arg(
2211        {"--dynatemp-exp"}, "N",
2212        string_format("dynamic temperature exponent (default: %.2f)", (double)params.sampling.dynatemp_exponent),
2213        [](common_params & params, const std::string & value) {
2214            params.sampling.dynatemp_exponent = std::stof(value);
2215        }
2216    ).set_sampling());
2217    add_opt(common_arg(
2218        {"--mirostat"}, "N",
2219        string_format("use Mirostat sampling.\nTop K, Nucleus and Locally Typical samplers are ignored if used.\n"
2220        "(default: %d, 0 = disabled, 1 = Mirostat, 2 = Mirostat 2.0)", params.sampling.mirostat),
2221        [](common_params & params, int value) {
2222            params.sampling.mirostat = value;
2223            params.sampling.user_sampling_config |= common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_MIROSTAT;
2224        }
2225    ).set_sampling());
2226    add_opt(common_arg(
2227        {"--mirostat-lr"}, "N",
2228        string_format("Mirostat learning rate, parameter eta (default: %.2f)", (double)params.sampling.mirostat_eta),
2229        [](common_params & params, const std::string & value) {
2230            params.sampling.mirostat_eta = std::stof(value);
2231            params.sampling.user_sampling_config |= common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_MIROSTAT_ETA;
2232        }
2233    ).set_sampling());
2234    add_opt(common_arg(
2235        {"--mirostat-ent"}, "N",
2236        string_format("Mirostat target entropy, parameter tau (default: %.2f)", (double)params.sampling.mirostat_tau),
2237        [](common_params & params, const std::string & value) {
2238            params.sampling.mirostat_tau = std::stof(value);
2239            params.sampling.user_sampling_config |= common_params_sampling_config::COMMON_PARAMS_SAMPLING_CONFIG_MIROSTAT_TAU;
2240        }
2241    ).set_sampling());
2242    add_opt(common_arg(
2243        {"-l", "--logit-bias"}, "TOKEN_ID(+/-)BIAS",
2244        "modifies the likelihood of token appearing in the completion,\n"
2245        "i.e. `--logit-bias 15043+1` to increase likelihood of token ' Hello',\n"
2246        "or `--logit-bias 15043-1` to decrease likelihood of token ' Hello'",
2247        [](common_params & params, const std::string & value) {
2248            std::stringstream ss(value);
2249            llama_token key;
2250            char sign;
2251            std::string value_str;
2252            try {
2253                if (ss >> key && ss >> sign && std::getline(ss, value_str) && (sign == '+' || sign == '-')) {
2254                    const float bias = std::stof(value_str) * ((sign == '-') ? -1.0f : 1.0f);
2255                    params.sampling.logit_bias.push_back({key, bias});
2256                } else {
2257                    throw std::invalid_argument("invalid input format");
2258                }
2259            } catch (const std::exception&) {
2260                throw std::invalid_argument("invalid input format");
2261            }
2262        }
2263    ).set_sampling());
2264    add_opt(common_arg(
2265        {"--grammar"}, "GRAMMAR",
2266        "BNF-like grammar to constrain generations (see samples in grammars/ dir)",
2267        [](common_params & params, const std::string & value) {
2268            params.sampling.grammar = {COMMON_GRAMMAR_TYPE_USER, value};
2269        }
2270    ).set_sampling());
2271    add_opt(common_arg(
2272        {"--grammar-file"}, "FNAME",
2273        "file to read grammar from",
2274        [](common_params & params, const std::string & value) {
2275            params.sampling.grammar = {COMMON_GRAMMAR_TYPE_USER, read_file(value)};
2276        }
2277    ).set_sampling());
2278    add_opt(common_arg(
2279        {"-j", "--json-schema"}, "SCHEMA",
2280        "JSON schema to constrain generations (https://json-schema.org/), e.g. `{\"type\": \"object\"}` for any JSON object",
2281        [](common_params & params, const std::string & value) {
2282            params.sampling.grammar = {COMMON_GRAMMAR_TYPE_OUTPUT_FORMAT, json_schema_to_grammar(json::parse(value))};
2283        }
2284    ).set_sampling());
2285    add_opt(common_arg(
2286        {"-jf", "--json-schema-file"}, "FILE",
2287        "File containing a JSON schema to constrain generations (https://json-schema.org/), e.g. `{\"type\": \"object\"}` for any JSON object",
2288        [](common_params & params, const std::string & value) {
2289            std::ifstream file(value);
2290            if (!file) {
2291                throw std::runtime_error(string_format("error: failed to open file '%s'\n", value.c_str()));
2292            }
2293            std::string schema;
2294            std::copy(
2295                std::istreambuf_iterator<char>(file),
2296                std::istreambuf_iterator<char>(),
2297                std::back_inserter(schema)
2298            );
2299            params.sampling.grammar = {COMMON_GRAMMAR_TYPE_OUTPUT_FORMAT, json_schema_to_grammar(json::parse(schema))};
2300        }
2301    ).set_sampling());
2302    add_opt(common_arg(
2303        {"-bs", "--backend-sampling"},
2304        "enable backend sampling (experimental) (default: disabled)",
2305        [](common_params & params) {
2306            params.sampling.backend_sampling = true;
2307        }
2308    ).set_sampling().set_env("LLAMA_ARG_BACKEND_SAMPLING"));
2309    add_opt(common_arg(
2310        {"--pooling"}, "{none,mean,cls,last,rank}",
2311        "pooling type for embeddings, use model default if unspecified",
2312        [](common_params & params, const std::string & value) {
2313            /**/ if (value == "none") { params.pooling_type = LLAMA_POOLING_TYPE_NONE; }
2314            else if (value == "mean") { params.pooling_type = LLAMA_POOLING_TYPE_MEAN; }
2315            else if (value == "cls")  { params.pooling_type = LLAMA_POOLING_TYPE_CLS;  }
2316            else if (value == "last") { params.pooling_type = LLAMA_POOLING_TYPE_LAST; }
2317            else if (value == "rank") { params.pooling_type = LLAMA_POOLING_TYPE_RANK; }
2318            else { throw std::invalid_argument("invalid value"); }
2319        }
2320    ).set_examples({LLAMA_EXAMPLE_EMBEDDING, LLAMA_EXAMPLE_RETRIEVAL, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_DEBUG}).set_env("LLAMA_ARG_POOLING"));
2321    add_opt(common_arg(
2322        {"--attention"}, "{causal,non-causal}",
2323        "attention type for embeddings, use model default if unspecified",
2324        [](common_params & params, const std::string & value) {
2325            /**/ if (value == "causal") { params.attention_type = LLAMA_ATTENTION_TYPE_CAUSAL; }
2326            else if (value == "non-causal") { params.attention_type = LLAMA_ATTENTION_TYPE_NON_CAUSAL; }
2327            else { throw std::invalid_argument("invalid value"); }
2328        }
2329    ).set_examples({LLAMA_EXAMPLE_EMBEDDING}));
2330    add_opt(common_arg(
2331        {"--rope-scaling"}, "{none,linear,yarn}",
2332        "RoPE frequency scaling method, defaults to linear unless specified by the model",
2333        [](common_params & params, const std::string & value) {
2334            /**/ if (value == "none") { params.rope_scaling_type = LLAMA_ROPE_SCALING_TYPE_NONE; }
2335            else if (value == "linear") { params.rope_scaling_type = LLAMA_ROPE_SCALING_TYPE_LINEAR; }
2336            else if (value == "yarn") { params.rope_scaling_type = LLAMA_ROPE_SCALING_TYPE_YARN; }
2337            else { throw std::invalid_argument("invalid value"); }
2338        }
2339    ).set_env("LLAMA_ARG_ROPE_SCALING_TYPE"));
2340    add_opt(common_arg(
2341        {"--rope-scale"}, "N",
2342        "RoPE context scaling factor, expands context by a factor of N",
2343        [](common_params & params, const std::string & value) {
2344            params.rope_freq_scale = 1.0f / std::stof(value);
2345        }
2346    ).set_env("LLAMA_ARG_ROPE_SCALE"));
2347    add_opt(common_arg(
2348        {"--rope-freq-base"}, "N",
2349        "RoPE base frequency, used by NTK-aware scaling (default: loaded from model)",
2350        [](common_params & params, const std::string & value) {
2351            params.rope_freq_base = std::stof(value);
2352        }
2353    ).set_env("LLAMA_ARG_ROPE_FREQ_BASE"));
2354    add_opt(common_arg(
2355        {"--rope-freq-scale"}, "N",
2356        "RoPE frequency scaling factor, expands context by a factor of 1/N",
2357        [](common_params & params, const std::string & value) {
2358            params.rope_freq_scale = std::stof(value);
2359        }
2360    ).set_env("LLAMA_ARG_ROPE_FREQ_SCALE"));
2361    add_opt(common_arg(
2362        {"--yarn-orig-ctx"}, "N",
2363        string_format("YaRN: original context size of model (default: %d = model training context size)", params.yarn_orig_ctx),
2364        [](common_params & params, int value) {
2365            params.yarn_orig_ctx = value;
2366        }
2367    ).set_env("LLAMA_ARG_YARN_ORIG_CTX"));
2368    add_opt(common_arg(
2369        {"--yarn-ext-factor"}, "N",
2370        string_format("YaRN: extrapolation mix factor (default: %.2f, 0.0 = full interpolation)", (double)params.yarn_ext_factor),
2371        [](common_params & params, const std::string & value) {
2372            params.yarn_ext_factor = std::stof(value);
2373        }
2374    ).set_env("LLAMA_ARG_YARN_EXT_FACTOR"));
2375    add_opt(common_arg(
2376        {"--yarn-attn-factor"}, "N",
2377        string_format("YaRN: scale sqrt(t) or attention magnitude (default: %.2f)", (double)params.yarn_attn_factor),
2378        [](common_params & params, const std::string & value) {
2379            params.yarn_attn_factor = std::stof(value);
2380        }
2381    ).set_env("LLAMA_ARG_YARN_ATTN_FACTOR"));
2382    add_opt(common_arg(
2383        {"--yarn-beta-slow"}, "N",
2384        string_format("YaRN: high correction dim or alpha (default: %.2f)", (double)params.yarn_beta_slow),
2385        [](common_params & params, const std::string & value) {
2386            params.yarn_beta_slow = std::stof(value);
2387        }
2388    ).set_env("LLAMA_ARG_YARN_BETA_SLOW"));
2389    add_opt(common_arg(
2390        {"--yarn-beta-fast"}, "N",
2391        string_format("YaRN: low correction dim or beta (default: %.2f)", (double)params.yarn_beta_fast),
2392        [](common_params & params, const std::string & value) {
2393            params.yarn_beta_fast = std::stof(value);
2394        }
2395    ).set_env("LLAMA_ARG_YARN_BETA_FAST"));
2396    add_opt(common_arg(
2397        {"-gan", "--grp-attn-n"}, "N",
2398        string_format("group-attention factor (default: %d)", params.grp_attn_n),
2399        [](common_params & params, int value) {
2400            params.grp_attn_n = value;
2401        }
2402    ).set_env("LLAMA_ARG_GRP_ATTN_N").set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_PASSKEY}));
2403    add_opt(common_arg(
2404        {"-gaw", "--grp-attn-w"}, "N",
2405        string_format("group-attention width (default: %d)", params.grp_attn_w),
2406        [](common_params & params, int value) {
2407            params.grp_attn_w = value;
2408        }
2409    ).set_env("LLAMA_ARG_GRP_ATTN_W").set_examples({LLAMA_EXAMPLE_COMPLETION}));
2410    add_opt(common_arg(
2411        {"-kvo", "--kv-offload"},
2412        {"-nkvo", "--no-kv-offload"},
2413        string_format("whether to enable KV cache offloading (default: %s)", params.no_kv_offload ? "disabled" : "enabled"),
2414        [](common_params & params, bool value) {
2415            params.no_kv_offload = !value;
2416        }
2417    ).set_env("LLAMA_ARG_KV_OFFLOAD"));
2418    add_opt(common_arg(
2419        {"--repack"},
2420        {"-nr", "--no-repack"},
2421        string_format("whether to enable weight repacking (default: %s)", params.no_extra_bufts ? "disabled" : "enabled"),
2422        [](common_params & params, bool value) {
2423            params.no_extra_bufts = !value;
2424        }
2425    ).set_env("LLAMA_ARG_REPACK"));
2426    add_opt(common_arg(
2427        {"--no-host"},
2428        "bypass host buffer allowing extra buffers to be used",
2429        [](common_params & params) {
2430            params.no_host = true;
2431        }
2432    ).set_env("LLAMA_ARG_NO_HOST"));
2433    add_opt(common_arg(
2434        {"-ctk", "--cache-type-k"}, "TYPE",
2435        string_format(
2436            "KV cache data type for K\n"
2437            "allowed values: %s\n"
2438            "(default: %s)",
2439            get_all_kv_cache_types().c_str(),
2440            ggml_type_name(params.cache_type_k)
2441        ),
2442        [](common_params & params, const std::string & value) {
2443            params.cache_type_k = kv_cache_type_from_str(value);
2444        }
2445    ).set_env("LLAMA_ARG_CACHE_TYPE_K"));
2446    add_opt(common_arg(
2447        {"-ctv", "--cache-type-v"}, "TYPE",
2448        string_format(
2449            "KV cache data type for V\n"
2450            "allowed values: %s\n"
2451            "(default: %s)",
2452            get_all_kv_cache_types().c_str(),
2453            ggml_type_name(params.cache_type_v)
2454        ),
2455        [](common_params & params, const std::string & value) {
2456            params.cache_type_v = kv_cache_type_from_str(value);
2457        }
2458    ).set_env("LLAMA_ARG_CACHE_TYPE_V"));
2459    add_opt(common_arg(
2460        {"--hellaswag"},
2461        "compute HellaSwag score over random tasks from datafile supplied with -f",
2462        [](common_params & params) {
2463            params.hellaswag = true;
2464        }
2465    ).set_examples({LLAMA_EXAMPLE_PERPLEXITY}));
2466    add_opt(common_arg(
2467        {"--hellaswag-tasks"}, "N",
2468        string_format("number of tasks to use when computing the HellaSwag score (default: %zu)", params.hellaswag_tasks),
2469        [](common_params & params, int value) {
2470            params.hellaswag_tasks = value;
2471        }
2472    ).set_examples({LLAMA_EXAMPLE_PERPLEXITY}));
2473    add_opt(common_arg(
2474        {"--winogrande"},
2475        "compute Winogrande score over random tasks from datafile supplied with -f",
2476        [](common_params & params) {
2477            params.winogrande = true;
2478        }
2479    ).set_examples({LLAMA_EXAMPLE_PERPLEXITY}));
2480    add_opt(common_arg(
2481        {"--winogrande-tasks"}, "N",
2482        string_format("number of tasks to use when computing the Winogrande score (default: %zu)", params.winogrande_tasks),
2483        [](common_params & params, int value) {
2484            params.winogrande_tasks = value;
2485        }
2486    ).set_examples({LLAMA_EXAMPLE_PERPLEXITY}));
2487    add_opt(common_arg(
2488        {"--multiple-choice"},
2489        "compute multiple choice score over random tasks from datafile supplied with -f",
2490        [](common_params & params) {
2491            params.multiple_choice = true;
2492        }
2493    ).set_examples({LLAMA_EXAMPLE_PERPLEXITY}));
2494    add_opt(common_arg(
2495        {"--multiple-choice-tasks"}, "N",
2496        string_format("number of tasks to use when computing the multiple choice score (default: %zu)", params.multiple_choice_tasks),
2497        [](common_params & params, int value) {
2498            params.multiple_choice_tasks = value;
2499        }
2500    ).set_examples({LLAMA_EXAMPLE_PERPLEXITY}));
2501    add_opt(common_arg(
2502        {"--kl-divergence"},
2503        "computes KL-divergence to logits provided via --kl-divergence-base",
2504        [](common_params & params) {
2505            params.kl_divergence = true;
2506        }
2507    ).set_examples({LLAMA_EXAMPLE_PERPLEXITY}));
2508    add_opt(common_arg(
2509        {"--save-all-logits", "--kl-divergence-base"}, "FNAME",
2510        "set logits file",
2511        [](common_params & params, const std::string & value) {
2512            params.logits_file = value;
2513        }
2514    ).set_examples({LLAMA_EXAMPLE_PERPLEXITY}));
2515    add_opt(common_arg(
2516        {"--ppl-stride"}, "N",
2517        string_format("stride for perplexity calculation (default: %d)", params.ppl_stride),
2518        [](common_params & params, int value) {
2519            params.ppl_stride = value;
2520        }
2521    ).set_examples({LLAMA_EXAMPLE_PERPLEXITY}));
2522    add_opt(common_arg(
2523        {"--ppl-output-type"}, "<0|1>",
2524        string_format("output type for perplexity calculation (default: %d)", params.ppl_output_type),
2525        [](common_params & params, int value) {
2526            params.ppl_output_type = value;
2527        }
2528    ).set_examples({LLAMA_EXAMPLE_PERPLEXITY}));
2529    add_opt(common_arg(
2530        {"-dt", "--defrag-thold"}, "N",
2531        string_format("KV cache defragmentation threshold (DEPRECATED)"),
2532        [](common_params & params, const std::string & value) {
2533            GGML_UNUSED(params);
2534            GGML_UNUSED(value);
2535            LOG_WRN("DEPRECATED: --defrag-thold is deprecated and no longer necessary to specify\n");
2536        }
2537    ).set_env("LLAMA_ARG_DEFRAG_THOLD"));
2538    if (ex == LLAMA_EXAMPLE_SERVER) {
2539        // this is to make sure this option appears in the server-specific section of the help message
2540        add_opt(common_arg(
2541            {"-np", "--parallel"}, "N",
2542            string_format("number of server slots (default: %d, -1 = auto)", params.n_parallel),
2543            [](common_params & params, int value) {
2544                if (value == 0) {
2545                    throw std::invalid_argument("error: invalid value for n_parallel\n");
2546                }
2547                params.n_parallel = value;
2548            }
2549        ).set_env("LLAMA_ARG_N_PARALLEL").set_examples({LLAMA_EXAMPLE_SERVER}));
2550    } else {
2551        add_opt(common_arg(
2552            {"-np", "--parallel"}, "N",
2553            string_format("number of parallel sequences to decode (default: %d)", params.n_parallel),
2554            [](common_params & params, int value) {
2555                params.n_parallel = value;
2556            }
2557        ).set_env("LLAMA_ARG_N_PARALLEL"));
2558    }
2559    add_opt(common_arg(
2560        {"-ns", "--sequences"}, "N",
2561        string_format("number of sequences to decode (default: %d)", params.n_sequences),
2562        [](common_params & params, int value) {
2563            params.n_sequences = value;
2564        }
2565    ).set_examples({LLAMA_EXAMPLE_PARALLEL}));
2566    add_opt(common_arg(
2567        {"-cb", "--cont-batching"},
2568        {"-nocb", "--no-cont-batching"},
2569        string_format("whether to enable continuous batching (a.k.a dynamic batching) (default: %s)", params.cont_batching ? "enabled" : "disabled"),
2570        [](common_params & params, bool value) {
2571            params.cont_batching = value;
2572        }
2573    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_CONT_BATCHING"));
2574    add_opt(common_arg(
2575        {"-mm", "--mmproj"}, "FILE",
2576        "path to a multimodal projector file. see tools/mtmd/README.md\n"
2577        "note: if -hf is used, this argument can be omitted",
2578        [](common_params & params, const std::string & value) {
2579            params.mmproj.path = value;
2580        }
2581    ).set_examples(mmproj_examples).set_env("LLAMA_ARG_MMPROJ"));
2582    add_opt(common_arg(
2583        {"-mmu", "--mmproj-url"}, "URL",
2584        "URL to a multimodal projector file. see tools/mtmd/README.md",
2585        [](common_params & params, const std::string & value) {
2586            params.mmproj.url = value;
2587        }
2588    ).set_examples(mmproj_examples).set_env("LLAMA_ARG_MMPROJ_URL"));
2589    add_opt(common_arg(
2590        {"--mmproj-auto"},
2591        {"--no-mmproj", "--no-mmproj-auto"},
2592        string_format("whether to use multimodal projector file (if available), useful when using -hf (default: %s)", params.no_mmproj ? "disabled" : "enabled"),
2593        [](common_params & params, bool value) {
2594            params.no_mmproj = !value;
2595        }
2596    ).set_examples({LLAMA_EXAMPLE_MTMD, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_DOWNLOAD}).set_env("LLAMA_ARG_MMPROJ_AUTO"));
2597    add_opt(common_arg(
2598        {"--mmproj-offload"},
2599        {"--no-mmproj-offload"},
2600        string_format("whether to enable GPU offloading for multimodal projector (default: %s)", params.mmproj_use_gpu ? "enabled" : "disabled"),
2601        [](common_params & params, bool value) {
2602            params.mmproj_use_gpu = value;
2603        }
2604    ).set_examples(mmproj_examples).set_env("LLAMA_ARG_MMPROJ_OFFLOAD"));
2605    add_opt(common_arg(
2606        // note: "-mmdev" must sort after "--rpc" in the preset map, else RPC devices are not registered yet
2607        {"-mmdev", "--mmproj-device"}, "DEVICE",
2608        "device to use for multimodal projector (none = don't offload, default: follows --device)\n"
2609        "use --list-devices to see a list of available devices",
2610        [](common_params & params, const std::string & value) {
2611            if (value == "none") {
2612                params.mmproj_use_gpu = false;
2613                params.mmproj_device  = nullptr;
2614                return;
2615            }
2616            auto devices = parse_device_list(value);
2617            // parse_device_list pushes nullptr at back so devices is length 2 for single device.
2618            if (devices.size() > 2) {
2619                throw std::invalid_argument("only one device may be specified for mmproj");
2620            }
2621            params.mmproj_use_gpu = true;
2622            params.mmproj_device  = devices.front();
2623        }
2624    ).set_examples(mmproj_examples).set_env("MTMD_BACKEND_DEVICE")); // no LLAMA_ARG_ prefix for backward compatibility reason
2625    add_opt(common_arg(
2626        {"--image", "--audio", "--video"}, "FILE",
2627        "path to an image, audio, or video file. use with multimodal models, use comma-separated values for multiple files\n",
2628        [](common_params & params, const std::string & value) {
2629            for (const auto & item : parse_csv_row(value)) {
2630                params.image.emplace_back(item);
2631            }
2632        }
2633    ).set_examples({LLAMA_EXAMPLE_MTMD, LLAMA_EXAMPLE_CLI}));
2634    add_opt(common_arg(
2635        {"--image-min-tokens"}, "N",
2636        "minimum number of tokens each image can take, only used by vision models with dynamic resolution (default: read from model)",
2637        [](common_params & params, int value) {
2638            params.image_min_tokens = value;
2639        }
2640    ).set_examples(mmproj_examples).set_env("LLAMA_ARG_IMAGE_MIN_TOKENS"));
2641    add_opt(common_arg(
2642        {"--image-max-tokens"}, "N",
2643        "maximum number of tokens each image can take, only used by vision models with dynamic resolution (default: read from model)",
2644        [](common_params & params, int value) {
2645            params.image_max_tokens = value;
2646        }
2647    ).set_examples(mmproj_examples).set_env("LLAMA_ARG_IMAGE_MAX_TOKENS"));
2648    add_opt(common_arg(
2649        {"--mtmd-batch-max-tokens"}, "N",
2650        string_format("maximum number of image tokens per batch when encoding images (default: %d)", params.mtmd_batch_max_tokens),
2651        [](common_params & params, int value) {
2652            params.mtmd_batch_max_tokens = value;
2653        }
2654    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_MTMD_BATCH_MAX_TOKENS"));
2655    add_opt(common_arg(
2656        {"--video-fps"}, "N",
2657        string_format("target video frame rate (default: %.1f)", params.video_fps),
2658        [](common_params & params, const std::string & value) {
2659            params.video_fps = std::stof(value);
2660        }
2661    ).set_examples(mmproj_examples).set_env("LLAMA_ARG_VIDEO_FPS"));
2662    add_opt(common_arg(
2663        {"--video-timestamp-interval"}, "N",
2664        string_format("interval in milliseconds between text timestamps (default: %" PRId64 ")", params.video_timestamp_interval_ms),
2665        [](common_params & params, int value) {
2666            params.video_timestamp_interval_ms = value;
2667        }
2668    ).set_examples(mmproj_examples).set_env("LLAMA_ARG_VIDEO_TIMESTAMP_INTERVAL"));
2669    add_opt(common_arg(
2670        {"--video-ffmpeg-dir"}, "DIR",
2671        "path to the directory containing ffmpeg and ffprobe (default: search in PATH)",
2672        [](common_params & params, const std::string & value) {
2673            params.video_ffmpeg_bin_dir = value;
2674        }
2675    ).set_examples(mmproj_examples).set_env("LLAMA_ARG_VIDEO_FFMPEG_DIR"));
2676    if (params.is_gen_docs || llama_supports_rpc()) {
2677        add_opt(common_arg(
2678            {"--rpc"}, "SERVERS",
2679            "comma-separated list of RPC servers (host:port)",
2680            [](common_params & params, const std::string & value) {
2681                add_rpc_devices(value);
2682                GGML_UNUSED(params);
2683            }
2684        ).set_env("LLAMA_ARG_RPC"));
2685    }
2686    add_opt(common_arg(
2687        {"-lm", "--load-mode"}, "MODE",
2688        "model loading mode (default: auto)\n"
2689        "- auto: mmap, unless a device does not support it\n"
2690        "- none: no special loading mode\n"
2691        "- mmap: memory-map model (if mmap disabled, slower load but may reduce pageouts if not using mlock)\n"
2692        "- mlock: force system to keep model in RAM rather than swapping or compressing\n"
2693        "- mmap+mlock: mmap + force system to keep model in RAM rather than swapping or compressing\n"
2694        "- dio: use DirectIO if available\n",
2695        [](common_params & params, const std::string & value) {
2696            /**/ if (value == "auto")       { params.load_mode = LLAMA_LOAD_MODE_AUTO;       }
2697            else if (value == "none")       { params.load_mode = LLAMA_LOAD_MODE_NONE;       }
2698            else if (value == "mmap")       { params.load_mode = LLAMA_LOAD_MODE_MMAP;       }
2699            else if (value == "mlock")      { params.load_mode = LLAMA_LOAD_MODE_MLOCK;      }
2700            else if (value == "mmap+mlock") { params.load_mode = LLAMA_LOAD_MODE_MMAP_MLOCK; }
2701            else if (value == "dio")        { params.load_mode = LLAMA_LOAD_MODE_DIRECT_IO;  }
2702            else { throw std::invalid_argument("invalid value"); }
2703        }
2704    ).set_env("LLAMA_ARG_LOAD_MODE"));
2705    add_opt(common_arg(
2706        {"-lzm", "--lazy-mode"}, "MODE",
2707        "on-demand reading of certain tensors, for example per-layer embeddings (default: auto)\n"
2708        "- on: read the rows of such tensors from disk on demand instead of keeping them resident (requires mmap)\n"
2709        "- auto: on, but only for tensors larger than 4 GiB\n"
2710        "- off: always keep them resident",
2711        [](common_params & params, const std::string & value) {
2712            /**/ if (value == "on")   { params.lazy_mode = LLAMA_LAZY_MODE_ON;   }
2713            else if (value == "auto") { params.lazy_mode = LLAMA_LAZY_MODE_AUTO; }
2714            else if (value == "off")  { params.lazy_mode = LLAMA_LAZY_MODE_OFF;  }
2715            else { throw std::invalid_argument("invalid value"); }
2716        }
2717    ).set_env("LLAMA_ARG_LAZY_MODE"));
2718    add_opt(common_arg(
2719        {"--numa"}, "TYPE",
2720        "attempt optimizations that help on some NUMA systems\n"
2721        "- distribute: spread execution evenly over all nodes\n"
2722        "- isolate: only spawn threads on CPUs on the node that execution started on\n"
2723        "- numactl: use the CPU map provided by numactl\n"
2724        "if run without this previously, it is recommended to drop the system page cache before using this\n"
2725        "see https://github.com/ggml-org/llama.cpp/issues/1437",
2726        [](common_params & params, const std::string & value) {
2727            /**/ if (value == "distribute" || value == "") { params.numa = GGML_NUMA_STRATEGY_DISTRIBUTE; }
2728            else if (value == "isolate") { params.numa = GGML_NUMA_STRATEGY_ISOLATE; }
2729            else if (value == "numactl") { params.numa = GGML_NUMA_STRATEGY_NUMACTL; }
2730            else { throw std::invalid_argument("invalid value"); }
2731        }
2732    ).set_env("LLAMA_ARG_NUMA"));
2733    add_opt(common_arg(
2734        {"-dev", "--device"}, "<dev1,dev2,..>",
2735        "comma-separated list of devices to use for offloading (none = don't offload)\n"
2736        "use --list-devices to see a list of available devices",
2737        [](common_params & params, const std::string & value) {
2738            params.devices = parse_device_list(value);
2739        }
2740    ).set_env("LLAMA_ARG_DEVICE"));
2741    add_opt(common_arg(
2742        {"--list-devices"},
2743        "print list of available devices and exit",
2744        [](common_params &) {
2745            common_print_available_devices();
2746            exit(0);
2747        }
2748    ));
2749    add_opt(common_arg(
2750        {"-ot", "--override-tensor"}, "<tensor name pattern>=<buffer type>,...",
2751        "override tensor buffer type", [](common_params & params, const std::string & value) {
2752            parse_tensor_buffer_overrides(value, params.tensor_buft_overrides);
2753        }
2754    ).set_env("LLAMA_ARG_OVERRIDE_TENSOR"));
2755    add_opt(common_arg(
2756        {"-cmoe", "--cpu-moe"},
2757        "keep all Mixture of Experts (MoE) weights in the CPU",
2758        [](common_params & params) {
2759            params.tensor_buft_overrides.push_back(llm_ffn_exps_cpu_override());
2760        }
2761    ).set_env("LLAMA_ARG_CPU_MOE"));
2762    add_opt(common_arg(
2763        {"-ncmoe", "--n-cpu-moe"}, "N",
2764        "keep the Mixture of Experts (MoE) weights of the first N layers in the CPU",
2765        [](common_params & params, int value) {
2766            if (value < 0) {
2767                throw std::invalid_argument("invalid value");
2768            }
2769            llm_add_n_cpu_ffn_overrides(value, LLM_FFN_EXPS_REGEX, params.tensor_buft_overrides);
2770        }
2771    ).set_env("LLAMA_ARG_N_CPU_MOE"));
2772    add_opt(common_arg(
2773        {"-ncffn", "--n-cpu-ffn"}, "N",
2774        "keep the dense FFN weights of the first N layers in the CPU\n"
2775        "(dense models; for MoE expert weights use --n-cpu-moe)",
2776        [](common_params & params, int value) {
2777            if (value < 0) {
2778                throw std::invalid_argument("invalid value");
2779            }
2780            llm_add_n_cpu_ffn_overrides(value, LLM_FFN_DENSE_REGEX, params.tensor_buft_overrides);
2781        }
2782    ).set_env("LLAMA_ARG_N_CPU_FFN"));
2783    GGML_ASSERT(params.n_gpu_layers < 0); // string_format would need to be extended for a default >= 0
2784    add_opt(common_arg(
2785        {"-ngl", "--gpu-layers", "--n-gpu-layers"}, "N",
2786        string_format("max. number of layers to store in VRAM, either an exact number, 'auto', or 'all' (default: %s)", params.n_gpu_layers == -1 ? "auto" : "all"),
2787        [](common_params & params, const std::string & value) {
2788            if (value == "auto") {
2789                params.n_gpu_layers = -1;
2790            } else if (value == "all") {
2791                params.n_gpu_layers = -2;
2792            } else {
2793                params.n_gpu_layers = std::stoi(value);
2794            }
2795            if (!llama_supports_gpu_offload()) {
2796                fprintf(stderr, "warning: no usable GPU found, --gpu-layers option will be ignored\n");
2797                fprintf(stderr, "warning: one possible reason is that llama.cpp was compiled without GPU support\n");
2798                fprintf(stderr, "warning: consult docs/build.md for compilation instructions\n");
2799            }
2800        }
2801    ).set_env("LLAMA_ARG_N_GPU_LAYERS"));
2802    add_opt(common_arg(
2803        {"-sm", "--split-mode"}, "{none,layer,row,tensor}",
2804        "how to split the model across multiple GPUs, one of:\n"
2805        "- none: use one GPU only\n"
2806        "- layer (default): split layers and KV across GPUs (pipelined)\n"
2807        "- row: split weight across GPUs by rows (parallelized)\n"
2808        "- tensor: split weights and KV across GPUs (parallelized, EXPERIMENTAL)",
2809        [](common_params & params, const std::string & value) {
2810            if (value == "none") {
2811                params.split_mode = LLAMA_SPLIT_MODE_NONE;
2812            } else if (value == "layer") {
2813                params.split_mode = LLAMA_SPLIT_MODE_LAYER;
2814            } else if (value == "row") {
2815                params.split_mode = LLAMA_SPLIT_MODE_ROW;
2816            } else if (value == "tensor") {
2817                params.split_mode = LLAMA_SPLIT_MODE_TENSOR;
2818            } else {
2819                throw std::invalid_argument("invalid value");
2820            }
2821            if (!llama_supports_gpu_offload()) {
2822                fprintf(stderr, "warning: llama.cpp was compiled without support for GPU offload. Setting the split mode has no effect.\n");
2823            }
2824        }
2825    ).set_env("LLAMA_ARG_SPLIT_MODE"));
2826    add_opt(common_arg(
2827        {"-ts", "--tensor-split"}, "N0,N1,N2,...",
2828        "fraction of the model to offload to each GPU, comma-separated list of proportions, e.g. 3,1",
2829        [](common_params & params, const std::string & value) {
2830            std::string arg_next = value;
2831
2832            // split string by , and /
2833            const std::regex regex{ R"([,/]+)" };
2834            std::sregex_token_iterator it{ arg_next.begin(), arg_next.end(), regex, -1 };
2835            std::vector<std::string> split_arg{ it, {} };
2836            if (split_arg.size() >= llama_max_devices()) {
2837                throw std::invalid_argument(
2838                    string_format("got %zu input configs, but system only has %zu devices", split_arg.size(), llama_max_devices())
2839                );
2840            }
2841            for (size_t i = 0; i < llama_max_devices(); ++i) {
2842                if (i < split_arg.size()) {
2843                    params.tensor_split[i] = std::stof(split_arg[i]);
2844                } else {
2845                    params.tensor_split[i] = 0.0f;
2846                }
2847            }
2848            if (!llama_supports_gpu_offload()) {
2849                fprintf(stderr, "warning: llama.cpp was compiled without support for GPU offload. Setting a tensor split has no effect.\n");
2850            }
2851        }
2852    ).set_env("LLAMA_ARG_TENSOR_SPLIT"));
2853    add_opt(common_arg(
2854        {"-mg", "--main-gpu"}, "INDEX",
2855        string_format("the GPU to use for the model (with split-mode = none), or for intermediate results and KV (with split-mode = row) (default: %d)", params.main_gpu),
2856        [](common_params & params, int value) {
2857            params.main_gpu = value;
2858            if (!llama_supports_gpu_offload()) {
2859                fprintf(stderr, "warning: llama.cpp was compiled without support for GPU offload. Setting the main GPU has no effect.\n");
2860            }
2861        }
2862    ).set_env("LLAMA_ARG_MAIN_GPU"));
2863    add_opt(common_arg(
2864        { "-fit", "--fit" }, "[on|off]",
2865        string_format("whether to adjust unset arguments to fit in device memory ('on' or 'off', default: '%s')", params.fit_params ? "on" : "off"),
2866        [](common_params & params, const std::string & value) {
2867            if (is_truthy(value)) {
2868                params.fit_params = true;
2869            } else if (is_falsey(value)) {
2870                params.fit_params = false;
2871            } else {
2872                throw std::runtime_error(
2873                    string_format("error: unknown value for --fit: '%s'\n", value.c_str()));
2874            }
2875        }
2876    ).set_env("LLAMA_ARG_FIT"));
2877    add_opt(common_arg(
2878        { "-fitp", "--fit-print" }, "[on|off]",
2879        string_format("print the estimated required memory ('on' or 'off', default: '%s')", params.fit_params_print ? "on" : "off"),
2880        [](common_params & params, const std::string & value) {
2881            if (is_truthy(value)) {
2882                params.fit_params_print = true;
2883            } else if (is_falsey(value)) {
2884                params.fit_params_print = false;
2885            } else {
2886                throw std::runtime_error(
2887                    string_format("error: unknown value for --fit-print: '%s'\n", value.c_str()));
2888            }
2889        }
2890    ).set_examples({LLAMA_EXAMPLE_FIT_PARAMS}).set_env("LLAMA_ARG_FIT_ESTIMATE"));
2891    add_opt(common_arg(
2892        { "-fitt", "--fit-target" }, "MiB0,MiB1,MiB2,...",
2893        string_format("target margin per device for --fit, comma-separated list of values, "
2894            "single value is broadcast across all devices, default: %zu", params.fit_params_target[0]/(1024*1024)),
2895        [](common_params & params, const std::string & value) {
2896            std::string arg_next = value;
2897
2898            // split string by , and /
2899            const std::regex regex{ R"([,/]+)" };
2900            std::sregex_token_iterator it{ arg_next.begin(), arg_next.end(), regex, -1 };
2901            std::vector<std::string> split_arg{ it, {} };
2902            if (split_arg.size() >= llama_max_devices()) {
2903                throw std::invalid_argument(
2904                    string_format("got %zu input configs, but system only has %zu devices", split_arg.size(), llama_max_devices())
2905                );
2906            }
2907            if (split_arg.size() == 1) {
2908                std::fill(params.fit_params_target.begin(), params.fit_params_target.end(), std::stoull(split_arg[0]) * 1024*1024);
2909                return;
2910            }
2911            for (size_t i = 0; i < split_arg.size(); i++) {
2912                params.fit_params_target[i] = std::stoull(split_arg[i]) * 1024*1024;
2913            }
2914        }
2915    ).set_env("LLAMA_ARG_FIT_TARGET"));
2916    add_opt(common_arg(
2917        { "-fitc", "--fit-ctx" }, "N",
2918        string_format("minimum ctx size that can be set by --fit option, default: %" PRIu32, params.fit_params_min_ctx),
2919        [](common_params & params, int value) {
2920            params.fit_params_min_ctx = value;
2921        }
2922    ).set_env("LLAMA_ARG_FIT_CTX"));
2923    add_opt(common_arg(
2924        {"--check-tensors"},
2925        string_format("check model tensor data for invalid values (default: %s)", params.check_tensors ? "true" : "false"),
2926        [](common_params & params) {
2927            params.check_tensors = true;
2928        }
2929    ));
2930    add_opt(common_arg(
2931        {"--override-kv"}, "KEY=TYPE:VALUE,...",
2932        "advanced option to override model metadata by key. to specify multiple overrides, either use comma-separated values.\n"
2933        "types: int, float, bool, str. example: --override-kv tokenizer.ggml.add_bos_token=bool:false,tokenizer.ggml.add_eos_token=bool:false",
2934        [](common_params & params, const std::string & value) {
2935            for (const auto & item : parse_csv_row(value)) {
2936                if (!string_parse_kv_override(item.c_str(), params.kv_overrides)) {
2937                    throw std::runtime_error(string_format("error: Invalid type for KV override: %s\n", item.c_str()));
2938                }
2939            }
2940        }
2941    ));
2942    add_opt(common_arg(
2943        {"--op-offload"},
2944        {"--no-op-offload"},
2945        string_format("whether to offload host tensor operations to device (default: %s)", params.no_op_offload ? "false" : "true"),
2946        [](common_params & params, bool value) {
2947            params.no_op_offload = !value;
2948        }
2949    ));
2950    add_opt(common_arg(
2951        {"--lora"}, "FNAME",
2952        "path to LoRA adapter (use comma-separated values to load multiple adapters)",
2953        [](common_params & params, const std::string & value) {
2954            for (const auto & item : parse_csv_row(value)) {
2955                params.lora_adapters.push_back({ item, 1.0, "", "", nullptr });
2956            }
2957        }
2958        // we define this arg on both COMMON and EXPORT_LORA, so when showing help message of export-lora, it will be categorized as "example-specific" arg
2959    ).set_examples({LLAMA_EXAMPLE_COMMON, LLAMA_EXAMPLE_EXPORT_LORA}));
2960    add_opt(common_arg(
2961        {"--lora-scaled"}, "FNAME:SCALE,...",
2962        "path to LoRA adapter with user defined scaling (format: FNAME:SCALE,...)\n"
2963        "note: use comma-separated values",
2964        [](common_params & params, const std::string & value) {
2965            for (const auto & item : parse_csv_row(value)) {
2966                auto parts = string_split<std::string>(item, ':');
2967                if (parts.size() != 2) {
2968                    throw std::invalid_argument("lora-scaled format: FNAME:SCALE");
2969                }
2970                params.lora_adapters.push_back({ parts[0], std::stof(parts[1]), "", "", nullptr });
2971            }
2972        }
2973        // we define this arg on both COMMON and EXPORT_LORA, so when showing help message of export-lora, it will be categorized as "example-specific" arg
2974    ).set_examples({LLAMA_EXAMPLE_COMMON, LLAMA_EXAMPLE_EXPORT_LORA}));
2975    add_opt(common_arg(
2976        {"--control-vector"}, "FNAME",
2977        "add a control vector\nnote: use comma-separated values to add multiple control vectors",
2978        [](common_params & params, const std::string & value) {
2979            for (const auto & item : parse_csv_row(value)) {
2980                params.control_vectors.push_back({ 1.0f, item, });
2981            }
2982        }
2983    ));
2984    add_opt(common_arg(
2985        {"--control-vector-scaled"}, "FNAME:SCALE,...",
2986        "add a control vector with user defined scaling SCALE\n"
2987        "note: use comma-separated values (format: FNAME:SCALE,...)",
2988        [](common_params & params, const std::string & value) {
2989            for (const auto & item : parse_csv_row(value)) {
2990                auto parts = string_split<std::string>(item, ':');
2991                if (parts.size() != 2) {
2992                    throw std::invalid_argument("control-vector-scaled format: FNAME:SCALE");
2993                }
2994                params.control_vectors.push_back({ std::stof(parts[1]), parts[0] });
2995            }
2996        }
2997    ));
2998    add_opt(common_arg(
2999        {"--control-vector-layer-range"}, "START", "END",
3000        "layer range to apply the control vector(s) to, start and end inclusive",
3001        [](common_params & params, const std::string & start, const std::string & end) {
3002            params.control_vector_layer_start = std::stoi(start);
3003            params.control_vector_layer_end = std::stoi(end);
3004        }
3005    ));
3006    add_opt(common_arg(
3007        {"-a", "--alias"}, "STRING",
3008        "set model name aliases, comma-separated (to be used by API)",
3009        [](common_params & params, const std::string & value) {
3010            for (auto & alias : string_split<std::string>(value, ',')) {
3011                alias = string_strip(alias);
3012                if (!alias.empty()) {
3013                    params.model_alias.insert(alias);
3014                }
3015            }
3016        }
3017    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_ALIAS"));
3018    add_opt(common_arg(
3019        {"--tags"}, "STRING",
3020        "set model tags, comma-separated (informational, not used for routing)",
3021        [](common_params & params, const std::string & value) {
3022            for (auto & tag : string_split<std::string>(value, ',')) {
3023                tag = string_strip(tag);
3024                if (!tag.empty()) {
3025                    params.model_tags.insert(tag);
3026                }
3027            }
3028        }
3029    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_TAGS"));
3030    add_opt(common_arg(
3031        {"-m", "--model"}, "FNAME",
3032        ex == LLAMA_EXAMPLE_EXPORT_LORA
3033            ? "model path from which to load base model"
3034            : "model path to load",
3035        [](common_params & params, const std::string & value) {
3036            params.model.path = value;
3037        }
3038    ).set_examples({LLAMA_EXAMPLE_COMMON, LLAMA_EXAMPLE_EXPORT_LORA, LLAMA_EXAMPLE_DOWNLOAD, LLAMA_EXAMPLE_TOKENIZE}).set_env("LLAMA_ARG_MODEL"));
3039    add_opt(common_arg(
3040        {"-mu", "--model-url"}, "MODEL_URL",
3041        "model download url (default: unused)",
3042        [](common_params & params, const std::string & value) {
3043            params.model.url = value;
3044        }
3045    ).set_examples({LLAMA_EXAMPLE_COMMON, LLAMA_EXAMPLE_DOWNLOAD, LLAMA_EXAMPLE_TOKENIZE}).set_env("LLAMA_ARG_MODEL_URL"));
3046    add_opt(common_arg(
3047        { "-dr", "--docker-repo" }, "[<repo>/]<model>[:quant]",
3048        "Docker Hub model repository. repo is optional, default to ai/. quant is optional, default to :latest.\n"
3049        "example: gemma3\n"
3050        "(default: unused)",
3051        [](common_params & params, const std::string & value) {
3052            params.model.docker_repo = value;
3053        }
3054    ).set_examples({LLAMA_EXAMPLE_COMMON, LLAMA_EXAMPLE_DOWNLOAD, LLAMA_EXAMPLE_TOKENIZE}).set_env("LLAMA_ARG_DOCKER_REPO"));
3055    add_opt(common_arg(
3056        {"-hf", "-hfr", "--hf-repo"}, "<user>/<model>[:quant]",
3057        "Hugging Face model repository; quant is optional, case-insensitive, default to Q4_K_M, or falls back to the first file in the repo if Q4_K_M doesn't exist.\n"
3058        "mmproj is also downloaded automatically if available. to disable, add --no-mmproj\n"
3059        "example: ggml-org/GLM-4.7-Flash-GGUF:Q4_K_M\n"
3060        "(default: unused)",
3061        [](common_params & params, const std::string & value) {
3062            params.model.hf_repo = value;
3063        }
3064    ).set_examples({LLAMA_EXAMPLE_COMMON, LLAMA_EXAMPLE_DOWNLOAD, LLAMA_EXAMPLE_TOKENIZE}).set_env("LLAMA_ARG_HF_REPO"));
3065    add_opt(common_arg(
3066        {"-hff", "--hf-file"}, "FILE",
3067        "Hugging Face model file. If specified, it will override the quant in --hf-repo (default: unused)",
3068        [](common_params & params, const std::string & value) {
3069            params.model.hf_file = value;
3070        }
3071    ).set_examples({LLAMA_EXAMPLE_COMMON, LLAMA_EXAMPLE_DOWNLOAD, LLAMA_EXAMPLE_TOKENIZE}).set_env("LLAMA_ARG_HF_FILE"));
3072    add_opt(common_arg(
3073        {"-hft", "--hf-token"}, "TOKEN",
3074        "Hugging Face access token (default: value from HF_TOKEN environment variable)",
3075        [](common_params & params, const std::string & value) {
3076            params.hf_token = value;
3077        }
3078    ).set_examples({LLAMA_EXAMPLE_COMMON, LLAMA_EXAMPLE_DOWNLOAD, LLAMA_EXAMPLE_TOKENIZE}).set_env("HF_TOKEN"));
3079    add_opt(common_arg(
3080        {"--mtp"},
3081        "also download the multi-token prediction (MTP) head, if available (default: unused)",
3082        [](common_params & params) {
3083            params.speculative.types.push_back(COMMON_SPECULATIVE_TYPE_DRAFT_MTP);
3084        }
3085    ).set_examples({LLAMA_EXAMPLE_DOWNLOAD}));
3086    add_opt(common_arg(
3087        {"--dflash"},
3088        "also download the DFlash sidecar, if available (default: unused)",
3089        [](common_params & params) {
3090            params.speculative.types.push_back(COMMON_SPECULATIVE_TYPE_DRAFT_DFLASH);
3091        }
3092    ).set_examples({LLAMA_EXAMPLE_DOWNLOAD}));
3093    add_opt(common_arg(
3094        {"--eagle3"},
3095        "also download the Eagle3 sidecar, if available (default: unused)",
3096        [](common_params & params) {
3097            params.speculative.types.push_back(COMMON_SPECULATIVE_TYPE_DRAFT_EAGLE3);
3098        }
3099    ).set_examples({LLAMA_EXAMPLE_DOWNLOAD}));
3100    add_opt(common_arg(
3101        {"--context-file"}, "FNAME",
3102        "file to load context from (use comma-separated values to specify multiple files)",
3103        [](common_params & params, const std::string & value) {
3104            for (const auto & item : parse_csv_row(value)) {
3105                std::ifstream file(item, std::ios::binary);
3106                if (!file) {
3107                    throw std::runtime_error(string_format("error: failed to open file '%s'\n", item.c_str()));
3108                }
3109                params.context_files.push_back(item);
3110            }
3111        }
3112    ).set_examples({LLAMA_EXAMPLE_RETRIEVAL}));
3113    add_opt(common_arg(
3114        {"--chunk-size"}, "N",
3115        string_format("minimum length of embedded text chunks (default: %d)", params.chunk_size),
3116        [](common_params & params, int value) {
3117            params.chunk_size = value;
3118        }
3119    ).set_examples({LLAMA_EXAMPLE_RETRIEVAL}));
3120    add_opt(common_arg(
3121        {"--chunk-separator"}, "STRING",
3122        string_format("separator between chunks (default: '%s')", params.chunk_separator.c_str()),
3123        [](common_params & params, const std::string & value) {
3124            params.chunk_separator = value;
3125        }
3126    ).set_examples({LLAMA_EXAMPLE_RETRIEVAL}));
3127    add_opt(common_arg(
3128        {"--junk"}, "N",
3129        string_format("number of times to repeat the junk text (default: %d)", params.n_junk),
3130        [](common_params & params, int value) {
3131            params.n_junk = value;
3132        }
3133    ).set_examples({LLAMA_EXAMPLE_PASSKEY, LLAMA_EXAMPLE_PARALLEL}));
3134    add_opt(common_arg(
3135        {"--pos"}, "N",
3136        string_format("position of the passkey in the junk text (default: %d)", params.i_pos),
3137        [](common_params & params, int value) {
3138            params.i_pos = value;
3139        }
3140    ).set_examples({LLAMA_EXAMPLE_PASSKEY}));
3141    add_opt(common_arg(
3142        {"-o", "--output", "--output-file"}, "FNAME",
3143        string_format("output file (default: '%s')", params.out_file.c_str()),
3144        [](common_params & params, const std::string & value) {
3145            params.out_file = value;
3146        }
3147    ).set_examples({LLAMA_EXAMPLE_IMATRIX, LLAMA_EXAMPLE_CVECTOR_GENERATOR, LLAMA_EXAMPLE_EXPORT_LORA, LLAMA_EXAMPLE_TTS, LLAMA_EXAMPLE_FINETUNE,
3148                    LLAMA_EXAMPLE_RESULTS, LLAMA_EXAMPLE_EXPORT_GRAPH_OPS, LLAMA_EXAMPLE_CLI}));
3149    add_opt(common_arg(
3150        {"-ofreq", "--output-frequency"}, "N",
3151        string_format("output the imatrix every N iterations (default: %d)", params.n_out_freq),
3152        [](common_params & params, int value) {
3153            params.n_out_freq = value;
3154        }
3155    ).set_examples({LLAMA_EXAMPLE_IMATRIX}));
3156    add_opt(common_arg(
3157        {"--output-format"}, "{gguf,dat}",
3158        string_format("output format for imatrix file (default: %s)", params.imat_dat > 0 ? "dat" : "gguf"),
3159        [](common_params & params, const std::string & value) {
3160            /**/ if (value == "gguf") { params.imat_dat = -1; }
3161            else if (value == "dat")  { params.imat_dat = 1;  }
3162            else { throw std::invalid_argument("invalid output format"); }
3163        }
3164    ).set_examples({LLAMA_EXAMPLE_IMATRIX}));
3165    add_opt(common_arg(
3166        {"--save-frequency"}, "N",
3167        string_format("save an imatrix copy every N iterations (default: %d)", params.n_save_freq),
3168        [](common_params & params, int value) {
3169            params.n_save_freq = value;
3170        }
3171    ).set_examples({LLAMA_EXAMPLE_IMATRIX}));
3172    add_opt(common_arg(
3173        {"--process-output"},
3174        string_format("collect data for the output tensor (default: %s)", params.process_output ? "true" : "false"),
3175        [](common_params & params) {
3176            params.process_output = true;
3177        }
3178    ).set_examples({LLAMA_EXAMPLE_IMATRIX}));
3179    add_opt(common_arg(
3180        {"--ppl"},
3181        {"--no-ppl"},
3182        string_format("whether to compute perplexity (default: %s)", params.compute_ppl ? "true" : "false"),
3183        [](common_params & params, bool value) {
3184            params.compute_ppl = value;
3185        }
3186    ).set_examples({LLAMA_EXAMPLE_IMATRIX}));
3187    add_opt(common_arg(
3188        {"--chunk", "--from-chunk"}, "N",
3189        string_format("start processing the input from chunk N (default: %d)", params.i_chunk),
3190        [](common_params & params, int value) {
3191            params.i_chunk = value;
3192        }
3193    ).set_examples({LLAMA_EXAMPLE_IMATRIX}));
3194    add_opt(common_arg(
3195        {"--show-statistics"},
3196        string_format("show imatrix statistics and then exit (default: %s)", params.show_statistics ? "true" : "false"),
3197        [](common_params & params) {
3198            params.show_statistics = true;
3199        }
3200    ).set_examples({LLAMA_EXAMPLE_IMATRIX}));
3201    add_opt(common_arg(
3202        {"--parse-special"},
3203        string_format("parse special tokens (chat, tool, etc) (default: %s)", params.parse_special ? "true" : "false"),
3204        [](common_params & params) {
3205            params.parse_special = true;
3206        }
3207    ).set_examples({LLAMA_EXAMPLE_IMATRIX}));
3208    add_opt(common_arg(
3209        {"--ids"},
3210        string_format("only print the token IDs, in a Python-parseable list form like [1, 2, 3] (default: %s)", params.tokenize_ids ? "true" : "false"),
3211        [](common_params & params) {
3212            params.tokenize_ids = true;
3213        }
3214    ).set_examples({LLAMA_EXAMPLE_TOKENIZE}));
3215    add_opt(common_arg(
3216        {"--stdin"},
3217        string_format("read the prompt from stdin (takes precedence over -f/--file and -p/--prompt) (default: %s)", params.tokenize_stdin ? "true" : "false"),
3218        [](common_params & params) {
3219            params.tokenize_stdin = true;
3220        }
3221    ).set_examples({LLAMA_EXAMPLE_TOKENIZE}));
3222    add_opt(common_arg(
3223        {"--no-bos"},
3224        string_format("do not add a BOS token to the prompt, even if the model normally uses one (default: %s)", params.tokenize_no_bos ? "true" : "false"),
3225        [](common_params & params) {
3226            params.tokenize_no_bos = true;
3227        }
3228    ).set_examples({LLAMA_EXAMPLE_TOKENIZE}));
3229    add_opt(common_arg(
3230        {"--no-parse-special"},
3231        string_format("do not parse special tokens (chat, tool, etc) (default: %s)", !params.parse_special ? "true" : "false"),
3232        [](common_params & params) {
3233            params.parse_special = false;
3234        }
3235    ).set_examples({LLAMA_EXAMPLE_TOKENIZE}));
3236    add_opt(common_arg(
3237        {"--show-count"},
3238        string_format("print the total number of tokens (default: %s)", params.tokenize_show_count ? "true" : "false"),
3239        [](common_params & params) {
3240            params.tokenize_show_count = true;
3241        }
3242    ).set_examples({LLAMA_EXAMPLE_TOKENIZE}));
3243    add_opt(common_arg(
3244        {"-pps"},
3245        string_format("is the prompt shared across parallel sequences (default: %s)", params.is_pp_shared ? "true" : "false"),
3246        [](common_params & params) {
3247            params.is_pp_shared = true;
3248        }
3249    ).set_examples({LLAMA_EXAMPLE_BENCH, LLAMA_EXAMPLE_PARALLEL}));
3250    add_opt(common_arg(
3251        {"-tgs"},
3252        string_format("is the text generation separated across the different sequences (default: %s)", params.is_tg_separate ? "true" : "false"),
3253        [](common_params & params) {
3254            params.is_tg_separate = true;
3255        }
3256    ).set_examples({LLAMA_EXAMPLE_BENCH, LLAMA_EXAMPLE_PARALLEL}));
3257    add_opt(common_arg(
3258        {"-npp"}, "n0,n1,...",
3259        "number of prompt tokens",
3260        [](common_params & params, const std::string & value) {
3261            auto p = string_split<int>(value, ',');
3262            params.n_pp.insert(params.n_pp.end(), p.begin(), p.end());
3263        }
3264    ).set_examples({LLAMA_EXAMPLE_BENCH}));
3265    add_opt(common_arg(
3266        {"-ntg"}, "n0,n1,...",
3267        "number of text generation tokens",
3268        [](common_params & params, const std::string & value) {
3269            auto p = string_split<int>(value, ',');
3270            params.n_tg.insert(params.n_tg.end(), p.begin(), p.end());
3271        }
3272    ).set_examples({LLAMA_EXAMPLE_BENCH}));
3273    add_opt(common_arg(
3274        {"-npl"}, "n0,n1,...",
3275        "number of parallel prompts",
3276        [](common_params & params, const std::string & value) {
3277            auto p = string_split<int>(value, ',');
3278            params.n_pl.insert(params.n_pl.end(), p.begin(), p.end());
3279        }
3280    ).set_examples({LLAMA_EXAMPLE_BENCH}));
3281    add_opt(common_arg(
3282        {"--embd-normalize"}, "N",
3283        string_format("normalisation for embeddings (default: %d) (-1=none, 0=max absolute int16, 1=taxicab, 2=euclidean, >2=p-norm)", params.embd_normalize),
3284        [](common_params & params, int value) {
3285            params.embd_normalize = value;
3286        }
3287    ).set_examples({LLAMA_EXAMPLE_EMBEDDING, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_DEBUG}));
3288    add_opt(common_arg(
3289        {"--embd-output-format"}, "FORMAT",
3290        "empty = default, \"array\" = [[],[]...], \"json\" = openai style, \"json+\" = same \"json\" + cosine similarity matrix, \"raw\" = plain whitespace-delimited output (one embedding per line)",
3291        [](common_params & params, const std::string & value) {
3292            params.embd_out = value;
3293        }
3294    ).set_examples({LLAMA_EXAMPLE_EMBEDDING}));
3295    add_opt(common_arg(
3296        {"--embd-separator"}, "STRING",
3297        "separator of embeddings (default \\n) for example \"<#sep#>\"",
3298        [](common_params & params, const std::string & value) {
3299            params.embd_sep = value;
3300        }
3301    ).set_examples({LLAMA_EXAMPLE_EMBEDDING}));
3302    add_opt(common_arg(
3303        {"--cls-separator"}, "STRING",
3304        "separator of classification sequences (default \\t) for example \"<#seq#>\"",
3305        [](common_params & params, const std::string & value) {
3306            params.cls_sep = value;
3307        }
3308    ).set_examples({LLAMA_EXAMPLE_EMBEDDING}));
3309    add_opt(common_arg(
3310        {"--host"}, "HOST",
3311        string_format("ip address to listen, or bind to an UNIX socket if the address ends with .sock (default: %s)", params.hostname.c_str()),
3312        [](common_params & params, const std::string & value) {
3313            params.hostname = value;
3314        }
3315    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_HOST"));
3316    add_opt(common_arg(
3317        {"--port"}, "PORT",
3318        string_format("port to listen (default: %d)", params.port),
3319        [](common_params & params, int value) {
3320            params.port = value;
3321        }
3322    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_PORT"));
3323    add_opt(common_arg(
3324        {"--reuse-port"},
3325        string_format("allow multiple sockets to bind to the same port (default: %s)", params.reuse_port ? "enabled" : "disabled"),
3326        [](common_params & params) {
3327            params.reuse_port = true;
3328        }
3329    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_REUSE_PORT"));
3330    add_opt(common_arg(
3331        {"--path"}, "PATH",
3332        string_format("path to serve static files from (default: %s)", params.public_path.c_str()),
3333        [](common_params & params, const std::string & value) {
3334            params.public_path = value;
3335        }
3336    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_STATIC_PATH"));
3337    add_opt(common_arg(
3338        {"--cors-origins"}, "ORIGINS",
3339        string_format(
3340            "comma-separated list of allowed origins for CORS (default: %s)\n"
3341            "if set to special value 'localhost', reflect the Origin header only if it is localhost",
3342        params.cors_origins.c_str()),
3343        [](common_params & params, const std::string & value) {
3344            params.cors_origins = value;
3345            params.cors_origins_explicit = true;
3346        }
3347    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_CORS_ORIGINS"));
3348    add_opt(common_arg(
3349        {"--cors-methods"}, "METHODS",
3350        string_format("comma-separated list of allowed methods for CORS (default: %s)", params.cors_methods.c_str()),
3351        [](common_params & params, const std::string & value) {
3352            params.cors_methods = value;
3353        }
3354    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_CORS_METHODS"));
3355    add_opt(common_arg(
3356        {"--cors-headers"}, "HEADERS",
3357        string_format("comma-separated list of allowed headers for CORS (default: %s)", params.cors_headers.c_str()),
3358        [](common_params & params, const std::string & value) {
3359            params.cors_headers = value;
3360        }
3361    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_CORS_HEADERS"));
3362    add_opt(common_arg(
3363        {"--cors-credentials"},
3364        {"--no-cors-credentials"},
3365        string_format(
3366            "whether to allow credentials for CORS (default: %s)\n"
3367            "note: if this is enabled and --cors-origins is set to * (default), the Origin header will be echoed back, and credentials will always be allowed",
3368        params.cors_credentials ? "enabled" : "disabled"),
3369        [](common_params & params, bool value) {
3370            params.cors_credentials = value;
3371        }
3372    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_CORS_CREDENTIALS"));
3373    add_opt(common_arg(
3374        {"--api-prefix"}, "PREFIX",
3375        string_format("prefix path the server serves from, without the trailing slash (default: %s)", params.api_prefix.c_str()),
3376        [](common_params & params, const std::string & value) {
3377            params.api_prefix = value;
3378        }
3379    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_API_PREFIX"));
3380    add_opt(common_arg(
3381        {"--ui-config", "--webui-config"}, "JSON",
3382        "JSON that provides default UI settings (overrides UI defaults)",
3383        [](common_params & params, const std::string & value) {
3384            params.ui_config_json = value;
3385        }
3386    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_UI_CONFIG"));
3387    add_opt(common_arg(
3388        {"--ui-config-file", "--webui-config-file"}, "PATH",
3389        "JSON file that provides default UI settings (overrides UI defaults)",
3390        [](common_params & params, const std::string & value) {
3391            params.ui_config_json = read_file(value);
3392        }
3393    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_UI_CONFIG_FILE"));
3394    add_opt(common_arg(
3395        {"--ui-mcp-proxy", "--webui-mcp-proxy"},
3396        {"--no-ui-mcp-proxy", "--no-webui-mcp-proxy"},
3397        "experimental: whether to enable MCP CORS proxy - do not enable in untrusted environments (default: disabled)",
3398        [](common_params & params, bool value) {
3399            params.ui_mcp_proxy = value;
3400        }
3401    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_UI_MCP_PROXY"));
3402    add_opt(common_arg(
3403        {"--tools"}, "TOOL1,TOOL2,...",
3404        "experimental: whether to enable built-in tools for AI agents - do not enable in untrusted environments (default: no tools)\n"
3405        "specify \"all\" to enable all tools\n"
3406        "available tools: read_file, file_glob_search, grep_search, exec_shell_command, write_file, edit_file, get_info\n"
3407        "note: for security reasons, this will limit --cors-origins to localhost by default",
3408        [](common_params & params, const std::string & value) {
3409            params.server_tools = parse_csv_row(value);
3410        }
3411    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_TOOLS"));
3412    add_opt(common_arg(
3413        {"--tools-runtime"}, "OPTION",
3414        "experimental: run tools in a separate runtime environment (default: none, use host environment)\n"
3415        "available options:\n"
3416        "  'docker:<image>', 'podman:<image>': spin up a new container and reuse it for all invocations, clean up on server exit\n"
3417        "  'docker-container:<id>', 'podman-container:<id>': use an existing container by ID, won't stop on server exit\n"
3418        "  'ssh:<target>': run tools on a remote POSIX host over SSH, key-based auth and a trusted host key are required\n",
3419        [](common_params & params, const std::string & value) {
3420            params.server_tools_runtime = value;
3421        }
3422    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_TOOLS_RUNTIME"));
3423    add_opt(common_arg(
3424        {"--mcp-servers-config"}, "PATH",
3425        "experimental: path to JSON file with MCP server definitions (Cursor-compatible format) - do not enable in untrusted environments (default: none)\n"
3426        "note: for security reasons, this will limit --cors-origins to localhost by default",
3427        [](common_params & params, const std::string & value) {
3428            params.mcp_servers_config = value;
3429        }
3430    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_MCP_SERVERS_CONFIG"));
3431    add_opt(common_arg(
3432        {"--mcp-servers-json"}, "JSON",
3433        "experimental: inline JSON with MCP server definitions (Cursor-compatible format) - do not enable in untrusted environments (default: none)\n"
3434        "note: for security reasons, this will limit --cors-origins to localhost by default",
3435        [](common_params & params, const std::string & value) {
3436            params.mcp_servers_json = value;
3437        }
3438    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_MCP_SERVERS_JSON"));
3439    add_opt(common_arg(
3440        {"-ag", "--agent"},
3441        {"-no-ag", "--no-agent"},
3442        "whether to enable CORS proxy and all built-in tools - do not enable in untrusted environments (default: disabled)\n"
3443        "note: for security reasons, this will limit --cors-origins to localhost by default",
3444        [](common_params & params, bool value) {
3445            if (value) {
3446                params.server_tools = {"all"};
3447                params.ui_mcp_proxy = true;
3448            } else {
3449                params.server_tools.clear();
3450                params.ui_mcp_proxy = false;
3451            }
3452            // note: do not modify cors_origins here, as the options are not evaluated in order (user may explicitly set --cors-origins before --agent)
3453        }
3454    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_AGENT"));
3455    add_opt(common_arg(
3456        {"--ui", "--webui"},
3457        {"--no-ui", "--no-webui"},
3458        string_format("whether to enable the Web UI (default: %s)", params.ui ? "enabled" : "disabled"),
3459        [](common_params & params, bool value) {
3460            params.ui = value;
3461        }
3462    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_UI"));
3463    add_opt(common_arg(
3464        {"--embedding", "--embeddings"},
3465        string_format("restrict to only support embedding use case; use only with dedicated embedding models (default: %s)", params.embedding ? "enabled" : "disabled"),
3466        [](common_params & params) {
3467            params.embedding = true;
3468        }
3469    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_DEBUG}).set_env("LLAMA_ARG_EMBEDDINGS"));
3470    add_opt(common_arg(
3471        {"--rerank", "--reranking"},
3472        string_format("enable reranking endpoint on server (default: %s)", "disabled"),
3473        [](common_params & params) {
3474            params.embedding = true;
3475            params.pooling_type = LLAMA_POOLING_TYPE_RANK;
3476        }
3477    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_RERANKING"));
3478    add_opt(common_arg(
3479        {"--api-key"}, "KEY",
3480        "API key to use for authentication, multiple keys can be provided as a comma-separated list (default: none)",
3481        [](common_params & params, const std::string & value) {
3482            for (const auto & key : parse_csv_row(value)) {
3483                if (!key.empty()) {
3484                    params.api_keys.push_back(key);
3485                }
3486            }
3487        }
3488    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_API_KEY"));
3489    add_opt(common_arg(
3490        {"--api-key-file"}, "FNAME",
3491        "path to file containing API keys, one per line; lines starting with a hash are treated as comments (default: none)",
3492        [](common_params & params, const std::string & value) {
3493            std::ifstream key_file(value);
3494            if (!key_file) {
3495                throw std::runtime_error(string_format("error: failed to open file '%s'\n", value.c_str()));
3496            }
3497            std::string key;
3498            while (std::getline(key_file, key)) {
3499                if (!key.empty() && key[0] != '#') {
3500                    params.api_keys.push_back(key);
3501                }
3502            }
3503            key_file.close();
3504        }
3505    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_API_KEY_FILE"));
3506    add_opt(common_arg(
3507        {"--ssl-key-file"}, "FNAME",
3508        "path to file a PEM-encoded SSL private key",
3509        [](common_params & params, const std::string & value) {
3510            params.ssl_file_key = value;
3511        }
3512    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_SSL_KEY_FILE"));
3513    add_opt(common_arg(
3514        {"--ssl-cert-file"}, "FNAME",
3515        "path to file a PEM-encoded SSL certificate",
3516        [](common_params & params, const std::string & value) {
3517            params.ssl_file_cert = value;
3518        }
3519    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_SSL_CERT_FILE"));
3520    add_opt(common_arg(
3521        {"--chat-template-kwargs"}, "STRING",
3522        "sets additional params for the json template parser, must be a valid json object string, e.g. '{\"key1\":\"value1\",\"key2\":\"value2\"}'",
3523        [](common_params & params, const std::string & value) {
3524            auto parsed = json::parse(value);
3525            for (const auto & item : parsed.items()) {
3526                if (item.key() == "enable_thinking") {
3527                    LOG_WRN("Setting 'enable_thinking' via --chat-template-kwargs is deprecated. "
3528                            "Use --reasoning on / --reasoning off instead.\n");
3529                }
3530                if (item.key() == "preserve_reasoning") {
3531                    LOG_WRN("Setting 'preserve_reasoning' via --chat-template-kwargs is deprecated. "
3532                            "Use --reasoning-preserve / --no-reasoning-preserve instead.\n");
3533                }
3534                params.default_template_kwargs[item.key()] = item.value().dump();
3535            }
3536        }
3537    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_CHAT_TEMPLATE_KWARGS"));
3538    add_opt(common_arg(
3539        {"-to", "--timeout"}, "N",
3540        string_format("server read/write timeout in seconds (default: %d)", params.timeout_read),
3541        [](common_params & params, int value) {
3542            params.timeout_read  = value;
3543            params.timeout_write = value;
3544        }
3545    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_TIMEOUT"));
3546    add_opt(common_arg(
3547        {"--sse-ping-interval"}, "N",
3548        string_format("server SSE ping interval in seconds (-1 = disabled, default: %d)", params.sse_ping_interval),
3549        [](common_params & params, int value) {
3550            params.sse_ping_interval = value;
3551        }
3552    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_SSE_PING_INTERVAL"));
3553    add_opt(common_arg(
3554        {"--threads-http"}, "N",
3555        string_format("number of threads used to process HTTP requests (default: %d)", params.n_threads_http),
3556        [](common_params & params, int value) {
3557            params.n_threads_http = value;
3558        }
3559    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_THREADS_HTTP"));
3560    add_opt(common_arg(
3561        {"--cache-prompt"},
3562        {"--no-cache-prompt"},
3563        string_format("whether to enable prompt caching (default: %s)", params.cache_prompt ? "enabled" : "disabled"),
3564        [](common_params & params, bool value) {
3565            params.cache_prompt = value;
3566        }
3567    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_CACHE_PROMPT"));
3568    add_opt(common_arg(
3569        {"--cache-reuse"}, "N",
3570        string_format(
3571            "min chunk size to attempt reusing from the cache via KV shifting, requires prompt caching to be enabled (default: %d)\n"
3572            "[(card)](https://ggml.ai/f0.png)", params.n_cache_reuse
3573        ),
3574        [](common_params & params, int value) {
3575            params.n_cache_reuse = value;
3576        }
3577    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_CACHE_REUSE"));
3578    add_opt(common_arg(
3579        {"--metrics"},
3580        string_format("enable prometheus compatible metrics endpoint (default: %s)", params.endpoint_metrics ? "enabled" : "disabled"),
3581        [](common_params & params) {
3582            params.endpoint_metrics = true;
3583        }
3584    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_ENDPOINT_METRICS"));
3585    add_opt(common_arg(
3586        {"--props"},
3587        string_format("enable changing global properties via POST /props (default: %s)", params.endpoint_props ? "enabled" : "disabled"),
3588        [](common_params & params) {
3589            params.endpoint_props = true;
3590        }
3591    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_ENDPOINT_PROPS"));
3592    add_opt(common_arg(
3593        {"--slots"},
3594        {"--no-slots"},
3595        string_format("expose slots monitoring endpoint (default: %s)", params.endpoint_slots ? "enabled" : "disabled"),
3596        [](common_params & params, bool value) {
3597            params.endpoint_slots = value;
3598        }
3599    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_ENDPOINT_SLOTS"));
3600    add_opt(common_arg(
3601        {"--slot-save-path"}, "PATH",
3602        "path to save slot kv cache (default: disabled)",
3603        [](common_params & params, const std::string & value) {
3604            params.slot_save_path = value;
3605            if (!fs_is_directory(params.slot_save_path)) {
3606                throw std::invalid_argument("not a directory: " + value);
3607            }
3608            // if doesn't end with DIRECTORY_SEPARATOR, add it
3609            if (!params.slot_save_path.empty() && params.slot_save_path[params.slot_save_path.size() - 1] != DIRECTORY_SEPARATOR) {
3610                params.slot_save_path += DIRECTORY_SEPARATOR;
3611            }
3612        }
3613    ).set_examples({LLAMA_EXAMPLE_SERVER}));
3614    add_opt(common_arg(
3615        {"--media-path"}, "PATH",
3616        "directory for loading local media files; files can be accessed via file:// URLs using relative paths (default: disabled)",
3617        [](common_params & params, const std::string & value) {
3618            params.media_path = value;
3619            if (!fs_is_directory(params.media_path)) {
3620                throw std::invalid_argument("not a directory: " + value);
3621            }
3622            // if doesn't end with DIRECTORY_SEPARATOR, add it
3623            if (!params.media_path.empty() && params.media_path[params.media_path.size() - 1] != DIRECTORY_SEPARATOR) {
3624                params.media_path += DIRECTORY_SEPARATOR;
3625            }
3626        }
3627    ).set_examples({LLAMA_EXAMPLE_SERVER}));
3628    add_opt(common_arg(
3629        {"--models-dir"}, "PATH",
3630        "directory containing models for the router server (default: disabled)",
3631        [](common_params & params, const std::string & value) {
3632            params.models_dir = value;
3633        }
3634    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_MODELS_DIR"));
3635    add_opt(common_arg(
3636        {"--models-preset"}, "PATH",
3637        "path to INI file containing model presets for the router server (default: disabled)",
3638        [](common_params & params, const std::string & value) {
3639            params.models_preset = value;
3640        }
3641    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_MODELS_PRESET"));
3642    add_opt(common_arg(
3643        {"--models-max"}, "N",
3644        string_format("for router server, maximum number of models to load simultaneously (default: %d, 0 = unlimited)", params.models_max),
3645        [](common_params & params, int value) {
3646            params.models_max = value;
3647        }
3648    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_MODELS_MAX"));
3649    add_opt(common_arg(
3650        {"--models-autoload"},
3651        {"--no-models-autoload"},
3652        string_format("for router server, whether to automatically load models (default: %s)", params.models_autoload ? "enabled" : "disabled"),
3653        [](common_params & params, bool value) {
3654            params.models_autoload = value;
3655        }
3656    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_MODELS_AUTOLOAD"));
3657    add_opt(common_arg(
3658        {"--jinja"},
3659        {"--no-jinja"},
3660        string_format("whether to use jinja template engine for chat (default: %s)", params.use_jinja ? "enabled" : "disabled"),
3661        [](common_params & params, bool value) {
3662            params.use_jinja = value;
3663        }
3664    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_MTMD}).set_env("LLAMA_ARG_JINJA"));
3665    add_opt(common_arg(
3666        {"--reasoning-format"}, "FORMAT",
3667        "controls whether thought tags are allowed and/or extracted from the response, and in which format they're returned; one of:\n"
3668        "- none: leaves thoughts unparsed in `message.content`\n"
3669        "- deepseek: puts thoughts in `message.reasoning_content`\n"
3670        "- deepseek-legacy: keeps `<think>` tags in `message.content` while also populating `message.reasoning_content`\n"
3671        "(default: auto)",
3672        [](common_params & params, const std::string & value) {
3673            params.reasoning_format = common_reasoning_format_from_name(value);
3674        }
3675    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_THINK"));
3676    add_opt(common_arg(
3677        {"-rea", "--reasoning"}, "[on|off|auto]",
3678        "Use reasoning/thinking in the chat ('on', 'off', or 'auto', default: 'auto' (detect from template))",
3679        [](common_params & params, const std::string & value) {
3680            if (is_truthy(value)) {
3681                params.enable_reasoning = 1;
3682                params.default_template_kwargs["enable_thinking"] = "true";
3683            } else if (is_falsey(value)) {
3684                params.enable_reasoning = 0;
3685                params.default_template_kwargs["enable_thinking"] = "false";
3686            } else if (is_autoy(value)) {
3687                params.enable_reasoning = -1;
3688            } else {
3689                throw std::invalid_argument(
3690                    string_format("error: unknown value for --reasoning: '%s'\n", value.c_str()));
3691            }
3692        }
3693    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_REASONING"));
3694    add_opt(common_arg(
3695        {"--reasoning-effort"}, "LEVEL",
3696        "reasoning effort level given to the chat template: 'default' to keep the template default,\n"
3697        "or a level such as 'minimal', 'low', 'medium', 'high', 'xhigh' or 'max' (default: default)",
3698        [](common_params & params, const std::string & value) {
3699            if (value == "default") {
3700                params.default_template_kwargs.erase("reasoning_effort");
3701            } else {
3702                params.default_template_kwargs["reasoning_effort"] = json(value).dump();
3703            }
3704        }
3705    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_REASONING_EFFORT"));
3706    add_opt(common_arg(
3707        {"--reasoning-budget"}, "N",
3708        "token budget for thinking: -1 for unrestricted, 0 for immediate end, N>0 for token budget (default: -1)",
3709        [](common_params & params, int value) {
3710            if (value < -1) { throw std::invalid_argument("invalid value"); }
3711            params.sampling.reasoning_budget_tokens = value;
3712        }
3713    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_THINK_BUDGET"));
3714    add_opt(common_arg(
3715        {"--reasoning-budget-message"}, "MESSAGE",
3716        "message injected before the end-of-thinking tag when reasoning budget is exhausted (default: none)",
3717        [](common_params & params, const std::string & value) {
3718            params.sampling.reasoning_budget_message = value;
3719        }
3720    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_THINK_BUDGET_MESSAGE"));
3721    add_opt(common_arg(
3722        {"--reasoning-preserve"},
3723        {"--no-reasoning-preserve"},
3724        "preserve reasoning trace in the full history, not just the last assistant message (default: enabled)\n"
3725        "compatible with certain templates having 'supports_preserve_reasoning' capability\n"
3726        "example: https://docs.z.ai/guides/capabilities/thinking-mode#preserved-thinking",
3727        [](common_params & params, bool value) {
3728            if (value) {
3729                params.default_template_kwargs["preserve_reasoning"] = "true";
3730            } else {
3731                params.default_template_kwargs["preserve_reasoning"] = "false";
3732            }
3733            params.preserve_reasoning_specified = true;
3734        }
3735    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_REASONING_PRESERVE"));
3736    add_opt(common_arg(
3737        {"--chat-template"}, "JINJA_TEMPLATE",
3738        string_format(
3739            "set custom jinja chat template (default: template taken from model's metadata)\n"
3740            "if suffix/prefix are specified, template will be disabled\n"
3741            "only commonly used templates are accepted (unless --jinja is set before this flag):\n"
3742            "list of built-in templates:\n%s", list_builtin_chat_templates().c_str()
3743        ),
3744        [](common_params & params, const std::string & value) {
3745            params.chat_template = value;
3746        }
3747    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_MTMD}).set_env("LLAMA_ARG_CHAT_TEMPLATE"));
3748    add_opt(common_arg(
3749        {"--chat-template-file"}, "JINJA_TEMPLATE_FILE",
3750        string_format(
3751            "set custom jinja chat template file (default: template taken from model's metadata)\n"
3752            "if suffix/prefix are specified, template will be disabled\n"
3753            "only commonly used templates are accepted (unless --jinja is set before this flag):\n"
3754            "list of built-in templates:\n%s", list_builtin_chat_templates().c_str()
3755        ),
3756        [](common_params & params, const std::string & value) {
3757            params.chat_template = read_file(value);
3758        }
3759    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_CHAT_TEMPLATE_FILE"));
3760    add_opt(common_arg(
3761        {"--skip-chat-parsing"},
3762        {"--no-skip-chat-parsing"},
3763        string_format(
3764            "force a pure content parser, even if a Jinja template is specified; model will output everything "
3765            "in the content section, including any reasoning and/or tool calls (default: disabled)"
3766        ),
3767        [](common_params & params, bool value) {
3768            params.force_pure_content_parser = value;
3769        }
3770    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_SKIP_CHAT_PARSING"));
3771    add_opt(common_arg(
3772        {"--prefill-assistant"},
3773        {"--no-prefill-assistant"},
3774        string_format(
3775            "whether to prefill the assistant's response if the last message is an assistant message (default: prefill enabled)\n"
3776            "when this flag is set, if the last message is an assistant message then it will be treated as a full message and not prefilled\n"
3777        ),
3778        [](common_params & params, bool value) {
3779            params.prefill_assistant = value;
3780        }
3781    ).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_PREFILL_ASSISTANT"));
3782    add_opt(common_arg(
3783        {"-sps", "--slot-prompt-similarity"}, "SIMILARITY",
3784        string_format("how much the prompt of a request must match the prompt of a slot in order to use that slot (default: %.2f, 0.0 = disabled)\n", params.slot_prompt_similarity),
3785        [](common_params & params, const std::string & value) {
3786            params.slot_prompt_similarity = std::stof(value);
3787        }
3788    ).set_examples({LLAMA_EXAMPLE_SERVER}));
3789    add_opt(common_arg(
3790        {"--lora-init-without-apply"},
3791        string_format("load LoRA adapters without applying them (apply later via POST /lora-adapters) (default: %s)", params.lora_init_without_apply ? "enabled" : "disabled"),
3792        [](common_params & params) {
3793            params.lora_init_without_apply = true;
3794        }
3795    ).set_examples({LLAMA_EXAMPLE_SERVER}));
3796    add_opt(common_arg(
3797        {"--sleep-idle-seconds"}, "SECONDS",
3798        string_format("number of seconds of idleness after which the server will sleep (default: %d; -1 = disabled)", params.sleep_idle_seconds),
3799        [](common_params & params, int value) {
3800            if (value == 0 || value < -1) {
3801                throw std::invalid_argument("invalid value: cannot be 0 or less than -1");
3802            }
3803            params.sleep_idle_seconds = value;
3804        }
3805    ).set_examples({LLAMA_EXAMPLE_SERVER}));
3806    add_opt(common_arg(
3807        {"--simple-io"},
3808        "use basic IO for better compatibility in subprocesses and limited consoles",
3809        [](common_params & params) {
3810            params.simple_io = true;
3811        }
3812    ).set_examples({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI}));
3813    add_opt(common_arg(
3814        {"--positive-file"}, "FNAME",
3815        string_format("positive prompts file, one prompt per line (default: '%s')", params.cvector_positive_file.c_str()),
3816        [](common_params & params, const std::string & value) {
3817            params.cvector_positive_file = value;
3818        }
3819    ).set_examples({LLAMA_EXAMPLE_CVECTOR_GENERATOR}));
3820    add_opt(common_arg(
3821        {"--negative-file"}, "FNAME",
3822        string_format("negative prompts file, one prompt per line (default: '%s')", params.cvector_negative_file.c_str()),
3823        [](common_params & params, const std::string & value) {
3824            params.cvector_negative_file = value;
3825        }
3826    ).set_examples({LLAMA_EXAMPLE_CVECTOR_GENERATOR}));
3827    add_opt(common_arg(
3828        {"--pca-batch"}, "N",
3829        string_format("batch size used for PCA. Larger batch runs faster, but uses more memory (default: %d)", params.n_pca_batch),
3830        [](common_params & params, int value) {
3831            params.n_pca_batch = value;
3832        }
3833    ).set_examples({LLAMA_EXAMPLE_CVECTOR_GENERATOR}));
3834    add_opt(common_arg(
3835        {"--pca-iter"}, "N",
3836        string_format("number of iterations used for PCA (default: %d)", params.n_pca_iterations),
3837        [](common_params & params, int value) {
3838            params.n_pca_iterations = value;
3839        }
3840    ).set_examples({LLAMA_EXAMPLE_CVECTOR_GENERATOR}));
3841    add_opt(common_arg(
3842        {"--method"}, "{pca, mean}",
3843        "dimensionality reduction method to be used (default: pca)",
3844        [](common_params & params, const std::string & value) {
3845            /**/ if (value == "pca") { params.cvector_dimre_method = DIMRE_METHOD_PCA; }
3846            else if (value == "mean") { params.cvector_dimre_method = DIMRE_METHOD_MEAN; }
3847            else { throw std::invalid_argument("invalid value"); }
3848        }
3849    ).set_examples({LLAMA_EXAMPLE_CVECTOR_GENERATOR}));
3850    add_opt(common_arg(
3851        {"--output-format"}, "{md,jsonl}",
3852        "output format for batched-bench results (default: md)",
3853        [](common_params & params, const std::string & value) {
3854            /**/ if (value == "jsonl") { params.batched_bench_output_jsonl = true; }
3855            else if (value == "md") { params.batched_bench_output_jsonl = false; }
3856            else { throw std::invalid_argument("invalid value"); }
3857        }
3858    ).set_examples({LLAMA_EXAMPLE_BENCH}));
3859    add_opt(common_arg(
3860        {"--log-disable"},
3861        "Log disable",
3862        [](common_params &) {
3863            common_log_pause(common_log_main());
3864        }
3865    ));
3866    add_opt(common_arg(
3867        {"--log-file"}, "FNAME",
3868        "Log to file",
3869        [](common_params &, const std::string & value) {
3870            common_log_set_file(common_log_main(), value.c_str());
3871        }
3872    ).set_env("LLAMA_ARG_LOG_FILE"));
3873    add_opt(common_arg(
3874        {"--log-jsonl"},
3875        {"--no-log-jsonl"},
3876        "Log as JSONL (one JSON object per line) to stdout, this also disables colored logging (default: disabled)",
3877        [](common_params &, bool value) {
3878            common_log_set_jsonl(value);
3879        }
3880    ).set_env("LLAMA_ARG_LOG_JSONL"));
3881    add_opt(common_arg(
3882        {"--log-prompts-dir"}, "PATH",
3883        "Log prompts to directory (auto-created if not present; only used for debugging, default: disabled)",
3884        [](common_params & params, const std::string & value) {
3885            params.path_prompts_log_dir = value;
3886            std::error_code ec;
3887            std::filesystem::create_directories(value, ec);
3888            if (ec) {
3889                fprintf(stderr, "warning: failed to create prompts-log-dir '%s': %s\n", value.c_str(), ec.message().c_str());
3890            }
3891        }
3892    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
3893    add_opt(common_arg(
3894        {"--log-colors"}, "[on|off|auto]",
3895        "Set colored logging ('on', 'off', or 'auto', default: 'auto')\n"
3896        "'auto' enables colors when output is to a terminal",
3897        [](common_params &, const std::string & value) {
3898            if (is_truthy(value)) {
3899                common_log_set_colors(common_log_main(), LOG_COLORS_ENABLED);
3900            } else if (is_falsey(value)) {
3901                common_log_set_colors(common_log_main(), LOG_COLORS_DISABLED);
3902            } else if (is_autoy(value)) {
3903                common_log_set_colors(common_log_main(), LOG_COLORS_AUTO);
3904            } else {
3905                throw std::invalid_argument(
3906                    string_format("error: unknown value for --log-colors: '%s'\n", value.c_str()));
3907            }
3908        }
3909    ).set_env("LLAMA_ARG_LOG_COLORS"));
3910    add_opt(common_arg(
3911        {"-v", "--verbose", "--log-verbose"},
3912        "Set verbosity level to infinity (i.e. log all messages, useful for debugging)",
3913        [](common_params & params) {
3914            params.verbosity = INT_MAX;
3915            common_log_set_verbosity_thold(INT_MAX);
3916        }
3917    ));
3918    add_opt(common_arg(
3919        {"--offline"},
3920        "Offline mode: forces use of cache, prevents network access",
3921        [](common_params & params) {
3922            params.offline = true;
3923        }
3924    ).set_examples({LLAMA_EXAMPLE_COMMON, LLAMA_EXAMPLE_DOWNLOAD, LLAMA_EXAMPLE_TOKENIZE}).set_env("LLAMA_ARG_OFFLINE"));
3925    add_opt(common_arg(
3926        {"-lv", "--verbosity", "--log-verbosity"}, "N",
3927        string_format("Set the verbosity threshold. Messages with a higher verbosity will be ignored. Values:\n"
3928            " - 0: generic output\n"
3929            " - 1: error\n"
3930            " - 2: warning\n"
3931            " - 3: info\n"
3932            " - 4: trace (more info)\n"
3933            " - 5: debug\n"
3934            "(default: %d)\n", params.verbosity),
3935        [](common_params & params, int value) {
3936            params.verbosity = value;
3937            common_log_set_verbosity_thold(value);
3938        }
3939    ).set_env("LLAMA_ARG_LOG_VERBOSITY"));
3940    add_opt(common_arg(
3941        {"--log-prefix"},
3942        {"--no-log-prefix"},
3943        "Enable prefix in log messages",
3944        [](common_params &, bool value) {
3945            common_log_set_prefix(common_log_main(), value);
3946        }
3947    ).set_env("LLAMA_ARG_LOG_PREFIX"));
3948    add_opt(common_arg(
3949        {"--log-timestamps"},
3950        {"--no-log-timestamps"},
3951        "Enable timestamps in log messages",
3952        [](common_params &, bool value) {
3953            common_log_set_timestamps(common_log_main(), value);
3954        }
3955    ).set_env("LLAMA_ARG_LOG_TIMESTAMPS"));
3956
3957    //
3958    // speculative parameters
3959    //
3960
3961    add_opt(common_arg(
3962        {"--spec-draft-hf", "-hfd", "-hfrd", "--hf-repo-draft"}, "<user>/<model>[:quant]",
3963        "Same as --hf-repo, but for the draft model (default: unused)",
3964        [](common_params & params, const std::string & value) {
3965            params.speculative.draft.mparams.hf_repo = value;
3966        }
3967    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SPEC_DRAFT_HF_REPO"));
3968    add_opt(common_arg(
3969        {"--spec-draft-threads", "-td", "--threads-draft"}, "N",
3970        "number of threads to use during generation (default: same as --threads)",
3971        [](common_params & params, int value) {
3972            params.speculative.draft.cpuparams.n_threads = value;
3973            if (params.speculative.draft.cpuparams.n_threads <= 0) {
3974                params.speculative.draft.cpuparams.n_threads = std::thread::hardware_concurrency();
3975            }
3976        }
3977    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
3978    add_opt(common_arg(
3979        {"--spec-draft-threads-batch", "-tbd", "--threads-batch-draft"}, "N",
3980        "number of threads to use during batch and prompt processing (default: same as --threads-draft)",
3981        [](common_params & params, int value) {
3982            params.speculative.draft.cpuparams_batch.n_threads = value;
3983            if (params.speculative.draft.cpuparams_batch.n_threads <= 0) {
3984                params.speculative.draft.cpuparams_batch.n_threads = std::thread::hardware_concurrency();
3985            }
3986        }
3987    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
3988    add_opt(common_arg(
3989        {"--spec-draft-cpu-mask", "-Cd", "--cpu-mask-draft"}, "M",
3990        "Draft model CPU affinity mask. Complements cpu-range-draft (default: same as --cpu-mask)",
3991        [](common_params & params, const std::string & mask) {
3992            params.speculative.draft.cpuparams.mask_valid = true;
3993            if (!parse_cpu_mask(mask, params.speculative.draft.cpuparams.cpumask)) {
3994                throw std::invalid_argument("invalid cpumask");
3995            }
3996        }
3997    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
3998    add_opt(common_arg(
3999        {"--spec-draft-cpu-range", "-Crd", "--cpu-range-draft"}, "lo-hi",
4000        "Ranges of CPUs for affinity. Complements --cpu-mask-draft",
4001        [](common_params & params, const std::string & range) {
4002            params.speculative.draft.cpuparams.mask_valid = true;
4003            if (!parse_cpu_range(range, params.speculative.draft.cpuparams.cpumask)) {
4004                throw std::invalid_argument("invalid range");
4005            }
4006        }
4007    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4008    add_opt(common_arg(
4009        {"--spec-draft-cpu-strict", "--cpu-strict-draft"}, "<0|1>",
4010        "Use strict CPU placement for draft model (default: same as --cpu-strict)",
4011        [](common_params & params, int value) {
4012            params.speculative.draft.cpuparams.strict_cpu = value;
4013        }
4014    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4015    add_opt(common_arg(
4016        {"--spec-draft-prio", "--prio-draft"}, "N",
4017        string_format("set draft process/thread priority : 0-normal, 1-medium, 2-high, 3-realtime (default: %d)\n", params.speculative.draft.cpuparams.priority),
4018        [](common_params & params, int prio) {
4019            if (prio < 0 || prio > 3) {
4020                throw std::invalid_argument("invalid value");
4021            }
4022            params.speculative.draft.cpuparams.priority = (enum ggml_sched_priority) prio;
4023        }
4024    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4025    add_opt(common_arg(
4026        {"--spec-draft-poll", "--poll-draft"}, "<0|1>",
4027        "Use polling to wait for draft model work (default: same as --poll)",
4028        [](common_params & params, int value) {
4029            params.speculative.draft.cpuparams.poll = value;
4030        }
4031    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4032    add_opt(common_arg(
4033        {"--spec-draft-cpu-mask-batch", "-Cbd", "--cpu-mask-batch-draft"}, "M",
4034        "Draft model CPU affinity mask. Complements cpu-range-draft (default: same as --cpu-mask)",
4035        [](common_params & params, const std::string & mask) {
4036            params.speculative.draft.cpuparams_batch.mask_valid = true;
4037            if (!parse_cpu_mask(mask, params.speculative.draft.cpuparams_batch.cpumask)) {
4038                throw std::invalid_argument("invalid cpumask");
4039            }
4040        }
4041    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4042    add_opt(common_arg(
4043        {"--spec-draft-cpu-range-batch", "-Crbd", "--cpu-range-batch-draft"}, "lo-hi",
4044        "Ranges of CPUs for affinity. Complements --cpu-mask-draft-batch)",
4045        [](common_params & params, const std::string & range) {
4046            params.speculative.draft.cpuparams_batch.mask_valid = true;
4047            if (!parse_cpu_range(range, params.speculative.draft.cpuparams_batch.cpumask)) {
4048                throw std::invalid_argument("invalid cpumask");
4049            }
4050        }
4051    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE}));
4052    add_opt(common_arg(
4053        {"--spec-draft-cpu-strict-batch", "--cpu-strict-batch-draft"}, "<0|1>",
4054        "Use strict CPU placement for draft model (default: --cpu-strict-draft)",
4055        [](common_params & params, int value) {
4056            params.speculative.draft.cpuparams_batch.strict_cpu = value;
4057        }
4058    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4059    add_opt(common_arg(
4060        {"--spec-draft-prio-batch", "--prio-batch-draft"}, "N",
4061        string_format("set draft process/thread priority : 0-normal, 1-medium, 2-high, 3-realtime (default: %d)\n", params.speculative.draft.cpuparams_batch.priority),
4062        [](common_params & params, int prio) {
4063            if (prio < 0 || prio > 3) {
4064                throw std::invalid_argument("invalid value");
4065            }
4066            params.speculative.draft.cpuparams_batch.priority = (enum ggml_sched_priority) prio;
4067        }
4068    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4069    add_opt(common_arg(
4070        {"--spec-draft-poll-batch", "--poll-batch-draft"}, "<0|1>",
4071        "Use polling to wait for draft model work (default: --poll-draft)",
4072        [](common_params & params, int value) {
4073            params.speculative.draft.cpuparams_batch.poll = value;
4074        }
4075    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4076    add_opt(common_arg(
4077        {"--spec-draft-type-k", "-ctkd", "--cache-type-k-draft"}, "TYPE",
4078        string_format(
4079            "KV cache data type for K for the draft model\n"
4080            "allowed values: %s\n"
4081            "(default: %s)",
4082            get_all_kv_cache_types().c_str(),
4083            ggml_type_name(params.speculative.draft.cache_type_k)
4084        ),
4085        [](common_params & params, const std::string & value) {
4086            params.speculative.draft.cache_type_k = kv_cache_type_from_str(value);
4087        }
4088    ).set_env("LLAMA_ARG_SPEC_DRAFT_CACHE_TYPE_K"));
4089    add_opt(common_arg(
4090        {"--spec-draft-type-v", "-ctvd", "--cache-type-v-draft"}, "TYPE",
4091        string_format(
4092            "KV cache data type for V for the draft model\n"
4093            "allowed values: %s\n"
4094            "(default: %s)",
4095            get_all_kv_cache_types().c_str(),
4096            ggml_type_name(params.speculative.draft.cache_type_v)
4097        ),
4098        [](common_params & params, const std::string & value) {
4099            params.speculative.draft.cache_type_v = kv_cache_type_from_str(value);
4100        }
4101    ).set_env("LLAMA_ARG_SPEC_DRAFT_CACHE_TYPE_V"));
4102    add_opt(common_arg(
4103        {"--spec-draft-override-tensor", "-otd", "--override-tensor-draft"}, "<tensor name pattern>=<buffer type>,...",
4104        "override tensor buffer type for draft model", [](common_params & params, const std::string & value) {
4105            parse_tensor_buffer_overrides(value, params.speculative.draft.tensor_buft_overrides);
4106        }
4107    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4108    add_opt(common_arg(
4109        {"--spec-draft-cpu-moe", "-cmoed", "--cpu-moe-draft"},
4110        "keep all Mixture of Experts (MoE) weights in the CPU for the draft model",
4111        [](common_params & params) {
4112            params.speculative.draft.tensor_buft_overrides.push_back(llm_ffn_exps_cpu_override());
4113        }
4114    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SPEC_DRAFT_CPU_MOE"));
4115    add_opt(common_arg(
4116        {"--spec-draft-n-cpu-moe", "--spec-draft-ncmoe", "-ncmoed", "--n-cpu-moe-draft"}, "N",
4117        "keep the Mixture of Experts (MoE) weights of the first N layers in the CPU for the draft model",
4118        [](common_params & params, int value) {
4119            if (value < 0) {
4120                throw std::invalid_argument("invalid value");
4121            }
4122            llm_add_n_cpu_ffn_overrides(value, LLM_FFN_EXPS_REGEX, params.speculative.draft.tensor_buft_overrides);
4123        }
4124    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SPEC_DRAFT_N_CPU_MOE"));
4125
4126    add_opt(common_arg(
4127        {"--spec-draft-n-max"}, "N",
4128        string_format("number of tokens to draft for speculative decoding (default: %d)", params.speculative.draft.n_max),
4129        [](common_params & params, int value) {
4130            if (value < 0) {
4131                throw std::invalid_argument("invalid value");
4132            }
4133            params.speculative.draft.n_max = value;
4134        }
4135    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_LOOKUP, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SPEC_DRAFT_N_MAX"));
4136    add_opt(common_arg(
4137        {"--spec-draft-n-min"}, "N",
4138        string_format("minimum number of draft tokens to use for speculative decoding (default: %d)", params.speculative.draft.n_min),
4139        [](common_params & params, int value) {
4140            params.speculative.draft.n_min = value;
4141        }
4142    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_LOOKUP, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SPEC_DRAFT_N_MIN"));
4143    add_opt(common_arg(
4144        {"--spec-synth-len"}, "L",
4145        "target mean synthetic acceptance length, including the target token (benchmarking only)",
4146        [](common_params & params, const std::string & value) {
4147            const std::string text = string_strip(value);
4148            size_t pos = 0;
4149            const double length = std::stod(text, &pos);
4150            if (pos != text.size() || length == -1.0) {
4151                throw std::invalid_argument("invalid value");
4152            }
4153            params.speculative.synth_len = length;
4154        }
4155    ).set_spec().set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SPEC_SYNTH_LEN"));
4156    add_opt(common_arg(
4157        {"--spec-synth-rates"}, "P0,P1,...",
4158        "comma-separated unconditional per-position synthetic acceptance probabilities (benchmarking only)",
4159        [](common_params & params, const std::string & value) {
4160            const auto values = string_split<std::string>(value, ',');
4161            std::vector<double> rates;
4162            rates.reserve(values.size());
4163            for (const auto & raw : values) {
4164                const std::string text = string_strip(raw);
4165                size_t pos = 0;
4166                const double rate = std::stod(text, &pos);
4167                if (pos != text.size()) {
4168                    throw std::invalid_argument("invalid value");
4169                }
4170                rates.push_back(rate);
4171            }
4172            params.speculative.synth_rates = std::move(rates);
4173        }
4174    ).set_spec().set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SPEC_SYNTH_RATES"));
4175
4176    add_opt(common_arg(
4177        {"--spec-draft-p-split", "--draft-p-split"}, "P",
4178        string_format("speculative decoding split probability (default: %.2f)", (double)params.speculative.draft.p_split),
4179        [](common_params & params, const std::string & value) {
4180            params.speculative.draft.p_split = std::stof(value);
4181        }
4182    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SPEC_DRAFT_P_SPLIT"));
4183    add_opt(common_arg(
4184        {"--spec-draft-p-min", "--draft-p-min"}, "P",
4185        string_format("minimum speculative decoding probability (greedy) (default: %.2f)", (double)params.speculative.draft.p_min),
4186        [](common_params & params, const std::string & value) {
4187            params.speculative.draft.p_min = std::stof(value);
4188        }
4189    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SPEC_DRAFT_P_MIN"));
4190    add_opt(common_arg(
4191        {"--spec-draft-backend-sampling"},
4192        {"--no-spec-draft-backend-sampling"},
4193        string_format("offload draft sampling to the backend (default: %s)",
4194                      params.speculative.draft.backend_sampling ? "enabled" : "disabled"),
4195        [](common_params & params, bool value) {
4196            params.speculative.draft.backend_sampling = value;
4197        }
4198    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SPEC_DRAFT_BACKEND_SAMPLING"));
4199    add_opt(common_arg(
4200        {"--spec-draft-device", "-devd", "--device-draft"}, "<dev1,dev2,..>",
4201        "comma-separated list of devices to use for offloading the draft model (none = don't offload, default: follows --device)\n"
4202        "use --list-devices to see a list of available devices",
4203        [](common_params & params, const std::string & value) {
4204            params.speculative.draft.devices = parse_device_list(value);
4205        }
4206    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4207    GGML_ASSERT(params.speculative.draft.n_gpu_layers < 0); // string_format would need to be extended for a default >= 0
4208    add_opt(common_arg(
4209        {"--spec-draft-ngl", "-ngld", "--gpu-layers-draft", "--n-gpu-layers-draft"}, "N",
4210        string_format("max. number of draft model layers to store in VRAM, either an exact number, 'auto', or 'all' (default: %s)",
4211            params.speculative.draft.n_gpu_layers == -1 ? "auto" : "all"),
4212        [](common_params & params, const std::string & value) {
4213            if (value == "auto") {
4214                params.speculative.draft.n_gpu_layers = -1;
4215            } else if (value == "all") {
4216                params.speculative.draft.n_gpu_layers = -2;
4217            } else {
4218                params.speculative.draft.n_gpu_layers = std::stoi(value);
4219            }
4220            if (!llama_supports_gpu_offload()) {
4221                fprintf(stderr, "warning: no usable GPU found, --gpu-layers-draft option will be ignored\n");
4222                fprintf(stderr, "warning: one possible reason is that llama.cpp was compiled without GPU support\n");
4223                fprintf(stderr, "warning: consult docs/build.md for compilation instructions\n");
4224            }
4225        }
4226    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_N_GPU_LAYERS_DRAFT"));
4227    add_opt(common_arg(
4228        {"--spec-draft-model", "-md", "--model-draft"}, "FNAME",
4229        "draft model for speculative decoding (default: unused)",
4230        [](common_params & params, const std::string & value) {
4231            params.speculative.draft.mparams.path = value;
4232            params.speculative.draft.mparams.hf_file = value; // will be used if --spec-draft-hf is set
4233        }
4234    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SPEC_DRAFT_MODEL"));
4235    add_opt(common_arg(
4236        {"--spec-type"}, common_speculative_all_types_str(),
4237        string_format("comma-separated list of types of speculative decoding to use (default: %s)\n",
4238            common_speculative_type_name_str(params.speculative.types).c_str()),
4239        [](common_params & params, const std::string & value) {
4240            const auto types_str = string_split<std::string>(value, ',');
4241            auto types = common_speculative_types_from_names(types_str);
4242            params.speculative.types.insert(params.speculative.types.end(), types.begin(), types.end());
4243        }
4244    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SPEC_TYPE"));
4245    add_opt(common_arg(
4246        {"--spec-ngram-mod-n-min"}, "N",
4247        string_format("minimum number of ngram tokens to use for ngram-based speculative decoding (default: %d)", params.speculative.ngram_mod.n_min),
4248        [](common_params & params, int value) {
4249            if (value < 0 || value > 1024) {
4250                throw std::invalid_argument("ngram n-min must be between 0 and 1024 inclusive");
4251            }
4252            params.speculative.ngram_mod.n_min = value;
4253        }
4254    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4255    add_opt(common_arg(
4256        {"--spec-ngram-mod-n-max"}, "N",
4257        string_format("maximum number of ngram tokens to use for ngram-based speculative decoding (default: %d)", params.speculative.ngram_mod.n_max),
4258        [](common_params & params, int value) {
4259            if (value < 0 || value > 1024) {
4260                throw std::invalid_argument("ngram n-max must be between 0 and 1024 inclusive");
4261            }
4262            params.speculative.ngram_mod.n_max = value;
4263        }
4264    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4265    add_opt(common_arg(
4266        {"--spec-ngram-mod-n-match"}, "N",
4267        string_format("ngram-mod lookup length (default: %d)", params.speculative.ngram_mod.n_match),
4268        [](common_params & params, int value) {
4269            if (value < 1 || value > 1024) {
4270                throw std::invalid_argument("ngram size N must be between 1 and 1024 inclusive");
4271            }
4272            params.speculative.ngram_mod.n_match = value;
4273        }
4274    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4275
4276    add_opt(common_arg(
4277        {"--spec-ngram-simple-size-n"}, "N",
4278        string_format("ngram size N for ngram-simple speculative decoding, length of lookup n-gram (default: %d)", params.speculative.ngram_simple.size_n),
4279        [](common_params & params, int value) {
4280            if (value < 1 || value > 1024) {
4281                throw std::invalid_argument("ngram size N must be between 1 and 1024 inclusive");
4282            }
4283            params.speculative.ngram_simple.size_n = value;
4284        }
4285    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4286    add_opt(common_arg(
4287        {"--spec-ngram-simple-size-m"}, "N",
4288        string_format("ngram size M for ngram-simple speculative decoding, length of draft m-gram (default: %d)", params.speculative.ngram_simple.size_m),
4289        [](common_params & params, int value) {
4290            if (value < 1 || value > 1024) {
4291                throw std::invalid_argument("ngram size M must be between 1 and 1024 inclusive");
4292            }
4293            params.speculative.ngram_simple.size_m = value;
4294        }
4295    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4296    add_opt(common_arg(
4297        {"--spec-ngram-simple-min-hits"}, "N",
4298        string_format("minimum hits for ngram-simple speculative decoding (default: %d)", params.speculative.ngram_simple.min_hits),
4299        [](common_params & params, int value) {
4300            if (value < 1) {
4301                throw std::invalid_argument("ngram min hits must be at least 1");
4302            }
4303            params.speculative.ngram_simple.min_hits = value;
4304        }
4305    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4306
4307    add_opt(common_arg(
4308        {"--spec-ngram-map-k-size-n"}, "N",
4309        string_format("ngram size N for ngram-map-k speculative decoding, length of lookup n-gram (default: %d)", params.speculative.ngram_map_k.size_n),
4310        [](common_params & params, int value) {
4311            if (value < 1 || value > 1024) {
4312                throw std::invalid_argument("ngram size N must be between 1 and 1024 inclusive");
4313            }
4314            params.speculative.ngram_map_k.size_n = value;
4315        }
4316    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4317    add_opt(common_arg(
4318        {"--spec-ngram-map-k-size-m"}, "N",
4319        string_format("ngram size M for ngram-map-k speculative decoding, length of draft m-gram (default: %d)", params.speculative.ngram_map_k.size_m),
4320        [](common_params & params, int value) {
4321            if (value < 1 || value > 1024) {
4322                throw std::invalid_argument("ngram size M must be between 1 and 1024 inclusive");
4323            }
4324            params.speculative.ngram_map_k.size_m = value;
4325        }
4326    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4327    add_opt(common_arg(
4328        {"--spec-ngram-map-k-min-hits"}, "N",
4329        string_format("minimum hits for ngram-map-k speculative decoding (default: %d)", params.speculative.ngram_map_k.min_hits),
4330        [](common_params & params, int value) {
4331            if (value < 1) {
4332                throw std::invalid_argument("ngram min hits must be at least 1");
4333            }
4334            params.speculative.ngram_map_k.min_hits = value;
4335        }
4336    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4337
4338    add_opt(common_arg(
4339        {"--spec-ngram-map-k4v-size-n"}, "N",
4340        string_format("ngram size N for ngram-map-k4v speculative decoding, length of lookup n-gram (default: %d)", params.speculative.ngram_map_k4v.size_n),
4341        [](common_params & params, int value) {
4342            if (value < 1 || value > 1024) {
4343                throw std::invalid_argument("ngram size N must be between 1 and 1024 inclusive");
4344            }
4345            params.speculative.ngram_map_k4v.size_n = value;
4346        }
4347    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4348    add_opt(common_arg(
4349        {"--spec-ngram-map-k4v-size-m"}, "N",
4350        string_format("ngram size M for ngram-map-k4v speculative decoding, length of draft m-gram (default: %d)", params.speculative.ngram_map_k4v.size_m),
4351        [](common_params & params, int value) {
4352            if (value < 1 || value > 1024) {
4353                throw std::invalid_argument("ngram size M must be between 1 and 1024 inclusive");
4354            }
4355            params.speculative.ngram_map_k4v.size_m = value;
4356        }
4357    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4358    add_opt(common_arg(
4359        {"--spec-ngram-map-k4v-min-hits"}, "N",
4360        string_format("minimum hits for ngram-map-k4v speculative decoding (default: %d)", params.speculative.ngram_map_k4v.min_hits),
4361        [](common_params & params, int value) {
4362            if (value < 1) {
4363                throw std::invalid_argument("ngram min hits must be at least 1");
4364            }
4365            params.speculative.ngram_map_k4v.min_hits = value;
4366        }
4367    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4368
4369    //
4370    // removed params
4371    //
4372
4373    add_opt(common_arg(
4374        {"--draft", "--draft-n", "--draft-max"}, "N",
4375        "the argument has been removed. use --spec-draft-n-max or --spec-ngram-mod-n-max",
4376        [](common_params & /*params*/, int /*value*/) {
4377            arg_removed("use --spec-draft-n-max or --spec-ngram-mod-n-max");
4378        }
4379    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_LOOKUP, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_DRAFT_MAX"));
4380    add_opt(common_arg(
4381        {"--draft-min", "--draft-n-min"}, "N",
4382        "the argument has been removed. use --spec-draft-n-min or --spec-ngram-mod-n-min",
4383        [](common_params & /*params*/, int /*value*/) {
4384            arg_removed("use --spec-draft-n-min or --spec-ngram-mod-n-min");
4385        }
4386    ).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_LOOKUP, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_DRAFT_MIN"));
4387    add_opt(common_arg(
4388        {"--spec-ngram-size-n"}, "N",
4389        "the argument has been removed. use the respective --spec-ngram-*-size-n or --spec-ngram-mod-n-match",
4390        [](common_params & /*params*/, int /*value*/) {
4391            arg_removed("use the respective --spec-ngram-*-size-n");
4392        }
4393    ).set_spec().set_examples({LLAMA_EXAMPLE_SERVER}));
4394    add_opt(common_arg(
4395        {"--spec-ngram-size-m"}, "N",
4396        "the argument has been removed. use the respective --spec-ngram-*-size-m",
4397        [](common_params & /*params*/, int /*value*/) {
4398            arg_removed("use the respective --spec-ngram-*-size-m");
4399        }
4400    ).set_spec().set_examples({LLAMA_EXAMPLE_SERVER}));
4401    add_opt(common_arg(
4402        {"--spec-ngram-min-hits"}, "N",
4403        "the argument has been removed. use the respective --spec-ngram-*-min-hits",
4404        [](common_params & /*params*/, int /*value*/) {
4405            arg_removed("use the respective --spec-ngram-*-min-hits");
4406        }
4407    ).set_spec().set_examples({LLAMA_EXAMPLE_SERVER}));
4408
4409    //
4410    // TTS params
4411    //
4412
4413    add_opt(common_arg(
4414        {"--tts-lang"}, "FNAME",
4415        "language (ISO 639-1) for audio generation\n"
4416        "see tts/README.md for per-model usage notes",
4417        [](common_params & params, const std::string & value) {
4418            params.tts_lang = value;
4419        }
4420    ).set_examples({LLAMA_EXAMPLE_TTS}));
4421    add_opt(common_arg(
4422        {"--tts-speaker-file"}, "FNAME",
4423        "speaker file path for audio generation",
4424        [](common_params & params, const std::string & value) {
4425            params.tts_speaker_file = value;
4426        }
4427    ).set_examples({LLAMA_EXAMPLE_TTS}));
4428
4429    //
4430    // diffusion params
4431    //
4432
4433    add_opt(common_arg(
4434        {"--diffusion-steps"}, "N",
4435        string_format("number of diffusion steps (default: %d)", params.diffusion.steps),
4436        [](common_params & params, int value) { params.diffusion.steps = value; }
4437    ).set_examples({ LLAMA_EXAMPLE_DIFFUSION }));
4438    add_opt(common_arg(
4439        {"--diffusion-visual"},
4440        string_format("enable visual diffusion mode (show progressive generation) (default: %s)", params.diffusion.visual_mode ? "true" : "false"),
4441        [](common_params & params) { params.diffusion.visual_mode = true; }
4442    ).set_examples({ LLAMA_EXAMPLE_DIFFUSION }));
4443    add_opt(common_arg(
4444        {"--diffusion-eps"}, "F",
4445        string_format("epsilon for timesteps (default: %.6f)", (double) params.diffusion.eps),
4446        [](common_params & params, const std::string & value) { params.diffusion.eps = std::stof(value); }
4447    ).set_examples({ LLAMA_EXAMPLE_DIFFUSION }));
4448    add_opt(common_arg(
4449        {"--diffusion-algorithm"}, "N",
4450        string_format(
4451            "diffusion algorithm: 0=DIFFUSION_ALGORITHM_ORIGIN, 1=DIFFUSION_ALGORITHM_ENTROPY_BASED, "
4452            "2=DIFFUSION_ALGORITHM_MARGIN_BASED, 3=DIFFUSION_ALGORITHM_RANDOM, "
4453            "4=DIFFUSION_ALGORITHM_CONFIDENCE_BASED (default: %d)", params.diffusion.algorithm),
4454        [](common_params & params, int value) { params.diffusion.algorithm = value; }
4455    ).set_examples({ LLAMA_EXAMPLE_DIFFUSION }));
4456    add_opt(common_arg(
4457        {"--diffusion-alg-temp"}, "F",
4458        string_format("dream algorithm temperature (default: %.3f)", (double) params.diffusion.alg_temp),
4459        [](common_params & params, const std::string & value) { params.diffusion.alg_temp = std::stof(value); }
4460    ).set_examples({ LLAMA_EXAMPLE_DIFFUSION }));
4461    add_opt(common_arg(
4462        {"--diffusion-block-length"}, "N",
4463        string_format("llada block length for generation (default: %d)", params.diffusion.block_length),
4464        [](common_params & params, int value) { params.diffusion.block_length = value; }
4465    ).set_examples({ LLAMA_EXAMPLE_DIFFUSION }));
4466    add_opt(common_arg(
4467        {"--diffusion-cfg-scale"}, "F",
4468        string_format("llada classifier-free guidance scale (default: %.3f)", (double) params.diffusion.cfg_scale),
4469        [](common_params & params, const std::string & value) { params.diffusion.cfg_scale = std::stof(value); }
4470    ).set_examples({ LLAMA_EXAMPLE_DIFFUSION }));
4471    add_opt(common_arg(
4472        {"--diffusion-add-gumbel-noise"}, "F",
4473        string_format("add gumbel noise to the logits if temp > 0.0 (default: %s)", params.diffusion.add_gumbel_noise ? "true" : "false"),
4474        [](common_params & params, const std::string & value) { params.diffusion.add_gumbel_noise = std::stof(value); }
4475    ).set_examples({ LLAMA_EXAMPLE_DIFFUSION }));
4476    add_opt(common_arg(
4477        { "-lr", "--learning-rate" }, "ALPHA",
4478        string_format("adamw or sgd optimizer alpha (default: %.2g); note: sgd alpha recommended ~10x (no momentum)", (double) params.lr.lr0),
4479        [](common_params & params, const std::string & value) { params.lr.lr0 = std::stof(value); }
4480    ).set_examples({ LLAMA_EXAMPLE_FINETUNE }));
4481    add_opt(common_arg({ "-lr-min", "--learning-rate-min" }, "ALPHA",
4482        string_format("(if >0) final learning rate after decay (if -decay-epochs is set, default=%.2g)",
4483            (double) params.lr.lr_min),
4484        [](common_params & params, const std::string & value) { params.lr.lr_min = std::stof(value); }
4485    ).set_examples({ LLAMA_EXAMPLE_FINETUNE }));
4486    add_opt(common_arg(
4487        {"-decay-epochs", "--learning-rate-decay-epochs"}, "ALPHA",
4488        string_format("(if >0) decay learning rate to -lr-min after this many epochs (exponential decay, default=%.2g)", (double) params.lr.decay_epochs),
4489        [](common_params & params, const std::string & value) { params.lr.decay_epochs = std::stof(value); }
4490    ).set_examples({ LLAMA_EXAMPLE_FINETUNE }));
4491    add_opt(common_arg(
4492        {"-wd", "--weight-decay"}, "WD",
4493        string_format("adamw or sgd optimizer weight decay (0 is off; recommend very small e.g. 1e-9) (default: %.2g).", (double) params.lr.wd),
4494        [](common_params & params, const std::string & value) { params.lr.wd = std::stof(value); }
4495    ).set_examples({ LLAMA_EXAMPLE_FINETUNE }));
4496    add_opt(common_arg(
4497        {"-val-split", "--val-split"}, "FRACTION",
4498        string_format("fraction of data to use as validation set for training (default: %.2g).", (double) params.val_split),
4499        [](common_params & params, const std::string & value) { params.val_split = std::stof(value); }
4500    ).set_examples({ LLAMA_EXAMPLE_FINETUNE }));
4501    add_opt(common_arg(
4502        {"-epochs", "--epochs"}, "N",
4503        string_format("optimizer max # of epochs (default: %d)", params.lr.epochs),
4504        [](common_params & params, int epochs) { params.lr.epochs = epochs; }
4505    ).set_examples({ LLAMA_EXAMPLE_FINETUNE }));
4506    add_opt(common_arg(
4507        {"-opt", "--optimizer"}, "sgd|adamw", "adamw or sgd",
4508        [](common_params & params, const std::string & name) {
4509            params.optimizer = common_opt_get_optimizer(name.c_str());
4510            if (params.optimizer == GGML_OPT_OPTIMIZER_TYPE_COUNT) {
4511                throw std::invalid_argument("invalid --optimizer, valid options: adamw, sgd");
4512            }
4513        }
4514    ).set_examples({ LLAMA_EXAMPLE_FINETUNE }));
4515    add_opt(common_arg(
4516        {"--check"},
4517        string_format("check rather than generate results (default: %s)", params.check ? "true" : "false"),
4518        [](common_params & params) {
4519            params.check = true;
4520        }
4521    ).set_examples({LLAMA_EXAMPLE_RESULTS}));
4522    add_opt(common_arg(
4523        {"--save-logits"},
4524        string_format("save final logits to files for verification (default: %s)", params.save_logits ? "true" : "false"),
4525        [](common_params & params) {
4526            params.save_logits = true;
4527        }
4528    ).set_examples({LLAMA_EXAMPLE_DEBUG}));
4529    add_opt(common_arg(
4530        {"--logits-output-dir"}, "PATH",
4531        string_format("directory for saving logits output files (default: %s)", params.logits_output_dir.c_str()),
4532        [](common_params & params, const std::string & value) {
4533            params.logits_output_dir = value;
4534        }
4535    ).set_examples({LLAMA_EXAMPLE_DEBUG}));
4536    add_opt(common_arg(
4537        {"--tensor-filter"}, "REGEX",
4538        "filter tensor names for debug output (regex pattern, can be specified multiple times)",
4539        [](common_params & params, const std::string & value) {
4540            params.tensor_filter.push_back(value);
4541        }
4542    ).set_examples({LLAMA_EXAMPLE_DEBUG}));
4543
4544    // presets
4545
4546    add_opt(common_arg(
4547        {"--embd-gemma-default"},
4548        string_format("use default EmbeddingGemma model (note: can download weights from the internet)"),
4549        [](common_params & params) {
4550            params.model.hf_repo = "ggml-org/embeddinggemma-300M-qat-q4_0-GGUF";
4551            params.model.hf_file = "embeddinggemma-300M-qat-Q4_0.gguf";
4552            params.port = 8011;
4553            params.n_ubatch = 2048;
4554            params.n_batch = 2048;
4555            params.n_parallel = 32;
4556            params.n_ctx = 2048*params.n_parallel;
4557            params.verbose_prompt = true;
4558            params.embedding = true;
4559        }
4560    ).set_examples({LLAMA_EXAMPLE_EMBEDDING, LLAMA_EXAMPLE_SERVER}));
4561
4562    add_opt(common_arg(
4563        {"--fim-qwen-1.5b-default"},
4564        string_format("use default Qwen 2.5 Coder 1.5B (note: can download weights from the internet)"),
4565        [](common_params & params) {
4566            params.model.hf_repo = "ggml-org/Qwen2.5-Coder-1.5B-Q8_0-GGUF";
4567            params.model.hf_file = "qwen2.5-coder-1.5b-q8_0.gguf";
4568            params.port = 8012;
4569            params.n_ubatch = 1024;
4570            params.n_batch = 1024;
4571            params.n_ctx = 0;
4572            params.n_cache_reuse = 256;
4573        }
4574    ).set_examples({LLAMA_EXAMPLE_SERVER}));
4575
4576    add_opt(common_arg(
4577        {"--fim-qwen-3b-default"},
4578        string_format("use default Qwen 2.5 Coder 3B (note: can download weights from the internet)"),
4579        [](common_params & params) {
4580            params.model.hf_repo = "ggml-org/Qwen2.5-Coder-3B-Q8_0-GGUF";
4581            params.model.hf_file = "qwen2.5-coder-3b-q8_0.gguf";
4582            params.port = 8012;
4583            params.n_ubatch = 1024;
4584            params.n_batch = 1024;
4585            params.n_ctx = 0;
4586            params.n_cache_reuse = 256;
4587        }
4588    ).set_examples({LLAMA_EXAMPLE_SERVER}));
4589
4590    add_opt(common_arg(
4591        {"--fim-qwen-7b-default"},
4592        string_format("use default Qwen 2.5 Coder 7B (note: can download weights from the internet)"),
4593        [](common_params & params) {
4594            params.model.hf_repo = "ggml-org/Qwen2.5-Coder-7B-Q8_0-GGUF";
4595            params.model.hf_file = "qwen2.5-coder-7b-q8_0.gguf";
4596            params.port = 8012;
4597            params.n_ubatch = 1024;
4598            params.n_batch = 1024;
4599            params.n_ctx = 0;
4600            params.n_cache_reuse = 256;
4601        }
4602    ).set_examples({LLAMA_EXAMPLE_SERVER}));
4603
4604    add_opt(common_arg(
4605        {"--fim-qwen-7b-spec"},
4606        string_format("use Qwen 2.5 Coder 7B + 0.5B draft for speculative decoding (note: can download weights from the internet)"),
4607        [](common_params & params) {
4608            params.model.hf_repo = "ggml-org/Qwen2.5-Coder-7B-Q8_0-GGUF";
4609            params.model.hf_file = "qwen2.5-coder-7b-q8_0.gguf";
4610            params.speculative.draft.mparams.hf_repo = "ggml-org/Qwen2.5-Coder-0.5B-Q8_0-GGUF";
4611            params.speculative.draft.mparams.hf_file = "qwen2.5-coder-0.5b-q8_0.gguf";
4612            params.port = 8012;
4613            params.n_ubatch = 1024;
4614            params.n_batch = 1024;
4615            params.n_ctx = 0;
4616            params.n_cache_reuse = 256;
4617        }
4618    ).set_examples({LLAMA_EXAMPLE_SERVER}));
4619
4620    add_opt(common_arg(
4621        {"--fim-qwen-14b-spec"},
4622        string_format("use Qwen 2.5 Coder 14B + 0.5B draft for speculative decoding (note: can download weights from the internet)"),
4623        [](common_params & params) {
4624            params.model.hf_repo = "ggml-org/Qwen2.5-Coder-14B-Q8_0-GGUF";
4625            params.model.hf_file = "qwen2.5-coder-14b-q8_0.gguf";
4626            params.speculative.draft.mparams.hf_repo = "ggml-org/Qwen2.5-Coder-0.5B-Q8_0-GGUF";
4627            params.speculative.draft.mparams.hf_file = "qwen2.5-coder-0.5b-q8_0.gguf";
4628            params.port = 8012;
4629            params.n_ubatch = 1024;
4630            params.n_batch = 1024;
4631            params.n_ctx = 0;
4632            params.n_cache_reuse = 256;
4633        }
4634    ).set_examples({LLAMA_EXAMPLE_SERVER}));
4635
4636    add_opt(common_arg(
4637        {"--fim-qwen-30b-default"},
4638        string_format("use default Qwen 3 Coder 30B A3B Instruct (note: can download weights from the internet)"),
4639        [](common_params & params) {
4640            params.model.hf_repo = "ggml-org/Qwen3-Coder-30B-A3B-Instruct-Q8_0-GGUF";
4641            params.model.hf_file = "qwen3-coder-30b-a3b-instruct-q8_0.gguf";
4642            params.port = 8012;
4643            params.n_ubatch = 1024;
4644            params.n_batch = 1024;
4645            params.n_ctx = 0;
4646            params.n_cache_reuse = 256;
4647        }
4648    ).set_examples({LLAMA_EXAMPLE_SERVER}));
4649
4650    add_opt(common_arg(
4651        {"--gpt-oss-20b-default"},
4652        string_format("use gpt-oss-20b (note: can download weights from the internet)"),
4653        [](common_params & params) {
4654            params.model.hf_repo = "ggml-org/gpt-oss-20b-GGUF";
4655            params.model.hf_file = "gpt-oss-20b-mxfp4.gguf";
4656            params.port = 8013;
4657            params.n_ubatch = 2048;
4658            params.n_batch = 32768;
4659            params.n_parallel = 2;
4660            params.n_ctx = 131072*params.n_parallel;
4661            params.sampling.temp = 1.0f;
4662            params.sampling.top_p = 1.0f;
4663            params.sampling.top_k = 0;
4664            params.sampling.min_p = 0.01f;
4665            params.use_jinja = true;
4666        }
4667    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4668
4669    add_opt(common_arg(
4670        {"--gpt-oss-120b-default"},
4671        string_format("use gpt-oss-120b (note: can download weights from the internet)"),
4672        [](common_params & params) {
4673            params.model.hf_repo = "ggml-org/gpt-oss-120b-GGUF";
4674            params.port = 8013;
4675            params.n_ubatch = 2048;
4676            params.n_batch = 32768;
4677            params.n_parallel = 2;
4678            params.n_ctx = 131072*params.n_parallel;
4679            params.sampling.temp = 1.0f;
4680            params.sampling.top_p = 1.0f;
4681            params.sampling.top_k = 0;
4682            params.sampling.min_p = 0.01f;
4683            params.use_jinja = true;
4684        }
4685    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4686
4687    add_opt(common_arg(
4688        {"--vision-gemma-4b-default"},
4689        string_format("use Gemma 3 4B QAT (note: can download weights from the internet)"),
4690        [](common_params & params) {
4691            params.model.hf_repo = "ggml-org/gemma-3-4b-it-qat-GGUF";
4692            params.port = 8014;
4693            params.n_ctx = 0;
4694            params.use_jinja = true;
4695        }
4696    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4697
4698    add_opt(common_arg(
4699        {"--vision-gemma-12b-default"},
4700        string_format("use Gemma 3 12B QAT (note: can download weights from the internet)"),
4701        [](common_params & params) {
4702            params.model.hf_repo = "ggml-org/gemma-3-12b-it-qat-GGUF";
4703            params.port = 8014;
4704            params.n_ctx = 0;
4705            params.use_jinja = true;
4706        }
4707    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4708
4709    add_opt(common_arg(
4710        {"--spec-default"},
4711        string_format("enable default speculative decoding config"),
4712        [](common_params & params) {
4713            params.speculative.types.push_back(COMMON_SPECULATIVE_TYPE_NGRAM_MOD);
4714            params.speculative.ngram_mod.n_match = 24;
4715            params.speculative.ngram_mod.n_min = 48;
4716            params.speculative.ngram_mod.n_max = 64;
4717
4718            // TODO: not sure if this is a good config - explore more settings and potentially enable it
4719            //params.speculative.types.push_back(COMMON_SPECULATIVE_TYPE_NGRAM_MAP_K4V);
4720            //params.speculative.ngram_map_k4v.size_n = 8;
4721            //params.speculative.ngram_map_k4v.size_m = 24;
4722            //params.speculative.ngram_map_k4v.min_hits = 2;
4723        }
4724    ).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
4725
4726    return ctx_arg;
4727}
4728
4729void common_params_add_preset_options(std::vector<common_arg> & args) {
4730    // arguments below won't be treated as CLI args, only preset options
4731    args.push_back(common_arg(
4732        {"load-on-startup"}, "NAME",
4733        "in server router mode, autoload this model on startup",
4734        [](common_params &, const std::string &) { /* unused */ }
4735    ).set_env(COMMON_ARG_PRESET_LOAD_ON_STARTUP).set_preset_only());
4736
4737    args.push_back(common_arg(
4738        {"stop-timeout"}, "SECONDS",
4739        "in server router mode, force-kill model instance after this many seconds of graceful shutdown",
4740        [](common_params &, int) { /* unused */ }
4741    ).set_env(COMMON_ARG_PRESET_STOP_TIMEOUT).set_preset_only());
4742
4743    args.push_back(common_arg(
4744        {"dedup-cache-models"}, "0|1",
4745        "in server router mode, hide a cached model from the model list when this preset resolves to the same model file",
4746        [](common_params &, const std::string &) { /* unused */ }
4747    ).set_env(COMMON_ARG_PRESET_DEDUP_CACHE_MODELS).set_preset_only());
4748
4749    // args.push_back(common_arg(
4750    //     {"pin"},
4751    //     "in server router mode, do not unload this model if models_max is exceeded",
4752    //     [](common_params &) { /* unused */ }
4753    // ).set_preset_only());
4754}