Skip to content

Commit d710034

Browse files
support input tags for deployments
1 parent 1583829 commit d710034

File tree

3 files changed

+125
-85
lines changed

3 files changed

+125
-85
lines changed

ads/aqua/modeldeployment/deployment.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ def create(
110110
private_endpoint_id: Optional[str] = None,
111111
container_image_uri: Optional[None] = None,
112112
cmd_var: List[str] = None,
113+
freeform_tags: Optional[dict] = None,
114+
defined_tags: Optional[dict] = None,
113115
) -> "AquaDeployment":
114116
"""
115117
Creates a new Aqua deployment
@@ -163,6 +165,10 @@ def create(
163165
Required parameter for BYOC based deployments if this parameter was not set during model registration.
164166
cmd_var: List[str]
165167
The cmd of model deployment container runtime.
168+
freeform_tags: dict
169+
Freeform tags for the model deployment
170+
defined_tags: dict
171+
Defined tags for the model deployment
166172
Returns
167173
-------
168174
AquaDeployment
@@ -172,7 +178,11 @@ def create(
172178
# TODO validate if the service model has no artifact and if it requires import step before deployment.
173179
# Create a model catalog entry in the user compartment
174180
aqua_model = AquaModelApp().create(
175-
model_id=model_id, compartment_id=compartment_id, project_id=project_id
181+
model_id=model_id,
182+
compartment_id=compartment_id,
183+
project_id=project_id,
184+
freeform_tags=freeform_tags,
185+
defined_tags=defined_tags,
176186
)
177187

178188
tags = {}
@@ -418,12 +428,14 @@ def create(
418428
if cmd_var:
419429
container_runtime.with_cmd(cmd_var)
420430

431+
tags = {**tags, **(freeform_tags or {})}
421432
# configure model deployment and deploy model on container runtime
422433
deployment = (
423434
ModelDeployment()
424435
.with_display_name(display_name)
425436
.with_description(description)
426437
.with_freeform_tags(**tags)
438+
.with_defined_tags(**(defined_tags or {}))
427439
.with_infrastructure(infrastructure)
428440
.with_runtime(container_runtime)
429441
).deploy(wait_for_completion=False)

ads/aqua/modeldeployment/entities.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,12 @@ def from_oci_model_deployment(
9898
),
9999
)
100100

101-
freeform_tags = oci_model_deployment.freeform_tags or UNKNOWN_DICT
102-
aqua_service_model_tag = freeform_tags.get(Tags.AQUA_SERVICE_MODEL_TAG, None)
103-
aqua_model_name = freeform_tags.get(Tags.AQUA_MODEL_NAME_TAG, UNKNOWN)
101+
tags = {}
102+
tags.update(oci_model_deployment.freeform_tags or UNKNOWN_DICT)
103+
tags.update(oci_model_deployment.defined_tags or UNKNOWN_DICT)
104+
105+
aqua_service_model_tag = tags.get(Tags.AQUA_SERVICE_MODEL_TAG, None)
106+
aqua_model_name = tags.get(Tags.AQUA_MODEL_NAME_TAG, UNKNOWN)
104107
private_endpoint_id = getattr(
105108
instance_configuration, "private_endpoint_id", UNKNOWN
106109
)
@@ -125,7 +128,7 @@ def from_oci_model_deployment(
125128
ocid=oci_model_deployment.id,
126129
region=region,
127130
),
128-
tags=freeform_tags,
131+
tags=tags,
129132
environment_variables=environment_variables,
130133
cmd=cmd,
131134
)

tests/unitary/with_extras/aqua/test_deployment.py

Lines changed: 105 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,9 @@ def test_create_deployment_for_foundation_model(
469469

470470
self.app.get_deployment_config = MagicMock(return_value=config)
471471

472+
freeform_tags = {"ftag1": "fvalue1", "ftag2": "fvalue2"}
473+
defined_tags = {"dtag1": "dvalue1", "dtag2": "dvalue2"}
474+
472475
container_index_json = os.path.join(
473476
self.curr_dir, "test_data/ui/container_index.json"
474477
)
@@ -483,6 +486,8 @@ def test_create_deployment_for_foundation_model(
483486
model_deployment_obj = ModelDeployment.from_yaml(uri=aqua_deployment)
484487
model_deployment_dsc_obj = copy.deepcopy(TestDataset.model_deployment_object[0])
485488
model_deployment_dsc_obj["lifecycle_state"] = "CREATING"
489+
model_deployment_dsc_obj["defined_tags"] = defined_tags
490+
model_deployment_dsc_obj["freeform_tags"].update(freeform_tags)
486491
model_deployment_obj.dsc_model_deployment = (
487492
oci.data_science.models.ModelDeploymentSummary(**model_deployment_dsc_obj)
488493
)
@@ -495,10 +500,16 @@ def test_create_deployment_for_foundation_model(
495500
log_group_id="ocid1.loggroup.oc1.<region>.<OCID>",
496501
access_log_id="ocid1.log.oc1.<region>.<OCID>",
497502
predict_log_id="ocid1.log.oc1.<region>.<OCID>",
503+
freeform_tags=freeform_tags,
504+
defined_tags=defined_tags,
498505
)
499506

500507
mock_create.assert_called_with(
501-
model_id=TestDataset.MODEL_ID, compartment_id=None, project_id=None
508+
model_id=TestDataset.MODEL_ID,
509+
compartment_id=None,
510+
project_id=None,
511+
freeform_tags=freeform_tags,
512+
defined_tags=defined_tags,
502513
)
503514
mock_get_container_image.assert_called()
504515
mock_deploy.assert_called()
@@ -508,6 +519,8 @@ def test_create_deployment_for_foundation_model(
508519
assert set(actual_attributes) == set(expected_attributes), "Attributes mismatch"
509520
expected_result = copy.deepcopy(TestDataset.aqua_deployment_object)
510521
expected_result["state"] = "CREATING"
522+
expected_result["tags"].update(freeform_tags)
523+
expected_result["tags"].update(defined_tags)
511524
assert actual_attributes == expected_result
512525

513526
@patch("ads.aqua.modeldeployment.deployment.get_container_config")
@@ -566,7 +579,11 @@ def test_create_deployment_for_fine_tuned_model(
566579
)
567580

568581
mock_create.assert_called_with(
569-
model_id=TestDataset.MODEL_ID, compartment_id=None, project_id=None
582+
model_id=TestDataset.MODEL_ID,
583+
compartment_id=None,
584+
project_id=None,
585+
freeform_tags=None,
586+
defined_tags=None,
570587
)
571588
mock_get_container_image.assert_called()
572589
mock_deploy.assert_called()
@@ -638,7 +655,11 @@ def test_create_deployment_for_gguf_model(
638655
)
639656

640657
mock_create.assert_called_with(
641-
model_id=TestDataset.MODEL_ID, compartment_id=None, project_id=None
658+
model_id=TestDataset.MODEL_ID,
659+
compartment_id=None,
660+
project_id=None,
661+
freeform_tags=None,
662+
defined_tags=None,
642663
)
643664
mock_get_container_image.assert_called()
644665
mock_deploy.assert_called()
@@ -654,83 +675,87 @@ def test_create_deployment_for_gguf_model(
654675
)
655676
assert actual_attributes == expected_result
656677

657-
# @patch("ads.aqua.modeldeployment.deployment.get_container_config")
658-
# @patch("ads.aqua.model.AquaModelApp.create")
659-
# @patch("ads.aqua.modeldeployment.deployment.get_container_image")
660-
# @patch("ads.model.deployment.model_deployment.ModelDeployment.deploy")
661-
# def test_create_deployment_for_tei_byoc_embedding_model(
662-
# self,
663-
# mock_deploy,
664-
# mock_get_container_image,
665-
# mock_create,
666-
# mock_get_container_config,
667-
# ):
668-
# """Test to create a deployment for fine-tuned model"""
669-
# aqua_model = os.path.join(
670-
# self.curr_dir, "test_data/deployment/aqua_tei_byoc_embedding_model.yaml"
671-
# )
672-
# datascience_model = DataScienceModel.from_yaml(uri=aqua_model)
673-
# mock_create.return_value = datascience_model
674-
#
675-
# config_json = os.path.join(
676-
# self.curr_dir, "test_data/deployment/deployment_config.json"
677-
# )
678-
# with open(config_json, "r") as _file:
679-
# config = json.load(_file)
680-
#
681-
# self.app.get_deployment_config = MagicMock(return_value=config)
682-
#
683-
# container_index_json = os.path.join(
684-
# self.curr_dir, "test_data/ui/container_index.json"
685-
# )
686-
# with open(container_index_json, "r") as _file:
687-
# container_index_config = json.load(_file)
688-
# mock_get_container_config.return_value = container_index_config
689-
#
690-
# mock_get_container_image.return_value = TestDataset.DEPLOYMENT_IMAGE_NAME
691-
# aqua_deployment = os.path.join(
692-
# self.curr_dir, "test_data/deployment/aqua_create_embedding_deployment.yaml"
693-
# )
694-
# model_deployment_obj = ModelDeployment.from_yaml(uri=aqua_deployment)
695-
# model_deployment_dsc_obj = copy.deepcopy(
696-
# TestDataset.model_deployment_object_tei_byoc[0]
697-
# )
698-
# model_deployment_dsc_obj["lifecycle_state"] = "CREATING"
699-
# model_deployment_obj.dsc_model_deployment = (
700-
# oci.data_science.models.ModelDeploymentSummary(**model_deployment_dsc_obj)
701-
# )
702-
# mock_deploy.return_value = model_deployment_obj
703-
#
704-
# result = self.app.create(
705-
# model_id=TestDataset.MODEL_ID,
706-
# instance_shape=TestDataset.DEPLOYMENT_SHAPE_NAME,
707-
# display_name="model-deployment-name",
708-
# log_group_id="ocid1.loggroup.oc1.<region>.<OCID>",
709-
# access_log_id="ocid1.log.oc1.<region>.<OCID>",
710-
# predict_log_id="ocid1.log.oc1.<region>.<OCID>",
711-
# container_family="odsc-tei-serving",
712-
# cmd_var=[],
713-
# )
714-
#
715-
# mock_create.assert_called_with(
716-
# model_id=TestDataset.MODEL_ID, compartment_id=None, project_id=None
717-
# )
718-
# mock_get_container_image.assert_called()
719-
# mock_deploy.assert_called()
720-
#
721-
# expected_attributes = set(AquaDeployment.__annotations__.keys())
722-
# actual_attributes = asdict(result)
723-
# assert set(actual_attributes) == set(expected_attributes), "Attributes mismatch"
724-
# expected_result = copy.deepcopy(TestDataset.aqua_deployment_object)
725-
# expected_result["state"] = "CREATING"
726-
# expected_result["shape_info"] = (
727-
# TestDataset.aqua_deployment_tei_byoc_embeddings_shape_info
728-
# )
729-
# expected_result["cmd"] = TestDataset.aqua_deployment_tei_byoc_embeddings_cmd
730-
# expected_result["environment_variables"] = (
731-
# TestDataset.aqua_deployment_tei_byoc_embeddings_env_vars
732-
# )
733-
# assert actual_attributes == expected_result
678+
@patch("ads.aqua.modeldeployment.deployment.get_container_config")
679+
@patch("ads.aqua.model.AquaModelApp.create")
680+
@patch("ads.aqua.modeldeployment.deployment.get_container_image")
681+
@patch("ads.model.deployment.model_deployment.ModelDeployment.deploy")
682+
def test_create_deployment_for_tei_byoc_embedding_model(
683+
self,
684+
mock_deploy,
685+
mock_get_container_image,
686+
mock_create,
687+
mock_get_container_config,
688+
):
689+
"""Test to create a deployment for fine-tuned model"""
690+
aqua_model = os.path.join(
691+
self.curr_dir, "test_data/deployment/aqua_tei_byoc_embedding_model.yaml"
692+
)
693+
datascience_model = DataScienceModel.from_yaml(uri=aqua_model)
694+
mock_create.return_value = datascience_model
695+
696+
config_json = os.path.join(
697+
self.curr_dir, "test_data/deployment/deployment_config.json"
698+
)
699+
with open(config_json, "r") as _file:
700+
config = json.load(_file)
701+
702+
self.app.get_deployment_config = MagicMock(return_value=config)
703+
704+
container_index_json = os.path.join(
705+
self.curr_dir, "test_data/ui/container_index.json"
706+
)
707+
with open(container_index_json, "r") as _file:
708+
container_index_config = json.load(_file)
709+
mock_get_container_config.return_value = container_index_config
710+
711+
mock_get_container_image.return_value = TestDataset.DEPLOYMENT_IMAGE_NAME
712+
aqua_deployment = os.path.join(
713+
self.curr_dir, "test_data/deployment/aqua_create_embedding_deployment.yaml"
714+
)
715+
model_deployment_obj = ModelDeployment.from_yaml(uri=aqua_deployment)
716+
model_deployment_dsc_obj = copy.deepcopy(
717+
TestDataset.model_deployment_object_tei_byoc[0]
718+
)
719+
model_deployment_dsc_obj["lifecycle_state"] = "CREATING"
720+
model_deployment_obj.dsc_model_deployment = (
721+
oci.data_science.models.ModelDeploymentSummary(**model_deployment_dsc_obj)
722+
)
723+
mock_deploy.return_value = model_deployment_obj
724+
725+
result = self.app.create(
726+
model_id=TestDataset.MODEL_ID,
727+
instance_shape=TestDataset.DEPLOYMENT_SHAPE_NAME,
728+
display_name="model-deployment-name",
729+
log_group_id="ocid1.loggroup.oc1.<region>.<OCID>",
730+
access_log_id="ocid1.log.oc1.<region>.<OCID>",
731+
predict_log_id="ocid1.log.oc1.<region>.<OCID>",
732+
container_family="odsc-tei-serving",
733+
cmd_var=[],
734+
)
735+
736+
mock_create.assert_called_with(
737+
model_id=TestDataset.MODEL_ID,
738+
compartment_id=None,
739+
project_id=None,
740+
freeform_tags=None,
741+
defined_tags=None,
742+
)
743+
mock_get_container_image.assert_called()
744+
mock_deploy.assert_called()
745+
746+
expected_attributes = set(AquaDeployment.__annotations__.keys())
747+
actual_attributes = asdict(result)
748+
assert set(actual_attributes) == set(expected_attributes), "Attributes mismatch"
749+
expected_result = copy.deepcopy(TestDataset.aqua_deployment_object)
750+
expected_result["state"] = "CREATING"
751+
expected_result["shape_info"] = (
752+
TestDataset.aqua_deployment_tei_byoc_embeddings_shape_info
753+
)
754+
expected_result["cmd"] = TestDataset.aqua_deployment_tei_byoc_embeddings_cmd
755+
expected_result["environment_variables"] = (
756+
TestDataset.aqua_deployment_tei_byoc_embeddings_env_vars
757+
)
758+
assert actual_attributes == expected_result
734759

735760
@parameterized.expand(
736761
[

0 commit comments

Comments
 (0)