From e5e506a12fb0797467469526bf37f1d5ca61a9a9 Mon Sep 17 00:00:00 2001 From: vansangpfiev Date: Tue, 19 Nov 2024 13:08:54 +0700 Subject: [PATCH 1/3] fix: log level does not work for macOS (#1703) * feat: API for configuring huggingface token * chore: API docs * chore: Token docs * chore: docs * fix: log level * fix: logging issue --------- Co-authored-by: vansangpfiev --- docs/sidebars.ts | 2 +- engine/services/engine_service.cc | 2 +- engine/services/hardware_service.cc | 5 ++++- engine/utils/logging_utils.h | 25 +++++++++++++++++++++++++ 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/docs/sidebars.ts b/docs/sidebars.ts index 8c0800345..15b29bada 100644 --- a/docs/sidebars.ts +++ b/docs/sidebars.ts @@ -104,7 +104,7 @@ const sidebars: SidebarsConfig = { type: "doc", id: "configurations/token", label: "Token", - } + }, ], }, { diff --git a/engine/services/engine_service.cc b/engine/services/engine_service.cc index d793989af..8d8a4a65c 100644 --- a/engine/services/engine_service.cc +++ b/engine/services/engine_service.cc @@ -899,7 +899,7 @@ cpp::result EngineService::LoadEngine( CTL_WRN("Method SetFileLogger is not supported yet"); } if (en->IsSupported("SetLogLevel")) { - en->SetLogLevel(trantor::Logger::logLevel()); + en->SetLogLevel(logging_utils_helper::global_log_level); } else { CTL_WRN("Method SetLogLevel is not supported yet"); } diff --git a/engine/services/hardware_service.cc b/engine/services/hardware_service.cc index b9f8fe63b..905b17107 100644 --- a/engine/services/hardware_service.cc +++ b/engine/services/hardware_service.cc @@ -57,6 +57,7 @@ HardwareInfo HardwareService::GetHardwareInfo() { } bool HardwareService::Restart(const std::string& host, int port) { + namespace luh = logging_utils_helper; if (!ahc_) return true; auto exe = commands::GetCortexServerBinary(); @@ -117,6 +118,7 @@ bool HardwareService::Restart(const std::string& host, int port) { std::string params = "--ignore_cout"; params += " --config_file_path " + get_config_file_path(); params += " --data_folder_path " + get_data_folder_path(); + params += " --loglevel " + luh::LogLevelStr(luh::global_log_level); std::string cmds = cortex_utils::GetCurrentPath() + "/" + exe + " " + params; // Create child process if (!CreateProcess( @@ -168,7 +170,8 @@ bool HardwareService::Restart(const std::string& host, int port) { std::string p = cortex_utils::GetCurrentPath() + "/" + exe; execl(p.c_str(), exe.c_str(), "--ignore_cout", "--config_file_path", get_config_file_path().c_str(), "--data_folder_path", - get_data_folder_path().c_str(), "--loglevel", "INFO", (char*)0); + get_data_folder_path().c_str(), "--loglevel", + luh::LogLevelStr(luh::global_log_level).c_str(), (char*)0); } else { // Parent process if (!TryConnectToServer(host, port)) { diff --git a/engine/utils/logging_utils.h b/engine/utils/logging_utils.h index 2c5affcd4..d2c04a7e8 100644 --- a/engine/utils/logging_utils.h +++ b/engine/utils/logging_utils.h @@ -32,25 +32,33 @@ inline bool is_server = false; } namespace logging_utils_helper { +// In macOS, the default log level is reset to INFO when we load engine +// Use a global log level to save the value +inline trantor::Logger::LogLevel global_log_level = trantor::Logger::kInfo; inline void SetLogLevel(const std::string& log_level, bool ignore_cout) { if (log_level == "TRACE") { trantor::Logger::setLogLevel(trantor::Logger::kTrace); + global_log_level = trantor::Logger::kTrace; if (!ignore_cout) std::cout << "Set log level to TRACE" << std::endl; } else if (log_level == "DEBUG") { trantor::Logger::setLogLevel(trantor::Logger::kDebug); + global_log_level = trantor::Logger::kDebug; if (!ignore_cout) std::cout << "Set log level to DEBUG" << std::endl; } else if (log_level == "INFO") { trantor::Logger::setLogLevel(trantor::Logger::kInfo); + global_log_level = trantor::Logger::kInfo; if (!ignore_cout) std::cout << "Set log level to INFO" << std::endl; } else if (log_level == "WARN") { trantor::Logger::setLogLevel(trantor::Logger::kWarn); + global_log_level = trantor::Logger::kWarn; if (!ignore_cout) std::cout << "Set log level to WARN" << std::endl; } else if (log_level == "ERROR") { trantor::Logger::setLogLevel(trantor::Logger::kError); + global_log_level = trantor::Logger::kError; if (!ignore_cout) std::cout << "Set log level to ERROR" << std::endl; } else { @@ -59,4 +67,21 @@ inline void SetLogLevel(const std::string& log_level, bool ignore_cout) { << std::endl; } } + +inline std::string LogLevelStr(const trantor::Logger::LogLevel& log_level) { + switch (log_level) { + case trantor::Logger::kTrace: + return "TRACE"; + case trantor::Logger::kDebug: + return "DEBUG"; + case trantor::Logger::kInfo: + return "INFO"; + case trantor::Logger::kWarn: + return "WARN"; + case trantor::Logger::kError: + return "ERROR"; + default: + return "UNKNOWN"; + } +} } // namespace logging_utils_helper \ No newline at end of file From e57f80c17245ed5c45c15e72efddd9c73a8c5771 Mon Sep 17 00:00:00 2001 From: vansangpfiev Date: Tue, 19 Nov 2024 15:50:26 +0700 Subject: [PATCH 2/3] fix: bypass check model id if llama_model_path exists (#1706) * fix: bypass check model id if llama_model_path exists * fix: correct logic * fix: check db first --------- Co-authored-by: vansangpfiev --- engine/controllers/models.cc | 10 +++++++++- engine/services/model_service.cc | 7 ++++++- engine/services/model_service.h | 13 +++++++++---- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/engine/controllers/models.cc b/engine/controllers/models.cc index 796f70d16..9e4ba1e9f 100644 --- a/engine/controllers/models.cc +++ b/engine/controllers/models.cc @@ -442,6 +442,14 @@ void Models::StartModel( // model_path has higher priority if (auto& o = (*(req->getJsonObject()))["llama_model_path"]; !o.isNull()) { params_override.model_path = o.asString(); + if (auto& mp = (*(req->getJsonObject()))["model_path"]; mp.isNull()) { + // Bypass if model does not exist in DB and llama_model_path exists + if (std::filesystem::exists(params_override.model_path.value()) && + !model_service_->HasModel(model_handle)) { + CTL_INF("llama_model_path exists, bypass check model id"); + params_override.bypass_llama_model_path = true; + } + } } if (auto& o = (*(req->getJsonObject()))["model_path"]; !o.isNull()) { @@ -489,7 +497,7 @@ void Models::StartModel( auto& v = result.value(); Json::Value ret; ret["message"] = "Started successfully!"; - if(v.warning) { + if (v.warning) { ret["warning"] = *(v.warning); } auto resp = cortex_utils::CreateCortexHttpJsonResponse(ret); diff --git a/engine/services/model_service.cc b/engine/services/model_service.cc index 3a8507c22..793e8ecb5 100644 --- a/engine/services/model_service.cc +++ b/engine/services/model_service.cc @@ -381,6 +381,10 @@ cpp::result ModelService::HandleUrl( return unique_model_id; } +bool ModelService::HasModel(const std::string& id) const { + return cortex::db::Models().HasModel(id); +} + cpp::result ModelService::DownloadModelFromCortexsoAsync( const std::string& name, const std::string& branch, @@ -745,7 +749,8 @@ cpp::result ModelService::StartModel( return cpp::fail( "Not enough VRAM - required: " + std::to_string(vram_needed_MiB) + " MiB, available: " + std::to_string(free_vram_MiB) + - " MiB - Should adjust ngl to " + std::to_string(free_vram_MiB / (vram_needed_MiB / ngl) - 1)); + " MiB - Should adjust ngl to " + + std::to_string(free_vram_MiB / (vram_needed_MiB / ngl) - 1)); } if (ram_needed_MiB > free_ram_MiB) { diff --git a/engine/services/model_service.h b/engine/services/model_service.h index 47d61c154..7b6375e54 100644 --- a/engine/services/model_service.h +++ b/engine/services/model_service.h @@ -3,10 +3,10 @@ #include #include #include +#include "common/engine_servicei.h" #include "config/model_config.h" #include "services/download_service.h" #include "services/inference_service.h" -#include "common/engine_servicei.h" struct ModelPullInfo { std::string id; @@ -26,12 +26,15 @@ struct StartParameterOverride { std::optional cache_type; std::optional mmproj; std::optional model_path; - bool bypass_model_check() const { return mmproj.has_value(); } + bool bypass_llama_model_path = false; + bool bypass_model_check() const { + return mmproj.has_value() || bypass_llama_model_path; + } }; struct StartModelResult { - bool success; - std::optional warning; + bool success; + std::optional warning; }; class ModelService { @@ -89,6 +92,8 @@ class ModelService { const std::string& url, std::optional temp_model_id, std::optional temp_name); + bool HasModel(const std::string& id) const; + private: /** * Handle downloading model which have following pattern: author/model_name From 027002fc48ad38ee24accc4a42948b9f9324376f Mon Sep 17 00:00:00 2001 From: vansangpfiev Date: Tue, 19 Nov 2024 17:51:09 +0700 Subject: [PATCH 3/3] fix: cortexrc race condition (#1707) Co-authored-by: vansangpfiev --- engine/cli/command_line_parser.cc | 5 +- engine/cli/commands/cortex_upd_cmd.cc | 5 +- engine/cli/main.cc | 5 +- engine/main.cc | 3 +- engine/test/components/test_cortex_config.cc | 18 +- .../test_file_manager_config_yaml_utils.cc | 7 +- engine/utils/config_yaml_utils.h | 361 ++++++++++-------- engine/utils/file_manager_utils.h | 10 +- 8 files changed, 228 insertions(+), 186 deletions(-) diff --git a/engine/cli/command_line_parser.cc b/engine/cli/command_line_parser.cc index 2996401fc..bb41dbe8b 100644 --- a/engine/cli/command_line_parser.cc +++ b/engine/cli/command_line_parser.cc @@ -602,8 +602,9 @@ void CommandLineParser::SetupSystemCommands() { << " to " << cml_data_.port); auto config_path = file_manager_utils::GetConfigurationPath(); cml_data_.config.apiServerPort = std::to_string(cml_data_.port); - auto result = config_yaml_utils::DumpYamlConfig(cml_data_.config, - config_path.string()); + auto result = + config_yaml_utils::CortexConfigMgr::GetInstance().DumpYamlConfig( + cml_data_.config, config_path.string()); if (result.has_error()) { CLI_LOG("Error update " << config_path.string() << result.error()); } diff --git a/engine/cli/commands/cortex_upd_cmd.cc b/engine/cli/commands/cortex_upd_cmd.cc index 231594346..fcb45fc5c 100644 --- a/engine/cli/commands/cortex_upd_cmd.cc +++ b/engine/cli/commands/cortex_upd_cmd.cc @@ -192,8 +192,9 @@ std::optional CheckNewUpdate( CTL_INF("Got the latest release, update to the config file: " << latest_version) config.latestRelease = latest_version; - auto result = config_yaml_utils::DumpYamlConfig( - config, file_manager_utils::GetConfigurationPath().string()); + auto result = + config_yaml_utils::CortexConfigMgr::GetInstance().DumpYamlConfig( + config, file_manager_utils::GetConfigurationPath().string()); if (result.has_error()) { CTL_ERR("Error update " << file_manager_utils::GetConfigurationPath().string() diff --git a/engine/cli/main.cc b/engine/cli/main.cc index 23553c0b3..ed3b1680f 100644 --- a/engine/cli/main.cc +++ b/engine/cli/main.cc @@ -151,8 +151,9 @@ int main(int argc, char* argv[]) { .count(); config.latestLlamacppRelease = res.value(); - auto upd_config_res = config_yaml_utils::DumpYamlConfig( - config, file_manager_utils::GetConfigurationPath().string()); + auto upd_config_res = + config_yaml_utils::CortexConfigMgr::GetInstance().DumpYamlConfig( + config, file_manager_utils::GetConfigurationPath().string()); if (upd_config_res.has_error()) { CTL_ERR("Failed to update config file: " << upd_config_res.error()); } else { diff --git a/engine/main.cc b/engine/main.cc index 5fdd69d6c..56f66154e 100644 --- a/engine/main.cc +++ b/engine/main.cc @@ -51,7 +51,8 @@ void RunServer(std::optional port, bool ignore_cout) { auto config_path = file_manager_utils::GetConfigurationPath(); config.apiServerPort = std::to_string(*port); auto result = - config_yaml_utils::DumpYamlConfig(config, config_path.string()); + config_yaml_utils::CortexConfigMgr::GetInstance().DumpYamlConfig( + config, config_path.string()); if (result.has_error()) { CTL_ERR("Error update " << config_path.string() << result.error()); } diff --git a/engine/test/components/test_cortex_config.cc b/engine/test/components/test_cortex_config.cc index 2a25d65f0..04f3ddf33 100644 --- a/engine/test/components/test_cortex_config.cc +++ b/engine/test/components/test_cortex_config.cc @@ -2,6 +2,7 @@ #include "utils/config_yaml_utils.h" namespace config_yaml_utils { +namespace cyu = config_yaml_utils; class CortexConfigTest : public ::testing::Test { protected: const std::string test_file_path = "test_config.yaml"; @@ -43,7 +44,8 @@ TEST_F(CortexConfigTest, DumpYamlConfig_WritesCorrectly) { 123456789, "v1.0.0"}; - auto result = DumpYamlConfig(config, test_file_path); + auto result = cyu::CortexConfigMgr::GetInstance().DumpYamlConfig( + config, test_file_path); EXPECT_FALSE(result.has_error()); // Verify that the file was created and contains the expected data @@ -72,11 +74,13 @@ TEST_F(CortexConfigTest, FromYaml_ReadsCorrectly) { 123456789, "v1.0.0"}; - auto result = DumpYamlConfig(config, test_file_path); + auto result = cyu::CortexConfigMgr::GetInstance().DumpYamlConfig( + config, test_file_path); EXPECT_FALSE(result.has_error()); // Now read from the YAML file - CortexConfig loaded_config = FromYaml(test_file_path, default_config); + CortexConfig loaded_config = cyu::CortexConfigMgr::GetInstance().FromYaml( + test_file_path, default_config); // Verify that the loaded configuration matches what was written EXPECT_EQ(loaded_config.logFolderPath, config.logFolderPath); @@ -92,7 +96,10 @@ TEST_F(CortexConfigTest, FromYaml_FileNotFound) { std::filesystem::remove(test_file_path); // Ensure the file does not exist EXPECT_THROW( - { FromYaml(test_file_path, default_config); }, + { + cyu::CortexConfigMgr::GetInstance().FromYaml(test_file_path, + default_config); + }, std::runtime_error); // Expect a runtime error due to missing file } @@ -102,7 +109,8 @@ TEST_F(CortexConfigTest, FromYaml_IncompleteConfigUsesDefaults) { out_file << "logFolderPath: log_path\n"; // Missing other fields out_file.close(); - CortexConfig loaded_config = FromYaml(test_file_path, default_config); + CortexConfig loaded_config = cyu::CortexConfigMgr::GetInstance().FromYaml( + test_file_path, default_config); // Verify that defaults are used where values are missing EXPECT_EQ(loaded_config.logFolderPath, "log_path"); diff --git a/engine/test/components/test_file_manager_config_yaml_utils.cc b/engine/test/components/test_file_manager_config_yaml_utils.cc index 3372fcfb1..f2c8c4075 100644 --- a/engine/test/components/test_file_manager_config_yaml_utils.cc +++ b/engine/test/components/test_file_manager_config_yaml_utils.cc @@ -63,7 +63,9 @@ TEST_F(FileManagerConfigTest, DumpYamlConfig) { .apiServerPort = "8080"}; std::string test_file = "test_config.yaml"; - auto result = config_yaml_utils::DumpYamlConfig(config, test_file); + auto result = + config_yaml_utils::CortexConfigMgr::GetInstance().DumpYamlConfig( + config, test_file); EXPECT_FALSE(result.has_error()); EXPECT_TRUE(std::filesystem::exists(test_file)); @@ -83,7 +85,8 @@ TEST_F(FileManagerConfigTest, FromYaml) { out_file.close(); config_yaml_utils::CortexConfig default_config{}; - auto config = config_yaml_utils::FromYaml(test_file, default_config); + auto config = config_yaml_utils::CortexConfigMgr::GetInstance().FromYaml( + test_file, default_config); EXPECT_EQ(config.logFolderPath, "/path/to/logs"); EXPECT_EQ(config.dataFolderPath, "/path/to/data"); diff --git a/engine/utils/config_yaml_utils.h b/engine/utils/config_yaml_utils.h index 6b1660467..187e1b4ef 100644 --- a/engine/utils/config_yaml_utils.h +++ b/engine/utils/config_yaml_utils.h @@ -4,11 +4,25 @@ #include #include #include +#include #include "utils/logging_utils.h" #include "utils/result.hpp" #include "yaml-cpp/yaml.h" namespace config_yaml_utils { + +const std::string kDefaultHost{"127.0.0.1"}; +const std::string kDefaultPort{"39281"}; +const int kDefaultMaxLines{100000}; +constexpr const uint64_t kDefaultCheckedForUpdateAt = 0u; +constexpr const uint64_t kDefaultCheckedForLlamacppUpdateAt = 0u; +constexpr const auto kDefaultLatestRelease = "default_version"; +constexpr const auto kDefaultLatestLlamacppRelease = ""; +constexpr const auto kDefaultCorsEnabled = true; +const std::vector kDefaultEnabledOrigins{ + "http://localhost:39281", "http://127.0.0.1:39281", "http://0.0.0.0:39281"}; +constexpr const auto kDefaultNoProxy = "example.com,::1,localhost,127.0.0.1"; + struct CortexConfig { std::string logFolderPath; std::string logLlamaCppPath; @@ -47,182 +61,191 @@ struct CortexConfig { bool verifyHostSsl; }; -const std::string kDefaultHost{"127.0.0.1"}; -const std::string kDefaultPort{"39281"}; -const int kDefaultMaxLines{100000}; -constexpr const uint64_t kDefaultCheckedForUpdateAt = 0u; -constexpr const uint64_t kDefaultCheckedForLlamacppUpdateAt = 0u; -constexpr const auto kDefaultLatestRelease = "default_version"; -constexpr const auto kDefaultLatestLlamacppRelease = ""; -constexpr const auto kDefaultCorsEnabled = true; -const std::vector kDefaultEnabledOrigins{ - "http://localhost:39281", "http://127.0.0.1:39281", "http://0.0.0.0:39281"}; -constexpr const auto kDefaultNoProxy = "example.com,::1,localhost,127.0.0.1"; +class CortexConfigMgr { + private: + CortexConfigMgr() {} + std::mutex mtx_; -inline cpp::result DumpYamlConfig(const CortexConfig& config, - const std::string& path) { - std::filesystem::path config_file_path{path}; + public: + CortexConfigMgr(CortexConfigMgr const&) = delete; + CortexConfigMgr& operator=(CortexConfigMgr const&) = delete; + ~CortexConfigMgr() {} - try { - std::ofstream out_file(config_file_path); - if (!out_file) { - throw std::runtime_error("Failed to open output file."); - } - YAML::Node node; - node["logFolderPath"] = config.logFolderPath; - node["logLlamaCppPath"] = config.logLlamaCppPath; - node["logTensorrtLLMPath"] = config.logTensorrtLLMPath; - node["logOnnxPath"] = config.logOnnxPath; - node["dataFolderPath"] = config.dataFolderPath; - node["maxLogLines"] = config.maxLogLines; - node["apiServerHost"] = config.apiServerHost; - node["apiServerPort"] = config.apiServerPort; - node["checkedForUpdateAt"] = config.checkedForUpdateAt; - node["checkedForLlamacppUpdateAt"] = config.checkedForLlamacppUpdateAt; - node["latestRelease"] = config.latestRelease; - node["latestLlamacppRelease"] = config.latestLlamacppRelease; - node["huggingFaceToken"] = config.huggingFaceToken; - node["gitHubUserAgent"] = config.gitHubUserAgent; - node["gitHubToken"] = config.gitHubToken; - node["llamacppVariant"] = config.llamacppVariant; - node["llamacppVersion"] = config.llamacppVersion; - node["enableCors"] = config.enableCors; - node["allowedOrigins"] = config.allowedOrigins; - node["proxyUrl"] = config.proxyUrl; - node["verifyProxySsl"] = config.verifyProxySsl; - node["verifyProxyHostSsl"] = config.verifyProxyHostSsl; - node["proxyUsername"] = config.proxyUsername; - node["proxyPassword"] = config.proxyPassword; - node["noProxy"] = config.noProxy; - node["verifyPeerSsl"] = config.verifyPeerSsl; - node["verifyHostSsl"] = config.verifyHostSsl; - - out_file << node; - out_file.close(); - return {}; - } catch (const std::exception& e) { - CTL_ERR("Error writing to file: " << e.what()); - return cpp::fail("Error writing to file: " + std::string(e.what())); + static CortexConfigMgr& GetInstance() { + static CortexConfigMgr ccm; + return ccm; } -} -inline CortexConfig FromYaml(const std::string& path, - const CortexConfig& default_cfg) { - std::filesystem::path config_file_path{path}; - if (!std::filesystem::exists(config_file_path)) { - throw std::runtime_error("File not found: " + path); + cpp::result DumpYamlConfig(const CortexConfig& config, + const std::string& path) { + std::lock_guard l(mtx_); + std::filesystem::path config_file_path{path}; + + try { + std::ofstream out_file(config_file_path); + if (!out_file) { + throw std::runtime_error("Failed to open output file."); + } + YAML::Node node; + node["logFolderPath"] = config.logFolderPath; + node["logLlamaCppPath"] = config.logLlamaCppPath; + node["logTensorrtLLMPath"] = config.logTensorrtLLMPath; + node["logOnnxPath"] = config.logOnnxPath; + node["dataFolderPath"] = config.dataFolderPath; + node["maxLogLines"] = config.maxLogLines; + node["apiServerHost"] = config.apiServerHost; + node["apiServerPort"] = config.apiServerPort; + node["checkedForUpdateAt"] = config.checkedForUpdateAt; + node["checkedForLlamacppUpdateAt"] = config.checkedForLlamacppUpdateAt; + node["latestRelease"] = config.latestRelease; + node["latestLlamacppRelease"] = config.latestLlamacppRelease; + node["huggingFaceToken"] = config.huggingFaceToken; + node["gitHubUserAgent"] = config.gitHubUserAgent; + node["gitHubToken"] = config.gitHubToken; + node["llamacppVariant"] = config.llamacppVariant; + node["llamacppVersion"] = config.llamacppVersion; + node["enableCors"] = config.enableCors; + node["allowedOrigins"] = config.allowedOrigins; + node["proxyUrl"] = config.proxyUrl; + node["verifyProxySsl"] = config.verifyProxySsl; + node["verifyProxyHostSsl"] = config.verifyProxyHostSsl; + node["proxyUsername"] = config.proxyUsername; + node["proxyPassword"] = config.proxyPassword; + node["noProxy"] = config.noProxy; + node["verifyPeerSsl"] = config.verifyPeerSsl; + node["verifyHostSsl"] = config.verifyHostSsl; + + out_file << node; + out_file.close(); + return {}; + } catch (const std::exception& e) { + CTL_ERR("Error writing to file: " << e.what()); + return cpp::fail("Error writing to file: " + std::string(e.what())); + } } - try { - auto node = YAML::LoadFile(config_file_path.string()); - bool should_update_config = - (!node["logFolderPath"] || !node["dataFolderPath"] || - !node["maxLogLines"] || !node["apiServerHost"] || - !node["apiServerPort"] || !node["checkedForUpdateAt"] || - !node["checkedForLlamacppUpdateAt"] || !node["latestRelease"] || - !node["latestLlamacppRelease"] || !node["logLlamaCppPath"] || - !node["logOnnxPath"] || !node["logTensorrtLLMPath"] || - !node["huggingFaceToken"] || !node["gitHubUserAgent"] || - !node["gitHubToken"] || !node["llamacppVariant"] || - !node["llamacppVersion"] || !node["enableCors"] || - !node["allowedOrigins"] || !node["proxyUrl"] || - !node["proxyUsername"] || !node["proxyPassword"] || - !node["verifyPeerSsl"] || !node["verifyHostSsl"] || - !node["verifyProxySsl"] || !node["verifyProxyHostSsl"] || - !node["noProxy"]); - - CortexConfig config = { - .logFolderPath = node["logFolderPath"] - ? node["logFolderPath"].as() - : default_cfg.logFolderPath, - .logLlamaCppPath = node["logLlamaCppPath"] - ? node["logLlamaCppPath"].as() - : default_cfg.logLlamaCppPath, - .logTensorrtLLMPath = node["logTensorrtLLMPath"] - ? node["logTensorrtLLMPath"].as() - : default_cfg.logTensorrtLLMPath, - .logOnnxPath = node["logOnnxPath"] - ? node["logOnnxPath"].as() - : default_cfg.logOnnxPath, - .dataFolderPath = node["dataFolderPath"] - ? node["dataFolderPath"].as() - : default_cfg.dataFolderPath, - .maxLogLines = node["maxLogLines"] ? node["maxLogLines"].as() - : default_cfg.maxLogLines, - .apiServerHost = node["apiServerHost"] - ? node["apiServerHost"].as() - : default_cfg.apiServerHost, - .apiServerPort = node["apiServerPort"] - ? node["apiServerPort"].as() - : default_cfg.apiServerPort, - .checkedForUpdateAt = node["checkedForUpdateAt"] - ? node["checkedForUpdateAt"].as() - : default_cfg.checkedForUpdateAt, - .checkedForLlamacppUpdateAt = - node["checkedForLlamacppUpdateAt"] - ? node["checkedForLlamacppUpdateAt"].as() - : default_cfg.checkedForLlamacppUpdateAt, - .latestRelease = node["latestRelease"] - ? node["latestRelease"].as() - : default_cfg.latestRelease, - .latestLlamacppRelease = - node["latestLlamacppRelease"] - ? node["latestLlamacppRelease"].as() - : default_cfg.latestLlamacppRelease, - .huggingFaceToken = node["huggingFaceToken"] - ? node["huggingFaceToken"].as() - : default_cfg.huggingFaceToken, - .gitHubUserAgent = node["gitHubUserAgent"] - ? node["gitHubUserAgent"].as() - : default_cfg.gitHubUserAgent, - .gitHubToken = node["gitHubToken"] - ? node["gitHubToken"].as() - : default_cfg.gitHubToken, - .llamacppVariant = node["llamacppVariant"] - ? node["llamacppVariant"].as() - : default_cfg.llamacppVariant, - .llamacppVersion = node["llamacppVersion"] - ? node["llamacppVersion"].as() - : default_cfg.llamacppVersion, - .enableCors = node["enableCors"] ? node["enableCors"].as() - : default_cfg.enableCors, - .allowedOrigins = - node["allowedOrigins"] - ? node["allowedOrigins"].as>() - : default_cfg.allowedOrigins, - .proxyUrl = node["proxyUrl"] ? node["proxyUrl"].as() - : default_cfg.proxyUrl, - .verifyProxySsl = node["verifyProxySsl"] - ? node["verifyProxySsl"].as() - : default_cfg.verifyProxySsl, - .verifyProxyHostSsl = node["verifyProxyHostSsl"] - ? node["verifyProxyHostSsl"].as() - : default_cfg.verifyProxyHostSsl, - .proxyUsername = node["proxyUsername"] - ? node["proxyUsername"].as() - : default_cfg.proxyUsername, - .proxyPassword = node["proxyPassword"] - ? node["proxyPassword"].as() - : default_cfg.proxyPassword, - .noProxy = node["noProxy"] ? node["noProxy"].as() - : default_cfg.noProxy, - .verifyPeerSsl = node["verifyPeerSsl"] - ? node["verifyPeerSsl"].as() - : default_cfg.verifyPeerSsl, - .verifyHostSsl = node["verifyHostSsl"] - ? node["verifyHostSsl"].as() - : default_cfg.verifyHostSsl, - }; - if (should_update_config) { - auto result = DumpYamlConfig(config, path); - if (result.has_error()) { - CTL_ERR("Failed to update config file: " << result.error()); + CortexConfig FromYaml(const std::string& path, + const CortexConfig& default_cfg) { + std::unique_lock l(mtx_); + std::filesystem::path config_file_path{path}; + if (!std::filesystem::exists(config_file_path)) { + throw std::runtime_error("File not found: " + path); + } + + try { + auto node = YAML::LoadFile(config_file_path.string()); + bool should_update_config = + (!node["logFolderPath"] || !node["dataFolderPath"] || + !node["maxLogLines"] || !node["apiServerHost"] || + !node["apiServerPort"] || !node["checkedForUpdateAt"] || + !node["checkedForLlamacppUpdateAt"] || !node["latestRelease"] || + !node["latestLlamacppRelease"] || !node["logLlamaCppPath"] || + !node["logOnnxPath"] || !node["logTensorrtLLMPath"] || + !node["huggingFaceToken"] || !node["gitHubUserAgent"] || + !node["gitHubToken"] || !node["llamacppVariant"] || + !node["llamacppVersion"] || !node["enableCors"] || + !node["allowedOrigins"] || !node["proxyUrl"] || + !node["proxyUsername"] || !node["proxyPassword"] || + !node["verifyPeerSsl"] || !node["verifyHostSsl"] || + !node["verifyProxySsl"] || !node["verifyProxyHostSsl"] || + !node["noProxy"]); + + CortexConfig config = { + .logFolderPath = node["logFolderPath"] + ? node["logFolderPath"].as() + : default_cfg.logFolderPath, + .logLlamaCppPath = node["logLlamaCppPath"] + ? node["logLlamaCppPath"].as() + : default_cfg.logLlamaCppPath, + .logTensorrtLLMPath = + node["logTensorrtLLMPath"] + ? node["logTensorrtLLMPath"].as() + : default_cfg.logTensorrtLLMPath, + .logOnnxPath = node["logOnnxPath"] + ? node["logOnnxPath"].as() + : default_cfg.logOnnxPath, + .dataFolderPath = node["dataFolderPath"] + ? node["dataFolderPath"].as() + : default_cfg.dataFolderPath, + .maxLogLines = node["maxLogLines"] ? node["maxLogLines"].as() + : default_cfg.maxLogLines, + .apiServerHost = node["apiServerHost"] + ? node["apiServerHost"].as() + : default_cfg.apiServerHost, + .apiServerPort = node["apiServerPort"] + ? node["apiServerPort"].as() + : default_cfg.apiServerPort, + .checkedForUpdateAt = node["checkedForUpdateAt"] + ? node["checkedForUpdateAt"].as() + : default_cfg.checkedForUpdateAt, + .checkedForLlamacppUpdateAt = + node["checkedForLlamacppUpdateAt"] + ? node["checkedForLlamacppUpdateAt"].as() + : default_cfg.checkedForLlamacppUpdateAt, + .latestRelease = node["latestRelease"] + ? node["latestRelease"].as() + : default_cfg.latestRelease, + .latestLlamacppRelease = + node["latestLlamacppRelease"] + ? node["latestLlamacppRelease"].as() + : default_cfg.latestLlamacppRelease, + .huggingFaceToken = node["huggingFaceToken"] + ? node["huggingFaceToken"].as() + : default_cfg.huggingFaceToken, + .gitHubUserAgent = node["gitHubUserAgent"] + ? node["gitHubUserAgent"].as() + : default_cfg.gitHubUserAgent, + .gitHubToken = node["gitHubToken"] + ? node["gitHubToken"].as() + : default_cfg.gitHubToken, + .llamacppVariant = node["llamacppVariant"] + ? node["llamacppVariant"].as() + : default_cfg.llamacppVariant, + .llamacppVersion = node["llamacppVersion"] + ? node["llamacppVersion"].as() + : default_cfg.llamacppVersion, + .enableCors = node["enableCors"] ? node["enableCors"].as() + : default_cfg.enableCors, + .allowedOrigins = + node["allowedOrigins"] + ? node["allowedOrigins"].as>() + : default_cfg.allowedOrigins, + .proxyUrl = node["proxyUrl"] ? node["proxyUrl"].as() + : default_cfg.proxyUrl, + .verifyProxySsl = node["verifyProxySsl"] + ? node["verifyProxySsl"].as() + : default_cfg.verifyProxySsl, + .verifyProxyHostSsl = node["verifyProxyHostSsl"] + ? node["verifyProxyHostSsl"].as() + : default_cfg.verifyProxyHostSsl, + .proxyUsername = node["proxyUsername"] + ? node["proxyUsername"].as() + : default_cfg.proxyUsername, + .proxyPassword = node["proxyPassword"] + ? node["proxyPassword"].as() + : default_cfg.proxyPassword, + .noProxy = node["noProxy"] ? node["noProxy"].as() + : default_cfg.noProxy, + .verifyPeerSsl = node["verifyPeerSsl"] + ? node["verifyPeerSsl"].as() + : default_cfg.verifyPeerSsl, + .verifyHostSsl = node["verifyHostSsl"] + ? node["verifyHostSsl"].as() + : default_cfg.verifyHostSsl, + }; + if (should_update_config) { + l.unlock(); + auto result = DumpYamlConfig(config, path); + if (result.has_error()) { + CTL_ERR("Failed to update config file: " << result.error()); + } } + return config; + } catch (const YAML::BadFile& e) { + CTL_ERR("Failed to read file: " << e.what()); + throw; } - return config; - } catch (const YAML::BadFile& e) { - CTL_ERR("Failed to read file: " << e.what()); - throw; } -} +}; + } // namespace config_yaml_utils diff --git a/engine/utils/file_manager_utils.h b/engine/utils/file_manager_utils.h index 73f92a10a..e8b69869e 100644 --- a/engine/utils/file_manager_utils.h +++ b/engine/utils/file_manager_utils.h @@ -17,6 +17,7 @@ #endif namespace file_manager_utils { +namespace cyu = config_yaml_utils; constexpr std::string_view kCortexConfigurationFileName = ".cortexrc"; constexpr std::string_view kDefaultConfigurationPath = "user_home"; constexpr std::string_view kProdVariant = "prod"; @@ -147,7 +148,8 @@ inline cpp::result UpdateCortexConfig( return cpp::fail("Config file not found: " + config_path.string()); } - return DumpYamlConfig(config, config_path.string()); + return cyu::CortexConfigMgr::GetInstance().DumpYamlConfig( + config, config_path.string()); } inline config_yaml_utils::CortexConfig GetDefaultConfig() { @@ -195,7 +197,8 @@ inline cpp::result CreateConfigFileIfNotExist() { CLI_LOG("Config file not found. Creating one at " + config_path.string()); auto config = GetDefaultConfig(); CLI_LOG("Default data folder path: " + config.dataFolderPath); - return DumpYamlConfig(config, config_path.string()); + return cyu::CortexConfigMgr::GetInstance().DumpYamlConfig(config, + config_path.string()); } inline config_yaml_utils::CortexConfig GetCortexConfig() { @@ -205,7 +208,8 @@ inline config_yaml_utils::CortexConfig GetCortexConfig() { file_manager_utils::GetHomeDirectoryPath() / default_data_folder_name; auto default_cfg = GetDefaultConfig(); - return config_yaml_utils::FromYaml(config_path.string(), default_cfg); + return config_yaml_utils::CortexConfigMgr::GetInstance().FromYaml( + config_path.string(), default_cfg); } inline std::filesystem::path GetCortexDataPath() {