Skip to content

Commit 69222e8

Browse files
Aqua BYOM Release (#875)
2 parents 79ab368 + a7b9ae0 commit 69222e8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+4819
-1669
lines changed

.github/workflows/run-unittests-py38-cov-report.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ jobs:
7979
run: |
8080
pip install -e ".[feature-store-marketplace]"
8181
- name: "Run unitary tests folder with maximum ADS dependencies"
82-
timeout-minutes: 40
82+
timeout-minutes: 60
8383
shell: bash
8484
env:
8585
CONDA_PREFIX: /usr/share/miniconda

.github/workflows/run-unittests-py39-py310.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ jobs:
8585
tests/unitary/with_extras/hpo
8686
8787
- name: "Run unitary tests folder with maximum ADS dependencies"
88-
timeout-minutes: 30
88+
timeout-minutes: 60
8989
shell: bash
9090
env:
9191
CONDA_PREFIX: /usr/share/miniconda

ads/aqua/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import os
88

99
from ads import logger, set_auth
10-
from ads.aqua.utils import fetch_service_compartment
10+
from ads.aqua.common.utils import fetch_service_compartment
1111
from ads.config import OCI_RESOURCE_PRINCIPAL_VERSION
1212

1313
ENV_VAR_LOG_LEVEL = "ADS_AQUA_LOG_LEVEL"

ads/aqua/base.py renamed to ads/aqua/app.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,23 @@
44
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
55

66
import os
7+
from dataclasses import fields
78
from typing import Dict, Union
89

910
import oci
1011
from oci.data_science.models import UpdateModelDetails, UpdateModelProvenanceDetails
1112

1213
from ads import set_auth
1314
from ads.aqua import logger
14-
from ads.aqua.data import Tags
15-
from ads.aqua.exception import AquaRuntimeError, AquaValueError
16-
from ads.aqua.utils import (
17-
UNKNOWN,
15+
from ads.aqua.common.enums import Tags
16+
from ads.aqua.common.errors import AquaRuntimeError, AquaValueError
17+
from ads.aqua.common.utils import (
1818
_is_valid_mvs,
1919
get_artifact_path,
2020
is_valid_ocid,
2121
load_config,
2222
)
23+
from ads.aqua.constants import UNKNOWN
2324
from ads.common import oci_client as oc
2425
from ads.common.auth import default_signer
2526
from ads.common.utils import extract_region
@@ -160,7 +161,7 @@ def create_model_version_set(
160161
"""
161162
# TODO: tag should be selected based on which operation (eval/FT) invoke this method
162163
# currently only used by fine-tuning flow.
163-
tag = Tags.AQUA_FINE_TUNING.value
164+
tag = Tags.AQUA_FINE_TUNING
164165

165166
if not model_version_set_id:
166167
try:
@@ -277,8 +278,8 @@ def get_config(self, model_id: str, config_file_name: str) -> Dict:
277278
oci_model = self.ds_client.get_model(model_id).data
278279
oci_aqua = (
279280
(
280-
Tags.AQUA_TAG.value in oci_model.freeform_tags
281-
or Tags.AQUA_TAG.value.lower() in oci_model.freeform_tags
281+
Tags.AQUA_TAG in oci_model.freeform_tags
282+
or Tags.AQUA_TAG.lower() in oci_model.freeform_tags
282283
)
283284
if oci_model.freeform_tags
284285
else False
@@ -319,3 +320,22 @@ def telemetry(self):
319320
bucket=AQUA_TELEMETRY_BUCKET, namespace=AQUA_TELEMETRY_BUCKET_NS
320321
)
321322
return self._telemetry
323+
324+
325+
class CLIBuilderMixin:
326+
"""
327+
CLI builder from API interface. To be used with the DataClass only.
328+
"""
329+
330+
def build_cli(self) -> str:
331+
"""
332+
Method to turn the dataclass attributes to CLI
333+
"""
334+
cmd = f"ads aqua {self._command}"
335+
params = [
336+
f"--{field.name} {getattr(self,field.name)}"
337+
for field in fields(self.__class__)
338+
if getattr(self, field.name)
339+
]
340+
cmd = f"{cmd} {' '.join(params)}"
341+
return cmd

ads/aqua/cli.py

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@
44
# Copyright (c) 2024 Oracle and/or its affiliates.
55
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
66
import os
7-
import sys
87

98
from ads.aqua import (
109
ENV_VAR_LOG_LEVEL,
11-
set_log_level,
1210
ODSC_MODEL_COMPARTMENT_OCID,
1311
logger,
12+
set_log_level,
1413
)
15-
from ads.aqua.deployment import AquaDeploymentApp
14+
from ads.aqua.common.errors import AquaCLIError, AquaConfigError
1615
from ads.aqua.evaluation import AquaEvaluationApp
17-
from ads.aqua.finetune import AquaFineTuningApp
16+
from ads.aqua.finetuning import AquaFineTuningApp
1817
from ads.aqua.model import AquaModelApp
19-
from ads.config import NB_SESSION_OCID
18+
from ads.aqua.modeldeployment import AquaDeploymentApp
2019
from ads.common.utils import LOG_LEVELS
20+
from ads.config import NB_SESSION_OCID
2121

2222

2323
class AquaCommand:
@@ -35,6 +35,8 @@ class AquaCommand:
3535

3636
def __init__(
3737
self,
38+
debug: bool = None,
39+
verbose: bool = None,
3840
log_level: str = os.environ.get(ENV_VAR_LOG_LEVEL, "ERROR").upper(),
3941
):
4042
"""
@@ -44,24 +46,64 @@ def __init__(
4446
-----
4547
log_level (str):
4648
Sets the logging level for the application.
47-
Default is retrieved from environment variable `LOG_LEVEL`,
49+
Default is retrieved from environment variable `ADS_AQUA_LOG_LEVEL`,
4850
or 'ERROR' if not set. Example values include 'DEBUG', 'INFO',
4951
'WARNING', 'ERROR', and 'CRITICAL'.
52+
debug (bool):
53+
Sets the logging level for the application to `DEBUG`.
54+
verbose (bool):
55+
Sets the logging level for the application to `INFO`.
56+
57+
Raises
58+
------
59+
AquaCLIError:
60+
When `--verbose` and `--debug` being used together.
61+
When missing required `ODSC_MODEL_COMPARTMENT_OCID` env var.
5062
"""
51-
if log_level.upper() not in LOG_LEVELS:
52-
logger.error(
53-
f"Log level should be one of {LOG_LEVELS}. Setting default to ERROR."
63+
if verbose is not None and debug is not None:
64+
raise AquaCLIError(
65+
"Cannot use `--debug` and `--verbose` at the same time. "
66+
"Please select either `--debug` for `DEBUG` level logging or "
67+
"`--verbose` for `INFO` level logging."
5468
)
55-
log_level = "ERROR"
56-
set_log_level(log_level)
57-
# gracefully exit if env var is not set
69+
elif verbose is not None:
70+
self._validate_value("--verbose", verbose)
71+
aqua_log_level = "INFO"
72+
elif debug is not None:
73+
self._validate_value("--debug", debug)
74+
aqua_log_level = "DEBUG"
75+
else:
76+
if log_level.upper() not in LOG_LEVELS:
77+
logger.warning(
78+
f"Log level should be one of {LOG_LEVELS}. Setting default to ERROR."
79+
)
80+
log_level = "ERROR"
81+
aqua_log_level = log_level.upper()
82+
83+
set_log_level(aqua_log_level)
84+
5885
if not ODSC_MODEL_COMPARTMENT_OCID:
59-
logger.debug(
60-
"ODSC_MODEL_COMPARTMENT_OCID environment variable is not set for Aqua."
61-
)
6286
if NB_SESSION_OCID:
63-
logger.error(
87+
raise AquaConfigError(
6488
f"Aqua is not available for the notebook session {NB_SESSION_OCID}. For more information, "
6589
f"please refer to the documentation."
6690
)
67-
sys.exit(1)
91+
raise AquaConfigError(
92+
"ODSC_MODEL_COMPARTMENT_OCID environment variable is not set for Aqua."
93+
)
94+
95+
@staticmethod
96+
def _validate_value(flag, value):
97+
"""Check if the given value for bool flag is valid.
98+
99+
Raises
100+
------
101+
AquaCLIError:
102+
When the given value for bool flag is invalid.
103+
"""
104+
if value not in [True, False]:
105+
raise AquaCLIError(
106+
f"Invalid input `{value}` for flag: {flag}, a boolean value is required. "
107+
"If you intend to chain a function call to the result, please separate the "
108+
"flag and the subsequent function call with separator `-`."
109+
)

ads/aqua/common/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
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/

ads/aqua/decorator.py renamed to ads/aqua/common/decorator.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import sys
99
from functools import wraps
10+
from typing import TYPE_CHECKING, Union
1011

1112
from oci.exceptions import (
1213
ClientError,
@@ -19,9 +20,12 @@
1920
)
2021
from tornado.web import HTTPError
2122

22-
from ads.aqua.exception import AquaError
23+
from ads.aqua.common.errors import AquaError
2324
from ads.aqua.extension.base_handler import AquaAPIhandler
2425

26+
if TYPE_CHECKING:
27+
from ads.aqua.extension.aqua_ws_msg_handler import AquaWSMsgHandler
28+
2529

2630
def handle_exceptions(func):
2731
"""Writes errors raised during call to JSON.
@@ -53,11 +57,13 @@ def handle_exceptions(func):
5357
"""
5458

5559
@wraps(func)
56-
def inner_function(self: AquaAPIhandler, *args, **kwargs):
60+
def inner_function(
61+
self: Union[AquaAPIhandler, "AquaWSMsgHandler"], *args, **kwargs
62+
):
5763
try:
5864
return func(self, *args, **kwargs)
5965
except ServiceError as error:
60-
self.write_error(
66+
return self.write_error(
6167
status_code=error.status or 500,
6268
message=error.message,
6369
reason=error.message,
@@ -69,25 +75,25 @@ def inner_function(self: AquaAPIhandler, *args, **kwargs):
6975
MissingEndpointForNonRegionalServiceClientError,
7076
RequestException,
7177
) as error:
72-
self.write_error(
78+
return self.write_error(
7379
status_code=400,
7480
reason=f"{type(error).__name__}: {str(error)}",
7581
exc_info=sys.exc_info(),
7682
)
7783
except ConnectTimeout as error:
78-
self.write_error(
84+
return self.write_error(
7985
status_code=408,
8086
reason=f"{type(error).__name__}: {str(error)}",
8187
exc_info=sys.exc_info(),
8288
)
8389
except (MultipartUploadError, CompositeOperationError) as error:
84-
self.write_error(
90+
return self.write_error(
8591
status_code=500,
8692
reason=f"{type(error).__name__}: {str(error)}",
8793
exc_info=sys.exc_info(),
8894
)
8995
except AquaError as error:
90-
self.write_error(
96+
return self.write_error(
9197
status_code=error.status,
9298
reason=error.reason,
9399
service_payload=error.service_payload,
@@ -100,7 +106,7 @@ def inner_function(self: AquaAPIhandler, *args, **kwargs):
100106
exc_info=sys.exc_info(),
101107
)
102108
except Exception as ex:
103-
self.write_error(
109+
return self.write_error(
104110
status_code=500,
105111
reason=f"{type(ex).__name__}: {str(ex)}",
106112
exc_info=sys.exc_info(),

ads/aqua/common/enums.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
# Copyright (c) 2024 Oracle and/or its affiliates.
4+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
5+
6+
"""
7+
aqua.common.enums
8+
~~~~~~~~~~~~~~
9+
This module contains the set of enums used in AQUA.
10+
"""
11+
from ads.common.extended_enum import ExtendedEnumMeta
12+
13+
14+
class DataScienceResource(str, metaclass=ExtendedEnumMeta):
15+
MODEL_DEPLOYMENT = "datasciencemodeldeployment"
16+
MODEL = "datasciencemodel"
17+
18+
19+
class Resource(str, metaclass=ExtendedEnumMeta):
20+
JOB = "jobs"
21+
JOBRUN = "jobruns"
22+
MODEL = "models"
23+
MODEL_DEPLOYMENT = "modeldeployments"
24+
MODEL_VERSION_SET = "model-version-sets"
25+
26+
27+
class Tags(str, metaclass=ExtendedEnumMeta):
28+
TASK = "task"
29+
LICENSE = "license"
30+
ORGANIZATION = "organization"
31+
AQUA_TAG = "OCI_AQUA"
32+
AQUA_SERVICE_MODEL_TAG = "aqua_service_model"
33+
AQUA_FINE_TUNED_MODEL_TAG = "aqua_fine_tuned_model"
34+
AQUA_MODEL_NAME_TAG = "aqua_model_name"
35+
AQUA_EVALUATION = "aqua_evaluation"
36+
AQUA_FINE_TUNING = "aqua_finetuning"
37+
READY_TO_FINE_TUNE = "ready_to_fine_tune"
38+
READY_TO_IMPORT = "ready_to_import"
39+
BASE_MODEL_CUSTOM = "aqua_custom_base_model"
40+
AQUA_EVALUATION_MODEL_ID = "evaluation_model_id"
41+
42+
43+
class InferenceContainerType(str, metaclass=ExtendedEnumMeta):
44+
CONTAINER_TYPE_VLLM = "vllm"
45+
CONTAINER_TYPE_TGI = "tgi"
46+
47+
48+
class InferenceContainerTypeFamily(str, metaclass=ExtendedEnumMeta):
49+
AQUA_VLLM_CONTAINER_FAMILY = "odsc-vllm-serving"
50+
AQUA_TGI_CONTAINER_FAMILY = "odsc-tgi-serving"
51+
52+
53+
class InferenceContainerParamType(str, metaclass=ExtendedEnumMeta):
54+
PARAM_TYPE_VLLM = "VLLM_PARAMS"
55+
PARAM_TYPE_TGI = "TGI_PARAMS"
56+
57+
58+
class HuggingFaceTags(str, metaclass=ExtendedEnumMeta):
59+
TEXT_GENERATION_INFERENCE = "text-generation-inference"
60+
61+
62+
class RqsAdditionalDetails(str, metaclass=ExtendedEnumMeta):
63+
METADATA = "metadata"
64+
CREATED_BY = "createdBy"
65+
DESCRIPTION = "description"
66+
MODEL_VERSION_SET_ID = "modelVersionSetId"
67+
MODEL_VERSION_SET_NAME = "modelVersionSetName"
68+
PROJECT_ID = "projectId"
69+
VERSION_LABEL = "versionLabel"

0 commit comments

Comments
 (0)