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.
Files changed (66) hide show
  1. ads/aqua/__init__.py +2 -1
  2. ads/aqua/app.py +46 -19
  3. ads/aqua/client/__init__.py +3 -0
  4. ads/aqua/client/client.py +799 -0
  5. ads/aqua/common/enums.py +19 -14
  6. ads/aqua/common/errors.py +3 -4
  7. ads/aqua/common/utils.py +2 -2
  8. ads/aqua/constants.py +1 -0
  9. ads/aqua/evaluation/constants.py +7 -7
  10. ads/aqua/evaluation/errors.py +3 -4
  11. ads/aqua/evaluation/evaluation.py +20 -12
  12. ads/aqua/extension/aqua_ws_msg_handler.py +14 -7
  13. ads/aqua/extension/base_handler.py +12 -9
  14. ads/aqua/extension/model_handler.py +29 -1
  15. ads/aqua/extension/models/ws_models.py +5 -6
  16. ads/aqua/finetuning/constants.py +3 -3
  17. ads/aqua/finetuning/entities.py +3 -0
  18. ads/aqua/finetuning/finetuning.py +32 -1
  19. ads/aqua/model/constants.py +7 -7
  20. ads/aqua/model/entities.py +2 -1
  21. ads/aqua/model/enums.py +4 -5
  22. ads/aqua/model/model.py +158 -76
  23. ads/aqua/modeldeployment/deployment.py +22 -10
  24. ads/aqua/modeldeployment/entities.py +3 -1
  25. ads/cli.py +16 -8
  26. ads/common/auth.py +33 -20
  27. ads/common/extended_enum.py +52 -44
  28. ads/llm/__init__.py +11 -8
  29. ads/llm/langchain/plugins/embeddings/__init__.py +4 -0
  30. ads/llm/langchain/plugins/embeddings/oci_data_science_model_deployment_endpoint.py +184 -0
  31. ads/model/artifact_downloader.py +3 -4
  32. ads/model/datascience_model.py +84 -64
  33. ads/model/generic_model.py +3 -3
  34. ads/model/model_metadata.py +17 -11
  35. ads/model/service/oci_datascience_model.py +12 -14
  36. ads/opctl/backend/marketplace/helm_helper.py +13 -14
  37. ads/opctl/cli.py +4 -5
  38. ads/opctl/cmds.py +28 -32
  39. ads/opctl/config/merger.py +8 -11
  40. ads/opctl/config/resolver.py +25 -30
  41. ads/opctl/operator/cli.py +9 -9
  42. ads/opctl/operator/common/backend_factory.py +56 -60
  43. ads/opctl/operator/common/const.py +5 -5
  44. ads/opctl/operator/lowcode/anomaly/const.py +8 -9
  45. ads/opctl/operator/lowcode/common/transformations.py +38 -3
  46. ads/opctl/operator/lowcode/common/utils.py +11 -1
  47. ads/opctl/operator/lowcode/feature_store_marketplace/operator_utils.py +43 -48
  48. ads/opctl/operator/lowcode/forecast/__main__.py +10 -0
  49. ads/opctl/operator/lowcode/forecast/const.py +6 -6
  50. ads/opctl/operator/lowcode/forecast/model/forecast_datasets.py +1 -1
  51. ads/opctl/operator/lowcode/forecast/operator_config.py +31 -0
  52. ads/opctl/operator/lowcode/forecast/schema.yaml +63 -0
  53. ads/opctl/operator/lowcode/forecast/whatifserve/__init__.py +7 -0
  54. ads/opctl/operator/lowcode/forecast/whatifserve/deployment_manager.py +233 -0
  55. ads/opctl/operator/lowcode/forecast/whatifserve/score.py +238 -0
  56. ads/opctl/operator/lowcode/pii/constant.py +6 -7
  57. ads/opctl/operator/lowcode/recommender/constant.py +12 -7
  58. ads/opctl/operator/runtime/marketplace_runtime.py +4 -10
  59. ads/opctl/operator/runtime/runtime.py +4 -6
  60. ads/pipeline/ads_pipeline_run.py +13 -25
  61. ads/pipeline/visualizer/graph_renderer.py +3 -4
  62. {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/METADATA +4 -2
  63. {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/RECORD +66 -59
  64. {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/LICENSE.txt +0 -0
  65. {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/WHEEL +0 -0
  66. {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 ExtendedEnumMeta
11
+ from ads.common.extended_enum import ExtendedEnum
12
12
 
13
13
 
14
- class DataScienceResource(str, metaclass=ExtendedEnumMeta):
14
+ class DataScienceResource(ExtendedEnum):
15
15
  MODEL_DEPLOYMENT = "datasciencemodeldeployment"
16
16
  MODEL = "datasciencemodel"
17
17
 
18
18
 
19
- class Resource(str, metaclass=ExtendedEnumMeta):
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(str, metaclass=ExtendedEnumMeta):
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(str, metaclass=ExtendedEnumMeta):
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(str, metaclass=ExtendedEnumMeta):
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(str, metaclass=ExtendedEnumMeta):
57
+ class CustomInferenceContainerTypeFamily(ExtendedEnum):
58
58
  AQUA_TEI_CONTAINER_FAMILY = "odsc-tei-serving"
59
59
 
60
60
 
61
- class InferenceContainerParamType(str, metaclass=ExtendedEnumMeta):
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(str, metaclass=ExtendedEnumMeta):
67
+ class EvaluationContainerTypeFamily(ExtendedEnum):
68
68
  AQUA_EVALUATION_CONTAINER_FAMILY = "odsc-llm-evaluate"
69
69
 
70
70
 
71
- class FineTuningContainerTypeFamily(str, metaclass=ExtendedEnumMeta):
71
+ class FineTuningContainerTypeFamily(ExtendedEnum):
72
72
  AQUA_FINETUNING_CONTAINER_FAMILY = "odsc-llm-fine-tuning"
73
73
 
74
74
 
75
- class HuggingFaceTags(str, metaclass=ExtendedEnumMeta):
75
+ class HuggingFaceTags(ExtendedEnum):
76
76
  TEXT_GENERATION_INFERENCE = "text-generation-inference"
77
77
 
78
78
 
79
- class RqsAdditionalDetails(str, metaclass=ExtendedEnumMeta):
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(str, metaclass=ExtendedEnumMeta):
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
- # -*- coding: utf-8 -*-
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 ExtendedEnumMeta
12
+ from ads.common.extended_enum import ExtendedEnum
14
13
 
15
14
 
16
- class ExitCode(str, metaclass=ExtendedEnumMeta):
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 ExtendedEnumMeta
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(str, metaclass=ExtendedEnumMeta):
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"
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
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 ExtendedEnumMeta
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(str, metaclass=ExtendedEnumMeta):
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(str, metaclass=ExtendedEnumMeta):
31
+ class EvaluationConfig(ExtendedEnum):
32
32
  PARAMS = "model_params"
33
33
 
34
34
 
35
- class EvaluationReportJson(str, metaclass=ExtendedEnumMeta):
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(str, metaclass=ExtendedEnumMeta):
46
+ class EvaluationMetricResult(ExtendedEnum):
47
47
  """Contains metric result's fields name in report.json."""
48
48
 
49
49
  SHORT_NAME = "key"
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
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 ExtendedEnumMeta
11
+ from ads.common.extended_enum import ExtendedEnum
13
12
 
14
13
 
15
- class EvaluationJobExitCode(str, metaclass=ExtendedEnumMeta):
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.debug(
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. {str(e)}")
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. {str(e)}")
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" f"{str(e)}"
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("".join(traceback.format_exception(*exc_info)))
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
- else:
78
- logger.warning(reply["message"])
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
- # -*- coding: utf-8 -*-
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("".join(traceback.format_exception(*exc_info)))
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.warning(reply["message"])
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", "true")).lower() == "true"
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 AquaEvaluationSummary, AquaEvaluationDetail
11
- from ads.aqua.model.entities import AquaModelSummary, AquaModel
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 ExtendedEnumMeta
12
+ from ads.common.extended_enum import ExtendedEnum
14
13
  from ads.common.serializer import DataClassSerializable
15
14
 
16
15
 
17
- class RequestResponseType(str, metaclass=ExtendedEnumMeta):
16
+ class RequestResponseType(ExtendedEnum):
18
17
  ListEvaluations = "ListEvaluations"
19
18
  EvaluationDetails = "EvaluationDetails"
20
19
  ListDeployments = "ListDeployments"
@@ -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 ExtendedEnumMeta
5
+ from ads.common.extended_enum import ExtendedEnum
6
6
 
7
7
 
8
- class FineTuneCustomMetadata(str, metaclass=ExtendedEnumMeta):
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(str, metaclass=ExtendedEnumMeta):
19
+ class FineTuningRestrictedParams(ExtendedEnum):
20
20
  OPTIMIZER = "optimizer"
21
21
 
22
22
 
@@ -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