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.
Files changed (87) hide show
  1. ads/aqua/__init__.py +1 -1
  2. ads/aqua/{base.py → app.py} +27 -7
  3. ads/aqua/cli.py +59 -17
  4. ads/aqua/common/__init__.py +5 -0
  5. ads/aqua/{decorator.py → common/decorator.py} +14 -8
  6. ads/aqua/common/enums.py +69 -0
  7. ads/aqua/{exception.py → common/errors.py} +28 -0
  8. ads/aqua/{utils.py → common/utils.py} +168 -77
  9. ads/aqua/config/config.py +18 -0
  10. ads/aqua/constants.py +51 -33
  11. ads/aqua/data.py +15 -26
  12. ads/aqua/evaluation/__init__.py +8 -0
  13. ads/aqua/evaluation/constants.py +53 -0
  14. ads/aqua/evaluation/entities.py +170 -0
  15. ads/aqua/evaluation/errors.py +71 -0
  16. ads/aqua/{evaluation.py → evaluation/evaluation.py} +122 -370
  17. ads/aqua/extension/__init__.py +2 -0
  18. ads/aqua/extension/aqua_ws_msg_handler.py +97 -0
  19. ads/aqua/extension/base_handler.py +0 -7
  20. ads/aqua/extension/common_handler.py +12 -6
  21. ads/aqua/extension/deployment_handler.py +70 -4
  22. ads/aqua/extension/errors.py +10 -0
  23. ads/aqua/extension/evaluation_handler.py +5 -3
  24. ads/aqua/extension/evaluation_ws_msg_handler.py +43 -0
  25. ads/aqua/extension/finetune_handler.py +41 -3
  26. ads/aqua/extension/model_handler.py +56 -4
  27. ads/aqua/extension/models/__init__.py +0 -0
  28. ads/aqua/extension/models/ws_models.py +69 -0
  29. ads/aqua/extension/ui_handler.py +65 -4
  30. ads/aqua/extension/ui_websocket_handler.py +124 -0
  31. ads/aqua/extension/utils.py +1 -1
  32. ads/aqua/finetuning/__init__.py +7 -0
  33. ads/aqua/finetuning/constants.py +17 -0
  34. ads/aqua/finetuning/entities.py +102 -0
  35. ads/aqua/{finetune.py → finetuning/finetuning.py} +162 -136
  36. ads/aqua/model/__init__.py +8 -0
  37. ads/aqua/model/constants.py +46 -0
  38. ads/aqua/model/entities.py +266 -0
  39. ads/aqua/model/enums.py +26 -0
  40. ads/aqua/{model.py → model/model.py} +401 -309
  41. ads/aqua/modeldeployment/__init__.py +8 -0
  42. ads/aqua/modeldeployment/constants.py +26 -0
  43. ads/aqua/{deployment.py → modeldeployment/deployment.py} +288 -227
  44. ads/aqua/modeldeployment/entities.py +142 -0
  45. ads/aqua/modeldeployment/inference.py +75 -0
  46. ads/aqua/ui.py +88 -8
  47. ads/cli.py +55 -7
  48. ads/common/serializer.py +2 -2
  49. ads/config.py +2 -1
  50. ads/jobs/builders/infrastructure/dsc_job.py +49 -6
  51. ads/model/datascience_model.py +1 -1
  52. ads/model/deployment/model_deployment.py +11 -0
  53. ads/model/model_metadata.py +17 -6
  54. ads/opctl/operator/lowcode/anomaly/README.md +0 -2
  55. ads/opctl/operator/lowcode/anomaly/__main__.py +3 -3
  56. ads/opctl/operator/lowcode/anomaly/environment.yaml +0 -2
  57. ads/opctl/operator/lowcode/anomaly/model/automlx.py +2 -2
  58. ads/opctl/operator/lowcode/anomaly/model/autots.py +1 -1
  59. ads/opctl/operator/lowcode/anomaly/model/base_model.py +13 -17
  60. ads/opctl/operator/lowcode/anomaly/operator_config.py +2 -0
  61. ads/opctl/operator/lowcode/anomaly/schema.yaml +1 -2
  62. ads/opctl/operator/lowcode/anomaly/utils.py +3 -2
  63. ads/opctl/operator/lowcode/common/transformations.py +2 -1
  64. ads/opctl/operator/lowcode/common/utils.py +1 -1
  65. ads/opctl/operator/lowcode/forecast/README.md +1 -3
  66. ads/opctl/operator/lowcode/forecast/__main__.py +3 -18
  67. ads/opctl/operator/lowcode/forecast/const.py +2 -0
  68. ads/opctl/operator/lowcode/forecast/environment.yaml +1 -2
  69. ads/opctl/operator/lowcode/forecast/model/arima.py +1 -0
  70. ads/opctl/operator/lowcode/forecast/model/automlx.py +7 -4
  71. ads/opctl/operator/lowcode/forecast/model/autots.py +1 -0
  72. ads/opctl/operator/lowcode/forecast/model/base_model.py +38 -22
  73. ads/opctl/operator/lowcode/forecast/model/factory.py +33 -4
  74. ads/opctl/operator/lowcode/forecast/model/forecast_datasets.py +15 -1
  75. ads/opctl/operator/lowcode/forecast/model/ml_forecast.py +234 -0
  76. ads/opctl/operator/lowcode/forecast/model/neuralprophet.py +9 -1
  77. ads/opctl/operator/lowcode/forecast/model/prophet.py +1 -0
  78. ads/opctl/operator/lowcode/forecast/model_evaluator.py +147 -0
  79. ads/opctl/operator/lowcode/forecast/operator_config.py +2 -1
  80. ads/opctl/operator/lowcode/forecast/schema.yaml +7 -2
  81. ads/opctl/operator/lowcode/forecast/utils.py +18 -44
  82. {oracle_ads-2.11.9.dist-info → oracle_ads-2.11.10.dist-info}/METADATA +9 -12
  83. {oracle_ads-2.11.9.dist-info → oracle_ads-2.11.10.dist-info}/RECORD +86 -61
  84. ads/aqua/job.py +0 -29
  85. {oracle_ads-2.11.9.dist-info → oracle_ads-2.11.10.dist-info}/LICENSE.txt +0 -0
  86. {oracle_ads-2.11.9.dist-info → oracle_ads-2.11.10.dist-info}/WHEEL +0 -0
  87. {oracle_ads-2.11.9.dist-info → oracle_ads-2.11.10.dist-info}/entry_points.txt +0 -0
@@ -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.exception import AquaResourceAccessError
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.utils import known_realm, fetch_service_compartment
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
- status dict:
37
- ok or compatible
38
- Raises:
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.deployment import AquaDeploymentApp, MDInferenceResponse, ModelParams
12
- from ads.aqua.extension.base_handler import AquaAPIhandler, Errors
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/?([^/]*)", AquaDeploymentHandler),
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, CreateAquaEvaluationDetails
12
- from ads.aqua.extension.base_handler import AquaAPIhandler, Errors
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.base_handler import AquaAPIhandler, Errors
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.finetune import AquaFineTuningApp, CreateFineTuningDetails
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
- return self.finish(AquaModelApp().list(compartment_id, project_id))
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
@@ -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.data import Tags
11
- from ads.aqua.decorator import handle_exceptions
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.value,
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.value,
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
  ]