From 8c70a6756d0d53db374678284f8cf161344d8e87 Mon Sep 17 00:00:00 2001 From: Louis Le Date: Mon, 4 Nov 2024 16:39:44 +0700 Subject: [PATCH 1/4] chore: add model import option parameter --- docs/static/openapi/cortex.json | 7 ++++++- engine/controllers/models.cc | 16 +++++++++++++++- engine/e2e-test/test_api_model_import.py | 15 +++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/docs/static/openapi/cortex.json b/docs/static/openapi/cortex.json index f6120a4ad..760d48bba 100644 --- a/docs/static/openapi/cortex.json +++ b/docs/static/openapi/cortex.json @@ -642,7 +642,8 @@ "example": { "model": "model-id", "modelPath": "/path/to/gguf", - "name": "model display name" + "name": "model display name", + "option": "symlink" } } } @@ -3187,6 +3188,10 @@ "name": { "type": "string", "description": "The display name of the model." + }, + "option": { + "type": "string", + "description": "Import options such as symlink or copy." } }, "required": ["model", "modelPath"] diff --git a/engine/controllers/models.cc b/engine/controllers/models.cc index 939f63f31..144791d87 100644 --- a/engine/controllers/models.cc +++ b/engine/controllers/models.cc @@ -1,5 +1,6 @@ #include "database/models.h" #include +#include #include #include "config/gguf_parser.h" #include "config/yaml_config.h" @@ -320,6 +321,7 @@ void Models::ImportModel( auto modelHandle = (*(req->getJsonObject())).get("model", "").asString(); auto modelPath = (*(req->getJsonObject())).get("modelPath", "").asString(); auto modelName = (*(req->getJsonObject())).get("name", "").asString(); + auto option = (*(req->getJsonObject())).get("option", "symlink").asString(); config::GGUFHandler gguf_handler; config::YamlHandler yaml_handler; cortex::db::Models modellist_utils_obj; @@ -339,7 +341,19 @@ void Models::ImportModel( std::filesystem::path(model_yaml_path).parent_path()); gguf_handler.Parse(modelPath); config::ModelConfig model_config = gguf_handler.GetModelConfig(); - model_config.files.push_back(modelPath); + // There are 2 options: symlink and copy + if (option == "copy") { + // Move GGUF file to the destination path + std::filesystem::path file_path = + std::filesystem::path(model_yaml_path).parent_path() / + std::filesystem::path(modelPath).filename(); + std::filesystem::copy_file( + modelPath, file_path, + std::filesystem::copy_options::update_existing); + model_config.files.push_back(file_path); + } else { + model_config.files.push_back(modelPath); + } model_config.model = modelHandle; model_config.name = modelName.empty() ? model_config.name : modelName; yaml_handler.UpdateModelConfig(model_config); diff --git a/engine/e2e-test/test_api_model_import.py b/engine/e2e-test/test_api_model_import.py index 3f8a82a0d..d3f092854 100644 --- a/engine/e2e-test/test_api_model_import.py +++ b/engine/e2e-test/test_api_model_import.py @@ -29,6 +29,21 @@ def test_model_import_with_name_should_be_success(self): response = requests.post("http://localhost:3928/models/import", json=body_json) assert response.status_code == 200 + @pytest.mark.skipif(False, reason="Expensive test. Only test when you have local gguf file.") + def test_model_import_with_name_should_be_success(self): + body_json = {'model': 'testing-model', + 'modelPath': '/path/to/local/gguf', + 'name': 'test_model', + 'option': 'copy'} + response = requests.post("http://localhost:3928/models/import", json=body_json) + assert response.status_code == 200 + # Test imported path + response = requests.get("http://localhost:3928/models/testing-model") + assert response.status_code == 200 + # Since this is a dynamic test - require actual file path + # it's not safe to assert with the gguf file name + assert response.json()['files'][0] != '/path/to/local/gguf' + def test_model_import_with_invalid_path_should_fail(self): body_json = {'model': 'tinyllama:gguf', 'modelPath': '/invalid/path/to/gguf'} From 875bc41e9a2d042916f16212caf19f36f748dad5 Mon Sep 17 00:00:00 2001 From: Louis Le Date: Mon, 4 Nov 2024 16:56:41 +0700 Subject: [PATCH 2/4] chore: update openai doc schema to enum --- docs/static/openapi/cortex.json | 3 ++- engine/controllers/models.cc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/static/openapi/cortex.json b/docs/static/openapi/cortex.json index 760d48bba..f0bef0cb4 100644 --- a/docs/static/openapi/cortex.json +++ b/docs/static/openapi/cortex.json @@ -3191,7 +3191,8 @@ }, "option": { "type": "string", - "description": "Import options such as symlink or copy." + "description": "Import options such as symlink or copy.", + "enum": ["symlink", "copy"] } }, "required": ["model", "modelPath"] diff --git a/engine/controllers/models.cc b/engine/controllers/models.cc index 144791d87..33de3357f 100644 --- a/engine/controllers/models.cc +++ b/engine/controllers/models.cc @@ -343,7 +343,7 @@ void Models::ImportModel( config::ModelConfig model_config = gguf_handler.GetModelConfig(); // There are 2 options: symlink and copy if (option == "copy") { - // Move GGUF file to the destination path + // Copy GGUF file to the destination path std::filesystem::path file_path = std::filesystem::path(model_yaml_path).parent_path() / std::filesystem::path(modelPath).filename(); From fb9a4912edd4f257ac41e764bdd025d8e3a944c8 Mon Sep 17 00:00:00 2001 From: Louis Le Date: Mon, 4 Nov 2024 16:58:22 +0700 Subject: [PATCH 3/4] chore: change back skipped test case --- engine/e2e-test/test_api_model_import.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/e2e-test/test_api_model_import.py b/engine/e2e-test/test_api_model_import.py index d3f092854..74481594c 100644 --- a/engine/e2e-test/test_api_model_import.py +++ b/engine/e2e-test/test_api_model_import.py @@ -29,7 +29,7 @@ def test_model_import_with_name_should_be_success(self): response = requests.post("http://localhost:3928/models/import", json=body_json) assert response.status_code == 200 - @pytest.mark.skipif(False, reason="Expensive test. Only test when you have local gguf file.") + @pytest.mark.skipif(True, reason="Expensive test. Only test when you have local gguf file.") def test_model_import_with_name_should_be_success(self): body_json = {'model': 'testing-model', 'modelPath': '/path/to/local/gguf', From 7705147e5254c870cfb3852a6037ac5d9a818c46 Mon Sep 17 00:00:00 2001 From: Louis Le Date: Mon, 4 Nov 2024 17:04:46 +0700 Subject: [PATCH 4/4] fix: C2664 - push_back path --- engine/controllers/models.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/controllers/models.cc b/engine/controllers/models.cc index 33de3357f..544b3588c 100644 --- a/engine/controllers/models.cc +++ b/engine/controllers/models.cc @@ -350,7 +350,7 @@ void Models::ImportModel( std::filesystem::copy_file( modelPath, file_path, std::filesystem::copy_options::update_existing); - model_config.files.push_back(file_path); + model_config.files.push_back(file_path.string()); } else { model_config.files.push_back(modelPath); }