oracle-ads 2.12.2__py3-none-any.whl → 2.12.4__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/common/enums.py +9 -0
- ads/aqua/common/utils.py +83 -6
- ads/aqua/config/config.py +0 -16
- ads/aqua/constants.py +2 -0
- ads/aqua/evaluation/entities.py +45 -50
- ads/aqua/evaluation/evaluation.py +26 -61
- ads/aqua/extension/deployment_handler.py +35 -0
- ads/aqua/extension/errors.py +1 -0
- ads/aqua/extension/evaluation_handler.py +0 -5
- ads/aqua/extension/finetune_handler.py +1 -2
- ads/aqua/extension/model_handler.py +38 -1
- ads/aqua/extension/ui_handler.py +22 -3
- ads/aqua/finetuning/entities.py +5 -4
- ads/aqua/finetuning/finetuning.py +13 -8
- ads/aqua/model/constants.py +1 -0
- ads/aqua/model/entities.py +2 -0
- ads/aqua/model/model.py +350 -140
- ads/aqua/modeldeployment/deployment.py +118 -62
- ads/aqua/modeldeployment/entities.py +10 -2
- ads/aqua/ui.py +29 -16
- ads/config.py +3 -8
- ads/dataset/dataset.py +2 -2
- ads/dataset/factory.py +1 -1
- ads/llm/deploy.py +6 -0
- ads/llm/guardrails/base.py +0 -1
- ads/llm/langchain/plugins/chat_models/oci_data_science.py +118 -41
- ads/llm/langchain/plugins/llms/oci_data_science_model_deployment_endpoint.py +18 -14
- ads/llm/templates/score_chain.jinja2 +0 -1
- ads/model/datascience_model.py +519 -16
- ads/model/deployment/model_deployment.py +13 -0
- ads/model/deployment/model_deployment_infrastructure.py +34 -0
- ads/model/generic_model.py +10 -0
- ads/model/model_properties.py +1 -0
- ads/model/service/oci_datascience_model.py +28 -0
- ads/opctl/operator/lowcode/anomaly/const.py +66 -1
- ads/opctl/operator/lowcode/anomaly/model/anomaly_merlion.py +161 -0
- ads/opctl/operator/lowcode/anomaly/model/autots.py +30 -15
- ads/opctl/operator/lowcode/anomaly/model/factory.py +15 -3
- ads/opctl/operator/lowcode/anomaly/model/randomcutforest.py +1 -1
- ads/opctl/operator/lowcode/anomaly/schema.yaml +10 -0
- ads/opctl/operator/lowcode/anomaly/utils.py +3 -0
- ads/opctl/operator/lowcode/forecast/cmd.py +3 -9
- ads/opctl/operator/lowcode/forecast/const.py +3 -4
- ads/opctl/operator/lowcode/forecast/model/factory.py +13 -12
- ads/opctl/operator/lowcode/forecast/model/ml_forecast.py +4 -3
- ads/opctl/operator/lowcode/forecast/operator_config.py +17 -10
- ads/opctl/operator/lowcode/forecast/schema.yaml +2 -2
- ads/oracledb/oracle_db.py +32 -20
- ads/secrets/adb.py +28 -6
- {oracle_ads-2.12.2.dist-info → oracle_ads-2.12.4.dist-info}/METADATA +3 -2
- {oracle_ads-2.12.2.dist-info → oracle_ads-2.12.4.dist-info}/RECORD +54 -55
- {oracle_ads-2.12.2.dist-info → oracle_ads-2.12.4.dist-info}/WHEEL +1 -1
- ads/aqua/config/deployment_config_defaults.json +0 -38
- ads/aqua/config/resource_limit_names.json +0 -9
- {oracle_ads-2.12.2.dist-info → oracle_ads-2.12.4.dist-info}/LICENSE.txt +0 -0
- {oracle_ads-2.12.2.dist-info → oracle_ads-2.12.4.dist-info}/entry_points.txt +0 -0
ads/aqua/common/enums.py
CHANGED
@@ -52,6 +52,7 @@ 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
|
+
AQUA_TEI_CONTAINER_FAMILY = "odsc-tei-serving"
|
55
56
|
|
56
57
|
|
57
58
|
class InferenceContainerParamType(str, metaclass=ExtendedEnumMeta):
|
@@ -80,3 +81,11 @@ class RqsAdditionalDetails(str, metaclass=ExtendedEnumMeta):
|
|
80
81
|
MODEL_VERSION_SET_NAME = "modelVersionSetName"
|
81
82
|
PROJECT_ID = "projectId"
|
82
83
|
VERSION_LABEL = "versionLabel"
|
84
|
+
|
85
|
+
|
86
|
+
class TextEmbeddingInferenceContainerParams(str, metaclass=ExtendedEnumMeta):
|
87
|
+
"""Contains a subset of params that are required for enabling model deployment in OCI Data Science. More options
|
88
|
+
are available at https://huggingface.co/docs/text-embeddings-inference/en/cli_arguments"""
|
89
|
+
|
90
|
+
MODEL_ID = "model-id"
|
91
|
+
PORT = "port"
|
ads/aqua/common/utils.py
CHANGED
@@ -35,6 +35,7 @@ from ads.aqua.common.enums import (
|
|
35
35
|
InferenceContainerParamType,
|
36
36
|
InferenceContainerType,
|
37
37
|
RqsAdditionalDetails,
|
38
|
+
TextEmbeddingInferenceContainerParams,
|
38
39
|
)
|
39
40
|
from ads.aqua.common.errors import (
|
40
41
|
AquaFileNotFoundError,
|
@@ -51,6 +52,7 @@ from ads.aqua.constants import (
|
|
51
52
|
MODEL_BY_REFERENCE_OSS_PATH_KEY,
|
52
53
|
SERVICE_MANAGED_CONTAINER_URI_SCHEME,
|
53
54
|
SUPPORTED_FILE_FORMATS,
|
55
|
+
TEI_CONTAINER_DEFAULT_HOST,
|
54
56
|
TGI_INFERENCE_RESTRICTED_PARAMS,
|
55
57
|
UNKNOWN,
|
56
58
|
UNKNOWN_JSON_STR,
|
@@ -63,7 +65,12 @@ from ads.common.extended_enum import ExtendedEnumMeta
|
|
63
65
|
from ads.common.object_storage_details import ObjectStorageDetails
|
64
66
|
from ads.common.oci_resource import SEARCH_TYPE, OCIResource
|
65
67
|
from ads.common.utils import copy_file, get_console_link, upload_to_os
|
66
|
-
from ads.config import
|
68
|
+
from ads.config import (
|
69
|
+
AQUA_MODEL_DEPLOYMENT_FOLDER,
|
70
|
+
AQUA_SERVICE_MODELS_BUCKET,
|
71
|
+
CONDA_BUCKET_NS,
|
72
|
+
TENANCY_OCID,
|
73
|
+
)
|
67
74
|
from ads.model import DataScienceModel, ModelVersionSet
|
68
75
|
|
69
76
|
logger = logging.getLogger("ads.aqua")
|
@@ -569,15 +576,13 @@ def get_container_image(
|
|
569
576
|
A dict of allowed configs.
|
570
577
|
"""
|
571
578
|
|
579
|
+
container_image = UNKNOWN
|
572
580
|
config = config_file_name or get_container_config()
|
573
581
|
config_file_name = service_config_path()
|
574
582
|
|
575
583
|
if container_type not in config:
|
576
|
-
|
577
|
-
f"{config_file_name} does not have config details for model: {container_type}"
|
578
|
-
)
|
584
|
+
return UNKNOWN
|
579
585
|
|
580
|
-
container_image = None
|
581
586
|
mapping = config[container_type]
|
582
587
|
versions = [obj["version"] for obj in mapping]
|
583
588
|
# assumes numbered versions, update if `latest` is used
|
@@ -1071,7 +1076,6 @@ def list_hf_models(query: str) -> List[str]:
|
|
1071
1076
|
try:
|
1072
1077
|
models = HfApi().list_models(
|
1073
1078
|
model_name=query,
|
1074
|
-
task="text-generation",
|
1075
1079
|
sort="downloads",
|
1076
1080
|
direction=-1,
|
1077
1081
|
limit=20,
|
@@ -1079,3 +1083,76 @@ def list_hf_models(query: str) -> List[str]:
|
|
1079
1083
|
return [model.id for model in models if model.disabled is None]
|
1080
1084
|
except HfHubHTTPError as err:
|
1081
1085
|
raise format_hf_custom_error_message(err) from err
|
1086
|
+
|
1087
|
+
|
1088
|
+
def generate_tei_cmd_var(os_path: str) -> List[str]:
|
1089
|
+
"""This utility functions generates CMD params for Text Embedding Inference container. Only the
|
1090
|
+
essential parameters for OCI model deployment are added, defaults are used for the rest.
|
1091
|
+
Parameters
|
1092
|
+
----------
|
1093
|
+
os_path: str
|
1094
|
+
OCI bucket path where the model artifacts are uploaded - oci://bucket@namespace/prefix
|
1095
|
+
|
1096
|
+
Returns
|
1097
|
+
-------
|
1098
|
+
cmd_var:
|
1099
|
+
List of command line arguments
|
1100
|
+
"""
|
1101
|
+
|
1102
|
+
cmd_prefix = "--"
|
1103
|
+
cmd_var = [
|
1104
|
+
f"{cmd_prefix}{TextEmbeddingInferenceContainerParams.MODEL_ID}",
|
1105
|
+
f"{AQUA_MODEL_DEPLOYMENT_FOLDER}{ObjectStorageDetails.from_path(os_path.rstrip('/')).filepath}/",
|
1106
|
+
f"{cmd_prefix}{TextEmbeddingInferenceContainerParams.PORT}",
|
1107
|
+
TEI_CONTAINER_DEFAULT_HOST,
|
1108
|
+
]
|
1109
|
+
|
1110
|
+
return cmd_var
|
1111
|
+
|
1112
|
+
|
1113
|
+
def parse_cmd_var(cmd_list: List[str]) -> dict:
|
1114
|
+
"""Helper functions that parses a list into a key-value dictionary. The list contains keys separated by the prefix
|
1115
|
+
'--' and the value of the key is the subsequent element.
|
1116
|
+
"""
|
1117
|
+
parsed_cmd = {}
|
1118
|
+
|
1119
|
+
for i, cmd in enumerate(cmd_list):
|
1120
|
+
if cmd.startswith("--"):
|
1121
|
+
if i + 1 < len(cmd_list) and not cmd_list[i + 1].startswith("--"):
|
1122
|
+
parsed_cmd[cmd] = cmd_list[i + 1]
|
1123
|
+
i += 1
|
1124
|
+
else:
|
1125
|
+
parsed_cmd[cmd] = None
|
1126
|
+
return parsed_cmd
|
1127
|
+
|
1128
|
+
|
1129
|
+
def validate_cmd_var(cmd_var: List[str], overrides: List[str]) -> List[str]:
|
1130
|
+
"""This function accepts two lists of parameters and combines them. If the second list shares the common parameter
|
1131
|
+
names/keys, then it raises an error.
|
1132
|
+
Parameters
|
1133
|
+
----------
|
1134
|
+
cmd_var: List[str]
|
1135
|
+
Default list of parameters
|
1136
|
+
overrides: List[str]
|
1137
|
+
List of parameters to override
|
1138
|
+
Returns
|
1139
|
+
-------
|
1140
|
+
List[str] of combined parameters
|
1141
|
+
"""
|
1142
|
+
cmd_var = [str(x) for x in cmd_var]
|
1143
|
+
if not overrides:
|
1144
|
+
return cmd_var
|
1145
|
+
overrides = [str(x) for x in overrides]
|
1146
|
+
|
1147
|
+
cmd_dict = parse_cmd_var(cmd_var)
|
1148
|
+
overrides_dict = parse_cmd_var(overrides)
|
1149
|
+
|
1150
|
+
# check for conflicts
|
1151
|
+
common_keys = set(cmd_dict.keys()) & set(overrides_dict.keys())
|
1152
|
+
if common_keys:
|
1153
|
+
raise AquaValueError(
|
1154
|
+
f"The following CMD input cannot be overridden for model deployment: {', '.join(common_keys)}"
|
1155
|
+
)
|
1156
|
+
|
1157
|
+
combined_cmd_var = cmd_var + overrides
|
1158
|
+
return combined_cmd_var
|
ads/aqua/config/config.py
CHANGED
@@ -29,19 +29,3 @@ def get_evaluation_service_config(
|
|
29
29
|
.get(ContainerSpec.CONTAINER_SPEC, {})
|
30
30
|
.get(container, {})
|
31
31
|
)
|
32
|
-
|
33
|
-
|
34
|
-
# TODO: move this to global config.json in object storage
|
35
|
-
def get_finetuning_config_defaults():
|
36
|
-
"""Generate and return the fine-tuning default configuration dictionary."""
|
37
|
-
return {
|
38
|
-
"shape": {
|
39
|
-
"VM.GPU.A10.1": {"batch_size": 1, "replica": "1-10"},
|
40
|
-
"VM.GPU.A10.2": {"batch_size": 1, "replica": "1-10"},
|
41
|
-
"BM.GPU.A10.4": {"batch_size": 1, "replica": 1},
|
42
|
-
"BM.GPU4.8": {"batch_size": 4, "replica": 1},
|
43
|
-
"BM.GPU.L40S-NC.4": {"batch_size": 4, "replica": 1},
|
44
|
-
"BM.GPU.A100-v2.8": {"batch_size": 6, "replica": 1},
|
45
|
-
"BM.GPU.H100.8": {"batch_size": 6, "replica": 1},
|
46
|
-
}
|
47
|
-
}
|
ads/aqua/constants.py
CHANGED
@@ -27,6 +27,7 @@ NB_SESSION_IDENTIFIER = "NB_SESSION_OCID"
|
|
27
27
|
LIFECYCLE_DETAILS_MISSING_JOBRUN = "The associated JobRun resource has been deleted."
|
28
28
|
READY_TO_DEPLOY_STATUS = "ACTIVE"
|
29
29
|
READY_TO_FINE_TUNE_STATUS = "TRUE"
|
30
|
+
PRIVATE_ENDPOINT_TYPE = "MODEL_DEPLOYMENT"
|
30
31
|
AQUA_GA_LIST = ["id19sfcrra6z"]
|
31
32
|
AQUA_MODEL_TYPE_SERVICE = "service"
|
32
33
|
AQUA_MODEL_TYPE_CUSTOM = "custom"
|
@@ -79,3 +80,4 @@ LLAMA_CPP_INFERENCE_RESTRICTED_PARAMS = {
|
|
79
80
|
"--port",
|
80
81
|
"--host",
|
81
82
|
}
|
83
|
+
TEI_CONTAINER_DEFAULT_HOST = "8080"
|
ads/aqua/evaluation/entities.py
CHANGED
@@ -9,19 +9,18 @@ aqua.evaluation.entities
|
|
9
9
|
This module contains dataclasses for aqua evaluation.
|
10
10
|
"""
|
11
11
|
|
12
|
-
from
|
13
|
-
from typing import List, Optional, Union
|
12
|
+
from pydantic import Field
|
13
|
+
from typing import Any, Dict, List, Optional, Union
|
14
14
|
|
15
15
|
from ads.aqua.data import AquaResourceIdentifier
|
16
|
-
from ads.
|
16
|
+
from ads.aqua.config.utils.serializer import Serializable
|
17
17
|
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
"""Dataclass to create aqua model evaluation.
|
19
|
+
class CreateAquaEvaluationDetails(Serializable):
|
20
|
+
"""Class for creating aqua model evaluation.
|
22
21
|
|
23
|
-
|
24
|
-
|
22
|
+
Properties
|
23
|
+
----------
|
25
24
|
evaluation_source_id: str
|
26
25
|
The evaluation source id. Must be either model or model deployment ocid.
|
27
26
|
evaluation_name: str
|
@@ -83,69 +82,64 @@ class CreateAquaEvaluationDetails(DataClassSerializable):
|
|
83
82
|
ocpus: Optional[float] = None
|
84
83
|
log_group_id: Optional[str] = None
|
85
84
|
log_id: Optional[str] = None
|
86
|
-
metrics: Optional[List] = None
|
85
|
+
metrics: Optional[List[str]] = None
|
87
86
|
force_overwrite: Optional[bool] = False
|
88
87
|
|
88
|
+
class Config:
|
89
|
+
extra = "ignore"
|
89
90
|
|
90
|
-
|
91
|
-
class AquaEvalReport(DataClassSerializable):
|
91
|
+
class AquaEvalReport(Serializable):
|
92
92
|
evaluation_id: str = ""
|
93
93
|
content: str = ""
|
94
94
|
|
95
|
+
class Config:
|
96
|
+
extra = "ignore"
|
95
97
|
|
96
|
-
|
97
|
-
class ModelParams(DataClassSerializable):
|
98
|
-
max_tokens: str = ""
|
99
|
-
top_p: str = ""
|
100
|
-
top_k: str = ""
|
101
|
-
temperature: str = ""
|
102
|
-
presence_penalty: Optional[float] = 0.0
|
103
|
-
frequency_penalty: Optional[float] = 0.0
|
104
|
-
stop: Optional[Union[str, List[str]]] = field(default_factory=list)
|
105
|
-
model: Optional[str] = "odsc-llm"
|
106
|
-
|
107
|
-
|
108
|
-
@dataclass(repr=False)
|
109
|
-
class AquaEvalParams(ModelParams, DataClassSerializable):
|
98
|
+
class AquaEvalParams(Serializable):
|
110
99
|
shape: str = ""
|
111
100
|
dataset_path: str = ""
|
112
101
|
report_path: str = ""
|
113
102
|
|
103
|
+
class Config:
|
104
|
+
extra = "allow"
|
114
105
|
|
115
|
-
|
116
|
-
class AquaEvalMetric(DataClassSerializable):
|
106
|
+
class AquaEvalMetric(Serializable):
|
117
107
|
key: str
|
118
108
|
name: str
|
119
109
|
description: str = ""
|
120
110
|
|
111
|
+
class Config:
|
112
|
+
extra = "ignore"
|
121
113
|
|
122
|
-
|
123
|
-
class AquaEvalMetricSummary(DataClassSerializable):
|
114
|
+
class AquaEvalMetricSummary(Serializable):
|
124
115
|
metric: str = ""
|
125
116
|
score: str = ""
|
126
117
|
grade: str = ""
|
127
118
|
|
119
|
+
class Config:
|
120
|
+
extra = "ignore"
|
128
121
|
|
129
|
-
|
130
|
-
class AquaEvalMetrics(DataClassSerializable):
|
122
|
+
class AquaEvalMetrics(Serializable):
|
131
123
|
id: str
|
132
124
|
report: str
|
133
|
-
metric_results: List[AquaEvalMetric] =
|
134
|
-
metric_summary_result: List[AquaEvalMetricSummary] =
|
125
|
+
metric_results: List[AquaEvalMetric] = Field(default_factory=list)
|
126
|
+
metric_summary_result: List[AquaEvalMetricSummary] = Field(default_factory=list)
|
135
127
|
|
128
|
+
class Config:
|
129
|
+
extra = "ignore"
|
136
130
|
|
137
|
-
|
138
|
-
class AquaEvaluationCommands(DataClassSerializable):
|
131
|
+
class AquaEvaluationCommands(Serializable):
|
139
132
|
evaluation_id: str
|
140
133
|
evaluation_target_id: str
|
141
|
-
input_data:
|
142
|
-
metrics:
|
134
|
+
input_data: Dict[str, Any]
|
135
|
+
metrics: List[str]
|
143
136
|
output_dir: str
|
144
|
-
params:
|
137
|
+
params: Dict[str, Any]
|
145
138
|
|
139
|
+
class Config:
|
140
|
+
extra = "ignore"
|
146
141
|
|
147
|
-
|
148
|
-
class AquaEvaluationSummary(DataClassSerializable):
|
142
|
+
class AquaEvaluationSummary(Serializable):
|
149
143
|
"""Represents a summary of Aqua evalution."""
|
150
144
|
|
151
145
|
id: str
|
@@ -154,17 +148,18 @@ class AquaEvaluationSummary(DataClassSerializable):
|
|
154
148
|
lifecycle_state: str
|
155
149
|
lifecycle_details: str
|
156
150
|
time_created: str
|
157
|
-
tags:
|
158
|
-
experiment: AquaResourceIdentifier =
|
159
|
-
source: AquaResourceIdentifier =
|
160
|
-
job: AquaResourceIdentifier =
|
161
|
-
parameters: AquaEvalParams =
|
151
|
+
tags: Dict[str, Any]
|
152
|
+
experiment: AquaResourceIdentifier = Field(default_factory=AquaResourceIdentifier)
|
153
|
+
source: AquaResourceIdentifier = Field(default_factory=AquaResourceIdentifier)
|
154
|
+
job: AquaResourceIdentifier = Field(default_factory=AquaResourceIdentifier)
|
155
|
+
parameters: AquaEvalParams = Field(default_factory=AquaEvalParams)
|
162
156
|
|
157
|
+
class Config:
|
158
|
+
extra = "ignore"
|
163
159
|
|
164
|
-
|
165
|
-
class AquaEvaluationDetail(AquaEvaluationSummary, DataClassSerializable):
|
160
|
+
class AquaEvaluationDetail(AquaEvaluationSummary):
|
166
161
|
"""Represents a details of Aqua evalution."""
|
167
162
|
|
168
|
-
log_group: AquaResourceIdentifier =
|
169
|
-
log: AquaResourceIdentifier =
|
170
|
-
introspection: dict =
|
163
|
+
log_group: AquaResourceIdentifier = Field(default_factory=AquaResourceIdentifier)
|
164
|
+
log: AquaResourceIdentifier = Field(default_factory=AquaResourceIdentifier)
|
165
|
+
introspection: dict = Field(default_factory=dict)
|
@@ -7,7 +7,6 @@ import os
|
|
7
7
|
import re
|
8
8
|
import tempfile
|
9
9
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
10
|
-
from dataclasses import asdict, fields
|
11
10
|
from datetime import datetime, timedelta
|
12
11
|
from pathlib import Path
|
13
12
|
from threading import Lock
|
@@ -46,7 +45,6 @@ from ads.aqua.common.utils import (
|
|
46
45
|
upload_local_to_os,
|
47
46
|
)
|
48
47
|
from ads.aqua.config.config import get_evaluation_service_config
|
49
|
-
from ads.aqua.config.evaluation.evaluation_service_config import EvaluationServiceConfig
|
50
48
|
from ads.aqua.constants import (
|
51
49
|
CONSOLE_LINK_RESOURCE_TYPE_MAPPING,
|
52
50
|
EVALUATION_REPORT,
|
@@ -75,7 +73,6 @@ from ads.aqua.evaluation.entities import (
|
|
75
73
|
AquaEvaluationSummary,
|
76
74
|
AquaResourceIdentifier,
|
77
75
|
CreateAquaEvaluationDetails,
|
78
|
-
ModelParams,
|
79
76
|
)
|
80
77
|
from ads.aqua.evaluation.errors import EVALUATION_JOB_EXIT_CODE_MESSAGE
|
81
78
|
from ads.aqua.ui import AquaContainerConfig
|
@@ -161,10 +158,11 @@ class AquaEvaluationApp(AquaApp):
|
|
161
158
|
try:
|
162
159
|
create_aqua_evaluation_details = CreateAquaEvaluationDetails(**kwargs)
|
163
160
|
except Exception as ex:
|
161
|
+
custom_errors = {
|
162
|
+
".".join(map(str, e["loc"])): e["msg"] for e in json.loads(ex.json())
|
163
|
+
}
|
164
164
|
raise AquaValueError(
|
165
|
-
"Invalid create evaluation parameters. "
|
166
|
-
"Allowable parameters are: "
|
167
|
-
f"{', '.join([field.name for field in fields(CreateAquaEvaluationDetails)])}."
|
165
|
+
f"Invalid create evaluation parameters. Error details: {custom_errors}."
|
168
166
|
) from ex
|
169
167
|
|
170
168
|
if not is_valid_ocid(create_aqua_evaluation_details.evaluation_source_id):
|
@@ -175,15 +173,7 @@ class AquaEvaluationApp(AquaApp):
|
|
175
173
|
|
176
174
|
# The model to evaluate
|
177
175
|
evaluation_source = None
|
178
|
-
# The evaluation service config
|
179
|
-
evaluation_config: EvaluationServiceConfig = get_evaluation_service_config()
|
180
|
-
# The evaluation inference configuration. The inference configuration will be extracted
|
181
|
-
# based on the inferencing container family.
|
182
176
|
eval_inference_configuration: Dict = {}
|
183
|
-
# The evaluation inference model sampling params. The system parameters that will not be
|
184
|
-
# visible for user, but will be applied implicitly for evaluation. The service model params
|
185
|
-
# will be extracted based on the container family and version.
|
186
|
-
eval_inference_service_model_params: Dict = {}
|
187
177
|
|
188
178
|
if (
|
189
179
|
DataScienceResource.MODEL_DEPLOYMENT
|
@@ -200,29 +190,14 @@ class AquaEvaluationApp(AquaApp):
|
|
200
190
|
runtime = ModelDeploymentContainerRuntime.from_dict(
|
201
191
|
evaluation_source.runtime.to_dict()
|
202
192
|
)
|
203
|
-
|
193
|
+
inference_config = AquaContainerConfig.from_container_index_json(
|
204
194
|
enable_spec=True
|
205
|
-
)
|
206
|
-
for (
|
207
|
-
|
208
|
-
inference_container_info,
|
209
|
-
) in container_config.inference.items():
|
210
|
-
if (
|
211
|
-
inference_container_info.name
|
212
|
-
== runtime.image[: runtime.image.rfind(":")]
|
213
|
-
):
|
195
|
+
).inference
|
196
|
+
for container in inference_config.values():
|
197
|
+
if container.name == runtime.image[: runtime.image.rfind(":")]:
|
214
198
|
eval_inference_configuration = (
|
215
|
-
|
216
|
-
inference_container_family
|
217
|
-
).to_dict()
|
218
|
-
)
|
219
|
-
eval_inference_service_model_params = (
|
220
|
-
evaluation_config.get_merged_inference_model_params(
|
221
|
-
inference_container_family,
|
222
|
-
inference_container_info.version,
|
223
|
-
)
|
199
|
+
container.spec.evaluation_configuration
|
224
200
|
)
|
225
|
-
|
226
201
|
except Exception:
|
227
202
|
logger.debug(
|
228
203
|
f"Could not load inference config details for the evaluation source id: "
|
@@ -277,19 +252,12 @@ class AquaEvaluationApp(AquaApp):
|
|
277
252
|
)
|
278
253
|
evaluation_dataset_path = dst_uri
|
279
254
|
|
280
|
-
evaluation_model_parameters =
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
**create_aqua_evaluation_details.model_parameters,
|
287
|
-
)
|
288
|
-
except Exception as ex:
|
289
|
-
raise AquaValueError(
|
290
|
-
"Invalid model parameters. Model parameters should "
|
291
|
-
f"be a dictionary with keys: {', '.join(list(ModelParams.__annotations__.keys()))}."
|
292
|
-
) from ex
|
255
|
+
evaluation_model_parameters = AquaEvalParams(
|
256
|
+
shape=create_aqua_evaluation_details.shape_name,
|
257
|
+
dataset_path=evaluation_dataset_path,
|
258
|
+
report_path=create_aqua_evaluation_details.report_path,
|
259
|
+
**create_aqua_evaluation_details.model_parameters,
|
260
|
+
)
|
293
261
|
|
294
262
|
target_compartment = (
|
295
263
|
create_aqua_evaluation_details.compartment_id or COMPARTMENT_OCID
|
@@ -370,7 +338,7 @@ class AquaEvaluationApp(AquaApp):
|
|
370
338
|
evaluation_model_taxonomy_metadata = ModelTaxonomyMetadata()
|
371
339
|
evaluation_model_taxonomy_metadata[
|
372
340
|
MetadataTaxonomyKeys.HYPERPARAMETERS
|
373
|
-
].value = {"model_params":
|
341
|
+
].value = {"model_params": evaluation_model_parameters.to_dict()}
|
374
342
|
|
375
343
|
evaluation_model = (
|
376
344
|
DataScienceModel()
|
@@ -443,7 +411,6 @@ class AquaEvaluationApp(AquaApp):
|
|
443
411
|
dataset_path=evaluation_dataset_path,
|
444
412
|
report_path=create_aqua_evaluation_details.report_path,
|
445
413
|
model_parameters={
|
446
|
-
**eval_inference_service_model_params,
|
447
414
|
**create_aqua_evaluation_details.model_parameters,
|
448
415
|
},
|
449
416
|
metrics=create_aqua_evaluation_details.metrics,
|
@@ -580,16 +547,14 @@ class AquaEvaluationApp(AquaApp):
|
|
580
547
|
**{
|
581
548
|
"AIP_SMC_EVALUATION_ARGUMENTS": json.dumps(
|
582
549
|
{
|
583
|
-
**
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
),
|
592
|
-
),
|
550
|
+
**self._build_launch_cmd(
|
551
|
+
evaluation_id=evaluation_id,
|
552
|
+
evaluation_source_id=evaluation_source_id,
|
553
|
+
dataset_path=dataset_path,
|
554
|
+
report_path=report_path,
|
555
|
+
model_parameters=model_parameters,
|
556
|
+
metrics=metrics,
|
557
|
+
).to_dict(),
|
593
558
|
**(inference_configuration or {}),
|
594
559
|
},
|
595
560
|
),
|
@@ -662,9 +627,9 @@ class AquaEvaluationApp(AquaApp):
|
|
662
627
|
"format": Path(dataset_path).suffix,
|
663
628
|
"url": dataset_path,
|
664
629
|
},
|
665
|
-
metrics=metrics,
|
630
|
+
metrics=metrics or [],
|
666
631
|
output_dir=report_path,
|
667
|
-
params=model_parameters,
|
632
|
+
params=model_parameters or {},
|
668
633
|
)
|
669
634
|
|
670
635
|
@telemetry(entry_point="plugin=evaluation&action=get", name="aqua")
|
@@ -54,6 +54,33 @@ class AquaDeploymentHandler(AquaAPIhandler):
|
|
54
54
|
else:
|
55
55
|
raise HTTPError(400, f"The request {self.request.path} is invalid.")
|
56
56
|
|
57
|
+
@handle_exceptions
|
58
|
+
def delete(self, model_deployment_id):
|
59
|
+
return self.finish(AquaDeploymentApp().delete(model_deployment_id))
|
60
|
+
|
61
|
+
@handle_exceptions
|
62
|
+
def put(self, *args, **kwargs):
|
63
|
+
"""
|
64
|
+
Handles put request for the activating and deactivating OCI datascience model deployments
|
65
|
+
Raises
|
66
|
+
------
|
67
|
+
HTTPError
|
68
|
+
Raises HTTPError if inputs are missing or are invalid
|
69
|
+
"""
|
70
|
+
url_parse = urlparse(self.request.path)
|
71
|
+
paths = url_parse.path.strip("/").split("/")
|
72
|
+
if len(paths) != 4 or paths[0] != "aqua" or paths[1] != "deployments":
|
73
|
+
raise HTTPError(400, f"The request {self.request.path} is invalid.")
|
74
|
+
|
75
|
+
model_deployment_id = paths[2]
|
76
|
+
action = paths[3]
|
77
|
+
if action == "activate":
|
78
|
+
return self.finish(AquaDeploymentApp().activate(model_deployment_id))
|
79
|
+
elif action == "deactivate":
|
80
|
+
return self.finish(AquaDeploymentApp().deactivate(model_deployment_id))
|
81
|
+
else:
|
82
|
+
raise HTTPError(400, f"The request {self.request.path} is invalid.")
|
83
|
+
|
57
84
|
@handle_exceptions
|
58
85
|
def post(self, *args, **kwargs):
|
59
86
|
"""
|
@@ -102,6 +129,9 @@ class AquaDeploymentHandler(AquaAPIhandler):
|
|
102
129
|
ocpus = input_data.get("ocpus")
|
103
130
|
memory_in_gbs = input_data.get("memory_in_gbs")
|
104
131
|
model_file = input_data.get("model_file")
|
132
|
+
private_endpoint_id = input_data.get("private_endpoint_id")
|
133
|
+
container_image_uri = input_data.get("container_image_uri")
|
134
|
+
cmd_var = input_data.get("cmd_var")
|
105
135
|
|
106
136
|
self.finish(
|
107
137
|
AquaDeploymentApp().create(
|
@@ -124,6 +154,9 @@ class AquaDeploymentHandler(AquaAPIhandler):
|
|
124
154
|
ocpus=ocpus,
|
125
155
|
memory_in_gbs=memory_in_gbs,
|
126
156
|
model_file=model_file,
|
157
|
+
private_endpoint_id=private_endpoint_id,
|
158
|
+
container_image_uri=container_image_uri,
|
159
|
+
cmd_var=cmd_var,
|
127
160
|
)
|
128
161
|
)
|
129
162
|
|
@@ -264,5 +297,7 @@ __handlers__ = [
|
|
264
297
|
("deployments/?([^/]*)/params", AquaDeploymentParamsHandler),
|
265
298
|
("deployments/config/?([^/]*)", AquaDeploymentHandler),
|
266
299
|
("deployments/?([^/]*)", AquaDeploymentHandler),
|
300
|
+
("deployments/?([^/]*)/activate", AquaDeploymentHandler),
|
301
|
+
("deployments/?([^/]*)/deactivate", AquaDeploymentHandler),
|
267
302
|
("inference", AquaDeploymentInferenceHandler),
|
268
303
|
]
|
ads/aqua/extension/errors.py
CHANGED
@@ -12,7 +12,6 @@ from ads.aqua.evaluation import AquaEvaluationApp
|
|
12
12
|
from ads.aqua.evaluation.entities import CreateAquaEvaluationDetails
|
13
13
|
from ads.aqua.extension.base_handler import AquaAPIhandler
|
14
14
|
from ads.aqua.extension.errors import Errors
|
15
|
-
from ads.aqua.extension.utils import validate_function_parameters
|
16
15
|
from ads.config import COMPARTMENT_OCID
|
17
16
|
|
18
17
|
|
@@ -47,10 +46,6 @@ class AquaEvaluationHandler(AquaAPIhandler):
|
|
47
46
|
if not input_data:
|
48
47
|
raise HTTPError(400, Errors.NO_INPUT_DATA)
|
49
48
|
|
50
|
-
validate_function_parameters(
|
51
|
-
data_class=CreateAquaEvaluationDetails, input_data=input_data
|
52
|
-
)
|
53
|
-
|
54
49
|
self.finish(
|
55
50
|
# TODO: decide what other kwargs will be needed for create aqua evaluation.
|
56
51
|
AquaEvaluationApp().create(
|
@@ -1,5 +1,4 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
|
-
# -*- coding: utf-8 -*-
|
3
2
|
# Copyright (c) 2024 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
|
|
@@ -9,8 +8,8 @@ from urllib.parse import urlparse
|
|
9
8
|
from tornado.web import HTTPError
|
10
9
|
|
11
10
|
from ads.aqua.common.decorator import handle_exceptions
|
12
|
-
from ads.aqua.extension.errors import Errors
|
13
11
|
from ads.aqua.extension.base_handler import AquaAPIhandler
|
12
|
+
from ads.aqua.extension.errors import Errors
|
14
13
|
from ads.aqua.extension.utils import validate_function_parameters
|
15
14
|
from ads.aqua.finetuning import AquaFineTuningApp
|
16
15
|
from ads.aqua.finetuning.entities import CreateFineTuningDetails
|
@@ -9,7 +9,10 @@ from tornado.web import HTTPError
|
|
9
9
|
|
10
10
|
from ads.aqua.common.decorator import handle_exceptions
|
11
11
|
from ads.aqua.common.errors import AquaRuntimeError, AquaValueError
|
12
|
-
from ads.aqua.common.utils import
|
12
|
+
from ads.aqua.common.utils import (
|
13
|
+
get_hf_model_info,
|
14
|
+
list_hf_models,
|
15
|
+
)
|
13
16
|
from ads.aqua.extension.base_handler import AquaAPIhandler
|
14
17
|
from ads.aqua.extension.errors import Errors
|
15
18
|
from ads.aqua.model import AquaModelApp
|
@@ -73,6 +76,8 @@ class AquaModelHandler(AquaAPIhandler):
|
|
73
76
|
paths = url_parse.path.strip("/")
|
74
77
|
if paths.startswith("aqua/model/cache"):
|
75
78
|
return self.finish(AquaModelApp().clear_model_list_cache())
|
79
|
+
elif id:
|
80
|
+
return self.finish(AquaModelApp().delete_model(id))
|
76
81
|
else:
|
77
82
|
raise HTTPError(400, f"The request {self.request.path} is invalid.")
|
78
83
|
|
@@ -123,6 +128,7 @@ class AquaModelHandler(AquaAPIhandler):
|
|
123
128
|
download_from_hf = (
|
124
129
|
str(input_data.get("download_from_hf", "false")).lower() == "true"
|
125
130
|
)
|
131
|
+
inference_container_uri = input_data.get("inference_container_uri")
|
126
132
|
|
127
133
|
return self.finish(
|
128
134
|
AquaModelApp().register(
|
@@ -134,9 +140,40 @@ class AquaModelHandler(AquaAPIhandler):
|
|
134
140
|
compartment_id=compartment_id,
|
135
141
|
project_id=project_id,
|
136
142
|
model_file=model_file,
|
143
|
+
inference_container_uri=inference_container_uri,
|
137
144
|
)
|
138
145
|
)
|
139
146
|
|
147
|
+
@handle_exceptions
|
148
|
+
def put(self, id):
|
149
|
+
try:
|
150
|
+
input_data = self.get_json_body()
|
151
|
+
except Exception as ex:
|
152
|
+
raise HTTPError(400, Errors.INVALID_INPUT_DATA_FORMAT) from ex
|
153
|
+
|
154
|
+
if not input_data:
|
155
|
+
raise HTTPError(400, Errors.NO_INPUT_DATA)
|
156
|
+
|
157
|
+
inference_container = input_data.get("inference_container")
|
158
|
+
inference_containers = AquaModelApp.list_valid_inference_containers()
|
159
|
+
if (
|
160
|
+
inference_container is not None
|
161
|
+
and inference_container not in inference_containers
|
162
|
+
):
|
163
|
+
raise HTTPError(
|
164
|
+
400, Errors.INVALID_VALUE_OF_PARAMETER.format("inference_container")
|
165
|
+
)
|
166
|
+
|
167
|
+
enable_finetuning = input_data.get("enable_finetuning")
|
168
|
+
task = input_data.get("task")
|
169
|
+
app=AquaModelApp()
|
170
|
+
self.finish(
|
171
|
+
app.edit_registered_model(
|
172
|
+
id, inference_container, enable_finetuning, task
|
173
|
+
)
|
174
|
+
)
|
175
|
+
app.clear_model_details_cache(model_id=id)
|
176
|
+
|
140
177
|
|
141
178
|
class AquaModelLicenseHandler(AquaAPIhandler):
|
142
179
|
"""Handler for Aqua Model license REST APIs."""
|