oracle-ads 2.13.12__py3-none-any.whl → 2.13.13__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/app.py +60 -8
- ads/aqua/cli.py +2 -0
- ads/aqua/client/client.py +38 -21
- ads/aqua/client/openai_client.py +20 -10
- ads/aqua/common/entities.py +58 -18
- ads/aqua/constants.py +2 -0
- ads/aqua/extension/common_handler.py +47 -2
- ads/aqua/extension/model_handler.py +50 -8
- ads/aqua/model/constants.py +1 -0
- ads/aqua/model/model.py +115 -56
- ads/aqua/modeldeployment/deployment.py +93 -20
- ads/aqua/modeldeployment/entities.py +146 -0
- ads/aqua/modeldeployment/model_group_config.py +7 -14
- ads/aqua/verify_policies/__init__.py +8 -0
- ads/aqua/verify_policies/constants.py +13 -0
- ads/aqua/verify_policies/entities.py +29 -0
- ads/aqua/verify_policies/messages.py +101 -0
- ads/aqua/verify_policies/utils.py +432 -0
- ads/aqua/verify_policies/verify.py +345 -0
- ads/aqua/version.json +3 -0
- ads/common/oci_logging.py +4 -7
- ads/model/deployment/model_deployment.py +51 -38
- {oracle_ads-2.13.12.dist-info → oracle_ads-2.13.13.dist-info}/METADATA +2 -1
- {oracle_ads-2.13.12.dist-info → oracle_ads-2.13.13.dist-info}/RECORD +27 -20
- {oracle_ads-2.13.12.dist-info → oracle_ads-2.13.13.dist-info}/WHEEL +0 -0
- {oracle_ads-2.13.12.dist-info → oracle_ads-2.13.13.dist-info}/entry_points.txt +0 -0
- {oracle_ads-2.13.12.dist-info → oracle_ads-2.13.13.dist-info}/licenses/LICENSE.txt +0 -0
@@ -0,0 +1,345 @@
|
|
1
|
+
import logging
|
2
|
+
|
3
|
+
import click
|
4
|
+
import oci.exceptions
|
5
|
+
|
6
|
+
from ads.aqua.verify_policies.constants import POLICY_HELP_LINK, TEST_JOB_NAME, TEST_JOB_RUN_NAME, TEST_LIMIT_NAME, \
|
7
|
+
TEST_MVS_NAME, TEST_MD_NAME, TEST_VM_SHAPE
|
8
|
+
from ads.aqua.verify_policies.messages import operation_messages
|
9
|
+
from ads.aqua.verify_policies.entities import OperationResultSuccess, OperationResultFailure, PolicyStatus
|
10
|
+
from ads.aqua.verify_policies.utils import PolicyValidationError, VerifyPoliciesUtils, RichStatusLog
|
11
|
+
from functools import wraps
|
12
|
+
|
13
|
+
logger = logging.getLogger("aqua.policies")
|
14
|
+
|
15
|
+
|
16
|
+
def with_spinner(func):
|
17
|
+
"""Decorator to wrap execution of a function with a rich UI spinner.
|
18
|
+
|
19
|
+
Displays status while the operation runs and logs success or failure messages
|
20
|
+
based on the policy verification result.
|
21
|
+
"""
|
22
|
+
|
23
|
+
@wraps(func)
|
24
|
+
def wrapper(self, function, **kwargs):
|
25
|
+
operation_message = operation_messages[function.__name__]
|
26
|
+
ignore_spinner = kwargs.pop("ignore_spinner", False)
|
27
|
+
|
28
|
+
def run_func():
|
29
|
+
return_value, result_status = func(self, function, **kwargs)
|
30
|
+
result_message = f"{self._rich_ui.get_status_emoji(result_status.status)} {result_status.operation}"
|
31
|
+
if result_status.status == PolicyStatus.SUCCESS:
|
32
|
+
logger.info(result_message)
|
33
|
+
else:
|
34
|
+
logger.warning(result_message)
|
35
|
+
logger.info(result_status.error)
|
36
|
+
logger.info(f"Policy hint: {result_status.policy_hint}")
|
37
|
+
logger.info(f"Refer to: {POLICY_HELP_LINK}")
|
38
|
+
|
39
|
+
return return_value, result_status
|
40
|
+
|
41
|
+
if ignore_spinner:
|
42
|
+
return run_func()
|
43
|
+
else:
|
44
|
+
with self._rich_ui.console.status(f"Verifying {operation_message['name']}") as status:
|
45
|
+
return run_func()
|
46
|
+
|
47
|
+
return wrapper
|
48
|
+
|
49
|
+
|
50
|
+
class AquaVerifyPoliciesApp:
|
51
|
+
"""
|
52
|
+
AquaVerifyPoliciesApp provides methods to verify IAM policies required for
|
53
|
+
various operations in OCI Data Science's AQUA (Accelerated Data Science) platform.
|
54
|
+
|
55
|
+
This utility is intended to help users validate whether they have the necessary
|
56
|
+
permissions to perform common AQUA workflows such as model registration,
|
57
|
+
deployment, evaluation, and fine-tuning.
|
58
|
+
|
59
|
+
Methods
|
60
|
+
-------
|
61
|
+
`common_policies()`: Validates basic read-level policies across AQUA components.
|
62
|
+
`model_register()`: Checks policies for object storage access and model registration.
|
63
|
+
`model_deployment()`: Validates policies for registering and deploying models.
|
64
|
+
`evaluation()`: Confirms ability to manage model version sets, jobs, and storage for evaluation.
|
65
|
+
`finetune()`: Verifies access required to fine-tune models.
|
66
|
+
"""
|
67
|
+
|
68
|
+
def __init__(self):
|
69
|
+
super().__init__()
|
70
|
+
self._util = VerifyPoliciesUtils()
|
71
|
+
self._rich_ui = RichStatusLog()
|
72
|
+
self.model_id = None
|
73
|
+
logger.propagate = False
|
74
|
+
logger.setLevel(logging.INFO)
|
75
|
+
|
76
|
+
def _get_operation_result(self, operation, status):
|
77
|
+
"""Maps a function and policy status to a corresponding result object.
|
78
|
+
|
79
|
+
Parameters:
|
80
|
+
operation (function): The operation being verified.
|
81
|
+
status (PolicyStatus): The outcome of the policy verification.
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
OperationResultSuccess or OperationResultFailure based on status.
|
85
|
+
"""
|
86
|
+
operation_message = operation_messages[operation.__name__]
|
87
|
+
if status == PolicyStatus.SUCCESS:
|
88
|
+
return OperationResultSuccess(operation=operation_message["name"])
|
89
|
+
if status == PolicyStatus.UNVERIFIED:
|
90
|
+
return OperationResultSuccess(operation=operation_message["name"], status=status)
|
91
|
+
if status == PolicyStatus.FAILURE:
|
92
|
+
return OperationResultFailure(operation=operation_message["name"], error=operation_message["error"],
|
93
|
+
policy_hint=f"{operation_message['policy_hint']}" )
|
94
|
+
|
95
|
+
@with_spinner
|
96
|
+
def _execute(self, function, **kwargs):
|
97
|
+
"""Executes a given operation function with policy validation and error handling.
|
98
|
+
Parameters:
|
99
|
+
function (callable): The function to execute.
|
100
|
+
kwargs (dict): Keyword arguments to pass to the function.
|
101
|
+
|
102
|
+
Returns:
|
103
|
+
Tuple: (result, OperationResult)
|
104
|
+
"""
|
105
|
+
result = None
|
106
|
+
try:
|
107
|
+
result = function(**kwargs)
|
108
|
+
status = PolicyStatus.SUCCESS
|
109
|
+
except oci.exceptions.ServiceError as oci_error:
|
110
|
+
if oci_error.status == 404:
|
111
|
+
logger.debug(oci_error)
|
112
|
+
status = PolicyStatus.FAILURE
|
113
|
+
else:
|
114
|
+
logger.error(oci_error)
|
115
|
+
raise oci_error
|
116
|
+
except PolicyValidationError as policy_error:
|
117
|
+
status = PolicyStatus.FAILURE
|
118
|
+
except Exception as e:
|
119
|
+
logger.error(e)
|
120
|
+
raise e
|
121
|
+
return result, self._get_operation_result(function, status)
|
122
|
+
|
123
|
+
def _test_model_register(self, **kwargs):
|
124
|
+
"""Verifies policies required to manage an object storage bucket and register a model.
|
125
|
+
|
126
|
+
Returns:
|
127
|
+
List of result dicts for bucket management and model registration.
|
128
|
+
"""
|
129
|
+
result = []
|
130
|
+
bucket = kwargs.pop("bucket")
|
131
|
+
_, test_manage_obs_policy = self._execute(self._util.manage_bucket, bucket=bucket, **kwargs)
|
132
|
+
result.append(test_manage_obs_policy.to_dict())
|
133
|
+
|
134
|
+
if test_manage_obs_policy.status == PolicyStatus.SUCCESS:
|
135
|
+
self.model_id, test_model_register = self._execute(self._util.register_model)
|
136
|
+
result.append(test_model_register.to_dict())
|
137
|
+
return result
|
138
|
+
|
139
|
+
def _test_delete_model(self, **kwargs):
|
140
|
+
"""Attempts to delete the test model created during model registration.
|
141
|
+
|
142
|
+
Returns:
|
143
|
+
List containing the result of model deletion.
|
144
|
+
"""
|
145
|
+
if self.model_id is not None:
|
146
|
+
_, test_delete_model_test = self._execute(self._util.aqua_model.ds_client.delete_model,
|
147
|
+
model_id=self.model_id, **kwargs)
|
148
|
+
return [test_delete_model_test.to_dict()]
|
149
|
+
else:
|
150
|
+
return [self._get_operation_result(self._util.aqua_model.ds_client.delete_model,
|
151
|
+
PolicyStatus.UNVERIFIED).to_dict()]
|
152
|
+
|
153
|
+
def _test_model_deployment(self, **kwargs):
|
154
|
+
"""Verifies policies required to create and delete a model deployment.
|
155
|
+
|
156
|
+
Returns:
|
157
|
+
List of result dicts for deployment creation and deletion.
|
158
|
+
"""
|
159
|
+
logger.info(f"Creating Model Deployment with name {TEST_MD_NAME}")
|
160
|
+
md_ocid, test_model_deployment = self._execute(self._util.create_model_deployment, model_id=self.model_id,
|
161
|
+
instance_shape=TEST_VM_SHAPE)
|
162
|
+
_, test_delete_md = self._execute(self._util.aqua_model.ds_client.delete_model_deployment, model_deployment_id=md_ocid)
|
163
|
+
return [test_model_deployment.to_dict(), test_delete_md.to_dict()]
|
164
|
+
|
165
|
+
def _test_manage_mvs(self, **kwargs):
|
166
|
+
"""Verifies policies required to create and delete a model version set (MVS).
|
167
|
+
|
168
|
+
Returns:
|
169
|
+
List of result dicts for MVS creation and deletion.
|
170
|
+
"""
|
171
|
+
logger.info(f"Creating ModelVersionSet with name {TEST_MVS_NAME}")
|
172
|
+
|
173
|
+
model_mvs, test_create_mvs = self._execute(self._util.create_model_version_set, name=TEST_MVS_NAME)
|
174
|
+
model_mvs_id = model_mvs[0]
|
175
|
+
if model_mvs_id:
|
176
|
+
logger.info(f"Deleting ModelVersionSet {TEST_MVS_NAME}")
|
177
|
+
_, delete_mvs = self._execute(self._util.aqua_model.ds_client.delete_model_version_set,
|
178
|
+
model_version_set_id=model_mvs_id)
|
179
|
+
else:
|
180
|
+
delete_mvs = self._get_operation_result(self._util.aqua_model.ds_client.delete_model_version_set,
|
181
|
+
PolicyStatus.UNVERIFIED)
|
182
|
+
return [test_create_mvs.to_dict(), delete_mvs.to_dict()]
|
183
|
+
|
184
|
+
def _test_manage_job(self, **kwargs):
|
185
|
+
"""Verifies policies required to create a job, create a job run, and delete the job.
|
186
|
+
|
187
|
+
Returns:
|
188
|
+
List of result dicts for job creation, job run creation, and job deletion.
|
189
|
+
"""
|
190
|
+
|
191
|
+
logger.info(f"Creating Job with name {TEST_JOB_NAME}")
|
192
|
+
|
193
|
+
# Create Job & JobRun.
|
194
|
+
job_id, test_create_job = self._execute(self._util.create_job, display_name=TEST_JOB_NAME,
|
195
|
+
**kwargs)
|
196
|
+
|
197
|
+
logger.info(f"Creating JobRun with name {TEST_JOB_RUN_NAME}")
|
198
|
+
|
199
|
+
_, test_create_job_run = self._execute(self._util.create_job_run, display_name=TEST_JOB_RUN_NAME,
|
200
|
+
job_id=job_id, **kwargs)
|
201
|
+
|
202
|
+
# Delete Job Run
|
203
|
+
if job_id:
|
204
|
+
_, delete_job = self._execute(self._util.aqua_model.ds_client.delete_job, job_id=job_id, delete_related_job_runs=True)
|
205
|
+
else:
|
206
|
+
delete_job = self._get_operation_result(self._util.aqua_model.ds_client.delete_job, PolicyStatus.UNVERIFIED)
|
207
|
+
|
208
|
+
return [test_create_job.to_dict(), test_create_job_run.to_dict(), delete_job.to_dict()]
|
209
|
+
|
210
|
+
def _prompt(self, message, bool=False):
|
211
|
+
"""Wrapper for Click prompt or confirmation.
|
212
|
+
|
213
|
+
Parameters:
|
214
|
+
message (str): The prompt message.
|
215
|
+
bool (bool): Whether to ask for confirmation instead of input.
|
216
|
+
|
217
|
+
Returns:
|
218
|
+
User input or confirmation (bool/str).
|
219
|
+
"""
|
220
|
+
if bool:
|
221
|
+
return click.confirm(message, default=False)
|
222
|
+
else:
|
223
|
+
return click.prompt(message, type=str)
|
224
|
+
|
225
|
+
def _consent(self):
|
226
|
+
"""
|
227
|
+
Prompts the user for confirmation before performing actions.
|
228
|
+
Exits if the user does not consent.
|
229
|
+
"""
|
230
|
+
answer = self._prompt("Do you want to continue?", bool=True)
|
231
|
+
if not answer:
|
232
|
+
exit(0)
|
233
|
+
|
234
|
+
def common_policies(self, **kwargs):
|
235
|
+
"""Verifies basic read-level policies across various AQUA components
|
236
|
+
(e.g. compartments, models, jobs, buckets, logs).
|
237
|
+
|
238
|
+
Returns:
|
239
|
+
List of result dicts for each verified operation.
|
240
|
+
"""
|
241
|
+
logger.info("[magenta]Verifying Common Policies")
|
242
|
+
basic_operations = [self._util.list_compartments, self._util.list_models, self._util.list_model_version_sets,
|
243
|
+
self._util.list_project, self._util.list_jobs, self._util.list_job_runs,
|
244
|
+
self._util.list_buckets,
|
245
|
+
self._util.list_log_groups
|
246
|
+
]
|
247
|
+
result = []
|
248
|
+
for op in basic_operations:
|
249
|
+
_, status = self._execute(op, **kwargs)
|
250
|
+
result.append(status.to_dict())
|
251
|
+
|
252
|
+
_, get_resource_availability_status = self._execute(self._util.get_resource_availability,
|
253
|
+
limit_name=TEST_LIMIT_NAME)
|
254
|
+
result.append(get_resource_availability_status.to_dict())
|
255
|
+
return result
|
256
|
+
|
257
|
+
def model_register(self, **kwargs):
|
258
|
+
"""Verifies policies required to register a model, including object storage access.
|
259
|
+
|
260
|
+
Returns:
|
261
|
+
List of result dicts for registration and cleanup.
|
262
|
+
"""
|
263
|
+
logger.info("[magenta]Verifying Model Register")
|
264
|
+
logger.info("Object and Model will be created.")
|
265
|
+
kwargs.pop("consent", None) == True or self._consent()
|
266
|
+
|
267
|
+
model_save_bucket = kwargs.pop("bucket", None) or self._prompt(
|
268
|
+
"Provide bucket name where model artifacts will be saved")
|
269
|
+
register_model_result = self._test_model_register(bucket=model_save_bucket)
|
270
|
+
delete_model_result = self._test_delete_model(**kwargs)
|
271
|
+
return [*register_model_result, *delete_model_result]
|
272
|
+
|
273
|
+
def model_deployment(self, **kwargs):
|
274
|
+
"""Verifies policies required to register and deploy a model, and perform cleanup.
|
275
|
+
|
276
|
+
Returns:
|
277
|
+
List of result dicts for registration, deployment, and cleanup.
|
278
|
+
"""
|
279
|
+
logger.info("[magenta]Verifying Model Deployment")
|
280
|
+
logger.info("Object, Model, Model deployment will be created.")
|
281
|
+
kwargs.pop("consent", None) == True or self._consent()
|
282
|
+
model_save_bucket = kwargs.pop("bucket", None) or self._prompt(
|
283
|
+
"Provide bucket name where model artifacts will be saved")
|
284
|
+
model_register = self._test_model_register(bucket=model_save_bucket)
|
285
|
+
model_deployment = self._test_model_deployment()
|
286
|
+
delete_model_result = self._test_delete_model(**kwargs)
|
287
|
+
|
288
|
+
return [*model_register, *model_deployment, *delete_model_result]
|
289
|
+
|
290
|
+
def evaluation(self, **kwargs):
|
291
|
+
"""Verifies policies for evaluation workloads including model version set,
|
292
|
+
job and job runs, and object storage access.
|
293
|
+
|
294
|
+
Returns:
|
295
|
+
List of result dicts for all evaluation steps.
|
296
|
+
"""
|
297
|
+
logger.info("[magenta]Verifying Evaluation")
|
298
|
+
logger.info("Model Version Set, Model, Object, Job and JobRun will be created.")
|
299
|
+
kwargs.pop("consent", None) == True or self._consent()
|
300
|
+
|
301
|
+
# Create & Delete MVS
|
302
|
+
test_manage_mvs = self._test_manage_mvs(**kwargs)
|
303
|
+
|
304
|
+
# Create & Model
|
305
|
+
model_save_bucket = kwargs.pop("bucket", None) or self._prompt(
|
306
|
+
"Provide bucket name where model artifacts will be saved")
|
307
|
+
register_model_result = self._test_model_register(bucket=model_save_bucket)
|
308
|
+
delete_model_result = self._test_delete_model(**kwargs)
|
309
|
+
|
310
|
+
# Manage Jobs & Job Runs
|
311
|
+
test_job_and_job_run = self._test_manage_job(**kwargs)
|
312
|
+
|
313
|
+
return [*test_manage_mvs, *register_model_result, *delete_model_result, *test_job_and_job_run]
|
314
|
+
|
315
|
+
def finetune(self, **kwargs):
|
316
|
+
"""Verifies policies for fine-tuning jobs, including managing object storage,
|
317
|
+
MVS.
|
318
|
+
|
319
|
+
Returns:
|
320
|
+
List of result dicts for each fine-tuning operation.
|
321
|
+
"""
|
322
|
+
logger.info("[magenta]Verifying Finetuning")
|
323
|
+
logger.info("Object, Model Version Set, Job and JobRun will be created. VCN will be used.")
|
324
|
+
kwargs.pop("consent", None) == True or self._consent()
|
325
|
+
|
326
|
+
# Manage bucket
|
327
|
+
bucket = kwargs.pop("bucket", None) or self._prompt(
|
328
|
+
"Provide bucket name required to save training datasets, scripts, and fine-tuned model outputs")
|
329
|
+
|
330
|
+
subnet_id = kwargs.pop("subnet_id", None)
|
331
|
+
ignore_subnet = kwargs.pop("ignore_subnet", False)
|
332
|
+
|
333
|
+
if subnet_id is None and not ignore_subnet and self._prompt("Do you want to use custom subnet", bool=True):
|
334
|
+
subnet_id = self._prompt("Provide subnet id")
|
335
|
+
|
336
|
+
_, test_manage_obs_policy = self._execute(self._util.manage_bucket, bucket=bucket, **kwargs)
|
337
|
+
|
338
|
+
# Create & Delete MVS
|
339
|
+
test_manage_mvs = self._test_manage_mvs(**kwargs)
|
340
|
+
|
341
|
+
# Manage Jobs & Job Runs
|
342
|
+
test_job_and_job_run = self._test_manage_job(subnet_id = subnet_id, **kwargs)
|
343
|
+
|
344
|
+
return [*test_manage_mvs, *test_job_and_job_run, test_manage_obs_policy.to_dict()]
|
345
|
+
|
ads/aqua/version.json
ADDED
ads/common/oci_logging.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
|
-
# -*- coding: utf-8; -*-
|
3
2
|
|
4
3
|
# Copyright (c) 2021, 2024 Oracle and/or its affiliates.
|
5
4
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
@@ -7,16 +6,16 @@
|
|
7
6
|
import datetime
|
8
7
|
import logging
|
9
8
|
import time
|
10
|
-
from typing import Dict,
|
9
|
+
from typing import Dict, List, Union
|
11
10
|
|
11
|
+
import oci.exceptions
|
12
12
|
import oci.logging
|
13
13
|
import oci.loggingsearch
|
14
|
-
|
14
|
+
|
15
15
|
from ads.common.decorator.utils import class_or_instance_method
|
16
16
|
from ads.common.oci_mixin import OCIModelMixin, OCIWorkRequestMixin
|
17
17
|
from ads.common.oci_resource import OCIResource, ResourceNotFoundError
|
18
18
|
|
19
|
-
|
20
19
|
logger = logging.getLogger(__name__)
|
21
20
|
|
22
21
|
# Maximum number of log records to be returned by default.
|
@@ -862,9 +861,7 @@ class ConsolidatedLog:
|
|
862
861
|
time_start=time_start,
|
863
862
|
log_filter=log_filter,
|
864
863
|
)
|
865
|
-
self._print(
|
866
|
-
sorted(tail_logs, key=lambda log: log["time"])
|
867
|
-
)
|
864
|
+
self._print(sorted(tail_logs, key=lambda log: log["time"]))
|
868
865
|
|
869
866
|
def head(
|
870
867
|
self,
|
@@ -1,22 +1,27 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
|
-
# -*- coding: utf-8; -*-
|
3
2
|
|
4
|
-
# Copyright (c) 2021,
|
3
|
+
# Copyright (c) 2021, 2025 Oracle and/or its affiliates.
|
5
4
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
6
5
|
|
7
6
|
|
8
7
|
import collections
|
9
8
|
import copy
|
10
9
|
import datetime
|
11
|
-
import oci
|
12
|
-
import warnings
|
13
10
|
import time
|
14
|
-
|
11
|
+
import warnings
|
12
|
+
from typing import Any, Dict, List, Union
|
15
13
|
|
14
|
+
import oci
|
16
15
|
import oci.loggingsearch
|
17
|
-
from ads.common import auth as authutil
|
18
16
|
import pandas as pd
|
19
|
-
from
|
17
|
+
from oci.data_science.models import (
|
18
|
+
CreateModelDeploymentDetails,
|
19
|
+
LogDetails,
|
20
|
+
UpdateModelDeploymentDetails,
|
21
|
+
)
|
22
|
+
|
23
|
+
from ads.common import auth as authutil
|
24
|
+
from ads.common import utils as ads_utils
|
20
25
|
from ads.common.oci_logging import (
|
21
26
|
LOG_INTERVAL,
|
22
27
|
LOG_RECORDS_LIMIT,
|
@@ -30,10 +35,10 @@ from ads.model.common.utils import _is_json_serializable
|
|
30
35
|
from ads.model.deployment.common.utils import send_request
|
31
36
|
from ads.model.deployment.model_deployment_infrastructure import (
|
32
37
|
DEFAULT_BANDWIDTH_MBPS,
|
38
|
+
DEFAULT_MEMORY_IN_GBS,
|
39
|
+
DEFAULT_OCPUS,
|
33
40
|
DEFAULT_REPLICA,
|
34
41
|
DEFAULT_SHAPE_NAME,
|
35
|
-
DEFAULT_OCPUS,
|
36
|
-
DEFAULT_MEMORY_IN_GBS,
|
37
42
|
MODEL_DEPLOYMENT_INFRASTRUCTURE_TYPE,
|
38
43
|
ModelDeploymentInfrastructure,
|
39
44
|
)
|
@@ -45,18 +50,14 @@ from ads.model.deployment.model_deployment_runtime import (
|
|
45
50
|
ModelDeploymentRuntimeType,
|
46
51
|
OCIModelDeploymentRuntimeType,
|
47
52
|
)
|
53
|
+
from ads.model.serde.model_input import JsonModelInputSERDE
|
48
54
|
from ads.model.service.oci_datascience_model_deployment import (
|
49
55
|
OCIDataScienceModelDeployment,
|
50
56
|
)
|
51
|
-
|
57
|
+
|
52
58
|
from .common import utils
|
53
59
|
from .common.utils import State
|
54
60
|
from .model_deployment_properties import ModelDeploymentProperties
|
55
|
-
from oci.data_science.models import (
|
56
|
-
LogDetails,
|
57
|
-
CreateModelDeploymentDetails,
|
58
|
-
UpdateModelDeploymentDetails,
|
59
|
-
)
|
60
61
|
|
61
62
|
DEFAULT_WAIT_TIME = 1200
|
62
63
|
DEFAULT_POLL_INTERVAL = 10
|
@@ -751,6 +752,8 @@ class ModelDeployment(Builder):
|
|
751
752
|
log_filter : str, optional
|
752
753
|
Expression for filtering the logs. This will be the WHERE clause of the query.
|
753
754
|
Defaults to None.
|
755
|
+
status_list : List[str], optional
|
756
|
+
List of status of model deployment. This is used to store list of status from logs.
|
754
757
|
|
755
758
|
Returns
|
756
759
|
-------
|
@@ -964,7 +967,9 @@ class ModelDeployment(Builder):
|
|
964
967
|
except oci.exceptions.ServiceError as ex:
|
965
968
|
# When bandwidth exceeds the allocated value, TooManyRequests error (429) will be raised by oci backend.
|
966
969
|
if ex.status == 429:
|
967
|
-
bandwidth_mbps =
|
970
|
+
bandwidth_mbps = (
|
971
|
+
self.infrastructure.bandwidth_mbps or DEFAULT_BANDWIDTH_MBPS
|
972
|
+
)
|
968
973
|
utils.get_logger().warning(
|
969
974
|
f"Load balancer bandwidth exceeds the allocated {bandwidth_mbps} Mbps."
|
970
975
|
"To estimate the actual bandwidth, use formula: (payload size in KB) * (estimated requests per second) * 8 / 1024."
|
@@ -1644,22 +1649,22 @@ class ModelDeployment(Builder):
|
|
1644
1649
|
}
|
1645
1650
|
|
1646
1651
|
if infrastructure.subnet_id:
|
1647
|
-
instance_configuration[
|
1648
|
-
infrastructure.
|
1649
|
-
|
1652
|
+
instance_configuration[infrastructure.CONST_SUBNET_ID] = (
|
1653
|
+
infrastructure.subnet_id
|
1654
|
+
)
|
1650
1655
|
|
1651
1656
|
if infrastructure.private_endpoint_id:
|
1652
1657
|
if not hasattr(
|
1653
1658
|
oci.data_science.models.InstanceConfiguration, "private_endpoint_id"
|
1654
1659
|
):
|
1655
1660
|
# TODO: add oci version with private endpoint support.
|
1656
|
-
raise
|
1661
|
+
raise OSError(
|
1657
1662
|
"Private endpoint is not supported in the current OCI SDK installed."
|
1658
1663
|
)
|
1659
1664
|
|
1660
|
-
instance_configuration[
|
1661
|
-
infrastructure.
|
1662
|
-
|
1665
|
+
instance_configuration[infrastructure.CONST_PRIVATE_ENDPOINT_ID] = (
|
1666
|
+
infrastructure.private_endpoint_id
|
1667
|
+
)
|
1663
1668
|
|
1664
1669
|
scaling_policy = {
|
1665
1670
|
infrastructure.CONST_POLICY_TYPE: "FIXED_SIZE",
|
@@ -1704,7 +1709,7 @@ class ModelDeployment(Builder):
|
|
1704
1709
|
oci.data_science.models,
|
1705
1710
|
"ModelDeploymentEnvironmentConfigurationDetails",
|
1706
1711
|
):
|
1707
|
-
raise
|
1712
|
+
raise OSError(
|
1708
1713
|
"Environment variable hasn't been supported in the current OCI SDK installed."
|
1709
1714
|
)
|
1710
1715
|
|
@@ -1720,9 +1725,9 @@ class ModelDeployment(Builder):
|
|
1720
1725
|
and runtime.inference_server.upper()
|
1721
1726
|
== MODEL_DEPLOYMENT_INFERENCE_SERVER_TRITON
|
1722
1727
|
):
|
1723
|
-
environment_variables[
|
1724
|
-
|
1725
|
-
|
1728
|
+
environment_variables["CONTAINER_TYPE"] = (
|
1729
|
+
MODEL_DEPLOYMENT_INFERENCE_SERVER_TRITON
|
1730
|
+
)
|
1726
1731
|
runtime.set_spec(runtime.CONST_ENV, environment_variables)
|
1727
1732
|
environment_configuration_details = {
|
1728
1733
|
runtime.CONST_ENVIRONMENT_CONFIG_TYPE: runtime.environment_config_type,
|
@@ -1734,7 +1739,7 @@ class ModelDeployment(Builder):
|
|
1734
1739
|
oci.data_science.models,
|
1735
1740
|
"OcirModelDeploymentEnvironmentConfigurationDetails",
|
1736
1741
|
):
|
1737
|
-
raise
|
1742
|
+
raise OSError(
|
1738
1743
|
"Container runtime hasn't been supported in the current OCI SDK installed."
|
1739
1744
|
)
|
1740
1745
|
environment_configuration_details["image"] = runtime.image
|
@@ -1742,9 +1747,9 @@ class ModelDeployment(Builder):
|
|
1742
1747
|
environment_configuration_details["cmd"] = runtime.cmd
|
1743
1748
|
environment_configuration_details["entrypoint"] = runtime.entrypoint
|
1744
1749
|
environment_configuration_details["serverPort"] = runtime.server_port
|
1745
|
-
environment_configuration_details[
|
1746
|
-
|
1747
|
-
|
1750
|
+
environment_configuration_details["healthCheckPort"] = (
|
1751
|
+
runtime.health_check_port
|
1752
|
+
)
|
1748
1753
|
|
1749
1754
|
model_deployment_configuration_details = {
|
1750
1755
|
infrastructure.CONST_DEPLOYMENT_TYPE: "SINGLE_MODEL",
|
@@ -1754,7 +1759,7 @@ class ModelDeployment(Builder):
|
|
1754
1759
|
|
1755
1760
|
if runtime.deployment_mode == ModelDeploymentMode.STREAM:
|
1756
1761
|
if not hasattr(oci.data_science.models, "StreamConfigurationDetails"):
|
1757
|
-
raise
|
1762
|
+
raise OSError(
|
1758
1763
|
"Model deployment mode hasn't been supported in the current OCI SDK installed."
|
1759
1764
|
)
|
1760
1765
|
model_deployment_configuration_details[
|
@@ -1786,9 +1791,13 @@ class ModelDeployment(Builder):
|
|
1786
1791
|
|
1787
1792
|
logs = {}
|
1788
1793
|
if (
|
1789
|
-
self.infrastructure.access_log
|
1790
|
-
self.infrastructure.access_log.get(
|
1791
|
-
|
1794
|
+
self.infrastructure.access_log
|
1795
|
+
and self.infrastructure.access_log.get(
|
1796
|
+
self.infrastructure.CONST_LOG_GROUP_ID, None
|
1797
|
+
)
|
1798
|
+
and self.infrastructure.access_log.get(
|
1799
|
+
self.infrastructure.CONST_LOG_ID, None
|
1800
|
+
)
|
1792
1801
|
):
|
1793
1802
|
logs[self.infrastructure.CONST_ACCESS] = {
|
1794
1803
|
self.infrastructure.CONST_LOG_GROUP_ID: self.infrastructure.access_log.get(
|
@@ -1799,9 +1808,13 @@ class ModelDeployment(Builder):
|
|
1799
1808
|
),
|
1800
1809
|
}
|
1801
1810
|
if (
|
1802
|
-
self.infrastructure.predict_log
|
1803
|
-
self.infrastructure.predict_log.get(
|
1804
|
-
|
1811
|
+
self.infrastructure.predict_log
|
1812
|
+
and self.infrastructure.predict_log.get(
|
1813
|
+
self.infrastructure.CONST_LOG_GROUP_ID, None
|
1814
|
+
)
|
1815
|
+
and self.infrastructure.predict_log.get(
|
1816
|
+
self.infrastructure.CONST_LOG_ID, None
|
1817
|
+
)
|
1805
1818
|
):
|
1806
1819
|
logs[self.infrastructure.CONST_PREDICT] = {
|
1807
1820
|
self.infrastructure.CONST_LOG_GROUP_ID: self.infrastructure.predict_log.get(
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: oracle_ads
|
3
|
-
Version: 2.13.
|
3
|
+
Version: 2.13.13
|
4
4
|
Summary: Oracle Accelerated Data Science SDK
|
5
5
|
Keywords: Oracle Cloud Infrastructure,OCI,Machine Learning,ML,Artificial Intelligence,AI,Data Science,Cloud,Oracle,GenAI,Generative AI,Forecast,Anomaly,Document Understanding,Anomaly Detection
|
6
6
|
Author: Oracle Data Science
|
@@ -50,6 +50,7 @@ Requires-Dist: fire ; extra == "aqua"
|
|
50
50
|
Requires-Dist: cachetools ; extra == "aqua"
|
51
51
|
Requires-Dist: huggingface_hub ; extra == "aqua"
|
52
52
|
Requires-Dist: python-dotenv ; extra == "aqua"
|
53
|
+
Requires-Dist: rich ; extra == "aqua"
|
53
54
|
Requires-Dist: hdfs[kerberos] ; extra == "bds"
|
54
55
|
Requires-Dist: ibis-framework[impala] ; extra == "bds"
|
55
56
|
Requires-Dist: sqlalchemy ; extra == "bds"
|