| 380 | }; |
| 381 | |
| 382 | common_presets common_preset_context::load_from_models_dir(const std::string & models_dir) const { |
| 383 | if (!std::filesystem::exists(models_dir) || !std::filesystem::is_directory(models_dir)) { |
| 384 | throw std::runtime_error(string_format("error: '%s' does not exist or is not a directory\n", models_dir.c_str())); |
| 385 | } |
| 386 | |
| 387 | std::vector<local_model> models; |
| 388 | auto scan_subdir = [&models](const std::string & subdir_path, const std::string & name) { |
| 389 | auto files = fs_list(subdir_path, false); |
| 390 | common_file_info model_file; |
| 391 | common_file_info first_shard_file; |
| 392 | common_file_info mmproj_file; |
| 393 | for (const auto & file : files) { |
| 394 | if (string_ends_with(file.name, ".gguf")) { |
| 395 | if (file.name.find("mmproj") != std::string::npos) { |
| 396 | mmproj_file = file; |
| 397 | } else if (file.name.find("-00001-of-") != std::string::npos) { |
| 398 | first_shard_file = file; |
| 399 | } else { |
| 400 | model_file = file; |
| 401 | } |
| 402 | } |
| 403 | } |
| 404 | // single file model |
| 405 | local_model model{ |
| 406 | /* name */ name, |
| 407 | /* path */ first_shard_file.path.empty() ? model_file.path : first_shard_file.path, |
| 408 | /* path_mmproj */ mmproj_file.path // can be empty |
| 409 | }; |
| 410 | if (!model.path.empty()) { |
| 411 | models.push_back(model); |
| 412 | } |
| 413 | }; |
| 414 | |
| 415 | auto files = fs_list(models_dir, true); |
| 416 | for (const auto & file : files) { |
| 417 | if (file.is_dir) { |
| 418 | scan_subdir(file.path, file.name); |
| 419 | } else if (string_ends_with(file.name, ".gguf")) { |
| 420 | // single file model |
| 421 | std::string name = file.name; |
| 422 | string_replace_all(name, ".gguf", ""); |
| 423 | local_model model{ |
| 424 | /* name */ name, |
| 425 | /* path */ file.path, |
| 426 | /* path_mmproj */ "" |
| 427 | }; |
| 428 | models.push_back(model); |
| 429 | } |
| 430 | } |
| 431 | |
| 432 | // convert local models to presets |
| 433 | common_presets out; |
| 434 | for (const auto & model : models) { |
| 435 | common_preset preset; |
| 436 | preset.name = model.name; |
| 437 | preset.set_option(*this, "LLAMA_ARG_MODEL", model.path); |
| 438 | if (!model.path_mmproj.empty()) { |
| 439 | preset.set_option(*this, "LLAMA_ARG_MMPROJ", model.path_mmproj); |
no test coverage detected