oracle-ads 2.12.8__py3-none-any.whl → 2.12.10rc0__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 -4
- ads/aqua/app.py +12 -2
- 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 +25 -3
- ads/aqua/extension/deployment_handler.py +8 -4
- ads/aqua/extension/finetune_handler.py +8 -14
- ads/aqua/extension/model_handler.py +25 -6
- ads/aqua/extension/ui_handler.py +13 -1
- ads/aqua/finetuning/constants.py +5 -2
- ads/aqua/finetuning/entities.py +70 -17
- ads/aqua/finetuning/finetuning.py +79 -82
- ads/aqua/model/entities.py +4 -1
- ads/aqua/model/model.py +95 -29
- ads/aqua/modeldeployment/deployment.py +13 -1
- ads/aqua/modeldeployment/entities.py +7 -4
- ads/aqua/ui.py +24 -2
- 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 +12 -5
- ads/opctl/operator/lowcode/common/utils.py +11 -5
- 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/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/schema.yaml +13 -0
- ads/opctl/operator/lowcode/forecast/utils.py +8 -6
- 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.10rc0.dist-info}/METADATA +9 -10
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10rc0.dist-info}/RECORD +71 -50
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10rc0.dist-info}/LICENSE.txt +0 -0
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10rc0.dist-info}/WHEEL +0 -0
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10rc0.dist-info}/entry_points.txt +0 -0
ads/aqua/__init__.py
CHANGED
@@ -1,12 +1,12 @@
|
|
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
|
|
7
6
|
import os
|
7
|
+
from logging import getLogger
|
8
8
|
|
9
|
-
from ads import
|
9
|
+
from ads import set_auth
|
10
10
|
from ads.aqua.common.utils import fetch_service_compartment
|
11
11
|
from ads.config import OCI_RESOURCE_PRINCIPAL_VERSION
|
12
12
|
|
@@ -19,6 +19,7 @@ def get_logger_level():
|
|
19
19
|
return level
|
20
20
|
|
21
21
|
|
22
|
+
logger = getLogger(__name__)
|
22
23
|
logger.setLevel(get_logger_level())
|
23
24
|
|
24
25
|
|
@@ -27,7 +28,6 @@ def set_log_level(log_level: str):
|
|
27
28
|
|
28
29
|
log_level = log_level.upper()
|
29
30
|
logger.setLevel(log_level.upper())
|
30
|
-
logger.handlers[0].setLevel(log_level)
|
31
31
|
|
32
32
|
|
33
33
|
if OCI_RESOURCE_PRINCIPAL_VERSION:
|
ads/aqua/app.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
# Copyright (c) 2024 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
|
+
import json
|
5
6
|
import os
|
6
7
|
from dataclasses import fields
|
7
8
|
from typing import Dict, Union
|
@@ -135,6 +136,8 @@ class AquaApp:
|
|
135
136
|
description: str = None,
|
136
137
|
compartment_id: str = None,
|
137
138
|
project_id: str = None,
|
139
|
+
freeform_tags: dict = None,
|
140
|
+
defined_tags: dict = None,
|
138
141
|
**kwargs,
|
139
142
|
) -> tuple:
|
140
143
|
"""Creates ModelVersionSet from given ID or Name.
|
@@ -153,7 +156,10 @@ class AquaApp:
|
|
153
156
|
Project OCID.
|
154
157
|
tag: (str, optional)
|
155
158
|
calling tag, can be Tags.AQUA_FINE_TUNING or Tags.AQUA_EVALUATION
|
156
|
-
|
159
|
+
freeform_tags: (dict, optional)
|
160
|
+
Freeform tags for the model version set
|
161
|
+
defined_tags: (dict, optional)
|
162
|
+
Defined tags for the model version set
|
157
163
|
Returns
|
158
164
|
-------
|
159
165
|
tuple: (model_version_set_id, model_version_set_name)
|
@@ -182,6 +188,7 @@ class AquaApp:
|
|
182
188
|
mvs_freeform_tags = {
|
183
189
|
tag: tag,
|
184
190
|
}
|
191
|
+
mvs_freeform_tags = {**mvs_freeform_tags, **(freeform_tags or {})}
|
185
192
|
model_version_set = (
|
186
193
|
ModelVersionSet()
|
187
194
|
.with_compartment_id(compartment_id)
|
@@ -189,6 +196,7 @@ class AquaApp:
|
|
189
196
|
.with_name(model_version_set_name)
|
190
197
|
.with_description(description)
|
191
198
|
.with_freeform_tags(**mvs_freeform_tags)
|
199
|
+
.with_defined_tags(**(defined_tags or {}))
|
192
200
|
# TODO: decide what parameters will be needed
|
193
201
|
# when refactor eval to use this method, we need to pass tag here.
|
194
202
|
.create(**kwargs)
|
@@ -340,7 +348,9 @@ class CLIBuilderMixin:
|
|
340
348
|
"""
|
341
349
|
cmd = f"ads aqua {self._command}"
|
342
350
|
params = [
|
343
|
-
f"--{field.name} {getattr(self,field.name)}"
|
351
|
+
f"--{field.name} {json.dumps(getattr(self, field.name))}"
|
352
|
+
if isinstance(getattr(self, field.name), dict)
|
353
|
+
else f"--{field.name} {getattr(self, field.name)}"
|
344
354
|
for field in fields(self.__class__)
|
345
355
|
if getattr(self, field.name) is not None
|
346
356
|
]
|
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"
|
@@ -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
|
)
|
@@ -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)
|
@@ -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
|
from typing import Optional
|
@@ -8,6 +8,9 @@ from urllib.parse import urlparse
|
|
8
8
|
from tornado.web import HTTPError
|
9
9
|
|
10
10
|
from ads.aqua.common.decorator import handle_exceptions
|
11
|
+
from ads.aqua.common.enums import (
|
12
|
+
CustomInferenceContainerTypeFamily,
|
13
|
+
)
|
11
14
|
from ads.aqua.common.errors import AquaRuntimeError, AquaValueError
|
12
15
|
from ads.aqua.common.utils import (
|
13
16
|
get_hf_model_info,
|
@@ -96,7 +99,7 @@ class AquaModelHandler(AquaAPIhandler):
|
|
96
99
|
)
|
97
100
|
|
98
101
|
@handle_exceptions
|
99
|
-
def post(self, *args, **kwargs):
|
102
|
+
def post(self, *args, **kwargs): # noqa: ARG002
|
100
103
|
"""
|
101
104
|
Handles post request for the registering any Aqua model.
|
102
105
|
Raises
|
@@ -128,15 +131,23 @@ class AquaModelHandler(AquaAPIhandler):
|
|
128
131
|
download_from_hf = (
|
129
132
|
str(input_data.get("download_from_hf", "false")).lower() == "true"
|
130
133
|
)
|
134
|
+
local_dir = input_data.get("local_dir")
|
135
|
+
cleanup_model_cache = (
|
136
|
+
str(input_data.get("cleanup_model_cache", "true")).lower() == "true"
|
137
|
+
)
|
131
138
|
inference_container_uri = input_data.get("inference_container_uri")
|
132
139
|
allow_patterns = input_data.get("allow_patterns")
|
133
140
|
ignore_patterns = input_data.get("ignore_patterns")
|
141
|
+
freeform_tags = input_data.get("freeform_tags")
|
142
|
+
defined_tags = input_data.get("defined_tags")
|
134
143
|
|
135
144
|
return self.finish(
|
136
145
|
AquaModelApp().register(
|
137
146
|
model=model,
|
138
147
|
os_path=os_path,
|
139
148
|
download_from_hf=download_from_hf,
|
149
|
+
local_dir=local_dir,
|
150
|
+
cleanup_model_cache=cleanup_model_cache,
|
140
151
|
inference_container=inference_container,
|
141
152
|
finetuning_container=finetuning_container,
|
142
153
|
compartment_id=compartment_id,
|
@@ -145,6 +156,8 @@ class AquaModelHandler(AquaAPIhandler):
|
|
145
156
|
inference_container_uri=inference_container_uri,
|
146
157
|
allow_patterns=allow_patterns,
|
147
158
|
ignore_patterns=ignore_patterns,
|
159
|
+
freeform_tags=freeform_tags,
|
160
|
+
defined_tags=defined_tags,
|
148
161
|
)
|
149
162
|
)
|
150
163
|
|
@@ -159,7 +172,9 @@ class AquaModelHandler(AquaAPIhandler):
|
|
159
172
|
raise HTTPError(400, Errors.NO_INPUT_DATA)
|
160
173
|
|
161
174
|
inference_container = input_data.get("inference_container")
|
175
|
+
inference_container_uri = input_data.get("inference_container_uri")
|
162
176
|
inference_containers = AquaModelApp.list_valid_inference_containers()
|
177
|
+
inference_containers.extend(CustomInferenceContainerTypeFamily.values())
|
163
178
|
if (
|
164
179
|
inference_container is not None
|
165
180
|
and inference_container not in inference_containers
|
@@ -170,10 +185,14 @@ class AquaModelHandler(AquaAPIhandler):
|
|
170
185
|
|
171
186
|
enable_finetuning = input_data.get("enable_finetuning")
|
172
187
|
task = input_data.get("task")
|
173
|
-
app=AquaModelApp()
|
188
|
+
app = AquaModelApp()
|
174
189
|
self.finish(
|
175
190
|
app.edit_registered_model(
|
176
|
-
id,
|
191
|
+
id,
|
192
|
+
inference_container,
|
193
|
+
inference_container_uri,
|
194
|
+
enable_finetuning,
|
195
|
+
task,
|
177
196
|
)
|
178
197
|
)
|
179
198
|
app.clear_model_details_cache(model_id=id)
|
@@ -218,7 +237,7 @@ class AquaHuggingFaceHandler(AquaAPIhandler):
|
|
218
237
|
return None
|
219
238
|
|
220
239
|
@handle_exceptions
|
221
|
-
def get(self, *args, **kwargs):
|
240
|
+
def get(self, *args, **kwargs): # noqa: ARG002
|
222
241
|
"""
|
223
242
|
Finds a list of matching models from hugging face based on query string provided from users.
|
224
243
|
|
@@ -239,7 +258,7 @@ class AquaHuggingFaceHandler(AquaAPIhandler):
|
|
239
258
|
return self.finish({"models": models})
|
240
259
|
|
241
260
|
@handle_exceptions
|
242
|
-
def post(self, *args, **kwargs):
|
261
|
+
def post(self, *args, **kwargs): # noqa: ARG002
|
243
262
|
"""Handles post request for the HF Models APIs
|
244
263
|
|
245
264
|
Raises
|
ads/aqua/extension/ui_handler.py
CHANGED
@@ -68,6 +68,8 @@ class AquaUIHandler(AquaAPIhandler):
|
|
68
68
|
return self.list_buckets()
|
69
69
|
elif paths.startswith("aqua/job/shapes"):
|
70
70
|
return self.list_job_shapes()
|
71
|
+
elif paths.startswith("aqua/modeldeployment/shapes"):
|
72
|
+
return self.list_model_deployment_shapes()
|
71
73
|
elif paths.startswith("aqua/vcn"):
|
72
74
|
return self.list_vcn()
|
73
75
|
elif paths.startswith("aqua/subnets"):
|
@@ -160,6 +162,15 @@ class AquaUIHandler(AquaAPIhandler):
|
|
160
162
|
AquaUIApp().list_job_shapes(compartment_id=compartment_id, **kwargs)
|
161
163
|
)
|
162
164
|
|
165
|
+
def list_model_deployment_shapes(self, **kwargs):
|
166
|
+
"""Lists model deployment shapes available in the specified compartment."""
|
167
|
+
compartment_id = self.get_argument("compartment_id", default=COMPARTMENT_OCID)
|
168
|
+
return self.finish(
|
169
|
+
AquaUIApp().list_model_deployment_shapes(
|
170
|
+
compartment_id=compartment_id, **kwargs
|
171
|
+
)
|
172
|
+
)
|
173
|
+
|
163
174
|
def list_vcn(self, **kwargs):
|
164
175
|
"""Lists the virtual cloud networks (VCNs) in the specified compartment."""
|
165
176
|
compartment_id = self.get_argument("compartment_id", default=COMPARTMENT_OCID)
|
@@ -255,8 +266,9 @@ class AquaCLIHandler(AquaAPIhandler):
|
|
255
266
|
__handlers__ = [
|
256
267
|
("logging/?([^/]*)", AquaUIHandler),
|
257
268
|
("compartments/?([^/]*)", AquaUIHandler),
|
258
|
-
# TODO: change url to evaluation/
|
269
|
+
# TODO: change url to evaluation/experiments/?([^/]*)
|
259
270
|
("experiment/?([^/]*)", AquaUIHandler),
|
271
|
+
("modeldeployment/?([^/]*)", AquaUIHandler),
|
260
272
|
("versionsets/?([^/]*)", AquaUIHandler),
|
261
273
|
("buckets/?([^/]*)", AquaUIHandler),
|
262
274
|
("job/shapes/?([^/]*)", AquaUIHandler),
|
ads/aqua/finetuning/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
|
from ads.common.extended_enum import ExtendedEnumMeta
|
@@ -17,4 +16,8 @@ class FineTuneCustomMetadata(str, metaclass=ExtendedEnumMeta):
|
|
17
16
|
SERVICE_MODEL_FINE_TUNE_CONTAINER = "finetune-container"
|
18
17
|
|
19
18
|
|
19
|
+
class FineTuningRestrictedParams(str, metaclass=ExtendedEnumMeta):
|
20
|
+
OPTIMIZER = "optimizer"
|
21
|
+
|
22
|
+
|
20
23
|
ENV_AQUA_FINE_TUNING_CONTAINER = "AQUA_FINE_TUNING_CONTAINER"
|