oracle-ads 2.12.10rc0__py3-none-any.whl → 2.13.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ads/aqua/__init__.py +2 -1
- ads/aqua/app.py +46 -19
- ads/aqua/client/__init__.py +3 -0
- ads/aqua/client/client.py +799 -0
- ads/aqua/common/enums.py +19 -14
- ads/aqua/common/errors.py +3 -4
- ads/aqua/common/utils.py +2 -2
- ads/aqua/constants.py +1 -0
- ads/aqua/evaluation/constants.py +7 -7
- ads/aqua/evaluation/errors.py +3 -4
- ads/aqua/evaluation/evaluation.py +20 -12
- ads/aqua/extension/aqua_ws_msg_handler.py +14 -7
- ads/aqua/extension/base_handler.py +12 -9
- ads/aqua/extension/model_handler.py +29 -1
- ads/aqua/extension/models/ws_models.py +5 -6
- ads/aqua/finetuning/constants.py +3 -3
- ads/aqua/finetuning/entities.py +3 -0
- ads/aqua/finetuning/finetuning.py +32 -1
- ads/aqua/model/constants.py +7 -7
- ads/aqua/model/entities.py +2 -1
- ads/aqua/model/enums.py +4 -5
- ads/aqua/model/model.py +158 -76
- ads/aqua/modeldeployment/deployment.py +22 -10
- ads/aqua/modeldeployment/entities.py +3 -1
- ads/cli.py +16 -8
- ads/common/auth.py +33 -20
- ads/common/extended_enum.py +52 -44
- ads/llm/__init__.py +11 -8
- ads/llm/langchain/plugins/embeddings/__init__.py +4 -0
- ads/llm/langchain/plugins/embeddings/oci_data_science_model_deployment_endpoint.py +184 -0
- ads/model/artifact_downloader.py +3 -4
- ads/model/datascience_model.py +84 -64
- ads/model/generic_model.py +3 -3
- ads/model/model_metadata.py +17 -11
- ads/model/service/oci_datascience_model.py +12 -14
- ads/opctl/backend/marketplace/helm_helper.py +13 -14
- ads/opctl/cli.py +4 -5
- ads/opctl/cmds.py +28 -32
- ads/opctl/config/merger.py +8 -11
- ads/opctl/config/resolver.py +25 -30
- ads/opctl/operator/cli.py +9 -9
- ads/opctl/operator/common/backend_factory.py +56 -60
- ads/opctl/operator/common/const.py +5 -5
- ads/opctl/operator/lowcode/anomaly/const.py +8 -9
- ads/opctl/operator/lowcode/common/transformations.py +38 -3
- ads/opctl/operator/lowcode/common/utils.py +11 -1
- ads/opctl/operator/lowcode/feature_store_marketplace/operator_utils.py +43 -48
- ads/opctl/operator/lowcode/forecast/__main__.py +10 -0
- ads/opctl/operator/lowcode/forecast/const.py +6 -6
- ads/opctl/operator/lowcode/forecast/model/forecast_datasets.py +1 -1
- ads/opctl/operator/lowcode/forecast/operator_config.py +31 -0
- ads/opctl/operator/lowcode/forecast/schema.yaml +63 -0
- ads/opctl/operator/lowcode/forecast/whatifserve/__init__.py +7 -0
- ads/opctl/operator/lowcode/forecast/whatifserve/deployment_manager.py +233 -0
- ads/opctl/operator/lowcode/forecast/whatifserve/score.py +238 -0
- ads/opctl/operator/lowcode/pii/constant.py +6 -7
- ads/opctl/operator/lowcode/recommender/constant.py +12 -7
- ads/opctl/operator/runtime/marketplace_runtime.py +4 -10
- ads/opctl/operator/runtime/runtime.py +4 -6
- ads/pipeline/ads_pipeline_run.py +13 -25
- ads/pipeline/visualizer/graph_renderer.py +3 -4
- {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/METADATA +4 -2
- {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/RECORD +66 -59
- {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/LICENSE.txt +0 -0
- {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/WHEEL +0 -0
- {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/entry_points.txt +0 -0
ads/aqua/common/enums.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
|
-
# Copyright (c) 2024 Oracle and/or its affiliates.
|
2
|
+
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
|
3
3
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
4
4
|
|
5
5
|
"""
|
@@ -8,15 +8,15 @@ aqua.common.enums
|
|
8
8
|
This module contains the set of enums used in AQUA.
|
9
9
|
"""
|
10
10
|
|
11
|
-
from ads.common.extended_enum import
|
11
|
+
from ads.common.extended_enum import ExtendedEnum
|
12
12
|
|
13
13
|
|
14
|
-
class DataScienceResource(
|
14
|
+
class DataScienceResource(ExtendedEnum):
|
15
15
|
MODEL_DEPLOYMENT = "datasciencemodeldeployment"
|
16
16
|
MODEL = "datasciencemodel"
|
17
17
|
|
18
18
|
|
19
|
-
class Resource(
|
19
|
+
class Resource(ExtendedEnum):
|
20
20
|
JOB = "jobs"
|
21
21
|
JOBRUN = "jobruns"
|
22
22
|
MODEL = "models"
|
@@ -24,7 +24,7 @@ class Resource(str, metaclass=ExtendedEnumMeta):
|
|
24
24
|
MODEL_VERSION_SET = "model-version-sets"
|
25
25
|
|
26
26
|
|
27
|
-
class Tags(
|
27
|
+
class Tags(ExtendedEnum):
|
28
28
|
TASK = "task"
|
29
29
|
LICENSE = "license"
|
30
30
|
ORGANIZATION = "organization"
|
@@ -42,41 +42,41 @@ class Tags(str, metaclass=ExtendedEnumMeta):
|
|
42
42
|
MODEL_ARTIFACT_FILE = "model_file"
|
43
43
|
|
44
44
|
|
45
|
-
class InferenceContainerType(
|
45
|
+
class InferenceContainerType(ExtendedEnum):
|
46
46
|
CONTAINER_TYPE_VLLM = "vllm"
|
47
47
|
CONTAINER_TYPE_TGI = "tgi"
|
48
48
|
CONTAINER_TYPE_LLAMA_CPP = "llama-cpp"
|
49
49
|
|
50
50
|
|
51
|
-
class InferenceContainerTypeFamily(
|
51
|
+
class InferenceContainerTypeFamily(ExtendedEnum):
|
52
52
|
AQUA_VLLM_CONTAINER_FAMILY = "odsc-vllm-serving"
|
53
53
|
AQUA_TGI_CONTAINER_FAMILY = "odsc-tgi-serving"
|
54
54
|
AQUA_LLAMA_CPP_CONTAINER_FAMILY = "odsc-llama-cpp-serving"
|
55
55
|
|
56
56
|
|
57
|
-
class CustomInferenceContainerTypeFamily(
|
57
|
+
class CustomInferenceContainerTypeFamily(ExtendedEnum):
|
58
58
|
AQUA_TEI_CONTAINER_FAMILY = "odsc-tei-serving"
|
59
59
|
|
60
60
|
|
61
|
-
class InferenceContainerParamType(
|
61
|
+
class InferenceContainerParamType(ExtendedEnum):
|
62
62
|
PARAM_TYPE_VLLM = "VLLM_PARAMS"
|
63
63
|
PARAM_TYPE_TGI = "TGI_PARAMS"
|
64
64
|
PARAM_TYPE_LLAMA_CPP = "LLAMA_CPP_PARAMS"
|
65
65
|
|
66
66
|
|
67
|
-
class EvaluationContainerTypeFamily(
|
67
|
+
class EvaluationContainerTypeFamily(ExtendedEnum):
|
68
68
|
AQUA_EVALUATION_CONTAINER_FAMILY = "odsc-llm-evaluate"
|
69
69
|
|
70
70
|
|
71
|
-
class FineTuningContainerTypeFamily(
|
71
|
+
class FineTuningContainerTypeFamily(ExtendedEnum):
|
72
72
|
AQUA_FINETUNING_CONTAINER_FAMILY = "odsc-llm-fine-tuning"
|
73
73
|
|
74
74
|
|
75
|
-
class HuggingFaceTags(
|
75
|
+
class HuggingFaceTags(ExtendedEnum):
|
76
76
|
TEXT_GENERATION_INFERENCE = "text-generation-inference"
|
77
77
|
|
78
78
|
|
79
|
-
class RqsAdditionalDetails(
|
79
|
+
class RqsAdditionalDetails(ExtendedEnum):
|
80
80
|
METADATA = "metadata"
|
81
81
|
CREATED_BY = "createdBy"
|
82
82
|
DESCRIPTION = "description"
|
@@ -86,9 +86,14 @@ class RqsAdditionalDetails(str, metaclass=ExtendedEnumMeta):
|
|
86
86
|
VERSION_LABEL = "versionLabel"
|
87
87
|
|
88
88
|
|
89
|
-
class TextEmbeddingInferenceContainerParams(
|
89
|
+
class TextEmbeddingInferenceContainerParams(ExtendedEnum):
|
90
90
|
"""Contains a subset of params that are required for enabling model deployment in OCI Data Science. More options
|
91
91
|
are available at https://huggingface.co/docs/text-embeddings-inference/en/cli_arguments"""
|
92
92
|
|
93
93
|
MODEL_ID = "model-id"
|
94
94
|
PORT = "port"
|
95
|
+
|
96
|
+
|
97
|
+
class ConfigFolder(ExtendedEnum):
|
98
|
+
CONFIG = "config"
|
99
|
+
ARTIFACT = "artifact"
|
ads/aqua/common/errors.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
|
-
#
|
3
|
-
# Copyright (c) 2024 Oracle and/or its affiliates.
|
2
|
+
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
|
4
3
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
5
4
|
|
6
5
|
"""
|
@@ -10,10 +9,10 @@ aqua.exception
|
|
10
9
|
This module contains the set of Aqua exceptions.
|
11
10
|
"""
|
12
11
|
|
13
|
-
from ads.common.extended_enum import
|
12
|
+
from ads.common.extended_enum import ExtendedEnum
|
14
13
|
|
15
14
|
|
16
|
-
class ExitCode(
|
15
|
+
class ExitCode(ExtendedEnum):
|
17
16
|
SUCCESS = 0
|
18
17
|
COMMON_ERROR = 1
|
19
18
|
INVALID_CONFIG = 10
|
ads/aqua/common/utils.py
CHANGED
@@ -65,7 +65,7 @@ from ads.aqua.constants import (
|
|
65
65
|
from ads.aqua.data import AquaResourceIdentifier
|
66
66
|
from ads.common.auth import AuthState, default_signer
|
67
67
|
from ads.common.decorator.threaded import threaded
|
68
|
-
from ads.common.extended_enum import
|
68
|
+
from ads.common.extended_enum import ExtendedEnum
|
69
69
|
from ads.common.object_storage_details import ObjectStorageDetails
|
70
70
|
from ads.common.oci_resource import SEARCH_TYPE, OCIResource
|
71
71
|
from ads.common.utils import copy_file, get_console_link, upload_to_os
|
@@ -80,7 +80,7 @@ from ads.model import DataScienceModel, ModelVersionSet
|
|
80
80
|
logger = logging.getLogger("ads.aqua")
|
81
81
|
|
82
82
|
|
83
|
-
class LifecycleStatus(
|
83
|
+
class LifecycleStatus(ExtendedEnum):
|
84
84
|
UNKNOWN = ""
|
85
85
|
|
86
86
|
@property
|
ads/aqua/constants.py
CHANGED
@@ -10,6 +10,7 @@ UNKNOWN_DICT = {}
|
|
10
10
|
README = "README.md"
|
11
11
|
LICENSE_TXT = "config/LICENSE.txt"
|
12
12
|
DEPLOYMENT_CONFIG = "deployment_config.json"
|
13
|
+
AQUA_MODEL_TOKENIZER_CONFIG = "tokenizer_config.json"
|
13
14
|
COMPARTMENT_MAPPING_KEY = "service-model-compartment"
|
14
15
|
CONTAINER_INDEX = "container_index.json"
|
15
16
|
EVALUATION_REPORT_JSON = "report.json"
|
ads/aqua/evaluation/constants.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
|
-
#
|
3
|
-
# Copyright (c) 2024 Oracle and/or its affiliates.
|
2
|
+
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
|
4
3
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
5
4
|
|
6
5
|
"""
|
@@ -9,9 +8,10 @@ aqua.evaluation.const
|
|
9
8
|
|
10
9
|
This module contains constants/enums used in Aqua Evaluation.
|
11
10
|
"""
|
11
|
+
|
12
12
|
from oci.data_science.models import JobRun
|
13
13
|
|
14
|
-
from ads.common.extended_enum import
|
14
|
+
from ads.common.extended_enum import ExtendedEnum
|
15
15
|
|
16
16
|
EVAL_TERMINATION_STATE = [
|
17
17
|
JobRun.LIFECYCLE_STATE_SUCCEEDED,
|
@@ -19,7 +19,7 @@ EVAL_TERMINATION_STATE = [
|
|
19
19
|
]
|
20
20
|
|
21
21
|
|
22
|
-
class EvaluationCustomMetadata(
|
22
|
+
class EvaluationCustomMetadata(ExtendedEnum):
|
23
23
|
EVALUATION_SOURCE = "evaluation_source"
|
24
24
|
EVALUATION_JOB_ID = "evaluation_job_id"
|
25
25
|
EVALUATION_JOB_RUN_ID = "evaluation_job_run_id"
|
@@ -28,11 +28,11 @@ class EvaluationCustomMetadata(str, metaclass=ExtendedEnumMeta):
|
|
28
28
|
EVALUATION_ERROR = "aqua_evaluate_error"
|
29
29
|
|
30
30
|
|
31
|
-
class EvaluationConfig(
|
31
|
+
class EvaluationConfig(ExtendedEnum):
|
32
32
|
PARAMS = "model_params"
|
33
33
|
|
34
34
|
|
35
|
-
class EvaluationReportJson(
|
35
|
+
class EvaluationReportJson(ExtendedEnum):
|
36
36
|
"""Contains evaluation report.json fields name."""
|
37
37
|
|
38
38
|
METRIC_SUMMARY_RESULT = "metric_summary_result"
|
@@ -43,7 +43,7 @@ class EvaluationReportJson(str, metaclass=ExtendedEnumMeta):
|
|
43
43
|
DATASET = "dataset"
|
44
44
|
|
45
45
|
|
46
|
-
class EvaluationMetricResult(
|
46
|
+
class EvaluationMetricResult(ExtendedEnum):
|
47
47
|
"""Contains metric result's fields name in report.json."""
|
48
48
|
|
49
49
|
SHORT_NAME = "key"
|
ads/aqua/evaluation/errors.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
|
-
#
|
3
|
-
# Copyright (c) 2024 Oracle and/or its affiliates.
|
2
|
+
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
|
4
3
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
5
4
|
"""
|
6
5
|
aqua.evaluation.errors
|
@@ -9,10 +8,10 @@ aqua.evaluation.errors
|
|
9
8
|
This module contains errors in Aqua Evaluation.
|
10
9
|
"""
|
11
10
|
|
12
|
-
from ads.common.extended_enum import
|
11
|
+
from ads.common.extended_enum import ExtendedEnum
|
13
12
|
|
14
13
|
|
15
|
-
class EvaluationJobExitCode(
|
14
|
+
class EvaluationJobExitCode(ExtendedEnum):
|
16
15
|
SUCCESS = 0
|
17
16
|
COMMON_ERROR = 1
|
18
17
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
|
-
# Copyright (c) 2024 Oracle and/or its affiliates.
|
2
|
+
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
|
3
3
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
4
4
|
import base64
|
5
5
|
import json
|
@@ -199,11 +199,11 @@ class AquaEvaluationApp(AquaApp):
|
|
199
199
|
eval_inference_configuration = (
|
200
200
|
container.spec.evaluation_configuration
|
201
201
|
)
|
202
|
-
except Exception:
|
202
|
+
except Exception as ex:
|
203
203
|
logger.debug(
|
204
204
|
f"Could not load inference config details for the evaluation source id: "
|
205
205
|
f"{create_aqua_evaluation_details.evaluation_source_id}. Please check if the container"
|
206
|
-
f" runtime has the correct SMC image information
|
206
|
+
f" runtime has the correct SMC image information.\nError: {str(ex)}"
|
207
207
|
)
|
208
208
|
elif (
|
209
209
|
DataScienceResource.MODEL
|
@@ -289,7 +289,7 @@ class AquaEvaluationApp(AquaApp):
|
|
289
289
|
f"Invalid experiment name. Please provide an experiment with `{Tags.AQUA_EVALUATION}` in tags."
|
290
290
|
)
|
291
291
|
except Exception:
|
292
|
-
logger.
|
292
|
+
logger.info(
|
293
293
|
f"Model version set {experiment_model_version_set_name} doesn't exist. "
|
294
294
|
"Creating new model version set."
|
295
295
|
)
|
@@ -711,21 +711,27 @@ class AquaEvaluationApp(AquaApp):
|
|
711
711
|
try:
|
712
712
|
log = utils.query_resource(log_id, return_all=False)
|
713
713
|
log_name = log.display_name if log else ""
|
714
|
-
except Exception:
|
714
|
+
except Exception as ex:
|
715
|
+
logger.debug(f"Failed to get associated log name. Error: {ex}")
|
715
716
|
pass
|
716
717
|
|
717
718
|
if loggroup_id:
|
718
719
|
try:
|
719
720
|
loggroup = utils.query_resource(loggroup_id, return_all=False)
|
720
721
|
loggroup_name = loggroup.display_name if loggroup else ""
|
721
|
-
except Exception:
|
722
|
+
except Exception as ex:
|
723
|
+
logger.debug(f"Failed to get associated loggroup name. Error: {ex}")
|
722
724
|
pass
|
723
725
|
|
724
726
|
try:
|
725
727
|
introspection = json.loads(
|
726
728
|
self._get_attribute_from_model_metadata(resource, "ArtifactTestResults")
|
727
729
|
)
|
728
|
-
except Exception:
|
730
|
+
except Exception as ex:
|
731
|
+
logger.debug(
|
732
|
+
f"There was an issue loading the model attribute as json object for evaluation {eval_id}. "
|
733
|
+
f"Setting introspection to empty.\n Error:{ex}"
|
734
|
+
)
|
729
735
|
introspection = {}
|
730
736
|
|
731
737
|
summary = AquaEvaluationDetail(
|
@@ -878,13 +884,13 @@ class AquaEvaluationApp(AquaApp):
|
|
878
884
|
try:
|
879
885
|
log_id = job_run_details.log_details.log_id
|
880
886
|
except Exception as e:
|
881
|
-
logger.debug(f"Failed to get associated log
|
887
|
+
logger.debug(f"Failed to get associated log.\nError: {str(e)}")
|
882
888
|
log_id = ""
|
883
889
|
|
884
890
|
try:
|
885
891
|
loggroup_id = job_run_details.log_details.log_group_id
|
886
892
|
except Exception as e:
|
887
|
-
logger.debug(f"Failed to get associated log
|
893
|
+
logger.debug(f"Failed to get associated log.\nError: {str(e)}")
|
888
894
|
loggroup_id = ""
|
889
895
|
|
890
896
|
loggroup_url = get_log_links(region=self.region, log_group_id=loggroup_id)
|
@@ -958,7 +964,7 @@ class AquaEvaluationApp(AquaApp):
|
|
958
964
|
)
|
959
965
|
except Exception as e:
|
960
966
|
logger.debug(
|
961
|
-
"Failed to load `report.json` from evaluation artifact
|
967
|
+
f"Failed to load `report.json` from evaluation artifact.\nError: {str(e)}"
|
962
968
|
)
|
963
969
|
json_report = {}
|
964
970
|
|
@@ -1047,6 +1053,7 @@ class AquaEvaluationApp(AquaApp):
|
|
1047
1053
|
return report
|
1048
1054
|
|
1049
1055
|
with tempfile.TemporaryDirectory() as temp_dir:
|
1056
|
+
logger.info(f"Downloading evaluation artifact for {eval_id}.")
|
1050
1057
|
DataScienceModel.from_id(eval_id).download_artifact(
|
1051
1058
|
temp_dir,
|
1052
1059
|
auth=self._auth,
|
@@ -1200,6 +1207,7 @@ class AquaEvaluationApp(AquaApp):
|
|
1200
1207
|
def load_evaluation_config(self, container: Optional[str] = None) -> Dict:
|
1201
1208
|
"""Loads evaluation config."""
|
1202
1209
|
|
1210
|
+
logger.info("Loading evaluation container config.")
|
1203
1211
|
# retrieve the evaluation config by container family name
|
1204
1212
|
evaluation_config = get_evaluation_service_config(container)
|
1205
1213
|
|
@@ -1279,9 +1287,9 @@ class AquaEvaluationApp(AquaApp):
|
|
1279
1287
|
raise AquaRuntimeError(
|
1280
1288
|
f"Not supported source type: {resource_type}"
|
1281
1289
|
)
|
1282
|
-
except Exception:
|
1290
|
+
except Exception as ex:
|
1283
1291
|
logger.debug(
|
1284
|
-
f"Failed to retrieve source information for evaluation {evaluation.identifier}
|
1292
|
+
f"Failed to retrieve source information for evaluation {evaluation.identifier}.\nError: {str(ex)}"
|
1285
1293
|
)
|
1286
1294
|
source_name = ""
|
1287
1295
|
|
@@ -1,10 +1,10 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
|
-
# -*- coding: utf-8 -*--
|
3
2
|
|
4
|
-
# Copyright (c) 2024 Oracle and/or its affiliates.
|
3
|
+
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
|
5
4
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
6
5
|
|
7
6
|
import traceback
|
7
|
+
import uuid
|
8
8
|
from abc import abstractmethod
|
9
9
|
from http.client import responses
|
10
10
|
from typing import List
|
@@ -34,7 +34,7 @@ class AquaWSMsgHandler:
|
|
34
34
|
self.telemetry = TelemetryClient(
|
35
35
|
bucket=AQUA_TELEMETRY_BUCKET, namespace=AQUA_TELEMETRY_BUCKET_NS
|
36
36
|
)
|
37
|
-
except:
|
37
|
+
except Exception:
|
38
38
|
pass
|
39
39
|
|
40
40
|
@staticmethod
|
@@ -66,16 +66,23 @@ class AquaWSMsgHandler:
|
|
66
66
|
"message": message,
|
67
67
|
"service_payload": service_payload,
|
68
68
|
"reason": reason,
|
69
|
+
"request_id": str(uuid.uuid4()),
|
69
70
|
}
|
70
71
|
exc_info = kwargs.get("exc_info")
|
71
72
|
if exc_info:
|
72
|
-
logger.error(
|
73
|
+
logger.error(
|
74
|
+
f"Error Request ID: {reply['request_id']}\n"
|
75
|
+
f"Error: {''.join(traceback.format_exception(*exc_info))}"
|
76
|
+
)
|
73
77
|
e = exc_info[1]
|
74
78
|
if isinstance(e, HTTPError):
|
75
79
|
reply["message"] = e.log_message or message
|
76
80
|
reply["reason"] = e.reason
|
77
|
-
|
78
|
-
|
81
|
+
|
82
|
+
logger.error(
|
83
|
+
f"Error Request ID: {reply['request_id']}\n"
|
84
|
+
f"Error: {reply['message']} {reply['reason']}"
|
85
|
+
)
|
79
86
|
# telemetry may not be present if there is an error while initializing
|
80
87
|
if hasattr(self, "telemetry"):
|
81
88
|
aqua_api_details = kwargs.get("aqua_api_details", {})
|
@@ -83,7 +90,7 @@ class AquaWSMsgHandler:
|
|
83
90
|
category="aqua/error",
|
84
91
|
action=str(status_code),
|
85
92
|
value=reason,
|
86
|
-
**aqua_api_details
|
93
|
+
**aqua_api_details,
|
87
94
|
)
|
88
95
|
response = AquaWsError(
|
89
96
|
status=status_code,
|
@@ -1,6 +1,5 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
|
-
#
|
3
|
-
# Copyright (c) 2024 Oracle and/or its affiliates.
|
2
|
+
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
|
4
3
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
5
4
|
|
6
5
|
|
@@ -35,7 +34,7 @@ class AquaAPIhandler(APIHandler):
|
|
35
34
|
self.telemetry = TelemetryClient(
|
36
35
|
bucket=AQUA_TELEMETRY_BUCKET, namespace=AQUA_TELEMETRY_BUCKET_NS
|
37
36
|
)
|
38
|
-
except:
|
37
|
+
except Exception:
|
39
38
|
pass
|
40
39
|
|
41
40
|
@staticmethod
|
@@ -82,19 +81,23 @@ class AquaAPIhandler(APIHandler):
|
|
82
81
|
"message": message,
|
83
82
|
"service_payload": service_payload,
|
84
83
|
"reason": reason,
|
84
|
+
"request_id": str(uuid.uuid4()),
|
85
85
|
}
|
86
86
|
exc_info = kwargs.get("exc_info")
|
87
87
|
if exc_info:
|
88
|
-
logger.error(
|
88
|
+
logger.error(
|
89
|
+
f"Error Request ID: {reply['request_id']}\n"
|
90
|
+
f"Error: {''.join(traceback.format_exception(*exc_info))}"
|
91
|
+
)
|
89
92
|
e = exc_info[1]
|
90
93
|
if isinstance(e, HTTPError):
|
91
94
|
reply["message"] = e.log_message or message
|
92
95
|
reply["reason"] = e.reason if e.reason else reply["reason"]
|
93
|
-
reply["request_id"] = str(uuid.uuid4())
|
94
|
-
else:
|
95
|
-
reply["request_id"] = str(uuid.uuid4())
|
96
96
|
|
97
|
-
logger.
|
97
|
+
logger.error(
|
98
|
+
f"Error Request ID: {reply['request_id']}\n"
|
99
|
+
f"Error: {reply['message']} {reply['reason']}"
|
100
|
+
)
|
98
101
|
|
99
102
|
# telemetry may not be present if there is an error while initializing
|
100
103
|
if hasattr(self, "telemetry"):
|
@@ -103,7 +106,7 @@ class AquaAPIhandler(APIHandler):
|
|
103
106
|
category="aqua/error",
|
104
107
|
action=str(status_code),
|
105
108
|
value=reason,
|
106
|
-
**aqua_api_details
|
109
|
+
**aqua_api_details,
|
107
110
|
)
|
108
111
|
|
109
112
|
self.finish(json.dumps(reply))
|
@@ -14,6 +14,7 @@ from ads.aqua.common.enums import (
|
|
14
14
|
from ads.aqua.common.errors import AquaRuntimeError, AquaValueError
|
15
15
|
from ads.aqua.common.utils import (
|
16
16
|
get_hf_model_info,
|
17
|
+
is_valid_ocid,
|
17
18
|
list_hf_models,
|
18
19
|
)
|
19
20
|
from ads.aqua.extension.base_handler import AquaAPIhandler
|
@@ -133,13 +134,17 @@ class AquaModelHandler(AquaAPIhandler):
|
|
133
134
|
)
|
134
135
|
local_dir = input_data.get("local_dir")
|
135
136
|
cleanup_model_cache = (
|
136
|
-
str(input_data.get("cleanup_model_cache", "
|
137
|
+
str(input_data.get("cleanup_model_cache", "false")).lower() == "true"
|
137
138
|
)
|
138
139
|
inference_container_uri = input_data.get("inference_container_uri")
|
139
140
|
allow_patterns = input_data.get("allow_patterns")
|
140
141
|
ignore_patterns = input_data.get("ignore_patterns")
|
141
142
|
freeform_tags = input_data.get("freeform_tags")
|
142
143
|
defined_tags = input_data.get("defined_tags")
|
144
|
+
ignore_model_artifact_check = (
|
145
|
+
str(input_data.get("ignore_model_artifact_check", "false")).lower()
|
146
|
+
== "true"
|
147
|
+
)
|
143
148
|
|
144
149
|
return self.finish(
|
145
150
|
AquaModelApp().register(
|
@@ -158,6 +163,7 @@ class AquaModelHandler(AquaAPIhandler):
|
|
158
163
|
ignore_patterns=ignore_patterns,
|
159
164
|
freeform_tags=freeform_tags,
|
160
165
|
defined_tags=defined_tags,
|
166
|
+
ignore_model_artifact_check=ignore_model_artifact_check,
|
161
167
|
)
|
162
168
|
)
|
163
169
|
|
@@ -311,8 +317,30 @@ class AquaHuggingFaceHandler(AquaAPIhandler):
|
|
311
317
|
)
|
312
318
|
|
313
319
|
|
320
|
+
class AquaModelTokenizerConfigHandler(AquaAPIhandler):
|
321
|
+
def get(self, model_id):
|
322
|
+
"""
|
323
|
+
Handles requests for retrieving the Hugging Face tokenizer configuration of a specified model.
|
324
|
+
Expected request format: GET /aqua/models/<model-ocid>/tokenizer
|
325
|
+
|
326
|
+
"""
|
327
|
+
|
328
|
+
path_list = urlparse(self.request.path).path.strip("/").split("/")
|
329
|
+
# Path should be /aqua/models/ocid1.iad.ahdxxx/tokenizer
|
330
|
+
# path_list=['aqua','models','<model-ocid>','tokenizer']
|
331
|
+
if (
|
332
|
+
len(path_list) == 4
|
333
|
+
and is_valid_ocid(path_list[2])
|
334
|
+
and path_list[3] == "tokenizer"
|
335
|
+
):
|
336
|
+
return self.finish(AquaModelApp().get_hf_tokenizer_config(model_id))
|
337
|
+
|
338
|
+
raise HTTPError(400, f"The request {self.request.path} is invalid.")
|
339
|
+
|
340
|
+
|
314
341
|
__handlers__ = [
|
315
342
|
("model/?([^/]*)", AquaModelHandler),
|
316
343
|
("model/?([^/]*)/license", AquaModelLicenseHandler),
|
344
|
+
("model/?([^/]*)/tokenizer", AquaModelTokenizerConfigHandler),
|
317
345
|
("model/hf/search/?([^/]*)", AquaHuggingFaceHandler),
|
318
346
|
]
|
@@ -1,20 +1,19 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
|
-
# -*- coding: utf-8 -*--
|
3
2
|
|
4
|
-
# Copyright (c) 2024 Oracle and/or its affiliates.
|
3
|
+
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
|
5
4
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
6
5
|
|
7
6
|
from dataclasses import dataclass
|
8
7
|
from typing import List, Optional
|
9
8
|
|
10
|
-
from ads.aqua.evaluation.entities import
|
11
|
-
from ads.aqua.model.entities import
|
9
|
+
from ads.aqua.evaluation.entities import AquaEvaluationDetail, AquaEvaluationSummary
|
10
|
+
from ads.aqua.model.entities import AquaModel, AquaModelSummary
|
12
11
|
from ads.aqua.modeldeployment.entities import AquaDeployment, AquaDeploymentDetail
|
13
|
-
from ads.common.extended_enum import
|
12
|
+
from ads.common.extended_enum import ExtendedEnum
|
14
13
|
from ads.common.serializer import DataClassSerializable
|
15
14
|
|
16
15
|
|
17
|
-
class RequestResponseType(
|
16
|
+
class RequestResponseType(ExtendedEnum):
|
18
17
|
ListEvaluations = "ListEvaluations"
|
19
18
|
EvaluationDetails = "EvaluationDetails"
|
20
19
|
ListDeployments = "ListDeployments"
|
ads/aqua/finetuning/constants.py
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
|
3
3
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
4
4
|
|
5
|
-
from ads.common.extended_enum import
|
5
|
+
from ads.common.extended_enum import ExtendedEnum
|
6
6
|
|
7
7
|
|
8
|
-
class FineTuneCustomMetadata(
|
8
|
+
class FineTuneCustomMetadata(ExtendedEnum):
|
9
9
|
FINE_TUNE_SOURCE = "fine_tune_source"
|
10
10
|
FINE_TUNE_SOURCE_NAME = "fine_tune_source_name"
|
11
11
|
FINE_TUNE_OUTPUT_PATH = "fine_tune_output_path"
|
@@ -16,7 +16,7 @@ class FineTuneCustomMetadata(str, metaclass=ExtendedEnumMeta):
|
|
16
16
|
SERVICE_MODEL_FINE_TUNE_CONTAINER = "finetune-container"
|
17
17
|
|
18
18
|
|
19
|
-
class FineTuningRestrictedParams(
|
19
|
+
class FineTuningRestrictedParams(ExtendedEnum):
|
20
20
|
OPTIMIZER = "optimizer"
|
21
21
|
|
22
22
|
|
ads/aqua/finetuning/entities.py
CHANGED
@@ -122,6 +122,8 @@ class CreateFineTuningDetails(Serializable):
|
|
122
122
|
The log group id for fine tuning job infrastructure.
|
123
123
|
log_id: (str, optional). Defaults to `None`.
|
124
124
|
The log id for fine tuning job infrastructure.
|
125
|
+
watch_logs: (bool, optional). Defaults to `False`.
|
126
|
+
The flag to watch the job run logs when a fine-tuning job is created.
|
125
127
|
force_overwrite: (bool, optional). Defaults to `False`.
|
126
128
|
Whether to force overwrite the existing file in object storage.
|
127
129
|
freeform_tags: (dict, optional)
|
@@ -148,6 +150,7 @@ class CreateFineTuningDetails(Serializable):
|
|
148
150
|
subnet_id: Optional[str] = None
|
149
151
|
log_id: Optional[str] = None
|
150
152
|
log_group_id: Optional[str] = None
|
153
|
+
watch_logs: Optional[bool] = False
|
151
154
|
force_overwrite: Optional[bool] = False
|
152
155
|
freeform_tags: Optional[dict] = None
|
153
156
|
defined_tags: Optional[dict] = None
|
@@ -4,6 +4,8 @@
|
|
4
4
|
|
5
5
|
import json
|
6
6
|
import os
|
7
|
+
import time
|
8
|
+
import traceback
|
7
9
|
from typing import Dict
|
8
10
|
|
9
11
|
from oci.data_science.models import (
|
@@ -149,6 +151,15 @@ class AquaFineTuningApp(AquaApp):
|
|
149
151
|
f"Logging is required for fine tuning if replica is larger than {DEFAULT_FT_REPLICA}."
|
150
152
|
)
|
151
153
|
|
154
|
+
if create_fine_tuning_details.watch_logs and not (
|
155
|
+
create_fine_tuning_details.log_id
|
156
|
+
and create_fine_tuning_details.log_group_id
|
157
|
+
):
|
158
|
+
raise AquaValueError(
|
159
|
+
"Logging is required for fine tuning if watch_logs is set to True. "
|
160
|
+
"Please provide log_id and log_group_id with the request parameters."
|
161
|
+
)
|
162
|
+
|
152
163
|
ft_parameters = self._get_finetuning_params(
|
153
164
|
create_fine_tuning_details.ft_parameters
|
154
165
|
)
|
@@ -382,6 +393,9 @@ class AquaFineTuningApp(AquaApp):
|
|
382
393
|
defined_tags=model_defined_tags,
|
383
394
|
),
|
384
395
|
)
|
396
|
+
logger.debug(
|
397
|
+
f"Successfully updated model custom metadata list and freeform tags for the model {ft_model.id}."
|
398
|
+
)
|
385
399
|
|
386
400
|
self.update_model_provenance(
|
387
401
|
model_id=ft_model.id,
|
@@ -389,6 +403,9 @@ class AquaFineTuningApp(AquaApp):
|
|
389
403
|
training_id=ft_job_run.id
|
390
404
|
),
|
391
405
|
)
|
406
|
+
logger.debug(
|
407
|
+
f"Successfully updated model provenance for the model {ft_model.id}."
|
408
|
+
)
|
392
409
|
|
393
410
|
# tracks the shape and replica used for fine-tuning the service models
|
394
411
|
telemetry_kwargs = (
|
@@ -416,6 +433,20 @@ class AquaFineTuningApp(AquaApp):
|
|
416
433
|
value=source.display_name,
|
417
434
|
)
|
418
435
|
|
436
|
+
if create_fine_tuning_details.watch_logs:
|
437
|
+
logger.info(
|
438
|
+
f"Watching fine-tuning job run logs for {ft_job_run.id}. Press Ctrl+C to stop watching logs.\n"
|
439
|
+
)
|
440
|
+
try:
|
441
|
+
ft_job_run.watch()
|
442
|
+
except KeyboardInterrupt:
|
443
|
+
logger.info(f"\nStopped watching logs for {ft_job_run.id}.\n")
|
444
|
+
time.sleep(1)
|
445
|
+
except Exception:
|
446
|
+
logger.debug(
|
447
|
+
f"Something unexpected occurred while watching logs.\n{traceback.format_exc()}"
|
448
|
+
)
|
449
|
+
|
419
450
|
return AquaFineTuningSummary(
|
420
451
|
id=ft_model.id,
|
421
452
|
name=ft_model.display_name,
|
@@ -564,7 +595,7 @@ class AquaFineTuningApp(AquaApp):
|
|
564
595
|
config = self.get_config(model_id, AQUA_MODEL_FINETUNING_CONFIG)
|
565
596
|
if not config:
|
566
597
|
logger.debug(
|
567
|
-
f"Fine-tuning config for custom model: {model_id} is not available."
|
598
|
+
f"Fine-tuning config for custom model: {model_id} is not available. Use defaults."
|
568
599
|
)
|
569
600
|
return config
|
570
601
|
|