oracle-ads 2.12.8__py3-none-any.whl → 2.12.10__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 +4 -3
- ads/aqua/app.py +40 -18
- ads/aqua/client/__init__.py +3 -0
- ads/aqua/client/client.py +799 -0
- ads/aqua/common/enums.py +3 -0
- ads/aqua/common/utils.py +62 -2
- ads/aqua/data.py +2 -19
- ads/aqua/evaluation/entities.py +6 -0
- ads/aqua/evaluation/evaluation.py +45 -15
- ads/aqua/extension/aqua_ws_msg_handler.py +14 -7
- ads/aqua/extension/base_handler.py +12 -9
- ads/aqua/extension/deployment_handler.py +8 -4
- ads/aqua/extension/finetune_handler.py +8 -14
- ads/aqua/extension/model_handler.py +30 -6
- ads/aqua/extension/ui_handler.py +13 -1
- ads/aqua/finetuning/constants.py +5 -2
- ads/aqua/finetuning/entities.py +73 -17
- ads/aqua/finetuning/finetuning.py +110 -82
- ads/aqua/model/entities.py +5 -1
- ads/aqua/model/model.py +230 -104
- ads/aqua/modeldeployment/deployment.py +35 -11
- ads/aqua/modeldeployment/entities.py +7 -4
- ads/aqua/ui.py +24 -2
- ads/cli.py +16 -8
- ads/common/auth.py +9 -9
- ads/llm/autogen/__init__.py +2 -0
- ads/llm/autogen/constants.py +15 -0
- ads/llm/autogen/reports/__init__.py +2 -0
- ads/llm/autogen/reports/base.py +67 -0
- ads/llm/autogen/reports/data.py +103 -0
- ads/llm/autogen/reports/session.py +526 -0
- ads/llm/autogen/reports/templates/chat_box.html +13 -0
- ads/llm/autogen/reports/templates/chat_box_lt.html +5 -0
- ads/llm/autogen/reports/templates/chat_box_rt.html +6 -0
- ads/llm/autogen/reports/utils.py +56 -0
- ads/llm/autogen/v02/__init__.py +4 -0
- ads/llm/autogen/{client_v02.py → v02/client.py} +23 -10
- ads/llm/autogen/v02/log_handlers/__init__.py +2 -0
- ads/llm/autogen/v02/log_handlers/oci_file_handler.py +83 -0
- ads/llm/autogen/v02/loggers/__init__.py +6 -0
- ads/llm/autogen/v02/loggers/metric_logger.py +320 -0
- ads/llm/autogen/v02/loggers/session_logger.py +580 -0
- ads/llm/autogen/v02/loggers/utils.py +86 -0
- ads/llm/autogen/v02/runtime_logging.py +163 -0
- ads/llm/guardrails/base.py +6 -5
- ads/llm/langchain/plugins/chat_models/oci_data_science.py +46 -20
- ads/llm/langchain/plugins/llms/oci_data_science_model_deployment_endpoint.py +38 -11
- ads/model/__init__.py +11 -13
- ads/model/artifact.py +47 -8
- ads/model/extractor/embedding_onnx_extractor.py +80 -0
- ads/model/framework/embedding_onnx_model.py +438 -0
- ads/model/generic_model.py +26 -24
- ads/model/model_metadata.py +8 -7
- ads/opctl/config/merger.py +13 -14
- ads/opctl/operator/common/operator_config.py +4 -4
- ads/opctl/operator/lowcode/common/transformations.py +50 -8
- ads/opctl/operator/lowcode/common/utils.py +22 -6
- ads/opctl/operator/lowcode/forecast/__main__.py +10 -0
- ads/opctl/operator/lowcode/forecast/const.py +3 -0
- ads/opctl/operator/lowcode/forecast/model/arima.py +19 -13
- ads/opctl/operator/lowcode/forecast/model/automlx.py +129 -36
- ads/opctl/operator/lowcode/forecast/model/autots.py +1 -0
- ads/opctl/operator/lowcode/forecast/model/base_model.py +58 -17
- ads/opctl/operator/lowcode/forecast/model/forecast_datasets.py +1 -1
- ads/opctl/operator/lowcode/forecast/model/neuralprophet.py +10 -3
- ads/opctl/operator/lowcode/forecast/model/prophet.py +25 -18
- ads/opctl/operator/lowcode/forecast/model_evaluator.py +3 -2
- ads/opctl/operator/lowcode/forecast/operator_config.py +31 -0
- ads/opctl/operator/lowcode/forecast/schema.yaml +76 -0
- ads/opctl/operator/lowcode/forecast/utils.py +8 -6
- 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/telemetry/base.py +18 -11
- ads/telemetry/client.py +33 -13
- ads/templates/schemas/openapi.json +1740 -0
- ads/templates/score_embedding_onnx.jinja2 +202 -0
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10.dist-info}/METADATA +11 -10
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10.dist-info}/RECORD +82 -56
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10.dist-info}/LICENSE.txt +0 -0
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10.dist-info}/WHEEL +0 -0
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10.dist-info}/entry_points.txt +0 -0
ads/aqua/common/enums.py
CHANGED
@@ -52,6 +52,9 @@ class InferenceContainerTypeFamily(str, metaclass=ExtendedEnumMeta):
|
|
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
|
+
|
56
|
+
|
57
|
+
class CustomInferenceContainerTypeFamily(str, metaclass=ExtendedEnumMeta):
|
55
58
|
AQUA_TEI_CONTAINER_FAMILY = "odsc-tei-serving"
|
56
59
|
|
57
60
|
|
ads/aqua/common/utils.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
|
"""AQUA utils and constants."""
|
5
5
|
|
@@ -11,6 +11,7 @@ import os
|
|
11
11
|
import random
|
12
12
|
import re
|
13
13
|
import shlex
|
14
|
+
import shutil
|
14
15
|
import subprocess
|
15
16
|
from datetime import datetime, timedelta
|
16
17
|
from functools import wraps
|
@@ -21,6 +22,8 @@ from typing import List, Union
|
|
21
22
|
import fsspec
|
22
23
|
import oci
|
23
24
|
from cachetools import TTLCache, cached
|
25
|
+
from huggingface_hub.constants import HF_HUB_CACHE
|
26
|
+
from huggingface_hub.file_download import repo_folder_name
|
24
27
|
from huggingface_hub.hf_api import HfApi, ModelInfo
|
25
28
|
from huggingface_hub.utils import (
|
26
29
|
GatedRepoError,
|
@@ -30,6 +33,7 @@ from huggingface_hub.utils import (
|
|
30
33
|
)
|
31
34
|
from oci.data_science.models import JobRun, Model
|
32
35
|
from oci.object_storage.models import ObjectSummary
|
36
|
+
from pydantic import ValidationError
|
33
37
|
|
34
38
|
from ads.aqua.common.enums import (
|
35
39
|
InferenceContainerParamType,
|
@@ -788,7 +792,9 @@ def get_ocid_substring(ocid: str, key_len: int) -> str:
|
|
788
792
|
return ocid[-key_len:] if ocid and len(ocid) > key_len else ""
|
789
793
|
|
790
794
|
|
791
|
-
def upload_folder(
|
795
|
+
def upload_folder(
|
796
|
+
os_path: str, local_dir: str, model_name: str, exclude_pattern: str = None
|
797
|
+
) -> str:
|
792
798
|
"""Upload the local folder to the object storage
|
793
799
|
|
794
800
|
Args:
|
@@ -818,6 +824,48 @@ def upload_folder(os_path: str, local_dir: str, model_name: str, exclude_pattern
|
|
818
824
|
return f"oci://{os_details.bucket}@{os_details.namespace}" + "/" + object_path
|
819
825
|
|
820
826
|
|
827
|
+
def cleanup_local_hf_model_artifact(
|
828
|
+
model_name: str,
|
829
|
+
local_dir: str = None,
|
830
|
+
):
|
831
|
+
"""
|
832
|
+
Helper function that deletes local artifacts downloaded from Hugging Face to free up disk space.
|
833
|
+
Parameters
|
834
|
+
----------
|
835
|
+
model_name (str): Name of the huggingface model
|
836
|
+
local_dir (str): Local directory where the object is downloaded
|
837
|
+
|
838
|
+
"""
|
839
|
+
if local_dir and os.path.exists(local_dir):
|
840
|
+
model_dir = os.path.join(local_dir, model_name)
|
841
|
+
model_dir = (
|
842
|
+
os.path.dirname(model_dir)
|
843
|
+
if "/" in model_name or os.sep in model_name
|
844
|
+
else model_dir
|
845
|
+
)
|
846
|
+
shutil.rmtree(model_dir, ignore_errors=True)
|
847
|
+
if os.path.exists(model_dir):
|
848
|
+
logger.debug(
|
849
|
+
f"Could not delete local model artifact directory: {model_dir}"
|
850
|
+
)
|
851
|
+
else:
|
852
|
+
logger.debug(f"Deleted local model artifact directory: {model_dir}.")
|
853
|
+
|
854
|
+
hf_local_path = os.path.join(
|
855
|
+
HF_HUB_CACHE, repo_folder_name(repo_id=model_name, repo_type="model")
|
856
|
+
)
|
857
|
+
shutil.rmtree(hf_local_path, ignore_errors=True)
|
858
|
+
|
859
|
+
if os.path.exists(hf_local_path):
|
860
|
+
logger.debug(
|
861
|
+
f"Could not clear the local Hugging Face cache directory {hf_local_path} for the model {model_name}."
|
862
|
+
)
|
863
|
+
else:
|
864
|
+
logger.debug(
|
865
|
+
f"Cleared contents of local Hugging Face cache directory {hf_local_path} for the model {model_name}."
|
866
|
+
)
|
867
|
+
|
868
|
+
|
821
869
|
def is_service_managed_container(container):
|
822
870
|
return container and container.startswith(SERVICE_MANAGED_CONTAINER_URI_SCHEME)
|
823
871
|
|
@@ -1159,3 +1207,15 @@ def validate_cmd_var(cmd_var: List[str], overrides: List[str]) -> List[str]:
|
|
1159
1207
|
|
1160
1208
|
combined_cmd_var = cmd_var + overrides
|
1161
1209
|
return combined_cmd_var
|
1210
|
+
|
1211
|
+
|
1212
|
+
def build_pydantic_error_message(ex: ValidationError):
|
1213
|
+
"""Added to handle error messages from pydantic model validator.
|
1214
|
+
Combine both loc and msg for errors where loc (field) is present in error details, else only build error
|
1215
|
+
message using msg field."""
|
1216
|
+
|
1217
|
+
return {
|
1218
|
+
".".join(map(str, e["loc"])): e["msg"]
|
1219
|
+
for e in ex.errors()
|
1220
|
+
if "loc" in e and e["loc"]
|
1221
|
+
} or "; ".join(e["msg"] for e in ex.errors())
|
ads/aqua/data.py
CHANGED
@@ -1,9 +1,8 @@
|
|
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
|
-
from dataclasses import dataclass
|
5
|
+
from dataclasses import dataclass
|
7
6
|
|
8
7
|
from ads.common.serializer import DataClassSerializable
|
9
8
|
|
@@ -13,19 +12,3 @@ class AquaResourceIdentifier(DataClassSerializable):
|
|
13
12
|
id: str = ""
|
14
13
|
name: str = ""
|
15
14
|
url: str = ""
|
16
|
-
|
17
|
-
|
18
|
-
@dataclass(repr=False)
|
19
|
-
class AquaJobSummary(DataClassSerializable):
|
20
|
-
"""Represents an Aqua job summary."""
|
21
|
-
|
22
|
-
id: str
|
23
|
-
name: str
|
24
|
-
console_url: str
|
25
|
-
lifecycle_state: str
|
26
|
-
lifecycle_details: str
|
27
|
-
time_created: str
|
28
|
-
tags: dict
|
29
|
-
experiment: AquaResourceIdentifier = field(default_factory=AquaResourceIdentifier)
|
30
|
-
source: AquaResourceIdentifier = field(default_factory=AquaResourceIdentifier)
|
31
|
-
job: AquaResourceIdentifier = field(default_factory=AquaResourceIdentifier)
|
ads/aqua/evaluation/entities.py
CHANGED
@@ -64,6 +64,10 @@ class CreateAquaEvaluationDetails(Serializable):
|
|
64
64
|
The metrics for the evaluation.
|
65
65
|
force_overwrite: (bool, optional). Defaults to `False`.
|
66
66
|
Whether to force overwrite the existing file in object storage.
|
67
|
+
freeform_tags: (dict, optional)
|
68
|
+
Freeform tags for the evaluation model
|
69
|
+
defined_tags: (dict, optional)
|
70
|
+
Defined tags for the evaluation model
|
67
71
|
"""
|
68
72
|
|
69
73
|
evaluation_source_id: str
|
@@ -85,6 +89,8 @@ class CreateAquaEvaluationDetails(Serializable):
|
|
85
89
|
log_id: Optional[str] = None
|
86
90
|
metrics: Optional[List[Dict[str, Any]]] = None
|
87
91
|
force_overwrite: Optional[bool] = False
|
92
|
+
freeform_tags: Optional[dict] = None
|
93
|
+
defined_tags: Optional[dict] = None
|
88
94
|
|
89
95
|
class Config:
|
90
96
|
extra = "ignore"
|
@@ -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
|
)
|
@@ -297,6 +297,10 @@ class AquaEvaluationApp(AquaApp):
|
|
297
297
|
evaluation_mvs_freeform_tags = {
|
298
298
|
Tags.AQUA_EVALUATION: Tags.AQUA_EVALUATION,
|
299
299
|
}
|
300
|
+
evaluation_mvs_freeform_tags = {
|
301
|
+
**evaluation_mvs_freeform_tags,
|
302
|
+
**(create_aqua_evaluation_details.freeform_tags or {}),
|
303
|
+
}
|
300
304
|
|
301
305
|
model_version_set = (
|
302
306
|
ModelVersionSet()
|
@@ -307,6 +311,9 @@ class AquaEvaluationApp(AquaApp):
|
|
307
311
|
create_aqua_evaluation_details.experiment_description
|
308
312
|
)
|
309
313
|
.with_freeform_tags(**evaluation_mvs_freeform_tags)
|
314
|
+
.with_defined_tags(
|
315
|
+
**(create_aqua_evaluation_details.defined_tags or {})
|
316
|
+
)
|
310
317
|
# TODO: decide what parameters will be needed
|
311
318
|
.create(**kwargs)
|
312
319
|
)
|
@@ -369,6 +376,10 @@ class AquaEvaluationApp(AquaApp):
|
|
369
376
|
Tags.AQUA_EVALUATION: Tags.AQUA_EVALUATION,
|
370
377
|
Tags.AQUA_EVALUATION_MODEL_ID: evaluation_model.id,
|
371
378
|
}
|
379
|
+
evaluation_job_freeform_tags = {
|
380
|
+
**evaluation_job_freeform_tags,
|
381
|
+
**(create_aqua_evaluation_details.freeform_tags or {}),
|
382
|
+
}
|
372
383
|
|
373
384
|
evaluation_job = Job(name=evaluation_model.display_name).with_infrastructure(
|
374
385
|
DataScienceJob()
|
@@ -379,6 +390,7 @@ class AquaEvaluationApp(AquaApp):
|
|
379
390
|
.with_shape_name(create_aqua_evaluation_details.shape_name)
|
380
391
|
.with_block_storage_size(create_aqua_evaluation_details.block_storage_size)
|
381
392
|
.with_freeform_tag(**evaluation_job_freeform_tags)
|
393
|
+
.with_defined_tag(**(create_aqua_evaluation_details.defined_tags or {}))
|
382
394
|
)
|
383
395
|
if (
|
384
396
|
create_aqua_evaluation_details.memory_in_gbs
|
@@ -425,6 +437,7 @@ class AquaEvaluationApp(AquaApp):
|
|
425
437
|
evaluation_job_run = evaluation_job.run(
|
426
438
|
name=evaluation_model.display_name,
|
427
439
|
freeform_tags=evaluation_job_freeform_tags,
|
440
|
+
defined_tags=(create_aqua_evaluation_details.defined_tags or {}),
|
428
441
|
wait=False,
|
429
442
|
)
|
430
443
|
logger.debug(
|
@@ -444,13 +457,20 @@ class AquaEvaluationApp(AquaApp):
|
|
444
457
|
for metadata in evaluation_model_custom_metadata.to_dict()["data"]
|
445
458
|
]
|
446
459
|
|
460
|
+
evaluation_model_freeform_tags = {
|
461
|
+
Tags.AQUA_EVALUATION: Tags.AQUA_EVALUATION,
|
462
|
+
**(create_aqua_evaluation_details.freeform_tags or {}),
|
463
|
+
}
|
464
|
+
evaluation_model_defined_tags = (
|
465
|
+
create_aqua_evaluation_details.defined_tags or {}
|
466
|
+
)
|
467
|
+
|
447
468
|
self.ds_client.update_model(
|
448
469
|
model_id=evaluation_model.id,
|
449
470
|
update_model_details=UpdateModelDetails(
|
450
471
|
custom_metadata_list=updated_custom_metadata_list,
|
451
|
-
freeform_tags=
|
452
|
-
|
453
|
-
},
|
472
|
+
freeform_tags=evaluation_model_freeform_tags,
|
473
|
+
defined_tags=evaluation_model_defined_tags,
|
454
474
|
),
|
455
475
|
)
|
456
476
|
|
@@ -524,6 +544,8 @@ class AquaEvaluationApp(AquaApp):
|
|
524
544
|
"evaluation_job_id": evaluation_job.id,
|
525
545
|
"evaluation_source": create_aqua_evaluation_details.evaluation_source_id,
|
526
546
|
"evaluation_experiment_id": experiment_model_version_set_id,
|
547
|
+
**evaluation_model_freeform_tags,
|
548
|
+
**evaluation_model_defined_tags,
|
527
549
|
},
|
528
550
|
parameters=AquaEvalParams(),
|
529
551
|
)
|
@@ -689,21 +711,27 @@ class AquaEvaluationApp(AquaApp):
|
|
689
711
|
try:
|
690
712
|
log = utils.query_resource(log_id, return_all=False)
|
691
713
|
log_name = log.display_name if log else ""
|
692
|
-
except Exception:
|
714
|
+
except Exception as ex:
|
715
|
+
logger.debug(f"Failed to get associated log name. Error: {ex}")
|
693
716
|
pass
|
694
717
|
|
695
718
|
if loggroup_id:
|
696
719
|
try:
|
697
720
|
loggroup = utils.query_resource(loggroup_id, return_all=False)
|
698
721
|
loggroup_name = loggroup.display_name if loggroup else ""
|
699
|
-
except Exception:
|
722
|
+
except Exception as ex:
|
723
|
+
logger.debug(f"Failed to get associated loggroup name. Error: {ex}")
|
700
724
|
pass
|
701
725
|
|
702
726
|
try:
|
703
727
|
introspection = json.loads(
|
704
728
|
self._get_attribute_from_model_metadata(resource, "ArtifactTestResults")
|
705
729
|
)
|
706
|
-
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
|
+
)
|
707
735
|
introspection = {}
|
708
736
|
|
709
737
|
summary = AquaEvaluationDetail(
|
@@ -856,13 +884,13 @@ class AquaEvaluationApp(AquaApp):
|
|
856
884
|
try:
|
857
885
|
log_id = job_run_details.log_details.log_id
|
858
886
|
except Exception as e:
|
859
|
-
logger.debug(f"Failed to get associated log
|
887
|
+
logger.debug(f"Failed to get associated log.\nError: {str(e)}")
|
860
888
|
log_id = ""
|
861
889
|
|
862
890
|
try:
|
863
891
|
loggroup_id = job_run_details.log_details.log_group_id
|
864
892
|
except Exception as e:
|
865
|
-
logger.debug(f"Failed to get associated log
|
893
|
+
logger.debug(f"Failed to get associated log.\nError: {str(e)}")
|
866
894
|
loggroup_id = ""
|
867
895
|
|
868
896
|
loggroup_url = get_log_links(region=self.region, log_group_id=loggroup_id)
|
@@ -936,7 +964,7 @@ class AquaEvaluationApp(AquaApp):
|
|
936
964
|
)
|
937
965
|
except Exception as e:
|
938
966
|
logger.debug(
|
939
|
-
"Failed to load `report.json` from evaluation artifact
|
967
|
+
f"Failed to load `report.json` from evaluation artifact.\nError: {str(e)}"
|
940
968
|
)
|
941
969
|
json_report = {}
|
942
970
|
|
@@ -1025,6 +1053,7 @@ class AquaEvaluationApp(AquaApp):
|
|
1025
1053
|
return report
|
1026
1054
|
|
1027
1055
|
with tempfile.TemporaryDirectory() as temp_dir:
|
1056
|
+
logger.info(f"Downloading evaluation artifact for {eval_id}.")
|
1028
1057
|
DataScienceModel.from_id(eval_id).download_artifact(
|
1029
1058
|
temp_dir,
|
1030
1059
|
auth=self._auth,
|
@@ -1178,6 +1207,7 @@ class AquaEvaluationApp(AquaApp):
|
|
1178
1207
|
def load_evaluation_config(self, container: Optional[str] = None) -> Dict:
|
1179
1208
|
"""Loads evaluation config."""
|
1180
1209
|
|
1210
|
+
logger.info("Loading evaluation container config.")
|
1181
1211
|
# retrieve the evaluation config by container family name
|
1182
1212
|
evaluation_config = get_evaluation_service_config(container)
|
1183
1213
|
|
@@ -1257,9 +1287,9 @@ class AquaEvaluationApp(AquaApp):
|
|
1257
1287
|
raise AquaRuntimeError(
|
1258
1288
|
f"Not supported source type: {resource_type}"
|
1259
1289
|
)
|
1260
|
-
except Exception:
|
1290
|
+
except Exception as ex:
|
1261
1291
|
logger.debug(
|
1262
|
-
f"Failed to retrieve source information for evaluation {evaluation.identifier}
|
1292
|
+
f"Failed to retrieve source information for evaluation {evaluation.identifier}.\nError: {str(ex)}"
|
1263
1293
|
)
|
1264
1294
|
source_name = ""
|
1265
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))
|
@@ -59,7 +59,7 @@ class AquaDeploymentHandler(AquaAPIhandler):
|
|
59
59
|
return self.finish(AquaDeploymentApp().delete(model_deployment_id))
|
60
60
|
|
61
61
|
@handle_exceptions
|
62
|
-
def put(self, *args, **kwargs):
|
62
|
+
def put(self, *args, **kwargs): # noqa: ARG002
|
63
63
|
"""
|
64
64
|
Handles put request for the activating and deactivating OCI datascience model deployments
|
65
65
|
Raises
|
@@ -82,7 +82,7 @@ class AquaDeploymentHandler(AquaAPIhandler):
|
|
82
82
|
raise HTTPError(400, f"The request {self.request.path} is invalid.")
|
83
83
|
|
84
84
|
@handle_exceptions
|
85
|
-
def post(self, *args, **kwargs):
|
85
|
+
def post(self, *args, **kwargs): # noqa: ARG002
|
86
86
|
"""
|
87
87
|
Handles post request for the deployment APIs
|
88
88
|
Raises
|
@@ -132,6 +132,8 @@ class AquaDeploymentHandler(AquaAPIhandler):
|
|
132
132
|
private_endpoint_id = input_data.get("private_endpoint_id")
|
133
133
|
container_image_uri = input_data.get("container_image_uri")
|
134
134
|
cmd_var = input_data.get("cmd_var")
|
135
|
+
freeform_tags = input_data.get("freeform_tags")
|
136
|
+
defined_tags = input_data.get("defined_tags")
|
135
137
|
|
136
138
|
self.finish(
|
137
139
|
AquaDeploymentApp().create(
|
@@ -157,6 +159,8 @@ class AquaDeploymentHandler(AquaAPIhandler):
|
|
157
159
|
private_endpoint_id=private_endpoint_id,
|
158
160
|
container_image_uri=container_image_uri,
|
159
161
|
cmd_var=cmd_var,
|
162
|
+
freeform_tags=freeform_tags,
|
163
|
+
defined_tags=defined_tags,
|
160
164
|
)
|
161
165
|
)
|
162
166
|
|
@@ -196,7 +200,7 @@ class AquaDeploymentInferenceHandler(AquaAPIhandler):
|
|
196
200
|
return False
|
197
201
|
|
198
202
|
@handle_exceptions
|
199
|
-
def post(self, *args, **kwargs):
|
203
|
+
def post(self, *args, **kwargs): # noqa: ARG002
|
200
204
|
"""
|
201
205
|
Handles inference request for the Active Model Deployments
|
202
206
|
Raises
|
@@ -262,7 +266,7 @@ class AquaDeploymentParamsHandler(AquaAPIhandler):
|
|
262
266
|
)
|
263
267
|
|
264
268
|
@handle_exceptions
|
265
|
-
def post(self, *args, **kwargs):
|
269
|
+
def post(self, *args, **kwargs): # noqa: ARG002
|
266
270
|
"""Handles post request for the deployment param handler API.
|
267
271
|
|
268
272
|
Raises
|
@@ -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
|
|
@@ -10,9 +10,7 @@ from tornado.web import HTTPError
|
|
10
10
|
from ads.aqua.common.decorator import handle_exceptions
|
11
11
|
from ads.aqua.extension.base_handler import AquaAPIhandler
|
12
12
|
from ads.aqua.extension.errors import Errors
|
13
|
-
from ads.aqua.extension.utils import validate_function_parameters
|
14
13
|
from ads.aqua.finetuning import AquaFineTuningApp
|
15
|
-
from ads.aqua.finetuning.entities import CreateFineTuningDetails
|
16
14
|
|
17
15
|
|
18
16
|
class AquaFineTuneHandler(AquaAPIhandler):
|
@@ -33,7 +31,7 @@ class AquaFineTuneHandler(AquaAPIhandler):
|
|
33
31
|
raise HTTPError(400, f"The request {self.request.path} is invalid.")
|
34
32
|
|
35
33
|
@handle_exceptions
|
36
|
-
def post(self, *args, **kwargs):
|
34
|
+
def post(self, *args, **kwargs): # noqa: ARG002
|
37
35
|
"""Handles post request for the fine-tuning API
|
38
36
|
|
39
37
|
Raises
|
@@ -43,17 +41,13 @@ class AquaFineTuneHandler(AquaAPIhandler):
|
|
43
41
|
"""
|
44
42
|
try:
|
45
43
|
input_data = self.get_json_body()
|
46
|
-
except Exception:
|
47
|
-
raise HTTPError(400, Errors.INVALID_INPUT_DATA_FORMAT)
|
44
|
+
except Exception as ex:
|
45
|
+
raise HTTPError(400, Errors.INVALID_INPUT_DATA_FORMAT) from ex
|
48
46
|
|
49
47
|
if not input_data:
|
50
48
|
raise HTTPError(400, Errors.NO_INPUT_DATA)
|
51
49
|
|
52
|
-
|
53
|
-
data_class=CreateFineTuningDetails, input_data=input_data
|
54
|
-
)
|
55
|
-
|
56
|
-
self.finish(AquaFineTuningApp().create(CreateFineTuningDetails(**input_data)))
|
50
|
+
self.finish(AquaFineTuningApp().create(**input_data))
|
57
51
|
|
58
52
|
def get_finetuning_config(self, model_id):
|
59
53
|
"""Gets the finetuning config for Aqua model."""
|
@@ -71,7 +65,7 @@ class AquaFineTuneParamsHandler(AquaAPIhandler):
|
|
71
65
|
)
|
72
66
|
|
73
67
|
@handle_exceptions
|
74
|
-
def post(self, *args, **kwargs):
|
68
|
+
def post(self, *args, **kwargs): # noqa: ARG002
|
75
69
|
"""Handles post request for the finetuning param handler API.
|
76
70
|
|
77
71
|
Raises
|
@@ -81,8 +75,8 @@ class AquaFineTuneParamsHandler(AquaAPIhandler):
|
|
81
75
|
"""
|
82
76
|
try:
|
83
77
|
input_data = self.get_json_body()
|
84
|
-
except Exception:
|
85
|
-
raise HTTPError(400, Errors.INVALID_INPUT_DATA_FORMAT)
|
78
|
+
except Exception as ex:
|
79
|
+
raise HTTPError(400, Errors.INVALID_INPUT_DATA_FORMAT) from ex
|
86
80
|
|
87
81
|
if not input_data:
|
88
82
|
raise HTTPError(400, Errors.NO_INPUT_DATA)
|