Skip to content

Commit 9f7c2bc

Browse files
authored
Merge branch 'main' into track_md_logs_for_error_logging
2 parents 056b442 + 7104fc3 commit 9f7c2bc

File tree

16 files changed

+1576
-35
lines changed

16 files changed

+1576
-35
lines changed

ads/aqua/cli.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from ads.aqua.finetuning import AquaFineTuningApp
1515
from ads.aqua.model import AquaModelApp
1616
from ads.aqua.modeldeployment import AquaDeploymentApp
17+
from ads.aqua.verify_policies import AquaVerifyPoliciesApp
1718
from ads.common.utils import LOG_LEVELS
1819

1920

@@ -29,6 +30,7 @@ class AquaCommand:
2930
fine_tuning = AquaFineTuningApp
3031
deployment = AquaDeploymentApp
3132
evaluation = AquaEvaluationApp
33+
verify_policies = AquaVerifyPoliciesApp
3234

3335
def __init__(
3436
self,

ads/aqua/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@
5555
SUPPORTED_FILE_FORMATS = ["jsonl"]
5656
MODEL_BY_REFERENCE_OSS_PATH_KEY = "artifact_location"
5757

58+
AQUA_CHAT_TEMPLATE_METADATA_KEY = "chat_template"
59+
5860
CONSOLE_LINK_RESOURCE_TYPE_MAPPING = {
5961
"datasciencemodel": "models",
6062
"datasciencemodeldeployment": "model-deployments",

ads/aqua/extension/model_handler.py

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@
1111
from ads.aqua.common.enums import CustomInferenceContainerTypeFamily
1212
from ads.aqua.common.errors import AquaRuntimeError
1313
from ads.aqua.common.utils import get_hf_model_info, is_valid_ocid, list_hf_models
14+
from ads.aqua.constants import AQUA_CHAT_TEMPLATE_METADATA_KEY
1415
from ads.aqua.extension.base_handler import AquaAPIhandler
1516
from ads.aqua.extension.errors import Errors
1617
from ads.aqua.model import AquaModelApp
1718
from ads.aqua.model.entities import AquaModelSummary, HFModelSummary
1819
from ads.config import SERVICE
20+
from ads.model import DataScienceModel
1921
from ads.model.common.utils import MetadataArtifactPathType
22+
from ads.model.service.oci_datascience_model import OCIDataScienceModel
2023

2124

2225
class AquaModelHandler(AquaAPIhandler):
@@ -320,26 +323,65 @@ def post(self, *args, **kwargs): # noqa: ARG002
320323
)
321324

322325

323-
class AquaModelTokenizerConfigHandler(AquaAPIhandler):
326+
class AquaModelChatTemplateHandler(AquaAPIhandler):
324327
def get(self, model_id):
325328
"""
326-
Handles requests for retrieving the Hugging Face tokenizer configuration of a specified model.
327-
Expected request format: GET /aqua/models/<model-ocid>/tokenizer
329+
Handles requests for retrieving the chat template from custom metadata of a specified model.
330+
Expected request format: GET /aqua/models/<model-ocid>/chat-template
328331
329332
"""
330333

331334
path_list = urlparse(self.request.path).path.strip("/").split("/")
332-
# Path should be /aqua/models/ocid1.iad.ahdxxx/tokenizer
333-
# path_list=['aqua','models','<model-ocid>','tokenizer']
335+
# Path should be /aqua/models/ocid1.iad.ahdxxx/chat-template
336+
# path_list=['aqua','models','<model-ocid>','chat-template']
334337
if (
335338
len(path_list) == 4
336339
and is_valid_ocid(path_list[2])
337-
and path_list[3] == "tokenizer"
340+
and path_list[3] == "chat-template"
338341
):
339-
return self.finish(AquaModelApp().get_hf_tokenizer_config(model_id))
342+
try:
343+
oci_data_science_model = OCIDataScienceModel.from_id(model_id)
344+
except Exception as e:
345+
raise HTTPError(404, f"Model not found for id: {model_id}. Details: {str(e)}")
346+
return self.finish(oci_data_science_model.get_custom_metadata_artifact("chat_template"))
340347

341348
raise HTTPError(400, f"The request {self.request.path} is invalid.")
342349

350+
@handle_exceptions
351+
def post(self, model_id: str):
352+
"""
353+
Handles POST requests to add a custom chat_template metadata artifact to a model.
354+
355+
Expected request format:
356+
POST /aqua/models/<model-ocid>/chat-template
357+
Body: { "chat_template": "<your_template_string>" }
358+
359+
"""
360+
try:
361+
input_body = self.get_json_body()
362+
except Exception as e:
363+
raise HTTPError(400, f"Invalid JSON body: {str(e)}")
364+
365+
chat_template = input_body.get("chat_template")
366+
if not chat_template:
367+
raise HTTPError(400, "Missing required field: 'chat_template'")
368+
369+
try:
370+
data_science_model = DataScienceModel.from_id(model_id)
371+
except Exception as e:
372+
raise HTTPError(404, f"Model not found for id: {model_id}. Details: {str(e)}")
373+
374+
try:
375+
result = data_science_model.create_custom_metadata_artifact(
376+
metadata_key_name=AQUA_CHAT_TEMPLATE_METADATA_KEY,
377+
path_type=MetadataArtifactPathType.CONTENT,
378+
artifact_path_or_content=chat_template.encode()
379+
)
380+
except Exception as e:
381+
raise HTTPError(500, f"Failed to create metadata artifact: {str(e)}")
382+
383+
return self.finish(result)
384+
343385

344386
class AquaModelDefinedMetadataArtifactHandler(AquaAPIhandler):
345387
"""
@@ -381,7 +423,7 @@ def post(self, model_id: str, metadata_key: str):
381423
("model/?([^/]*)", AquaModelHandler),
382424
("model/?([^/]*)/license", AquaModelLicenseHandler),
383425
("model/?([^/]*)/readme", AquaModelReadmeHandler),
384-
("model/?([^/]*)/tokenizer", AquaModelTokenizerConfigHandler),
426+
("model/?([^/]*)/chat-template", AquaModelChatTemplateHandler),
385427
("model/hf/search/?([^/]*)", AquaHuggingFaceHandler),
386428
(
387429
"model/?([^/]*)/definedMetadata/?([^/]*)",

ads/aqua/model/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class ModelTask(ExtendedEnum):
2626
TEXT_GENERATION = "text-generation"
2727
IMAGE_TEXT_TO_TEXT = "image-text-to-text"
2828
IMAGE_TO_TEXT = "image-to-text"
29+
TIME_SERIES_FORECASTING = "time-series-forecasting"
2930

3031

3132
class FineTuningMetricCategories(ExtendedEnum):

ads/aqua/modeldeployment/deployment.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@
4848
)
4949
from ads.aqua.data import AquaResourceIdentifier
5050
from ads.aqua.model import AquaModelApp
51-
from ads.aqua.model.constants import AquaModelMetadataKeys, ModelCustomMetadataFields
51+
from ads.aqua.model.constants import (
52+
AquaModelMetadataKeys,
53+
ModelCustomMetadataFields,
54+
ModelTask,
55+
)
5256
from ads.aqua.model.utils import (
5357
extract_base_model_from_ft,
5458
extract_fine_tune_artifacts_path,
@@ -215,6 +219,14 @@ def create(
215219
freeform_tags=freeform_tags,
216220
defined_tags=defined_tags,
217221
)
222+
task_tag = aqua_model.freeform_tags.get(Tags.TASK, UNKNOWN)
223+
if (
224+
task_tag == ModelTask.TIME_SERIES_FORECASTING
225+
or task_tag == ModelTask.TIME_SERIES_FORECASTING.replace("-", "_")
226+
):
227+
create_deployment_details.env_var.update(
228+
{Tags.TASK.upper(): ModelTask.TIME_SERIES_FORECASTING}
229+
)
218230
return self._create(
219231
aqua_model=aqua_model,
220232
create_deployment_details=create_deployment_details,
@@ -854,14 +866,17 @@ def list(self, **kwargs) -> List["AquaDeployment"]:
854866
aqua_model_id = model_deployment.freeform_tags.get(
855867
Tags.AQUA_MODEL_ID_TAG, UNKNOWN
856868
)
857-
if "datasciencemodelgroup" in aqua_model_id:
869+
if (
870+
"datasciencemodelgroup" in aqua_model_id
871+
or model_deployment.model_deployment_configuration_details.deployment_type
872+
== "UNKNOWN_ENUM_VALUE"
873+
):
858874
continue
859875
results.append(
860876
AquaDeployment.from_oci_model_deployment(
861877
model_deployment, self.region
862878
)
863879
)
864-
865880
# log telemetry if MD is in active or failed state
866881
deployment_id = model_deployment.id
867882
state = model_deployment.lifecycle_state.upper()

ads/aqua/verify_policies/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*--
3+
4+
# Copyright (c) 2024 Oracle and/or its affiliates.
5+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
6+
from ads.aqua.verify_policies.verify import AquaVerifyPoliciesApp
7+
8+
__all__ = ["AquaVerifyPoliciesApp"]

ads/aqua/verify_policies/constants.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
OBS_MANAGE_TEST_FILE = "AQUA Policy Verification - OBJECT STORAGE"
2+
TEST_MODEL_NAME="AQUA Policy Verification - Model"
3+
TEST_MD_NAME="AQUA Policy Verification - Model Deployment"
4+
TEST_JOB_NAME="AQUA Policy Verification - Job"
5+
TEST_JOB_RUN_NAME="AQUA Policy Verification - Job Run"
6+
TEST_MVS_NAME="AQUA Policy Verification - Model Version Set"
7+
TEST_VM_SHAPE="VM.Standard.E4.Flex"
8+
TEST_DEFAULT_JOB_SHAPE = "VM.Standard.E3.Flex"
9+
TEST_LIMIT_NAME = "ds-gpu-a10-count"
10+
DUMMY_TEST_BYTE = b"7IV6cktUGcHIhur4bXTv"
11+
POLICY_HELP_LINK = "https://github.com/oracle-samples/oci-data-science-ai-samples/blob/main/ai-quick-actions/policies/README.md"
12+
13+

ads/aqua/verify_policies/entities.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from dataclasses import dataclass
2+
from ads.common.extended_enum import ExtendedEnum
3+
from ads.common.serializer import DataClassSerializable
4+
5+
6+
class PolicyStatus(ExtendedEnum):
7+
SUCCESS = "SUCCESS"
8+
FAILURE = "FAILURE"
9+
UNVERIFIED = "UNVERIFIED"
10+
11+
12+
@dataclass(repr=False)
13+
class OperationResultSuccess(DataClassSerializable):
14+
operation: str
15+
status: PolicyStatus = PolicyStatus.SUCCESS
16+
17+
18+
@dataclass(repr=False)
19+
class OperationResultFailure(DataClassSerializable):
20+
operation: str
21+
error: str
22+
policy_hint: str
23+
status: PolicyStatus = PolicyStatus.FAILURE
24+
25+
26+
@dataclass(repr=False)
27+
class CommonSettings(DataClassSerializable):
28+
compartment_id: str
29+
project_id: str

ads/aqua/verify_policies/messages.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
from ads.aqua.verify_policies.utils import VerifyPoliciesUtils
2+
3+
utils = VerifyPoliciesUtils()
4+
operation_messages = {
5+
utils.list_compartments.__name__: {
6+
"name": "List Compartments",
7+
"error": "Unable to retrieve the list of compartments. Please verify that you have the required permissions to list compartments in your tenancy. ",
8+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to inspect compartments in tenancy"
9+
},
10+
utils.list_models.__name__: {
11+
"name": "List Models",
12+
"error": "Failed to fetch available models. Ensure that the policies allow you to list models from the Model Catalog in the selected compartment.",
13+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-models in compartment <your-compartment-name>"
14+
},
15+
utils.list_project.__name__: {
16+
"name": "List Projects",
17+
"error": "Failed to list Data Science projects. Verify that you have the appropriate permission to access projects in the selected compartment.",
18+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-projects in compartment <your-compartment-name>"
19+
},
20+
utils.list_model_version_sets.__name__: {
21+
"name": "List Model Version Sets",
22+
"error": "Unable to load model version sets. Check your access rights to list model version sets in the selected compartment.",
23+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-modelversionsets in compartment <your-compartment-name>"
24+
},
25+
utils.list_jobs.__name__: {
26+
"name": "List Jobs",
27+
"error": "Job list could not be retrieved. Please confirm that you have the necessary permissions to view jobs in the compartment.",
28+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-jobs in compartment <your-compartment-name>"
29+
},
30+
utils.list_job_runs.__name__: {
31+
"name": "List Job Runs",
32+
"error": "Job Runs list could not be retrieved. Please confirm that you have the necessary permissions to view job runs in the compartme",
33+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-job-runs in compartment <your-compartment-name>"
34+
},
35+
utils.list_buckets.__name__: {
36+
"name": "List Object Storage Buckets",
37+
"error": "Cannot fetch Object Storage buckets. Verify that you have access to list buckets within the specified compartment.",
38+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to read objectstorage-namespaces in compartment <your-compartment-name>\nAllow dynamic-group aqua-dynamic-group to read buckets in compartment <your-compartment-name>"
39+
},
40+
utils.manage_bucket.__name__: {
41+
"name": "Object Storage Access",
42+
"error": "Failed to access the Object Storage bucket. Verify that the bucket exists and you have write permissions.",
43+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage object-family in compartment <your-compartment-name> where any {target.bucket.name='<your-bucket-name>'}"
44+
},
45+
utils.list_log_groups.__name__: {
46+
"name": "List Log Groups",
47+
"error": "Log groups or logs could not be retrieved. Please confirm you have logging read access for the selected compartment.",
48+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to use logging-family in compartment <your-compartment-name>"
49+
},
50+
utils.get_resource_availability.__name__: {
51+
"name": "Verify Shape Limits",
52+
"error": "Failed to retrieve shape limits for your compartment. Make sure the required policies are in place to read shape and quota data.",
53+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to read resource-availability in compartment <your-compartment-name>"
54+
},
55+
utils.register_model.__name__: {
56+
"name": "Register Model",
57+
"error": "Model registration failed. Ensure you have the correct permissions to write to the Model Catalog and access Object Storage.",
58+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-models in compartment <your-compartment-name>"
59+
},
60+
utils.aqua_model.delete_model.__name__: {
61+
"name": "Delete Model",
62+
"error": "Could not delete model. Please confirm you have delete permissions for Model Catalog resources in the compartment.",
63+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-models in compartment <your-compartment-name>"
64+
},
65+
utils.create_job.__name__: {
66+
"name": "Create Job",
67+
"error": "Job could not be created. Please check if you have permissions to create Data Science jobs.",
68+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-jobs in compartment <your-compartment-name>"
69+
},
70+
utils.create_job_run.__name__: {
71+
"name": "Create Job Run",
72+
"error": "Job Run could not be created. Confirm that you are allowed to run jobs in the selected compartment.",
73+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-job-runs in compartment <your-compartment-name>"
74+
},
75+
"delete_job": {
76+
"name": "Delete Job",
77+
"error": "Job could not be deleted. Please check if you have permissions to delete Data Science jobs.",
78+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-jobs in compartment <your-compartment-name>"
79+
},
80+
utils.aqua_model.create_model_version_set.__name__: {
81+
"name": "Create Model Version Set",
82+
"error": "Unable to create a model version set for storing evaluation results. Ensure that required Model Catalog permissions are set.",
83+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-modelversionsets in compartment <your-compartment-name>"
84+
},
85+
utils.aqua_model.ds_client.delete_model_version_set.__name__: {
86+
"name": "Delete Model Version Set",
87+
"error": "Unable to delete a model version. Ensure that required Model Catalog permissions are set.",
88+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-modelversionsets in compartment <your-compartment-name>"
89+
},
90+
utils.create_model_deployment.__name__: {
91+
"name": "Create Model Deployment",
92+
"error": "Model deployment could not be created. Confirm you have correct permissions to deploy models to the Model Deployment service.",
93+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-model-deployments in compartment <your-compartment-name>"
94+
},
95+
utils.aqua_model.ds_client.delete_model_deployment.__name__: {
96+
"name": "Delete Model Deployment",
97+
"error": "Unable to delete the model deployment. Please check if you have appropriate permissions to manage deployments.",
98+
"policy_hint": "Allow dynamic-group aqua-dynamic-group to manage data-science-model-deployments in compartment <your-compartment-name>"
99+
}
100+
101+
}

0 commit comments

Comments
 (0)