From 95fe7fae59fb54f127358c2bf233d0e954b71397 Mon Sep 17 00:00:00 2001 From: Lu Peng Date: Wed, 20 Sep 2023 18:08:55 -0400 Subject: [PATCH 1/4] Fixed unpatched object storage url bug in unit test. --- .../model_deployment_infrastructure.py | 1 + .../with_extras/model/test_artifact.py | 15 +++++- .../with_extras/model/test_env_info.py | 22 +++++++- .../with_extras/model/test_generic_model.py | 51 ++++++++++++++++--- .../model/test_model_deployment_details.py | 14 ++++- .../model/test_model_metadata_mixin.py | 29 ++++++++++- .../model/test_model_provenance_details.py | 16 +++++- .../with_extras/model/test_runtime_info.py | 42 +++++++++++++-- 8 files changed, 172 insertions(+), 18 deletions(-) diff --git a/ads/model/deployment/model_deployment_infrastructure.py b/ads/model/deployment/model_deployment_infrastructure.py index 519b5a62f..0bce46cf8 100644 --- a/ads/model/deployment/model_deployment_infrastructure.py +++ b/ads/model/deployment/model_deployment_infrastructure.py @@ -223,6 +223,7 @@ def _load_default_properties(self) -> Dict: defaults[self.CONST_REPLICA] = DEFAULT_REPLICA if NB_SESSION_OCID: + nb_session = None try: nb_session = DSCNotebookSession.from_ocid(NB_SESSION_OCID) except Exception as e: diff --git a/tests/unitary/with_extras/model/test_artifact.py b/tests/unitary/with_extras/model/test_artifact.py index e55f7c36c..e8f824894 100644 --- a/tests/unitary/with_extras/model/test_artifact.py +++ b/tests/unitary/with_extras/model/test_artifact.py @@ -138,10 +138,23 @@ def test_prepare_runtime_yaml_inference_training( (TrainingEnvInfo, mlcpu_path_cust, None, None, training_info_cust), ], ) + @patch("ads.model.runtime.env_info.get_service_packs") def test__populate_env_info_inference( - self, env_info_class, conda_pack, bucketname, namespace, expected_env_info + self, mock_get_service_packs, env_info_class, conda_pack, bucketname, namespace, expected_env_info ): """test _populate_env_info.""" + env_path = ( + expected_env_info.inference_env_path if isinstance(expected_env_info, InferenceEnvInfo) + else expected_env_info.training_env_path + ) + mock_get_service_packs.return_value = ( + { + env_path : ("mlcpuv1", "3.6") + }, + { + "mlcpuv1" : (env_path, "3.6") + } + ) env_info = self.artifact._populate_env_info( env_info_class, conda_pack=conda_pack, diff --git a/tests/unitary/with_extras/model/test_env_info.py b/tests/unitary/with_extras/model/test_env_info.py index 8f3ac8ade..cf555f68c 100644 --- a/tests/unitary/with_extras/model/test_env_info.py +++ b/tests/unitary/with_extras/model/test_env_info.py @@ -177,7 +177,16 @@ def test_from_slug_prod_sp(self): info.training_env_type = "service_pack" info.training_python_version = "3.6" - def test_from_slug_not_exist(self): + @patch("ads.model.runtime.env_info.get_service_packs") + def test_from_slug_not_exist(self, mock_get_service_packs): + mock_get_service_packs.return_value = ( + { + "test_path" : ("mlcpuv1", "3.6"), + }, + { + "mlcpuv1" : ("test_path", "3.6"), + } + ) with pytest.warns(UserWarning, match="not a service pack"): TrainingEnvInfo.from_slug( "not_exist", namespace="ociodscdev", bucketname="service-conda-packs" @@ -256,7 +265,16 @@ def test_from_slug_prod_sp(self): info.inference_env_type = "service_pack" info.inference_python_version = "3.6" - def test_from_slug_not_exist(self): + @patch("ads.model.runtime.env_info.get_service_packs") + def test_from_slug_not_exist(self, mock_get_service_packs): + mock_get_service_packs.return_value = ( + { + "test_path" : ("mlcpuv1", "3.6"), + }, + { + "mlcpuv1" : ("test_path", "3.6"), + } + ) with pytest.warns(UserWarning, match="not a service pack"): InferenceEnvInfo.from_slug( "not_exist", namespace="ociodscdev", bucketname="service-conda-packs" diff --git a/tests/unitary/with_extras/model/test_generic_model.py b/tests/unitary/with_extras/model/test_generic_model.py index 7773b8a84..527a2528c 100644 --- a/tests/unitary/with_extras/model/test_generic_model.py +++ b/tests/unitary/with_extras/model/test_generic_model.py @@ -279,14 +279,29 @@ def test_prepare_fail(self, mock_handle_model_file_name): "oci://service-conda-packs@ociodscdev/service_pack/cpu/General_Machine_Learning_for_CPUs/1.0/mlcpuv1" ) + @patch("ads.model.runtime.env_info.get_service_packs") @patch("ads.common.auth.default_signer") - def test_prepare_both_conda_env(self, mock_signer): + def test_prepare_both_conda_env(self, mock_signer, mock_get_service_packs): """prepare a model by only providing inference conda env.""" + inference_conda_env="oci://service-conda-packs@ociodscdev/service_pack/cpu/General_Machine_Learning_for_CPUs/1.0/mlcpuv1" + inference_python_version="3.6" + training_conda_env="oci://service-conda-packs@ociodscdev/service_pack/cpu/Oracle_Database_for_CPU_Python_3.7/1.0/database_p37_cpu_v1" + training_python_version="3.7" + mock_get_service_packs.return_value = ( + { + inference_conda_env : ("mlcpuv1", inference_python_version), + training_conda_env : ("database_p37_cpu_v1", training_python_version) + }, + { + "mlcpuv1" : (inference_conda_env, inference_python_version), + "database_p37_cpu_v1" : (training_conda_env, training_python_version) + } + ) self.generic_model.prepare( - inference_conda_env="oci://service-conda-packs@ociodscdev/service_pack/cpu/General_Machine_Learning_for_CPUs/1.0/mlcpuv1", - inference_python_version="3.6", - training_conda_env="oci://service-conda-packs@ociodscdev/service_pack/cpu/Oracle_Database_for_CPU_Python_3.7/1.0/database_p37_cpu_v1", - training_python_version="3.7", + inference_conda_env=inference_conda_env, + inference_python_version=inference_python_version, + training_conda_env=training_conda_env, + training_python_version=training_python_version, model_file_name="fake_model_name", force_overwrite=True, ) @@ -349,8 +364,19 @@ def test_reload(self): @patch.object(GenericModel, "_random_display_name", return_value="test_name") @patch.object(DataScienceModel, "create") - def test_save(self, mock_dsc_model_create, mock__random_display_name): + @patch("ads.model.runtime.env_info.get_service_packs") + def test_save(self, mock_get_service_packs, mock_dsc_model_create, mock__random_display_name): """test saving a model to artifact.""" + inference_conda_env="oci://service-conda-packs@ociodscdev/service_pack/cpu/Data_Exploration_and_Manipulation_for_CPU_Python_3.7/3.0/dataexpl_p37_cpu_v3" + inference_python_version="3.7" + mock_get_service_packs.return_value = ( + { + inference_conda_env : ("dataexpl_p37_cpu_v3", inference_python_version), + }, + { + "dataexpl_p37_cpu_v3" : (inference_conda_env, inference_python_version), + } + ) mock_dsc_model_create.return_value = MagicMock(id="fake_id") self.generic_model.prepare( inference_conda_env="dataexpl_p37_cpu_v3", @@ -371,8 +397,19 @@ def test_save(self, mock_dsc_model_create, mock__random_display_name): parallel_process_count=utils.DEFAULT_PARALLEL_PROCESS_COUNT, ) - def test_save_not_implemented_error(self): + @patch("ads.model.runtime.env_info.get_service_packs") + def test_save_not_implemented_error(self, mock_get_service_packs): """test saving a model to artifact.""" + inference_conda_env="oci://service-conda-packs@ociodscdev/service_pack/cpu/Data_Exploration_and_Manipulation_for_CPU_Python_3.7/3.0/dataexpl_p37_cpu_v3" + inference_python_version="3.7" + mock_get_service_packs.return_value = ( + { + inference_conda_env : ("dataexpl_p37_cpu_v3", inference_python_version), + }, + { + "dataexpl_p37_cpu_v3" : (inference_conda_env, inference_python_version), + } + ) self.generic_model._serialize = False self.generic_model.prepare( inference_conda_env="dataexpl_p37_cpu_v3", diff --git a/tests/unitary/with_extras/model/test_model_deployment_details.py b/tests/unitary/with_extras/model/test_model_deployment_details.py index e6122cb3f..eeb2a9de4 100644 --- a/tests/unitary/with_extras/model/test_model_deployment_details.py +++ b/tests/unitary/with_extras/model/test_model_deployment_details.py @@ -5,6 +5,7 @@ import os from unittest import TestCase +from unittest.mock import patch import yaml from ads.model.runtime.model_deployment_details import ModelDeploymentDetails @@ -27,7 +28,18 @@ def setUpClass(cls): with open(os.path.join(curr_dir, "runtime_fail.yaml"), encoding="utf-8") as rt: cls.runtime_dict_fail = yaml.load(rt, loader) - def test_from_dict(self): + @patch("ads.model.runtime.env_info.get_service_packs") + def test_from_dict(self, mock_get_service_packs): + inference_conda_env="oci://service-conda-packs@ociodscdev/service_pack/cpu/General_Machine_Learning_for_CPUs/1.0/mlcpuv1" + inference_python_version="3.6" + mock_get_service_packs.return_value = ( + { + inference_conda_env : ("mlcpuv1", inference_python_version), + }, + { + "mlcpuv1" : (inference_conda_env, inference_python_version), + } + ) model_deployment = ModelDeploymentDetails.from_dict( self.runtime_dict["MODEL_DEPLOYMENT"] ) diff --git a/tests/unitary/with_extras/model/test_model_metadata_mixin.py b/tests/unitary/with_extras/model/test_model_metadata_mixin.py index 520aab631..1cdfb162b 100644 --- a/tests/unitary/with_extras/model/test_model_metadata_mixin.py +++ b/tests/unitary/with_extras/model/test_model_metadata_mixin.py @@ -3,6 +3,7 @@ # Copyright (c) 2022, 2023 Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ +from unittest.mock import patch import numpy as np import pytest from sklearn import datasets, linear_model @@ -104,7 +105,19 @@ def test_metadata_generic_model_container_runtime(self): ) assert model.metadata_provenance.training_id is None - def test_metadata_sklearn_model(self): + @patch("ads.model.runtime.env_info.get_service_packs") + def test_metadata_sklearn_model(self, mock_get_service_packs): + conda_env="oci://service-conda-packs@ociodscdev/service_pack/cpu/Data_Exploration_and_Manipulation_for_CPU_Python_3.7/3.0/dataexpl_p37_cpu_v3" + python_version="3.7" + mock_get_service_packs.return_value = ( + { + conda_env : ("dataexpl_p37_cpu_v3", python_version), + }, + { + "dataexpl_p37_cpu_v3" : (conda_env, python_version), + + } + ) model = SklearnModel(self.rgr, artifact_dir="./test_sklearn") model.prepare( inference_conda_env="dataexpl_p37_cpu_v3", @@ -146,7 +159,19 @@ def test_metadata_sklearn_model(self): ) assert model.metadata_provenance.training_id is None - def test_metadata_xgboost_model(self): + @patch("ads.model.runtime.env_info.get_service_packs") + def test_metadata_xgboost_model(self, mock_get_service_packs): + conda_env="oci://service-conda-packs@ociodscdev/service_pack/cpu/Data_Exploration_and_Manipulation_for_CPU_Python_3.7/3.0/dataexpl_p37_cpu_v3" + python_version="3.7" + mock_get_service_packs.return_value = ( + { + conda_env : ("dataexpl_p37_cpu_v3", python_version), + }, + { + "dataexpl_p37_cpu_v3" : (conda_env, python_version), + + } + ) model = XGBoostModel(self.xgb_rgr, artifact_dir="./test_xgboost") model.prepare( inference_conda_env="dataexpl_p37_cpu_v3", diff --git a/tests/unitary/with_extras/model/test_model_provenance_details.py b/tests/unitary/with_extras/model/test_model_provenance_details.py index 299443410..499be7c19 100644 --- a/tests/unitary/with_extras/model/test_model_provenance_details.py +++ b/tests/unitary/with_extras/model/test_model_provenance_details.py @@ -4,6 +4,7 @@ # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ import os +from unittest.mock import patch import yaml from ads.model.runtime.model_provenance_details import ( @@ -57,8 +58,19 @@ def setup_class(cls): with open(os.path.join(curr_dir, "runtime_fail.yaml"), encoding="utf-8") as rt: cls.runtime_dict_fail = yaml.load(rt, loader) - def test_from_dict(self): - + @patch("ads.model.runtime.env_info.get_service_packs") + def test_from_dict(self, mock_get_service_packs): + conda_env="oci://service_conda_packs@ociodscdev/service_pack/cpu/General_Machine_Learning_for_CPUs/1.0/mlcpuv1" + python_version="3.6" + mock_get_service_packs.return_value = ( + { + conda_env : ("mlcpuv1", python_version), + }, + { + "mlcpuv1" : (conda_env, python_version), + + } + ) model_provenance = ModelProvenanceDetails.from_dict( self.runtime_dict["MODEL_PROVENANCE"] ) diff --git a/tests/unitary/with_extras/model/test_runtime_info.py b/tests/unitary/with_extras/model/test_runtime_info.py index c4da7f6be..2297a1f2b 100644 --- a/tests/unitary/with_extras/model/test_runtime_info.py +++ b/tests/unitary/with_extras/model/test_runtime_info.py @@ -36,7 +36,19 @@ def test__validate_dict_fail(self): with pytest.raises(AssertionError): RuntimeInfo._validate_dict(self.runtime_dict_fail) - def test_from_yaml(self): + @patch("ads.model.runtime.env_info.get_service_packs") + def test_from_yaml(self, mock_get_service_packs): + conda_env="oci://service_conda_packs@ociodscdev/service_pack/cpu/General_Machine_Learning_for_CPUs/1.0/mlcpuv1" + python_version="3.6" + mock_get_service_packs.return_value = ( + { + conda_env : ("mlcpuv1", python_version), + }, + { + "mlcpuv1" : (conda_env, python_version), + + } + ) runtime_info = RuntimeInfo.from_yaml( uri=os.path.join(self.curr_dir, "runtime.yaml") ) @@ -95,7 +107,19 @@ def test_from_yaml(self): @patch.object(InferenceEnvInfo, "_validate", side_effect=DocumentError) @patch.object(TrainingEnvInfo, "_validate", side_effect=DocumentError) - def test_from_yaml_fail(self, mock_inference, mock_training): + @patch("ads.model.runtime.env_info.get_service_packs") + def test_from_yaml_fail(self, mock_get_service_packs, mock_inference, mock_training): + conda_env="oci://service_conda_packs@ociodscdev/service_pack/cpu/General_Machine_Learning_for_CPUs/1.0/mlcpuv1" + python_version="3.6" + mock_get_service_packs.return_value = ( + { + conda_env : ("mlcpuv1", python_version), + }, + { + "mlcpuv1" : (conda_env, python_version), + + } + ) with pytest.raises(DocumentError): RuntimeInfo.from_yaml(uri=os.path.join(self.curr_dir, "runtime_fail.yaml")) @@ -119,7 +143,19 @@ def test_from_yaml_wrong_format(self, mock_provenance, mock_deployment): with pytest.raises(FileNotFoundError): RuntimeInfo.from_yaml(uri=os.path.join(self.curr_dir, "fake.yaml")) - def test_from_and_to_yaml_file(self): + @patch("ads.model.runtime.env_info.get_service_packs") + def test_from_and_to_yaml_file(self, mock_get_service_packs): + conda_env="oci://service_conda_packs@ociodscdev/service_pack/cpu/General_Machine_Learning_for_CPUs/1.0/mlcpuv1" + python_version="3.6" + mock_get_service_packs.return_value = ( + { + conda_env : ("mlcpuv1", python_version), + }, + { + "mlcpuv1" : (conda_env, python_version), + + } + ) runtime = RuntimeInfo.from_yaml(uri=os.path.join(self.curr_dir, "runtime.yaml")) runtime.to_yaml(uri=os.path.join(self.curr_dir, "runtime_copy.yaml")) runtime_copy = RuntimeInfo.from_yaml( From 06a37f05048139cab0389078ab010c7432a40b10 Mon Sep 17 00:00:00 2001 From: Lu Peng Date: Wed, 20 Sep 2023 18:38:05 -0400 Subject: [PATCH 2/4] Updated pr. --- tests/unitary/with_extras/model/test_generic_model.py | 2 +- tests/unitary/with_extras/model/test_model_metadata_mixin.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unitary/with_extras/model/test_generic_model.py b/tests/unitary/with_extras/model/test_generic_model.py index 527a2528c..afe1f9f8a 100644 --- a/tests/unitary/with_extras/model/test_generic_model.py +++ b/tests/unitary/with_extras/model/test_generic_model.py @@ -386,7 +386,7 @@ def test_save(self, mock_get_service_packs, mock_dsc_model_create, mock__random_ force_overwrite=True, training_id=None, ) - self.generic_model.save() + self.generic_model.save(ignore_introspection=True) assert self.generic_model.model_id is not None and isinstance( self.generic_model.model_id, str ) diff --git a/tests/unitary/with_extras/model/test_model_metadata_mixin.py b/tests/unitary/with_extras/model/test_model_metadata_mixin.py index 1cdfb162b..ad9b41f7e 100644 --- a/tests/unitary/with_extras/model/test_model_metadata_mixin.py +++ b/tests/unitary/with_extras/model/test_model_metadata_mixin.py @@ -217,7 +217,7 @@ def test_metadata_xgboost_model(self, mock_get_service_packs): assert model.metadata_provenance.training_id is None assert ( model.runtime_info.model_deployment.inference_conda_env.inference_env_path - == "oci://service-conda-packs@id19sfcrra6z/service_pack/cpu/Data_Exploration_and_Manipulation_for_CPU_Python_3.7/3.0/dataexpl_p37_cpu_v3" + == "oci://service-conda-packs@ociodscdev/service_pack/cpu/Data_Exploration_and_Manipulation_for_CPU_Python_3.7/3.0/dataexpl_p37_cpu_v3" ) def teardown_method(self): From 24b326251b4b6f78c868ad591e54c9073faa39b4 Mon Sep 17 00:00:00 2001 From: Lu Peng Date: Wed, 20 Sep 2023 18:40:58 -0400 Subject: [PATCH 3/4] Updated pr. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 28560e6e0..045599f60 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,7 +57,7 @@ dependencies = [ "asteval>=0.9.25", "cerberus>=1.3.4", "cloudpickle>=1.6.0", - "fsspec>=0.8.7", + "fsspec>=0.8.7,<2023.9.1", # v2.9.1 introduced issues, releved by unit tests "gitpython>=3.1.2", "jinja2>=2.11.2", "matplotlib>=3.1.3", From c174d72b6b9243f0c20b4dd51bf2e2c83df922f1 Mon Sep 17 00:00:00 2001 From: Lu Peng Date: Thu, 21 Sep 2023 12:20:31 -0400 Subject: [PATCH 4/4] Fixed issue caused by https://github.com/microsoft/onnxruntime/issues/17631. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 045599f60..f5700f404 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -109,7 +109,7 @@ onnx = [ "lightgbm==3.3.1", "onnx>=1.12.0", "onnxmltools>=1.10.0", - "onnxruntime>=1.10.0", + "onnxruntime>=1.10.0,<1.16", # v1.16 introduced issues https://github.com/microsoft/onnxruntime/issues/17631, releved by unit tests "oracle_ads[viz]", "protobuf<=3.20", "skl2onnx>=1.10.4",