@@ -420,6 +420,8 @@ static bool common_params_parse_ex(int argc, char ** argv, common_params_context
420420 }
421421 };
422422
423+ std::set<std::string> seen_args;
424+
423425 for (int i = 1 ; i < argc; i++) {
424426 const std::string arg_prefix = " --" ;
425427
@@ -430,6 +432,9 @@ static bool common_params_parse_ex(int argc, char ** argv, common_params_context
430432 if (arg_to_options.find (arg) == arg_to_options.end ()) {
431433 throw std::invalid_argument (string_format (" error: invalid argument: %s" , arg.c_str ()));
432434 }
435+ if (!seen_args.insert (arg).second ) {
436+ LOG_WRN (" DEPRECATED: argument '%s' specified multiple times, use comma-separated values instead (only last value will be used)\n " , arg.c_str ());
437+ }
433438 auto & tmp = arg_to_options[arg];
434439 auto opt = *tmp.first ;
435440 bool is_positive = tmp.second ;
@@ -750,6 +755,8 @@ bool common_params_to_map(int argc, char ** argv, llama_example ex, std::map<com
750755 }
751756 };
752757
758+ std::set<std::string> seen_args;
759+
753760 for (int i = 1 ; i < argc; i++) {
754761 const std::string arg_prefix = " --" ;
755762
@@ -760,6 +767,9 @@ bool common_params_to_map(int argc, char ** argv, llama_example ex, std::map<com
760767 if (arg_to_options.find (arg) == arg_to_options.end ()) {
761768 throw std::invalid_argument (string_format (" error: invalid argument: %s" , arg.c_str ()));
762769 }
770+ if (!seen_args.insert (arg).second ) {
771+ LOG_WRN (" DEPRECATED: argument '%s' specified multiple times, use comma-separated values instead (only last value will be used)\n " , arg.c_str ());
772+ }
763773 auto opt = *arg_to_options[arg];
764774 std::string val;
765775 if (opt.value_hint != nullptr ) {
@@ -1226,13 +1236,15 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
12261236 ).set_examples ({LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI, LLAMA_EXAMPLE_DIFFUSION}));
12271237 add_opt (common_arg (
12281238 {" --in-file" }, " FNAME" ,
1229- " an input file (repeat to specify multiple files)" ,
1239+ " an input file (use comma-separated values to specify multiple files)" ,
12301240 [](common_params & params, const std::string & value) {
1231- std::ifstream file (value);
1232- if (!file) {
1233- throw std::runtime_error (string_format (" error: failed to open file '%s'\n " , value.c_str ()));
1241+ for (const auto & item : string_split<std::string>(value, ' ,' )) {
1242+ std::ifstream file (item);
1243+ if (!file) {
1244+ throw std::runtime_error (string_format (" error: failed to open file '%s'\n " , item.c_str ()));
1245+ }
1246+ params.in_files .push_back (item);
12341247 }
1235- params.in_files .push_back (value);
12361248 }
12371249 ).set_examples ({LLAMA_EXAMPLE_IMATRIX}));
12381250 add_opt (common_arg (
@@ -1969,9 +1981,11 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
19691981 ).set_examples (mmproj_examples).set_env (" LLAMA_ARG_MMPROJ_OFFLOAD" ));
19701982 add_opt (common_arg (
19711983 {" --image" , " --audio" }, " FILE" ,
1972- " path to an image or audio file. use with multimodal models, can be repeated if you have multiple files\n " ,
1984+ " path to an image or audio file. use with multimodal models, use comma-separated values for multiple files\n " ,
19731985 [](common_params & params, const std::string & value) {
1974- params.image .emplace_back (value);
1986+ for (const auto & item : string_split<std::string>(value, ' ,' )) {
1987+ params.image .emplace_back (item);
1988+ }
19751989 }
19761990 ).set_examples ({LLAMA_EXAMPLE_MTMD, LLAMA_EXAMPLE_CLI}));
19771991 add_opt (common_arg (
@@ -2218,12 +2232,39 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
22182232 }
22192233 ));
22202234 add_opt (common_arg (
2221- {" --override-kv" }, " KEY=TYPE:VALUE" ,
2222- " advanced option to override model metadata by key. may be specified multiple times .\n "
2223- " types: int, float, bool, str. example: --override-kv tokenizer.ggml.add_bos_token=bool:false" ,
2235+ {" --override-kv" }, " KEY=TYPE:VALUE,... " ,
2236+ " advanced option to override model metadata by key. to specify multiple overrides, either use comma-separated or repeat this argument .\n "
2237+ " types: int, float, bool, str. example: --override-kv tokenizer.ggml.add_bos_token=bool:false,tokenizer.ggml.add_eos_token=bool:false " ,
22242238 [](common_params & params, const std::string & value) {
2225- if (!string_parse_kv_override (value.c_str (), params.kv_overrides )) {
2226- throw std::runtime_error (string_format (" error: Invalid type for KV override: %s\n " , value.c_str ()));
2239+ std::vector<std::string> kv_overrides;
2240+
2241+ std::string current;
2242+ bool escaping = false ;
2243+
2244+ for (const char c : value) {
2245+ if (escaping) {
2246+ current.push_back (c);
2247+ escaping = false ;
2248+ } else if (c == ' \\ ' ) {
2249+ escaping = true ;
2250+ } else if (c == ' ,' ) {
2251+ kv_overrides.push_back (current);
2252+ current.clear ();
2253+ } else {
2254+ current.push_back (c);
2255+ }
2256+ }
2257+
2258+ if (escaping) {
2259+ current.push_back (' \\ ' );
2260+ }
2261+
2262+ kv_overrides.push_back (current);
2263+
2264+ for (const auto & kv_override : kv_overrides) {
2265+ if (!string_parse_kv_override (kv_override.c_str (), params.kv_overrides )) {
2266+ throw std::runtime_error (string_format (" error: Invalid type for KV override: %s\n " , kv_override.c_str ()));
2267+ }
22272268 }
22282269 }
22292270 ));
@@ -2237,33 +2278,50 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
22372278 ));
22382279 add_opt (common_arg (
22392280 {" --lora" }, " FNAME" ,
2240- " path to LoRA adapter (can be repeated to use multiple adapters)" ,
2281+ " path to LoRA adapter (use comma-separated values to load multiple adapters)" ,
22412282 [](common_params & params, const std::string & value) {
2242- params.lora_adapters .push_back ({ std::string (value), 1.0 , " " , " " , nullptr });
2283+ for (const auto & item : string_split<std::string>(value, ' ,' )) {
2284+ params.lora_adapters .push_back ({ item, 1.0 , " " , " " , nullptr });
2285+ }
22432286 }
22442287 // 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
22452288 ).set_examples ({LLAMA_EXAMPLE_COMMON, LLAMA_EXAMPLE_EXPORT_LORA}));
22462289 add_opt (common_arg (
2247- {" --lora-scaled" }, " FNAME" , " SCALE" ,
2248- " path to LoRA adapter with user defined scaling (can be repeated to use multiple adapters)" ,
2249- [](common_params & params, const std::string & fname, const std::string & scale) {
2250- params.lora_adapters .push_back ({ fname, std::stof (scale), " " , " " , nullptr });
2290+ {" --lora-scaled" }, " FNAME:SCALE,..." ,
2291+ " path to LoRA adapter with user defined scaling (format: FNAME:SCALE,...)\n "
2292+ " note: use comma-separated values" ,
2293+ [](common_params & params, const std::string & value) {
2294+ for (const auto & item : string_split<std::string>(value, ' ,' )) {
2295+ auto parts = string_split<std::string>(item, ' :' );
2296+ if (parts.size () != 2 ) {
2297+ throw std::invalid_argument (" lora-scaled format: FNAME:SCALE" );
2298+ }
2299+ params.lora_adapters .push_back ({ parts[0 ], std::stof (parts[1 ]), " " , " " , nullptr });
2300+ }
22512301 }
22522302 // 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
22532303 ).set_examples ({LLAMA_EXAMPLE_COMMON, LLAMA_EXAMPLE_EXPORT_LORA}));
22542304 add_opt (common_arg (
22552305 {" --control-vector" }, " FNAME" ,
2256- " add a control vector\n note: this argument can be repeated to add multiple control vectors" ,
2306+ " add a control vector\n note: use comma-separated values to add multiple control vectors" ,
22572307 [](common_params & params, const std::string & value) {
2258- params.control_vectors .push_back ({ 1 .0f , value, });
2308+ for (const auto & item : string_split<std::string>(value, ' ,' )) {
2309+ params.control_vectors .push_back ({ 1 .0f , item, });
2310+ }
22592311 }
22602312 ));
22612313 add_opt (common_arg (
2262- {" --control-vector-scaled" }, " FNAME" , " SCALE" ,
2314+ {" --control-vector-scaled" }, " FNAME: SCALE,... " ,
22632315 " add a control vector with user defined scaling SCALE\n "
2264- " note: this argument can be repeated to add multiple scaled control vectors" ,
2265- [](common_params & params, const std::string & fname, const std::string & scale) {
2266- params.control_vectors .push_back ({ std::stof (scale), fname });
2316+ " note: use comma-separated values (format: FNAME:SCALE,...)" ,
2317+ [](common_params & params, const std::string & value) {
2318+ for (const auto & item : string_split<std::string>(value, ' ,' )) {
2319+ auto parts = string_split<std::string>(item, ' :' );
2320+ if (parts.size () != 2 ) {
2321+ throw std::invalid_argument (" control-vector-scaled format: FNAME:SCALE" );
2322+ }
2323+ params.control_vectors .push_back ({ std::stof (parts[1 ]), parts[0 ] });
2324+ }
22672325 }
22682326 ));
22692327 add_opt (common_arg (
@@ -2353,13 +2411,15 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
23532411 ).set_env (" HF_TOKEN" ));
23542412 add_opt (common_arg (
23552413 {" --context-file" }, " FNAME" ,
2356- " file to load context from (repeat to specify multiple files)" ,
2414+ " file to load context from (use comma-separated values to specify multiple files)" ,
23572415 [](common_params & params, const std::string & value) {
2358- std::ifstream file (value, std::ios::binary);
2359- if (!file) {
2360- throw std::runtime_error (string_format (" error: failed to open file '%s'\n " , value.c_str ()));
2416+ for (const auto & item : string_split<std::string>(value, ' ,' )) {
2417+ std::ifstream file (item, std::ios::binary);
2418+ if (!file) {
2419+ throw std::runtime_error (string_format (" error: failed to open file '%s'\n " , item.c_str ()));
2420+ }
2421+ params.context_files .push_back (item);
23612422 }
2362- params.context_files .push_back (value);
23632423 }
23642424 ).set_examples ({LLAMA_EXAMPLE_RETRIEVAL}));
23652425 add_opt (common_arg (
0 commit comments