From 7e04aaf53f7ed743ae7cdfc0b730e454275774ca Mon Sep 17 00:00:00 2001 From: Lu Peng Date: Mon, 13 Nov 2023 00:49:17 -0500 Subject: [PATCH 1/9] Fixed model deployment failed return value. --- ads/model/deployment/model_deployment.py | 104 ++++++++++-------- ads/model/generic_model.py | 66 ++++++----- .../oci_datascience_model_deployment.py | 12 +- .../test_model_deployment_v2.py | 39 ------- 4 files changed, 104 insertions(+), 117 deletions(-) diff --git a/ads/model/deployment/model_deployment.py b/ads/model/deployment/model_deployment.py index efc63db78..a439e4662 100644 --- a/ads/model/deployment/model_deployment.py +++ b/ads/model/deployment/model_deployment.py @@ -85,7 +85,7 @@ class LogNotConfiguredError(Exception): # pragma: no cover pass -class ModelDeploymentFailedError(Exception): # pragma: no cover +class ModelDeploymentPredictError(Exception): # pragma: no cover pass @@ -607,11 +607,6 @@ def deploy( ------- ModelDeployment The instance of ModelDeployment. - - Raises - ------ - ModelDeploymentFailedError - If model deployment fails to deploy """ create_model_deployment_details = ( self._build_model_deployment_details() @@ -619,19 +614,17 @@ def deploy( else self.properties.build() ) - response = self.dsc_model_deployment.create( - create_model_deployment_details=create_model_deployment_details, - wait_for_completion=wait_for_completion, - max_wait_time=max_wait_time, - poll_interval=poll_interval, - ) - - if response.lifecycle_state == State.FAILED.name: - raise ModelDeploymentFailedError( - f"Model deployment {response.id} failed to deploy: {response.lifecycle_details}" + try: + response = self.dsc_model_deployment.create( + create_model_deployment_details=create_model_deployment_details, + wait_for_completion=wait_for_completion, + max_wait_time=max_wait_time, + poll_interval=poll_interval, ) - - return self._update_from_oci_model(response) + except: + raise + finally: + return self._update_from_oci_model(response) def delete( self, @@ -657,12 +650,16 @@ def delete( ModelDeployment The instance of ModelDeployment. """ - response = self.dsc_model_deployment.delete( - wait_for_completion=wait_for_completion, - max_wait_time=max_wait_time, - poll_interval=poll_interval, - ) - return self._update_from_oci_model(response) + try: + response = self.dsc_model_deployment.delete( + wait_for_completion=wait_for_completion, + max_wait_time=max_wait_time, + poll_interval=poll_interval, + ) + except: + raise + finally: + return self._update_from_oci_model(response) def update( self, @@ -718,14 +715,17 @@ def update( else self._update_model_deployment_details(**kwargs) ) - response = self.dsc_model_deployment.update( - update_model_deployment_details=update_model_deployment_details, - wait_for_completion=wait_for_completion, - max_wait_time=max_wait_time, - poll_interval=poll_interval, - ) - - return self._update_from_oci_model(response) + try: + response = self.dsc_model_deployment.update( + update_model_deployment_details=update_model_deployment_details, + wait_for_completion=wait_for_completion, + max_wait_time=max_wait_time, + poll_interval=poll_interval, + ) + except: + raise + finally: + return self._update_from_oci_model(response) def watch( self, @@ -890,6 +890,10 @@ def predict( Prediction results. """ + if self.sync().lifecycle_state != "ACTIVE": + raise ModelDeploymentPredictError( + "Model Deployment must be in `ACTIVE` state before predict can be called." + ) endpoint = f"{self.url}/predict" signer = authutil.default_signer()["signer"] header = { @@ -953,7 +957,7 @@ def predict( except oci.exceptions.ServiceError as ex: # When bandwidth exceeds the allocated value, TooManyRequests error (429) will be raised by oci backend. if ex.status == 429: - bandwidth_mbps = self.infrastructure.bandwidth_mbps or MODEL_DEPLOYMENT_BANDWIDTH_MBPS + bandwidth_mbps = self.infrastructure.bandwidth_mbps or DEFAULT_BANDWIDTH_MBPS utils.get_logger().warning( f"Load balancer bandwidth exceeds the allocated {bandwidth_mbps} Mbps." "To estimate the actual bandwidth, use formula: (payload size in KB) * (estimated requests per second) * 8 / 1024." @@ -985,13 +989,16 @@ def activate( ModelDeployment The instance of ModelDeployment. """ - response = self.dsc_model_deployment.activate( - wait_for_completion=wait_for_completion, - max_wait_time=max_wait_time, - poll_interval=poll_interval, - ) - - return self._update_from_oci_model(response) + try: + response = self.dsc_model_deployment.activate( + wait_for_completion=wait_for_completion, + max_wait_time=max_wait_time, + poll_interval=poll_interval, + ) + except: + raise + finally: + return self._update_from_oci_model(response) def deactivate( self, @@ -1017,13 +1024,16 @@ def deactivate( ModelDeployment The instance of ModelDeployment. """ - response = self.dsc_model_deployment.deactivate( - wait_for_completion=wait_for_completion, - max_wait_time=max_wait_time, - poll_interval=poll_interval, - ) - - return self._update_from_oci_model(response) + try: + response = self.dsc_model_deployment.deactivate( + wait_for_completion=wait_for_completion, + max_wait_time=max_wait_time, + poll_interval=poll_interval, + ) + except: + raise + finally: + return self._update_from_oci_model(response) def _log_details(self, log_type: str = ModelDeploymentLogType.ACCESS): """Gets log details for the provided `log_type`. diff --git a/ads/model/generic_model.py b/ads/model/generic_model.py index 7ec241c1d..8cd0c831f 100644 --- a/ads/model/generic_model.py +++ b/ads/model/generic_model.py @@ -2315,16 +2315,20 @@ def deploy( .with_runtime(runtime) ) - self.model_deployment = model_deployment.deploy( - wait_for_completion=wait_for_completion, - max_wait_time=max_wait_time, - poll_interval=poll_interval, - ) - self._summary_status.update_status( - detail="Deployed the model", - status=self.model_deployment.state.name.upper(), - ) - return self.model_deployment + try: + self.model_deployment = model_deployment.deploy( + wait_for_completion=wait_for_completion, + max_wait_time=max_wait_time, + poll_interval=poll_interval, + ) + self._summary_status.update_status( + detail="Deployed the model", + status=self.model_deployment.state.name.upper(), + ) + except: + raise + finally: + return self.model_deployment def prepare_save_deploy( self, @@ -2792,25 +2796,29 @@ def restart_deployment( """ if not self.model_deployment: raise ValueError("Use `deploy()` method to start model deployment.") - logger.info( - f"Deactivating model deployment {self.model_deployment.model_deployment_id}." - ) - self.model_deployment.deactivate( - max_wait_time=max_wait_time, poll_interval=poll_interval - ) - logger.info( - f"Model deployment {self.model_deployment.model_deployment_id} has successfully been deactivated." - ) - logger.info( - f"Activating model deployment {self.model_deployment.model_deployment_id}." - ) - self.model_deployment.activate( - max_wait_time=max_wait_time, poll_interval=poll_interval - ) - logger.info( - f"Model deployment {self.model_deployment.model_deployment_id} has successfully been activated." - ) - return self.model_deployment + try: + logger.info( + f"Deactivating model deployment {self.model_deployment.model_deployment_id}." + ) + self.model_deployment.deactivate( + max_wait_time=max_wait_time, poll_interval=poll_interval + ) + logger.info( + f"Model deployment {self.model_deployment.model_deployment_id} has successfully been deactivated." + ) + logger.info( + f"Activating model deployment {self.model_deployment.model_deployment_id}." + ) + self.model_deployment.activate( + max_wait_time=max_wait_time, poll_interval=poll_interval + ) + logger.info( + f"Model deployment {self.model_deployment.model_deployment_id} has successfully been activated." + ) + except: + raise + finally: + return self.model_deployment @class_or_instance_method def delete( diff --git a/ads/model/service/oci_datascience_model_deployment.py b/ads/model/service/oci_datascience_model_deployment.py index fc1d9bf2e..815934d52 100644 --- a/ads/model/service/oci_datascience_model_deployment.py +++ b/ads/model/service/oci_datascience_model_deployment.py @@ -212,6 +212,8 @@ def activate( f"Error while trying to activate model deployment: {self.id}" ) raise e + finally: + return self.sync() return self.sync() else: @@ -264,6 +266,8 @@ def create( f"Error while trying to create model deployment: {self.id}" ) raise e + finally: + return self.sync() return self.sync() @@ -328,6 +332,8 @@ def deactivate( f"Error while trying to deactivate model deployment: {self.id}" ) raise e + finally: + return self.sync() return self.sync() else: @@ -399,6 +405,8 @@ def delete( f"Error while trying to delete model deployment: {self.id}" ) raise e + finally: + return self.sync() return self.sync() @@ -454,8 +462,8 @@ def update( except Exception as e: logger.error(f"Error while trying to update model deployment: {self.id}") raise e - - return self.sync() + finally: + return self.sync() @classmethod def list( diff --git a/tests/unitary/default_setup/model_deployment/test_model_deployment_v2.py b/tests/unitary/default_setup/model_deployment/test_model_deployment_v2.py index ab637eecf..4d1efee7c 100644 --- a/tests/unitary/default_setup/model_deployment/test_model_deployment_v2.py +++ b/tests/unitary/default_setup/model_deployment/test_model_deployment_v2.py @@ -21,7 +21,6 @@ from ads.model.deployment.model_deployment import ( ModelDeployment, ModelDeploymentLogType, - ModelDeploymentFailedError, ) from ads.model.deployment.model_deployment_infrastructure import ( ModelDeploymentInfrastructure, @@ -1148,44 +1147,6 @@ def test_deploy( mock_create_model_deployment.assert_called_with(create_model_deployment_details) mock_sync.assert_called() - @patch.object(OCIDataScienceMixin, "sync") - @patch.object( - oci.data_science.DataScienceClient, - "create_model_deployment", - ) - @patch.object(DataScienceModel, "create") - def test_deploy_failed( - self, mock_create, mock_create_model_deployment, mock_sync - ): - dsc_model = MagicMock() - dsc_model.id = "fakeid.datasciencemodel.oc1.iad.xxx" - mock_create.return_value = dsc_model - response = oci.response.Response( - status=MagicMock(), - headers=MagicMock(), - request=MagicMock(), - data=oci.data_science.models.ModelDeployment( - id="test_model_deployment_id", - lifecycle_state="FAILED", - lifecycle_details="The specified log object is not found or user is not authorized.", - ), - ) - mock_sync.return_value = response.data - model_deployment = self.initialize_model_deployment() - create_model_deployment_details = ( - model_deployment._build_model_deployment_details() - ) - with pytest.raises( - ModelDeploymentFailedError, - match=f"Model deployment {response.data.id} failed to deploy: {response.data.lifecycle_details}", - ): - model_deployment.deploy(wait_for_completion=False) - mock_create.assert_called() - mock_create_model_deployment.assert_called_with( - create_model_deployment_details - ) - mock_sync.assert_called() - @patch.object( OCIDataScienceModelDeployment, "activate", From 731dc71f81d9a5ad25af5b7024c4df3cb14c5426 Mon Sep 17 00:00:00 2001 From: Lu Peng Date: Mon, 13 Nov 2023 10:07:37 -0500 Subject: [PATCH 2/9] Updated pr. --- ads/model/deployment/model_deployment.py | 20 ++++++++++---------- ads/model/generic_model.py | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ads/model/deployment/model_deployment.py b/ads/model/deployment/model_deployment.py index a439e4662..c30d3199d 100644 --- a/ads/model/deployment/model_deployment.py +++ b/ads/model/deployment/model_deployment.py @@ -621,8 +621,8 @@ def deploy( max_wait_time=max_wait_time, poll_interval=poll_interval, ) - except: - raise + except Exception as ex: + raise ex finally: return self._update_from_oci_model(response) @@ -656,8 +656,8 @@ def delete( max_wait_time=max_wait_time, poll_interval=poll_interval, ) - except: - raise + except Exception as ex: + raise ex finally: return self._update_from_oci_model(response) @@ -722,8 +722,8 @@ def update( max_wait_time=max_wait_time, poll_interval=poll_interval, ) - except: - raise + except Exception as ex: + raise ex finally: return self._update_from_oci_model(response) @@ -995,8 +995,8 @@ def activate( max_wait_time=max_wait_time, poll_interval=poll_interval, ) - except: - raise + except Exception as ex: + raise ex finally: return self._update_from_oci_model(response) @@ -1030,8 +1030,8 @@ def deactivate( max_wait_time=max_wait_time, poll_interval=poll_interval, ) - except: - raise + except Exception as ex: + raise ex finally: return self._update_from_oci_model(response) diff --git a/ads/model/generic_model.py b/ads/model/generic_model.py index 8cd0c831f..6f4c121d1 100644 --- a/ads/model/generic_model.py +++ b/ads/model/generic_model.py @@ -2325,8 +2325,8 @@ def deploy( detail="Deployed the model", status=self.model_deployment.state.name.upper(), ) - except: - raise + except Exception as ex: + raise ex finally: return self.model_deployment @@ -2815,8 +2815,8 @@ def restart_deployment( logger.info( f"Model deployment {self.model_deployment.model_deployment_id} has successfully been activated." ) - except: - raise + except Exception as ex: + raise ex finally: return self.model_deployment From d6b6b4257f8a654d2c992f98fabdfbf13f146916 Mon Sep 17 00:00:00 2001 From: Lu Peng Date: Mon, 13 Nov 2023 10:32:52 -0500 Subject: [PATCH 3/9] Updated pr. --- ads/model/deployment/model_deployment.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ads/model/deployment/model_deployment.py b/ads/model/deployment/model_deployment.py index c30d3199d..1bf1b17ab 100644 --- a/ads/model/deployment/model_deployment.py +++ b/ads/model/deployment/model_deployment.py @@ -890,9 +890,11 @@ def predict( Prediction results. """ - if self.sync().lifecycle_state != "ACTIVE": + current_state = self.sync().lifecycle_state + if current_state != "ACTIVE": raise ModelDeploymentPredictError( - "Model Deployment must be in `ACTIVE` state before predict can be called." + f"Predict() can't be called when model deployment is in {current_state} state. " + "Make sure model deployment is `ACTIVE` before calling predict." ) endpoint = f"{self.url}/predict" signer = authutil.default_signer()["signer"] From 7a53130ac5fc1f908e67d395c5dfc192603d15c8 Mon Sep 17 00:00:00 2001 From: Lu Peng Date: Mon, 13 Nov 2023 10:33:39 -0500 Subject: [PATCH 4/9] Updated pr. --- ads/model/deployment/model_deployment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ads/model/deployment/model_deployment.py b/ads/model/deployment/model_deployment.py index 1bf1b17ab..31da5188d 100644 --- a/ads/model/deployment/model_deployment.py +++ b/ads/model/deployment/model_deployment.py @@ -893,7 +893,7 @@ def predict( current_state = self.sync().lifecycle_state if current_state != "ACTIVE": raise ModelDeploymentPredictError( - f"Predict() can't be called when model deployment is in {current_state} state. " + f"Predict() can't be called when model deployment is `{current_state}`. " "Make sure model deployment is `ACTIVE` before calling predict." ) endpoint = f"{self.url}/predict" From 286af833fa0c458b83fa77eb825713251a9baef6 Mon Sep 17 00:00:00 2001 From: Lu Peng <118394507+lu-ohai@users.noreply.github.com> Date: Mon, 13 Nov 2023 13:55:48 -0500 Subject: [PATCH 5/9] Update generic_model.py --- ads/model/generic_model.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ads/model/generic_model.py b/ads/model/generic_model.py index 6f4c121d1..622abbc52 100644 --- a/ads/model/generic_model.py +++ b/ads/model/generic_model.py @@ -1574,7 +1574,10 @@ def from_model_deployment( current_state = model_deployment.state.name.upper() if current_state != ModelDeploymentState.ACTIVE.name: - raise NotActiveDeploymentError(current_state) + logger.warning( + "Model deployment should be in `ACTIVE` state while being fetched. " + f"Current model deployment state: `{current_state}`" + ) model = cls.from_model_catalog( model_id=model_deployment.properties.model_id, From 3ad2e7398ebb46af57eda2cbe857bab8098397bd Mon Sep 17 00:00:00 2001 From: Lu Peng <118394507+lu-ohai@users.noreply.github.com> Date: Mon, 13 Nov 2023 15:54:22 -0500 Subject: [PATCH 6/9] Update generic_model.py --- ads/model/generic_model.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ads/model/generic_model.py b/ads/model/generic_model.py index 622abbc52..8cf96f98f 100644 --- a/ads/model/generic_model.py +++ b/ads/model/generic_model.py @@ -2324,13 +2324,13 @@ def deploy( max_wait_time=max_wait_time, poll_interval=poll_interval, ) + except Exception as ex: + raise ex + finally: self._summary_status.update_status( detail="Deployed the model", status=self.model_deployment.state.name.upper(), ) - except Exception as ex: - raise ex - finally: return self.model_deployment def prepare_save_deploy( From 5cfdb4f392f867b019ab9b068f80bb89ba1382d4 Mon Sep 17 00:00:00 2001 From: Lu Peng Date: Mon, 13 Nov 2023 23:22:53 -0500 Subject: [PATCH 7/9] Fixed unit test. --- .../model_deployment/test_model_deployment.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/unitary/default_setup/model_deployment/test_model_deployment.py b/tests/unitary/default_setup/model_deployment/test_model_deployment.py index 9018e7729..25fb0e07b 100644 --- a/tests/unitary/default_setup/model_deployment/test_model_deployment.py +++ b/tests/unitary/default_setup/model_deployment/test_model_deployment.py @@ -28,8 +28,10 @@ class ModelDeploymentTestCase(unittest.TestCase): ) @patch("requests.post") - def test_predict(self, mock_post): + @patch("ads.model.deployment.model_deployment.ModelDeployment.sync") + def test_predict(self, mock_sync, mock_post): """Ensures predict model passes with valid input parameters.""" + mock_sync.return_value = Mock(lifecycle_state="ACTIVE") mock_post.return_value = Mock( status_code=200, json=lambda: {"result": "result"} ) @@ -50,8 +52,10 @@ def test_predict(self, mock_post): self.test_model_deployment.predict(data=np.array([1, 2, 3])) @patch("requests.post") - def test_predict_with_bytes(self, mock_post): + @patch("ads.model.deployment.model_deployment.ModelDeployment.sync") + def test_predict_with_bytes(self, mock_sync, mock_post): """Ensures predict model passes with bytes input.""" + mock_sync.return_value = Mock(lifecycle_state="ACTIVE") byte_data = b"[[1,2,3,4]]" with patch.object(authutil, "default_signer") as mock_auth: auth = MagicMock() @@ -66,8 +70,10 @@ def test_predict_with_bytes(self, mock_post): ) @patch("requests.post") - def test_predict_with_auto_serialize_data(self, mock_post): + @patch("ads.model.deployment.model_deployment.ModelDeployment.sync") + def test_predict_with_auto_serialize_data(self, mock_sync, mock_post): """Ensures predict model passes with valid input parameters.""" + mock_sync.return_value = Mock(lifecycle_state="ACTIVE") mock_post.return_value = Mock( status_code=200, json=lambda: {"result": "result"} ) From 35af9cdb12eeed94d4df1d9e2132d3d5d61f7f8f Mon Sep 17 00:00:00 2001 From: Lu Peng Date: Tue, 14 Nov 2023 00:02:37 -0500 Subject: [PATCH 8/9] Fixed unit test. --- .../with_extras/model/test_generic_model.py | 39 ------------------- 1 file changed, 39 deletions(-) diff --git a/tests/unitary/with_extras/model/test_generic_model.py b/tests/unitary/with_extras/model/test_generic_model.py index afe1f9f8a..c115dc8dd 100644 --- a/tests/unitary/with_extras/model/test_generic_model.py +++ b/tests/unitary/with_extras/model/test_generic_model.py @@ -1051,45 +1051,6 @@ def test_from_model_deployment( assert test_result == test_model - @patch.object( - ModelDeployment, - "state", - new_callable=PropertyMock, - return_value=ModelDeploymentState.FAILED, - ) - @patch.object(ModelDeployment, "from_id") - @patch("ads.common.auth.default_signer") - @patch("ads.common.oci_client.OCIClientFactory") - def test_from_model_deployment_fail( - self, - mock_client, - mock_default_signer, - mock_from_id, - mock_model_deployment_state, - ): - """Tests loading model from model deployment.""" - test_auth_config = {"signer": {"config": "value"}} - mock_default_signer.return_value = test_auth_config - test_model_deployment_id = "md_ocid" - test_model_id = "model_ocid" - md_props = ModelDeploymentProperties(model_id=test_model_id) - md = ModelDeployment(properties=md_props) - mock_from_id.return_value = md - - with pytest.raises(NotActiveDeploymentError): - GenericModel.from_model_deployment( - model_deployment_id=test_model_deployment_id, - model_file_name="test.pkl", - artifact_dir="test_dir", - auth=test_auth_config, - force_overwrite=True, - properties=None, - bucket_uri="test_bucket_uri", - remove_existing_artifact=True, - compartment_id="test_compartment_id", - ) - mock_from_id.assert_called_with(test_model_deployment_id) - @patch.object(ModelDeployment, "update") @patch.object(ModelDeployment, "from_id") @patch("ads.common.auth.default_signer") From fabd11ed78f8a9586c9842ebeb3487dd3d4cb5e7 Mon Sep 17 00:00:00 2001 From: Lu Peng Date: Tue, 14 Nov 2023 16:29:39 -0500 Subject: [PATCH 9/9] Updated pr. --- ads/model/deployment/model_deployment.py | 95 ++++++++----------- ads/model/generic_model.py | 68 ++++++------- .../oci_datascience_model_deployment.py | 29 ++---- 3 files changed, 79 insertions(+), 113 deletions(-) diff --git a/ads/model/deployment/model_deployment.py b/ads/model/deployment/model_deployment.py index 31da5188d..ac85b6b61 100644 --- a/ads/model/deployment/model_deployment.py +++ b/ads/model/deployment/model_deployment.py @@ -614,17 +614,14 @@ def deploy( else self.properties.build() ) - try: - response = self.dsc_model_deployment.create( - create_model_deployment_details=create_model_deployment_details, - wait_for_completion=wait_for_completion, - max_wait_time=max_wait_time, - poll_interval=poll_interval, - ) - except Exception as ex: - raise ex - finally: - return self._update_from_oci_model(response) + response = self.dsc_model_deployment.create( + create_model_deployment_details=create_model_deployment_details, + wait_for_completion=wait_for_completion, + max_wait_time=max_wait_time, + poll_interval=poll_interval, + ) + + return self._update_from_oci_model(response) def delete( self, @@ -650,16 +647,13 @@ def delete( ModelDeployment The instance of ModelDeployment. """ - try: - response = self.dsc_model_deployment.delete( - wait_for_completion=wait_for_completion, - max_wait_time=max_wait_time, - poll_interval=poll_interval, - ) - except Exception as ex: - raise ex - finally: - return self._update_from_oci_model(response) + response = self.dsc_model_deployment.delete( + wait_for_completion=wait_for_completion, + max_wait_time=max_wait_time, + poll_interval=poll_interval, + ) + + return self._update_from_oci_model(response) def update( self, @@ -715,17 +709,14 @@ def update( else self._update_model_deployment_details(**kwargs) ) - try: - response = self.dsc_model_deployment.update( - update_model_deployment_details=update_model_deployment_details, - wait_for_completion=wait_for_completion, - max_wait_time=max_wait_time, - poll_interval=poll_interval, - ) - except Exception as ex: - raise ex - finally: - return self._update_from_oci_model(response) + response = self.dsc_model_deployment.update( + update_model_deployment_details=update_model_deployment_details, + wait_for_completion=wait_for_completion, + max_wait_time=max_wait_time, + poll_interval=poll_interval, + ) + + return self._update_from_oci_model(response) def watch( self, @@ -891,10 +882,10 @@ def predict( """ current_state = self.sync().lifecycle_state - if current_state != "ACTIVE": + if current_state != State.ACTIVE.name: raise ModelDeploymentPredictError( - f"Predict() can't be called when model deployment is `{current_state}`. " - "Make sure model deployment is `ACTIVE` before calling predict." + "This model deployment is not in active state, you will not be able to use predict end point. " + f"Current model deployment state: {current_state} " ) endpoint = f"{self.url}/predict" signer = authutil.default_signer()["signer"] @@ -991,16 +982,13 @@ def activate( ModelDeployment The instance of ModelDeployment. """ - try: - response = self.dsc_model_deployment.activate( - wait_for_completion=wait_for_completion, - max_wait_time=max_wait_time, - poll_interval=poll_interval, - ) - except Exception as ex: - raise ex - finally: - return self._update_from_oci_model(response) + response = self.dsc_model_deployment.activate( + wait_for_completion=wait_for_completion, + max_wait_time=max_wait_time, + poll_interval=poll_interval, + ) + + return self._update_from_oci_model(response) def deactivate( self, @@ -1026,16 +1014,13 @@ def deactivate( ModelDeployment The instance of ModelDeployment. """ - try: - response = self.dsc_model_deployment.deactivate( - wait_for_completion=wait_for_completion, - max_wait_time=max_wait_time, - poll_interval=poll_interval, - ) - except Exception as ex: - raise ex - finally: - return self._update_from_oci_model(response) + response = self.dsc_model_deployment.deactivate( + wait_for_completion=wait_for_completion, + max_wait_time=max_wait_time, + poll_interval=poll_interval, + ) + + return self._update_from_oci_model(response) def _log_details(self, log_type: str = ModelDeploymentLogType.ACCESS): """Gets log details for the provided `log_type`. diff --git a/ads/model/generic_model.py b/ads/model/generic_model.py index 8cf96f98f..43d18f379 100644 --- a/ads/model/generic_model.py +++ b/ads/model/generic_model.py @@ -1575,7 +1575,7 @@ def from_model_deployment( current_state = model_deployment.state.name.upper() if current_state != ModelDeploymentState.ACTIVE.name: logger.warning( - "Model deployment should be in `ACTIVE` state while being fetched. " + "This model deployment is not in active state, you will not be able to use predict end point. " f"Current model deployment state: `{current_state}`" ) @@ -2318,20 +2318,16 @@ def deploy( .with_runtime(runtime) ) - try: - self.model_deployment = model_deployment.deploy( - wait_for_completion=wait_for_completion, - max_wait_time=max_wait_time, - poll_interval=poll_interval, - ) - except Exception as ex: - raise ex - finally: - self._summary_status.update_status( - detail="Deployed the model", - status=self.model_deployment.state.name.upper(), - ) - return self.model_deployment + self.model_deployment = model_deployment.deploy( + wait_for_completion=wait_for_completion, + max_wait_time=max_wait_time, + poll_interval=poll_interval, + ) + self._summary_status.update_status( + detail="Deployed the model", + status=self.model_deployment.state.name.upper(), + ) + return self.model_deployment def prepare_save_deploy( self, @@ -2799,29 +2795,25 @@ def restart_deployment( """ if not self.model_deployment: raise ValueError("Use `deploy()` method to start model deployment.") - try: - logger.info( - f"Deactivating model deployment {self.model_deployment.model_deployment_id}." - ) - self.model_deployment.deactivate( - max_wait_time=max_wait_time, poll_interval=poll_interval - ) - logger.info( - f"Model deployment {self.model_deployment.model_deployment_id} has successfully been deactivated." - ) - logger.info( - f"Activating model deployment {self.model_deployment.model_deployment_id}." - ) - self.model_deployment.activate( - max_wait_time=max_wait_time, poll_interval=poll_interval - ) - logger.info( - f"Model deployment {self.model_deployment.model_deployment_id} has successfully been activated." - ) - except Exception as ex: - raise ex - finally: - return self.model_deployment + logger.info( + f"Deactivating model deployment {self.model_deployment.model_deployment_id}." + ) + self.model_deployment.deactivate( + max_wait_time=max_wait_time, poll_interval=poll_interval + ) + logger.info( + f"Model deployment {self.model_deployment.model_deployment_id} has successfully been deactivated." + ) + logger.info( + f"Activating model deployment {self.model_deployment.model_deployment_id}." + ) + self.model_deployment.activate( + max_wait_time=max_wait_time, poll_interval=poll_interval + ) + logger.info( + f"Model deployment {self.model_deployment.model_deployment_id} has successfully been activated." + ) + return self.model_deployment @class_or_instance_method def delete( diff --git a/ads/model/service/oci_datascience_model_deployment.py b/ads/model/service/oci_datascience_model_deployment.py index 815934d52..e522f65c4 100644 --- a/ads/model/service/oci_datascience_model_deployment.py +++ b/ads/model/service/oci_datascience_model_deployment.py @@ -209,11 +209,8 @@ def activate( ) except Exception as e: logger.error( - f"Error while trying to activate model deployment: {self.id}" + "Error while trying to activate model deployment: " + str(e) ) - raise e - finally: - return self.sync() return self.sync() else: @@ -263,11 +260,8 @@ def create( ) except Exception as e: logger.error( - f"Error while trying to create model deployment: {self.id}" + "Error while trying to create model deployment: " + str(e) ) - raise e - finally: - return self.sync() return self.sync() @@ -329,11 +323,8 @@ def deactivate( ) except Exception as e: logger.error( - f"Error while trying to deactivate model deployment: {self.id}" + "Error while trying to deactivate model deployment: " + str(e) ) - raise e - finally: - return self.sync() return self.sync() else: @@ -402,11 +393,8 @@ def delete( ) except Exception as e: logger.error( - f"Error while trying to delete model deployment: {self.id}" + "Error while trying to delete model deployment: " + str(e) ) - raise e - finally: - return self.sync() return self.sync() @@ -460,10 +448,11 @@ def update( ) self.workflow_req_id = response.headers.get("opc-work-request-id", None) except Exception as e: - logger.error(f"Error while trying to update model deployment: {self.id}") - raise e - finally: - return self.sync() + logger.error( + "Error while trying to update model deployment: " + str(e) + ) + + return self.sync() @classmethod def list(