common : through an error for unsupported multiple options

This commit updates the argument parsing to check for valid multiple
value options, for example using --file --file with llama-completions is
something that is supported and this is the case for a few other options
as well. But for the majority of options specifying them multiple times
is not supported and this will now thow an error.

For example using multiple --model options will now result in an error:
```console
$ llama-completion -m models/Qwen2.5-0.5B-Instruct.gguf --model models/Qwen2.5-0.5B-Instruct.gguf
error: argument '--model' cannot be specified multiple times
```
But using multiple --file options will only result in a warning:
```console
$ llama-completion -m models/Qwen2.5-0.5B-Instruct.gguf -f test_file.txt -f test_file.txt
DEPRECATED: argument '-f' specified multiple times, use comma-separated values instead (only last value will be used)
...
```
This commit is contained in:
Daniel Bevenius 2026-01-29 08:50:46 +01:00
parent b96d588668
commit 45d36360bf
No known key found for this signature in database
1 changed files with 29 additions and 18 deletions

View File

@ -430,6 +430,26 @@ static bool parse_bool_value(const std::string & value) {
// CLI argument parsing functions
//
static void check_duplicate_arg(const std::string & arg) {
static const std::set<std::string> multi_value_options = {
"--lora",
"--lora-scaled",
"--control-vector",
"--control-vector-scaled",
"-f", "--file",
"--context-file",
"--api-key",
"--logit-bias",
"--tensor-filter"
};
if (multi_value_options.find(arg) != multi_value_options.end()) {
LOG_INF("DEPRECATED: argument '%s' specified multiple times, use comma-separated values instead (only last value will be used)\n", arg.c_str());
} else {
throw std::invalid_argument(string_format("error: argument '%s' cannot be specified multiple times", arg.c_str()));
}
}
static bool common_params_parse_ex(int argc, char ** argv, common_params_context & ctx_arg) {
common_params & params = ctx_arg.params;
@ -476,7 +496,7 @@ static bool common_params_parse_ex(int argc, char ** argv, common_params_context
};
auto parse_cli_args = [&]() {
std::set<std::string> seen_args;
std::set<common_arg *> seen_options;
for (int i = 1; i < argc; i++) {
const std::string arg_prefix = "--";
@ -488,17 +508,12 @@ static bool common_params_parse_ex(int argc, char ** argv, common_params_context
if (arg_to_options.find(arg) == arg_to_options.end()) {
throw std::invalid_argument(string_format("error: invalid argument: %s", arg.c_str()));
}
if (!seen_args.insert(arg).second) {
if (arg == "-m" || arg == "--model") {
LOG_WRN("DEPRECATED: multiple %s options are not supported (only last value will be used). "
"Use router mode for llama-server (see --help)\n", arg.c_str());
} else {
LOG_WRN("DEPRECATED: argument '%s' specified multiple times, use comma-separated values instead (only last value will be used)\n", arg.c_str());
}
}
auto & tmp = arg_to_options[arg];
auto opt = *tmp.first;
bool is_positive = tmp.second;
if (!seen_options.insert(tmp.first).second) {
check_duplicate_arg(arg);
}
if (opt.has_value_from_env()) {
fprintf(stderr, "warn: %s environment variable is set, but will be overwritten by command line argument %s\n", opt.env, arg.c_str());
}
@ -840,7 +855,7 @@ bool common_params_to_map(int argc, char ** argv, llama_example ex, std::map<com
}
};
std::set<std::string> seen_args;
std::set<common_arg *> seen_options;
for (int i = 1; i < argc; i++) {
const std::string arg_prefix = "--";
@ -852,15 +867,11 @@ bool common_params_to_map(int argc, char ** argv, llama_example ex, std::map<com
if (arg_to_options.find(arg) == arg_to_options.end()) {
throw std::invalid_argument(string_format("error: invalid argument: %s", arg.c_str()));
}
if (!seen_args.insert(arg).second) {
if (arg == "-m" || arg == "--model") {
LOG_WRN("DEPRECATED: multiple %s options are not supported (only last value will be used). "
"Use router mode for llama-server (see --help)\n", arg.c_str());
} else {
LOG_WRN("DEPRECATED: argument '%s' specified multiple times, use comma-separated values instead (only last value will be used)\n", arg.c_str());
}
auto opt_ptr = arg_to_options[arg];
if (!seen_options.insert(opt_ptr).second) {
check_duplicate_arg(arg);
}
auto opt = *arg_to_options[arg];
auto opt = *opt_ptr;
std::string val;
if (opt.value_hint == nullptr && opt.value_hint_2 == nullptr) {
// bool arg (need to reverse the meaning for negative args)