oracle-ads 2.11.9__py3-none-any.whl → 2.11.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 +1 -1
- ads/aqua/{base.py → app.py} +27 -7
- ads/aqua/cli.py +59 -17
- ads/aqua/common/__init__.py +5 -0
- ads/aqua/{decorator.py → common/decorator.py} +14 -8
- ads/aqua/common/enums.py +69 -0
- ads/aqua/{exception.py → common/errors.py} +28 -0
- ads/aqua/{utils.py → common/utils.py} +168 -77
- ads/aqua/config/config.py +18 -0
- ads/aqua/constants.py +51 -33
- ads/aqua/data.py +15 -26
- ads/aqua/evaluation/__init__.py +8 -0
- ads/aqua/evaluation/constants.py +53 -0
- ads/aqua/evaluation/entities.py +170 -0
- ads/aqua/evaluation/errors.py +71 -0
- ads/aqua/{evaluation.py → evaluation/evaluation.py} +122 -370
- ads/aqua/extension/__init__.py +2 -0
- ads/aqua/extension/aqua_ws_msg_handler.py +97 -0
- ads/aqua/extension/base_handler.py +0 -7
- ads/aqua/extension/common_handler.py +12 -6
- ads/aqua/extension/deployment_handler.py +70 -4
- ads/aqua/extension/errors.py +10 -0
- ads/aqua/extension/evaluation_handler.py +5 -3
- ads/aqua/extension/evaluation_ws_msg_handler.py +43 -0
- ads/aqua/extension/finetune_handler.py +41 -3
- ads/aqua/extension/model_handler.py +56 -4
- ads/aqua/extension/models/__init__.py +0 -0
- ads/aqua/extension/models/ws_models.py +69 -0
- ads/aqua/extension/ui_handler.py +65 -4
- ads/aqua/extension/ui_websocket_handler.py +124 -0
- ads/aqua/extension/utils.py +1 -1
- ads/aqua/finetuning/__init__.py +7 -0
- ads/aqua/finetuning/constants.py +17 -0
- ads/aqua/finetuning/entities.py +102 -0
- ads/aqua/{finetune.py → finetuning/finetuning.py} +162 -136
- ads/aqua/model/__init__.py +8 -0
- ads/aqua/model/constants.py +46 -0
- ads/aqua/model/entities.py +266 -0
- ads/aqua/model/enums.py +26 -0
- ads/aqua/{model.py → model/model.py} +401 -309
- ads/aqua/modeldeployment/__init__.py +8 -0
- ads/aqua/modeldeployment/constants.py +26 -0
- ads/aqua/{deployment.py → modeldeployment/deployment.py} +288 -227
- ads/aqua/modeldeployment/entities.py +142 -0
- ads/aqua/modeldeployment/inference.py +75 -0
- ads/aqua/ui.py +88 -8
- ads/cli.py +55 -7
- ads/common/serializer.py +2 -2
- ads/config.py +2 -1
- ads/jobs/builders/infrastructure/dsc_job.py +49 -6
- ads/model/datascience_model.py +1 -1
- ads/model/deployment/model_deployment.py +11 -0
- ads/model/model_metadata.py +17 -6
- ads/opctl/operator/lowcode/anomaly/README.md +0 -2
- ads/opctl/operator/lowcode/anomaly/__main__.py +3 -3
- ads/opctl/operator/lowcode/anomaly/environment.yaml +0 -2
- ads/opctl/operator/lowcode/anomaly/model/automlx.py +2 -2
- ads/opctl/operator/lowcode/anomaly/model/autots.py +1 -1
- ads/opctl/operator/lowcode/anomaly/model/base_model.py +13 -17
- ads/opctl/operator/lowcode/anomaly/operator_config.py +2 -0
- ads/opctl/operator/lowcode/anomaly/schema.yaml +1 -2
- ads/opctl/operator/lowcode/anomaly/utils.py +3 -2
- ads/opctl/operator/lowcode/common/transformations.py +2 -1
- ads/opctl/operator/lowcode/common/utils.py +1 -1
- ads/opctl/operator/lowcode/forecast/README.md +1 -3
- ads/opctl/operator/lowcode/forecast/__main__.py +3 -18
- ads/opctl/operator/lowcode/forecast/const.py +2 -0
- ads/opctl/operator/lowcode/forecast/environment.yaml +1 -2
- ads/opctl/operator/lowcode/forecast/model/arima.py +1 -0
- ads/opctl/operator/lowcode/forecast/model/automlx.py +7 -4
- ads/opctl/operator/lowcode/forecast/model/autots.py +1 -0
- ads/opctl/operator/lowcode/forecast/model/base_model.py +38 -22
- ads/opctl/operator/lowcode/forecast/model/factory.py +33 -4
- ads/opctl/operator/lowcode/forecast/model/forecast_datasets.py +15 -1
- ads/opctl/operator/lowcode/forecast/model/ml_forecast.py +234 -0
- ads/opctl/operator/lowcode/forecast/model/neuralprophet.py +9 -1
- ads/opctl/operator/lowcode/forecast/model/prophet.py +1 -0
- ads/opctl/operator/lowcode/forecast/model_evaluator.py +147 -0
- ads/opctl/operator/lowcode/forecast/operator_config.py +2 -1
- ads/opctl/operator/lowcode/forecast/schema.yaml +7 -2
- ads/opctl/operator/lowcode/forecast/utils.py +18 -44
- {oracle_ads-2.11.9.dist-info → oracle_ads-2.11.10.dist-info}/METADATA +9 -12
- {oracle_ads-2.11.9.dist-info → oracle_ads-2.11.10.dist-info}/RECORD +86 -61
- ads/aqua/job.py +0 -29
- {oracle_ads-2.11.9.dist-info → oracle_ads-2.11.10.dist-info}/LICENSE.txt +0 -0
- {oracle_ads-2.11.9.dist-info → oracle_ads-2.11.10.dist-info}/WHEEL +0 -0
- {oracle_ads-2.11.9.dist-info → oracle_ads-2.11.10.dist-info}/entry_points.txt +0 -0
ads/aqua/extension/__init__.py
CHANGED
@@ -14,6 +14,7 @@ from ads.aqua.extension.evaluation_handler import __handlers__ as __eval_handler
|
|
14
14
|
from ads.aqua.extension.finetune_handler import __handlers__ as __finetune_handlers__
|
15
15
|
from ads.aqua.extension.model_handler import __handlers__ as __model_handlers__
|
16
16
|
from ads.aqua.extension.ui_handler import __handlers__ as __ui_handlers__
|
17
|
+
from ads.aqua.extension.ui_websocket_handler import __handlers__ as __ws_handlers__
|
17
18
|
|
18
19
|
__handlers__ = (
|
19
20
|
__finetune_handlers__
|
@@ -22,6 +23,7 @@ __handlers__ = (
|
|
22
23
|
+ __deployment_handlers__
|
23
24
|
+ __ui_handlers__
|
24
25
|
+ __eval_handlers__
|
26
|
+
+ __ws_handlers__
|
25
27
|
)
|
26
28
|
|
27
29
|
|
@@ -0,0 +1,97 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*--
|
3
|
+
|
4
|
+
# Copyright (c) 2024 Oracle and/or its affiliates.
|
5
|
+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
6
|
+
|
7
|
+
import traceback
|
8
|
+
from abc import abstractmethod
|
9
|
+
from http.client import responses
|
10
|
+
from typing import List
|
11
|
+
|
12
|
+
from tornado.web import HTTPError
|
13
|
+
|
14
|
+
from ads.aqua import logger
|
15
|
+
from ads.aqua.common.decorator import handle_exceptions
|
16
|
+
from ads.aqua.extension.base_handler import AquaAPIhandler
|
17
|
+
from ads.aqua.extension.models.ws_models import (
|
18
|
+
AquaWsError,
|
19
|
+
BaseRequest,
|
20
|
+
BaseResponse,
|
21
|
+
ErrorResponse,
|
22
|
+
RequestResponseType,
|
23
|
+
)
|
24
|
+
from ads.config import AQUA_TELEMETRY_BUCKET, AQUA_TELEMETRY_BUCKET_NS
|
25
|
+
from ads.telemetry.client import TelemetryClient
|
26
|
+
|
27
|
+
|
28
|
+
class AquaWSMsgHandler:
|
29
|
+
message: str
|
30
|
+
|
31
|
+
def __init__(self, message: str):
|
32
|
+
self.message = message
|
33
|
+
try:
|
34
|
+
self.telemetry = TelemetryClient(
|
35
|
+
bucket=AQUA_TELEMETRY_BUCKET, namespace=AQUA_TELEMETRY_BUCKET_NS
|
36
|
+
)
|
37
|
+
except:
|
38
|
+
pass
|
39
|
+
|
40
|
+
@staticmethod
|
41
|
+
@abstractmethod
|
42
|
+
def get_message_types() -> List[RequestResponseType]:
|
43
|
+
"""This method should be implemented by the child class.
|
44
|
+
This method should return a list of RequestResponseType that the child class can handle
|
45
|
+
"""
|
46
|
+
pass
|
47
|
+
|
48
|
+
@abstractmethod
|
49
|
+
@handle_exceptions
|
50
|
+
def process(self) -> BaseResponse:
|
51
|
+
"""This method should be implemented by the child class.
|
52
|
+
This method will contain the core logic to be executed for handling the message
|
53
|
+
"""
|
54
|
+
pass
|
55
|
+
|
56
|
+
def write_error(self, status_code, **kwargs):
|
57
|
+
"""AquaWSMSGhandler errors are JSON, not human pages."""
|
58
|
+
reason = kwargs.get("reason")
|
59
|
+
service_payload = kwargs.get("service_payload", {})
|
60
|
+
default_msg = responses.get(status_code, "Unknown HTTP Error")
|
61
|
+
message = AquaAPIhandler.get_default_error_messages(
|
62
|
+
service_payload, str(status_code), kwargs.get("message", default_msg)
|
63
|
+
)
|
64
|
+
reply = {
|
65
|
+
"status": status_code,
|
66
|
+
"message": message,
|
67
|
+
"service_payload": service_payload,
|
68
|
+
"reason": reason,
|
69
|
+
}
|
70
|
+
exc_info = kwargs.get("exc_info")
|
71
|
+
if exc_info:
|
72
|
+
logger.error("".join(traceback.format_exception(*exc_info)))
|
73
|
+
e = exc_info[1]
|
74
|
+
if isinstance(e, HTTPError):
|
75
|
+
reply["message"] = e.log_message or message
|
76
|
+
reply["reason"] = e.reason
|
77
|
+
else:
|
78
|
+
logger.warning(reply["message"])
|
79
|
+
# telemetry may not be present if there is an error while initializing
|
80
|
+
if hasattr(self, "telemetry"):
|
81
|
+
self.telemetry.record_event_async(
|
82
|
+
category="aqua/error",
|
83
|
+
action=str(status_code),
|
84
|
+
value=reason,
|
85
|
+
)
|
86
|
+
response = AquaWsError(
|
87
|
+
status=status_code,
|
88
|
+
message=message,
|
89
|
+
service_payload=service_payload,
|
90
|
+
reason=reason,
|
91
|
+
)
|
92
|
+
base_message = BaseRequest.from_json(self.message, ignore_unknown=True)
|
93
|
+
return ErrorResponse(
|
94
|
+
message_id=base_message.message_id,
|
95
|
+
kind=RequestResponseType.Error,
|
96
|
+
data=response,
|
97
|
+
)
|
@@ -137,10 +137,3 @@ class AquaAPIhandler(APIHandler):
|
|
137
137
|
return messages[status_code]
|
138
138
|
else:
|
139
139
|
return default_msg
|
140
|
-
|
141
|
-
|
142
|
-
# todo: remove after error handler is implemented
|
143
|
-
class Errors(str):
|
144
|
-
INVALID_INPUT_DATA_FORMAT = "Invalid format of input data."
|
145
|
-
NO_INPUT_DATA = "No input data provided."
|
146
|
-
MISSING_REQUIRED_PARAMETER = "Missing required parameter: '{}'"
|
@@ -6,11 +6,15 @@
|
|
6
6
|
|
7
7
|
from importlib import metadata
|
8
8
|
|
9
|
+
import requests
|
10
|
+
from tornado.web import HTTPError
|
11
|
+
|
9
12
|
from ads.aqua import ODSC_MODEL_COMPARTMENT_OCID
|
10
|
-
from ads.aqua.decorator import handle_exceptions
|
11
|
-
from ads.aqua.
|
13
|
+
from ads.aqua.common.decorator import handle_exceptions
|
14
|
+
from ads.aqua.common.errors import AquaResourceAccessError, AquaRuntimeError
|
15
|
+
from ads.aqua.common.utils import fetch_service_compartment, known_realm
|
12
16
|
from ads.aqua.extension.base_handler import AquaAPIhandler
|
13
|
-
from ads.aqua.
|
17
|
+
from ads.aqua.extension.errors import Errors
|
14
18
|
|
15
19
|
|
16
20
|
class ADSVersionHandler(AquaAPIhandler):
|
@@ -33,9 +37,11 @@ class CompatibilityCheckHandler(AquaAPIhandler):
|
|
33
37
|
|
34
38
|
Returns
|
35
39
|
-------
|
36
|
-
|
37
|
-
|
38
|
-
|
40
|
+
status dict:
|
41
|
+
ok or compatible
|
42
|
+
|
43
|
+
Raises
|
44
|
+
------
|
39
45
|
AquaResourceAccessError: raised when aqua is not accessible in the given session/region.
|
40
46
|
|
41
47
|
"""
|
@@ -7,9 +7,11 @@ from urllib.parse import urlparse
|
|
7
7
|
|
8
8
|
from tornado.web import HTTPError
|
9
9
|
|
10
|
-
from ads.aqua.decorator import handle_exceptions
|
11
|
-
from ads.aqua.
|
12
|
-
from ads.aqua.extension.base_handler import AquaAPIhandler
|
10
|
+
from ads.aqua.common.decorator import handle_exceptions
|
11
|
+
from ads.aqua.extension.errors import Errors
|
12
|
+
from ads.aqua.extension.base_handler import AquaAPIhandler
|
13
|
+
from ads.aqua.modeldeployment import AquaDeploymentApp, MDInferenceResponse
|
14
|
+
from ads.aqua.modeldeployment.entities import ModelParams
|
13
15
|
from ads.config import COMPARTMENT_OCID, PROJECT_OCID
|
14
16
|
|
15
17
|
|
@@ -93,6 +95,11 @@ class AquaDeploymentHandler(AquaAPIhandler):
|
|
93
95
|
description = input_data.get("description")
|
94
96
|
instance_count = input_data.get("instance_count")
|
95
97
|
bandwidth_mbps = input_data.get("bandwidth_mbps")
|
98
|
+
web_concurrency = input_data.get("web_concurrency")
|
99
|
+
server_port = input_data.get("server_port")
|
100
|
+
health_check_port = input_data.get("health_check_port")
|
101
|
+
env_var = input_data.get("env_var")
|
102
|
+
container_family = input_data.get("container_family")
|
96
103
|
|
97
104
|
self.finish(
|
98
105
|
AquaDeploymentApp().create(
|
@@ -107,6 +114,11 @@ class AquaDeploymentHandler(AquaAPIhandler):
|
|
107
114
|
access_log_id=access_log_id,
|
108
115
|
predict_log_id=predict_log_id,
|
109
116
|
bandwidth_mbps=bandwidth_mbps,
|
117
|
+
web_concurrency=web_concurrency,
|
118
|
+
server_port=server_port,
|
119
|
+
health_check_port=health_check_port,
|
120
|
+
env_var=env_var,
|
121
|
+
container_family=container_family,
|
110
122
|
)
|
111
123
|
)
|
112
124
|
|
@@ -192,8 +204,62 @@ class AquaDeploymentInferenceHandler(AquaAPIhandler):
|
|
192
204
|
)
|
193
205
|
|
194
206
|
|
207
|
+
class AquaDeploymentParamsHandler(AquaAPIhandler):
|
208
|
+
"""Handler for Aqua deployment params REST APIs.
|
209
|
+
|
210
|
+
Methods
|
211
|
+
-------
|
212
|
+
get(self, model_id)
|
213
|
+
Retrieves a list of model deployment parameters.
|
214
|
+
post(self, *args, **kwargs)
|
215
|
+
Validates parameters for the given model id.
|
216
|
+
"""
|
217
|
+
|
218
|
+
@handle_exceptions
|
219
|
+
def get(self, model_id):
|
220
|
+
"""Handle GET request."""
|
221
|
+
instance_shape = self.get_argument("instance_shape")
|
222
|
+
return self.finish(
|
223
|
+
AquaDeploymentApp().get_deployment_default_params(
|
224
|
+
model_id=model_id, instance_shape=instance_shape
|
225
|
+
)
|
226
|
+
)
|
227
|
+
|
228
|
+
@handle_exceptions
|
229
|
+
def post(self, *args, **kwargs):
|
230
|
+
"""Handles post request for the deployment param handler API.
|
231
|
+
|
232
|
+
Raises
|
233
|
+
------
|
234
|
+
HTTPError
|
235
|
+
Raises HTTPError if inputs are missing or are invalid.
|
236
|
+
"""
|
237
|
+
try:
|
238
|
+
input_data = self.get_json_body()
|
239
|
+
except Exception:
|
240
|
+
raise HTTPError(400, Errors.INVALID_INPUT_DATA_FORMAT)
|
241
|
+
|
242
|
+
if not input_data:
|
243
|
+
raise HTTPError(400, Errors.NO_INPUT_DATA)
|
244
|
+
|
245
|
+
model_id = input_data.get("model_id")
|
246
|
+
if not model_id:
|
247
|
+
raise HTTPError(400, Errors.MISSING_REQUIRED_PARAMETER.format("model_id"))
|
248
|
+
|
249
|
+
params = input_data.get("params")
|
250
|
+
container_family = input_data.get("container_family")
|
251
|
+
return self.finish(
|
252
|
+
AquaDeploymentApp().validate_deployment_params(
|
253
|
+
model_id=model_id,
|
254
|
+
params=params,
|
255
|
+
container_family=container_family,
|
256
|
+
)
|
257
|
+
)
|
258
|
+
|
259
|
+
|
195
260
|
__handlers__ = [
|
196
|
-
("deployments/?([^/]*)",
|
261
|
+
("deployments/?([^/]*)/params", AquaDeploymentParamsHandler),
|
197
262
|
("deployments/config/?([^/]*)", AquaDeploymentHandler),
|
263
|
+
("deployments/?([^/]*)", AquaDeploymentHandler),
|
198
264
|
("inference", AquaDeploymentInferenceHandler),
|
199
265
|
]
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# Copyright (c) 2024 Oracle and/or its affiliates.
|
4
|
+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
5
|
+
|
6
|
+
|
7
|
+
class Errors(str):
|
8
|
+
INVALID_INPUT_DATA_FORMAT = "Invalid format of input data."
|
9
|
+
NO_INPUT_DATA = "No input data provided."
|
10
|
+
MISSING_REQUIRED_PARAMETER = "Missing required parameter: '{}'"
|
@@ -7,9 +7,11 @@ from urllib.parse import urlparse
|
|
7
7
|
|
8
8
|
from tornado.web import HTTPError
|
9
9
|
|
10
|
-
from ads.aqua.decorator import handle_exceptions
|
11
|
-
from ads.aqua.evaluation import AquaEvaluationApp
|
12
|
-
from ads.aqua.
|
10
|
+
from ads.aqua.common.decorator import handle_exceptions
|
11
|
+
from ads.aqua.evaluation import AquaEvaluationApp
|
12
|
+
from ads.aqua.evaluation.entities import CreateAquaEvaluationDetails
|
13
|
+
from ads.aqua.extension.errors import Errors
|
14
|
+
from ads.aqua.extension.base_handler import AquaAPIhandler
|
13
15
|
from ads.aqua.extension.utils import validate_function_parameters
|
14
16
|
from ads.config import COMPARTMENT_OCID
|
15
17
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*--
|
3
|
+
|
4
|
+
# Copyright (c) 2024 Oracle and/or its affiliates.
|
5
|
+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
6
|
+
|
7
|
+
from typing import List, Union
|
8
|
+
|
9
|
+
from tornado.web import HTTPError
|
10
|
+
|
11
|
+
from ads.aqua.common.decorator import handle_exceptions
|
12
|
+
from ads.aqua.evaluation import AquaEvaluationApp
|
13
|
+
from ads.aqua.extension.aqua_ws_msg_handler import AquaWSMsgHandler
|
14
|
+
from ads.aqua.extension.models.ws_models import (
|
15
|
+
ListEvaluationsRequest,
|
16
|
+
ListEvaluationsResponse,
|
17
|
+
RequestResponseType,
|
18
|
+
)
|
19
|
+
from ads.config import COMPARTMENT_OCID
|
20
|
+
|
21
|
+
|
22
|
+
class AquaEvaluationWSMsgHandler(AquaWSMsgHandler):
|
23
|
+
@staticmethod
|
24
|
+
def get_message_types() -> List[RequestResponseType]:
|
25
|
+
return [RequestResponseType.ListEvaluations]
|
26
|
+
|
27
|
+
def __init__(self, message: Union[str, bytes]):
|
28
|
+
super().__init__(message)
|
29
|
+
|
30
|
+
@handle_exceptions
|
31
|
+
def process(self) -> ListEvaluationsResponse:
|
32
|
+
list_eval_request = ListEvaluationsRequest.from_json(self.message)
|
33
|
+
|
34
|
+
eval_list = AquaEvaluationApp().list(
|
35
|
+
list_eval_request.compartment_id or COMPARTMENT_OCID,
|
36
|
+
list_eval_request.project_id,
|
37
|
+
)
|
38
|
+
response = ListEvaluationsResponse(
|
39
|
+
message_id=list_eval_request.message_id,
|
40
|
+
kind=RequestResponseType.ListEvaluations,
|
41
|
+
data=eval_list,
|
42
|
+
)
|
43
|
+
return response
|
@@ -8,10 +8,12 @@ from urllib.parse import urlparse
|
|
8
8
|
|
9
9
|
from tornado.web import HTTPError
|
10
10
|
|
11
|
-
from ads.aqua.decorator import handle_exceptions
|
12
|
-
from ads.aqua.extension.
|
11
|
+
from ads.aqua.common.decorator import handle_exceptions
|
12
|
+
from ads.aqua.extension.errors import Errors
|
13
|
+
from ads.aqua.extension.base_handler import AquaAPIhandler
|
13
14
|
from ads.aqua.extension.utils import validate_function_parameters
|
14
|
-
from ads.aqua.
|
15
|
+
from ads.aqua.finetuning import AquaFineTuningApp
|
16
|
+
from ads.aqua.finetuning.entities import CreateFineTuningDetails
|
15
17
|
|
16
18
|
|
17
19
|
class AquaFineTuneHandler(AquaAPIhandler):
|
@@ -59,7 +61,43 @@ class AquaFineTuneHandler(AquaAPIhandler):
|
|
59
61
|
return self.finish(AquaFineTuningApp().get_finetuning_config(model_id=model_id))
|
60
62
|
|
61
63
|
|
64
|
+
class AquaFineTuneParamsHandler(AquaAPIhandler):
|
65
|
+
"""Handler for Aqua finetuning params REST APIs."""
|
66
|
+
|
67
|
+
@handle_exceptions
|
68
|
+
def get(self, model_id):
|
69
|
+
"""Handle GET request."""
|
70
|
+
return self.finish(
|
71
|
+
AquaFineTuningApp().get_finetuning_default_params(model_id=model_id)
|
72
|
+
)
|
73
|
+
|
74
|
+
@handle_exceptions
|
75
|
+
def post(self, *args, **kwargs):
|
76
|
+
"""Handles post request for the finetuning param handler API.
|
77
|
+
|
78
|
+
Raises
|
79
|
+
------
|
80
|
+
HTTPError
|
81
|
+
Raises HTTPError if inputs are missing or are invalid.
|
82
|
+
"""
|
83
|
+
try:
|
84
|
+
input_data = self.get_json_body()
|
85
|
+
except Exception:
|
86
|
+
raise HTTPError(400, Errors.INVALID_INPUT_DATA_FORMAT)
|
87
|
+
|
88
|
+
if not input_data:
|
89
|
+
raise HTTPError(400, Errors.NO_INPUT_DATA)
|
90
|
+
|
91
|
+
params = input_data.get("params", None)
|
92
|
+
return self.finish(
|
93
|
+
AquaFineTuningApp().validate_finetuning_params(
|
94
|
+
params=params,
|
95
|
+
)
|
96
|
+
)
|
97
|
+
|
98
|
+
|
62
99
|
__handlers__ = [
|
100
|
+
("finetuning/?([^/]*)/params", AquaFineTuneParamsHandler),
|
63
101
|
("finetuning/?([^/]*)", AquaFineTuneHandler),
|
64
102
|
("finetuning/config/?([^/]*)", AquaFineTuneHandler),
|
65
103
|
]
|
@@ -3,11 +3,13 @@
|
|
3
3
|
# Copyright (c) 2024 Oracle and/or its affiliates.
|
4
4
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
5
5
|
|
6
|
+
import re
|
7
|
+
from typing import Optional
|
6
8
|
from urllib.parse import urlparse
|
7
9
|
|
8
10
|
from tornado.web import HTTPError
|
9
|
-
|
10
|
-
from ads.aqua.decorator import handle_exceptions
|
11
|
+
from ads.aqua.extension.errors import Errors
|
12
|
+
from ads.aqua.common.decorator import handle_exceptions
|
11
13
|
from ads.aqua.extension.base_handler import AquaAPIhandler
|
12
14
|
from ads.aqua.model import AquaModelApp
|
13
15
|
|
@@ -41,7 +43,56 @@ class AquaModelHandler(AquaAPIhandler):
|
|
41
43
|
compartment_id = self.get_argument("compartment_id", default=None)
|
42
44
|
# project_id is no needed.
|
43
45
|
project_id = self.get_argument("project_id", default=None)
|
44
|
-
|
46
|
+
model_type = self.get_argument("model_type", default=None)
|
47
|
+
return self.finish(
|
48
|
+
AquaModelApp().list(
|
49
|
+
compartment_id=compartment_id,
|
50
|
+
project_id=project_id,
|
51
|
+
model_type=model_type,
|
52
|
+
)
|
53
|
+
)
|
54
|
+
|
55
|
+
@handle_exceptions
|
56
|
+
def post(self, *args, **kwargs):
|
57
|
+
"""
|
58
|
+
Handles post request for the registering any Aqua model.
|
59
|
+
Raises
|
60
|
+
------
|
61
|
+
HTTPError
|
62
|
+
Raises HTTPError if inputs are missing or are invalid
|
63
|
+
"""
|
64
|
+
try:
|
65
|
+
input_data = self.get_json_body()
|
66
|
+
except Exception:
|
67
|
+
raise HTTPError(400, Errors.INVALID_INPUT_DATA_FORMAT)
|
68
|
+
|
69
|
+
if not input_data:
|
70
|
+
raise HTTPError(400, Errors.NO_INPUT_DATA)
|
71
|
+
|
72
|
+
# required input parameters
|
73
|
+
model = input_data.get("model")
|
74
|
+
if not model:
|
75
|
+
raise HTTPError(400, Errors.MISSING_REQUIRED_PARAMETER.format("model"))
|
76
|
+
os_path = input_data.get("os_path")
|
77
|
+
if not os_path:
|
78
|
+
raise HTTPError(400, Errors.MISSING_REQUIRED_PARAMETER.format("os_path"))
|
79
|
+
|
80
|
+
inference_container = input_data.get("inference_container")
|
81
|
+
finetuning_container = input_data.get("finetuning_container")
|
82
|
+
compartment_id = input_data.get("compartment_id")
|
83
|
+
project_id = input_data.get("project_id")
|
84
|
+
|
85
|
+
return self.finish(
|
86
|
+
AquaModelApp().register(
|
87
|
+
model=model,
|
88
|
+
os_path=os_path,
|
89
|
+
inference_container=inference_container,
|
90
|
+
finetuning_container=finetuning_container,
|
91
|
+
compartment_id=compartment_id,
|
92
|
+
project_id=project_id,
|
93
|
+
)
|
94
|
+
)
|
95
|
+
|
45
96
|
|
46
97
|
class AquaModelLicenseHandler(AquaAPIhandler):
|
47
98
|
"""Handler for Aqua Model license REST APIs."""
|
@@ -49,10 +100,11 @@ class AquaModelLicenseHandler(AquaAPIhandler):
|
|
49
100
|
@handle_exceptions
|
50
101
|
def get(self, model_id):
|
51
102
|
"""Handle GET request."""
|
52
|
-
|
103
|
+
|
53
104
|
model_id = model_id.split("/")[0]
|
54
105
|
return self.finish(AquaModelApp().load_license(model_id))
|
55
106
|
|
107
|
+
|
56
108
|
__handlers__ = [
|
57
109
|
("model/?([^/]*)", AquaModelHandler),
|
58
110
|
("model/?([^/]*)/license", AquaModelLicenseHandler),
|
File without changes
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*--
|
3
|
+
|
4
|
+
# Copyright (c) 2024 Oracle and/or its affiliates.
|
5
|
+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
6
|
+
|
7
|
+
from dataclasses import dataclass
|
8
|
+
from typing import List, Optional
|
9
|
+
|
10
|
+
from ads.aqua.evaluation.entities import AquaEvaluationSummary
|
11
|
+
from ads.aqua.model.entities import AquaModelSummary
|
12
|
+
from ads.common.extended_enum import ExtendedEnumMeta
|
13
|
+
from ads.common.serializer import DataClassSerializable
|
14
|
+
|
15
|
+
|
16
|
+
class RequestResponseType(str, metaclass=ExtendedEnumMeta):
|
17
|
+
ListEvaluations = "ListEvaluations"
|
18
|
+
ListModels = "ListModels"
|
19
|
+
Error = "Error"
|
20
|
+
|
21
|
+
|
22
|
+
@dataclass
|
23
|
+
class BaseResponse(DataClassSerializable):
|
24
|
+
message_id: str
|
25
|
+
kind: RequestResponseType
|
26
|
+
data: object
|
27
|
+
|
28
|
+
|
29
|
+
@dataclass
|
30
|
+
class BaseRequest(DataClassSerializable):
|
31
|
+
message_id: str
|
32
|
+
kind: RequestResponseType
|
33
|
+
|
34
|
+
|
35
|
+
@dataclass
|
36
|
+
class ListEvaluationsRequest(BaseRequest):
|
37
|
+
compartment_id: Optional[str] = None
|
38
|
+
limit: Optional[int] = None
|
39
|
+
project_id: Optional[str] = None
|
40
|
+
kind = RequestResponseType.ListEvaluations
|
41
|
+
|
42
|
+
|
43
|
+
@dataclass
|
44
|
+
class ListModelsRequest(BaseRequest):
|
45
|
+
compartment_id: Optional[str] = None
|
46
|
+
|
47
|
+
|
48
|
+
@dataclass
|
49
|
+
class ListEvaluationsResponse(BaseResponse):
|
50
|
+
data: List[AquaEvaluationSummary]
|
51
|
+
|
52
|
+
|
53
|
+
@dataclass
|
54
|
+
class ListModelsResponse(BaseResponse):
|
55
|
+
data: List[AquaModelSummary]
|
56
|
+
|
57
|
+
|
58
|
+
@dataclass
|
59
|
+
class AquaWsError(DataClassSerializable):
|
60
|
+
status: str
|
61
|
+
message: str
|
62
|
+
service_payload: Optional[dict]
|
63
|
+
reason: Optional[str]
|
64
|
+
|
65
|
+
|
66
|
+
@dataclass
|
67
|
+
class ErrorResponse(BaseResponse):
|
68
|
+
data: AquaWsError
|
69
|
+
kind = RequestResponseType.Error
|
ads/aqua/extension/ui_handler.py
CHANGED
@@ -3,17 +3,30 @@
|
|
3
3
|
# Copyright (c) 2024 Oracle and/or its affiliates.
|
4
4
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
5
5
|
|
6
|
+
from dataclasses import dataclass
|
6
7
|
from urllib.parse import urlparse
|
7
8
|
|
8
9
|
from tornado.web import HTTPError
|
9
10
|
|
10
|
-
from ads.aqua.
|
11
|
-
from ads.aqua.
|
11
|
+
from ads.aqua.common.decorator import handle_exceptions
|
12
|
+
from ads.aqua.common.enums import Tags
|
13
|
+
from ads.aqua.extension.errors import Errors
|
12
14
|
from ads.aqua.extension.base_handler import AquaAPIhandler
|
15
|
+
from ads.aqua.extension.utils import validate_function_parameters
|
16
|
+
from ads.aqua.model.entities import ImportModelDetails
|
13
17
|
from ads.aqua.ui import AquaUIApp
|
14
18
|
from ads.config import COMPARTMENT_OCID
|
15
19
|
|
16
20
|
|
21
|
+
@dataclass
|
22
|
+
class CLIDetails:
|
23
|
+
"""Interface to capture payload and command details for generating ads cli command"""
|
24
|
+
|
25
|
+
command: str
|
26
|
+
subcommand: str
|
27
|
+
payload: dict
|
28
|
+
|
29
|
+
|
17
30
|
class AquaUIHandler(AquaAPIhandler):
|
18
31
|
"""
|
19
32
|
Handler for Aqua UI REST APIs.
|
@@ -63,6 +76,8 @@ class AquaUIHandler(AquaAPIhandler):
|
|
63
76
|
return self.get_shape_availability()
|
64
77
|
elif paths.startswith("aqua/bucket/versioning"):
|
65
78
|
return self.is_bucket_versioned()
|
79
|
+
elif paths.startswith("aqua/containers"):
|
80
|
+
return self.list_containers()
|
66
81
|
else:
|
67
82
|
raise HTTPError(400, f"The request {self.request.path} is invalid.")
|
68
83
|
|
@@ -92,6 +107,10 @@ class AquaUIHandler(AquaAPIhandler):
|
|
92
107
|
"""Lists the compartments in a compartment specified by ODSC_MODEL_COMPARTMENT_OCID env variable."""
|
93
108
|
return self.finish(AquaUIApp().list_compartments())
|
94
109
|
|
110
|
+
def list_containers(self):
|
111
|
+
"""Lists the AQUA containers."""
|
112
|
+
return self.finish(AquaUIApp().list_containers())
|
113
|
+
|
95
114
|
def get_default_compartment(self):
|
96
115
|
"""Returns user compartment ocid."""
|
97
116
|
return self.finish(AquaUIApp().get_default_compartment())
|
@@ -103,7 +122,7 @@ class AquaUIHandler(AquaAPIhandler):
|
|
103
122
|
return self.finish(
|
104
123
|
AquaUIApp().list_model_version_sets(
|
105
124
|
compartment_id=compartment_id,
|
106
|
-
target_tag=Tags.AQUA_FINE_TUNING
|
125
|
+
target_tag=Tags.AQUA_FINE_TUNING,
|
107
126
|
**kwargs,
|
108
127
|
)
|
109
128
|
)
|
@@ -115,7 +134,7 @@ class AquaUIHandler(AquaAPIhandler):
|
|
115
134
|
return self.finish(
|
116
135
|
AquaUIApp().list_model_version_sets(
|
117
136
|
compartment_id=compartment_id,
|
118
|
-
target_tag=Tags.AQUA_EVALUATION
|
137
|
+
target_tag=Tags.AQUA_EVALUATION,
|
119
138
|
**kwargs,
|
120
139
|
)
|
121
140
|
)
|
@@ -175,6 +194,46 @@ class AquaUIHandler(AquaAPIhandler):
|
|
175
194
|
return self.finish(AquaUIApp().is_bucket_versioned(bucket_uri=bucket_uri))
|
176
195
|
|
177
196
|
|
197
|
+
class AquaCLIHandler(AquaAPIhandler):
|
198
|
+
"""Handler for Aqua model import
|
199
|
+
command_interface_map is a map of command+subcommand to corresponding API dataclas.
|
200
|
+
Eg. In command `ads aqua model register ....`, command is `model` and subcommand is `register`
|
201
|
+
The key in the map will be f"{command}_{sub_command}" and value will be a DataClass
|
202
|
+
"""
|
203
|
+
|
204
|
+
command_interface_map = {"model_register": ImportModelDetails}
|
205
|
+
|
206
|
+
@handle_exceptions
|
207
|
+
def post(self, *args, **kwargs):
|
208
|
+
"""Handles cli command construction
|
209
|
+
|
210
|
+
Raises
|
211
|
+
------
|
212
|
+
HTTPError
|
213
|
+
Raises HTTPError if inputs are missing or are invalid.
|
214
|
+
"""
|
215
|
+
try:
|
216
|
+
input_data = self.get_json_body()
|
217
|
+
except Exception:
|
218
|
+
raise HTTPError(400, Errors.INVALID_INPUT_DATA_FORMAT)
|
219
|
+
|
220
|
+
if not input_data:
|
221
|
+
raise HTTPError(400, Errors.NO_INPUT_DATA)
|
222
|
+
|
223
|
+
validate_function_parameters(data_class=CLIDetails, input_data=input_data)
|
224
|
+
command_details = CLIDetails(**input_data)
|
225
|
+
|
226
|
+
interface = AquaCLIHandler.command_interface_map[
|
227
|
+
f"{command_details.command}_{command_details.subcommand}"
|
228
|
+
]
|
229
|
+
|
230
|
+
validate_function_parameters(
|
231
|
+
data_class=interface, input_data=command_details.payload
|
232
|
+
)
|
233
|
+
payload = interface(**command_details.payload)
|
234
|
+
self.finish({"command": payload.build_cli()})
|
235
|
+
|
236
|
+
|
178
237
|
__handlers__ = [
|
179
238
|
("logging/?([^/]*)", AquaUIHandler),
|
180
239
|
("compartments/?([^/]*)", AquaUIHandler),
|
@@ -187,4 +246,6 @@ __handlers__ = [
|
|
187
246
|
("subnets/?([^/]*)", AquaUIHandler),
|
188
247
|
("shapes/limit/?([^/]*)", AquaUIHandler),
|
189
248
|
("bucket/versioning/?([^/]*)", AquaUIHandler),
|
249
|
+
("containers/?([^/]*)", AquaUIHandler),
|
250
|
+
("cli/?([^/]*)", AquaCLIHandler),
|
190
251
|
]
|