oracle-ads 2.13.4__py3-none-any.whl → 2.13.6__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 +6 -0
- ads/aqua/client/openai_client.py +305 -0
- ads/aqua/common/entities.py +224 -2
- ads/aqua/common/enums.py +17 -0
- ads/aqua/common/utils.py +143 -3
- ads/aqua/config/container_config.py +9 -0
- ads/aqua/constants.py +29 -1
- ads/aqua/evaluation/entities.py +6 -1
- ads/aqua/evaluation/evaluation.py +191 -7
- ads/aqua/extension/aqua_ws_msg_handler.py +6 -36
- ads/aqua/extension/base_handler.py +13 -71
- ads/aqua/extension/deployment_handler.py +67 -76
- ads/aqua/extension/errors.py +19 -0
- ads/aqua/extension/utils.py +114 -2
- ads/aqua/finetuning/finetuning.py +50 -1
- ads/aqua/model/constants.py +3 -0
- ads/aqua/model/enums.py +5 -0
- ads/aqua/model/model.py +247 -24
- ads/aqua/modeldeployment/deployment.py +671 -152
- ads/aqua/modeldeployment/entities.py +551 -42
- ads/aqua/modeldeployment/inference.py +4 -5
- ads/aqua/modeldeployment/utils.py +525 -0
- ads/aqua/resources/gpu_shapes_index.json +94 -0
- ads/dataset/recommendation.py +11 -20
- ads/opctl/operator/lowcode/pii/model/report.py +9 -16
- ads/opctl/utils.py +1 -1
- {oracle_ads-2.13.4.dist-info → oracle_ads-2.13.6.dist-info}/METADATA +1 -1
- {oracle_ads-2.13.4.dist-info → oracle_ads-2.13.6.dist-info}/RECORD +31 -28
- {oracle_ads-2.13.4.dist-info → oracle_ads-2.13.6.dist-info}/WHEEL +0 -0
- {oracle_ads-2.13.4.dist-info → oracle_ads-2.13.6.dist-info}/entry_points.txt +0 -0
- {oracle_ads-2.13.4.dist-info → oracle_ads-2.13.6.dist-info}/licenses/LICENSE.txt +0 -0
ads/aqua/model/model.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
2
|
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
|
3
3
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
4
|
+
import json
|
4
5
|
import os
|
5
6
|
import pathlib
|
6
7
|
from datetime import datetime, timedelta
|
@@ -14,6 +15,7 @@ from oci.data_science.models import JobRun, Metadata, Model, UpdateModelDetails
|
|
14
15
|
|
15
16
|
from ads.aqua import ODSC_MODEL_COMPARTMENT_OCID, logger
|
16
17
|
from ads.aqua.app import AquaApp
|
18
|
+
from ads.aqua.common.entities import AquaMultiModelRef
|
17
19
|
from ads.aqua.common.enums import (
|
18
20
|
ConfigFolder,
|
19
21
|
CustomInferenceContainerTypeFamily,
|
@@ -37,12 +39,13 @@ from ads.aqua.common.utils import (
|
|
37
39
|
get_artifact_path,
|
38
40
|
get_container_config,
|
39
41
|
get_hf_model_info,
|
42
|
+
get_preferred_compatible_family,
|
40
43
|
list_os_files_with_extension,
|
41
44
|
load_config,
|
42
45
|
read_file,
|
43
46
|
upload_folder,
|
44
47
|
)
|
45
|
-
from ads.aqua.config.container_config import AquaContainerConfig
|
48
|
+
from ads.aqua.config.container_config import AquaContainerConfig, Usage
|
46
49
|
from ads.aqua.constants import (
|
47
50
|
AQUA_MODEL_ARTIFACT_CONFIG,
|
48
51
|
AQUA_MODEL_ARTIFACT_CONFIG_MODEL_NAME,
|
@@ -77,6 +80,7 @@ from ads.aqua.model.entities import (
|
|
77
80
|
ImportModelDetails,
|
78
81
|
ModelValidationResult,
|
79
82
|
)
|
83
|
+
from ads.aqua.model.enums import MultiModelSupportedTaskType
|
80
84
|
from ads.common.auth import default_signer
|
81
85
|
from ads.common.oci_resource import SEARCH_TYPE, OCIResource
|
82
86
|
from ads.common.utils import UNKNOWN, get_console_link
|
@@ -91,6 +95,7 @@ from ads.config import (
|
|
91
95
|
TENANCY_OCID,
|
92
96
|
)
|
93
97
|
from ads.model import DataScienceModel
|
98
|
+
from ads.model.common.utils import MetadataArtifactPathType
|
94
99
|
from ads.model.model_metadata import (
|
95
100
|
MetadataCustomCategory,
|
96
101
|
ModelCustomMetadata,
|
@@ -135,40 +140,45 @@ class AquaModelApp(AquaApp):
|
|
135
140
|
@telemetry(entry_point="plugin=model&action=create", name="aqua")
|
136
141
|
def create(
|
137
142
|
self,
|
138
|
-
model_id: str,
|
139
|
-
project_id: str,
|
140
|
-
compartment_id: str = None,
|
141
|
-
freeform_tags: Optional[
|
142
|
-
defined_tags: Optional[
|
143
|
+
model_id: Union[str, AquaMultiModelRef],
|
144
|
+
project_id: Optional[str] = None,
|
145
|
+
compartment_id: Optional[str] = None,
|
146
|
+
freeform_tags: Optional[Dict] = None,
|
147
|
+
defined_tags: Optional[Dict] = None,
|
143
148
|
**kwargs,
|
144
149
|
) -> DataScienceModel:
|
145
|
-
"""
|
150
|
+
"""
|
151
|
+
Creates a custom Aqua model from a service model.
|
146
152
|
|
147
153
|
Parameters
|
148
154
|
----------
|
149
|
-
model_id: str
|
150
|
-
The
|
151
|
-
project_id: str
|
152
|
-
The project
|
153
|
-
compartment_id: str
|
154
|
-
The compartment
|
155
|
-
If not provided, compartment
|
156
|
-
freeform_tags:
|
157
|
-
Freeform tags for the model
|
158
|
-
defined_tags:
|
159
|
-
Defined tags for the model
|
155
|
+
model_id : Union[str, AquaMultiModelRef]
|
156
|
+
The model ID as a string or a AquaMultiModelRef instance to be deployed.
|
157
|
+
project_id : Optional[str]
|
158
|
+
The project ID for the custom model.
|
159
|
+
compartment_id : Optional[str]
|
160
|
+
The compartment ID for the custom model. Defaults to None.
|
161
|
+
If not provided, the compartment ID will be fetched from environment variables.
|
162
|
+
freeform_tags : Optional[Dict]
|
163
|
+
Freeform tags for the model.
|
164
|
+
defined_tags : Optional[Dict]
|
165
|
+
Defined tags for the model.
|
166
|
+
|
160
167
|
Returns
|
161
168
|
-------
|
162
|
-
DataScienceModel
|
169
|
+
DataScienceModel
|
163
170
|
The instance of DataScienceModel.
|
164
171
|
"""
|
172
|
+
model_id = (
|
173
|
+
model_id.model_id if isinstance(model_id, AquaMultiModelRef) else model_id
|
174
|
+
)
|
165
175
|
service_model = DataScienceModel.from_id(model_id)
|
166
176
|
target_project = project_id or PROJECT_OCID
|
167
177
|
target_compartment = compartment_id or COMPARTMENT_OCID
|
168
178
|
|
169
179
|
if service_model.compartment_id != ODSC_MODEL_COMPARTMENT_OCID:
|
170
180
|
logger.info(
|
171
|
-
f"Aqua Model {model_id} already exists in user's compartment."
|
181
|
+
f"Aqua Model {model_id} already exists in the user's compartment."
|
172
182
|
"Skipped copying."
|
173
183
|
)
|
174
184
|
return service_model
|
@@ -195,14 +205,13 @@ class AquaModelApp(AquaApp):
|
|
195
205
|
.with_custom_metadata_list(service_model.custom_metadata_list)
|
196
206
|
.with_defined_metadata_list(service_model.defined_metadata_list)
|
197
207
|
.with_provenance_metadata(service_model.provenance_metadata)
|
198
|
-
# TODO: decide what kwargs will be needed.
|
199
208
|
.create(model_by_reference=True, **kwargs)
|
200
209
|
)
|
201
210
|
logger.info(
|
202
211
|
f"Aqua Model {custom_model.id} created with the service model {model_id}."
|
203
212
|
)
|
204
213
|
|
205
|
-
#
|
214
|
+
# Track unique models that were created in the user's compartment
|
206
215
|
self.telemetry.record_event_async(
|
207
216
|
category="aqua/service/model",
|
208
217
|
action="create",
|
@@ -211,6 +220,217 @@ class AquaModelApp(AquaApp):
|
|
211
220
|
|
212
221
|
return custom_model
|
213
222
|
|
223
|
+
@telemetry(entry_point="plugin=model&action=create", name="aqua")
|
224
|
+
def create_multi(
|
225
|
+
self,
|
226
|
+
models: List[AquaMultiModelRef],
|
227
|
+
project_id: Optional[str] = None,
|
228
|
+
compartment_id: Optional[str] = None,
|
229
|
+
freeform_tags: Optional[Dict] = None,
|
230
|
+
defined_tags: Optional[Dict] = None,
|
231
|
+
**kwargs, # noqa: ARG002
|
232
|
+
) -> DataScienceModel:
|
233
|
+
"""
|
234
|
+
Creates a multi-model grouping using the provided model list.
|
235
|
+
|
236
|
+
Parameters
|
237
|
+
----------
|
238
|
+
models : List[AquaMultiModelRef]
|
239
|
+
List of AquaMultiModelRef instances for creating a multi-model group.
|
240
|
+
project_id : Optional[str]
|
241
|
+
The project ID for the multi-model group.
|
242
|
+
compartment_id : Optional[str]
|
243
|
+
The compartment ID for the multi-model group.
|
244
|
+
freeform_tags : Optional[Dict]
|
245
|
+
Freeform tags for the model.
|
246
|
+
defined_tags : Optional[Dict]
|
247
|
+
Defined tags for the model.
|
248
|
+
|
249
|
+
Returns
|
250
|
+
-------
|
251
|
+
DataScienceModel
|
252
|
+
Instance of DataScienceModel object.
|
253
|
+
"""
|
254
|
+
|
255
|
+
if not models:
|
256
|
+
raise AquaValueError(
|
257
|
+
"Model list cannot be empty. Please provide at least one model for deployment."
|
258
|
+
)
|
259
|
+
|
260
|
+
artifact_list = []
|
261
|
+
display_name_list = []
|
262
|
+
model_custom_metadata = ModelCustomMetadata()
|
263
|
+
|
264
|
+
# Get container config
|
265
|
+
container_config = get_container_config()
|
266
|
+
|
267
|
+
service_inference_containers = AquaContainerConfig.from_container_index_json(
|
268
|
+
config=container_config
|
269
|
+
).inference.values()
|
270
|
+
|
271
|
+
supported_container_families = [
|
272
|
+
container_config_item.family
|
273
|
+
for container_config_item in service_inference_containers
|
274
|
+
if any(
|
275
|
+
usage in container_config_item.usages
|
276
|
+
for usage in [Usage.MULTI_MODEL, Usage.OTHER]
|
277
|
+
)
|
278
|
+
]
|
279
|
+
|
280
|
+
if not supported_container_families:
|
281
|
+
raise AquaValueError(
|
282
|
+
"Currently, there are no containers that support multi-model deployment."
|
283
|
+
)
|
284
|
+
|
285
|
+
selected_models_deployment_containers = set()
|
286
|
+
|
287
|
+
# Process each model
|
288
|
+
for model in models:
|
289
|
+
source_model = DataScienceModel.from_id(model.model_id)
|
290
|
+
display_name = source_model.display_name
|
291
|
+
# Update model name in user's input model
|
292
|
+
model.model_name = model.model_name or display_name
|
293
|
+
|
294
|
+
# TODO Uncomment the section below, if only service models should be allowed for multi-model deployment
|
295
|
+
# if not source_model.freeform_tags.get(Tags.AQUA_SERVICE_MODEL_TAG, UNKNOWN):
|
296
|
+
# raise AquaValueError(
|
297
|
+
# f"Invalid selected model {display_name}. "
|
298
|
+
# "Currently only service models are supported for multi model deployment."
|
299
|
+
# )
|
300
|
+
|
301
|
+
if (
|
302
|
+
source_model.freeform_tags.get(Tags.TASK, UNKNOWN).lower()
|
303
|
+
not in MultiModelSupportedTaskType
|
304
|
+
):
|
305
|
+
raise AquaValueError(
|
306
|
+
f"Invalid or missing {Tags.TASK} tag for selected model {display_name}. "
|
307
|
+
f"Currently only `{MultiModelSupportedTaskType.values()}` models are supported for multi model deployment."
|
308
|
+
)
|
309
|
+
|
310
|
+
display_name_list.append(display_name)
|
311
|
+
|
312
|
+
# Retrieve model artifact
|
313
|
+
model_artifact_path = source_model.artifact
|
314
|
+
if not model_artifact_path:
|
315
|
+
raise AquaValueError(
|
316
|
+
f"Model '{display_name}' (ID: {model.model_id}) has no artifacts. "
|
317
|
+
"Please register the model first."
|
318
|
+
)
|
319
|
+
|
320
|
+
# Update model artifact location in user's input model
|
321
|
+
model.artifact_location = model_artifact_path
|
322
|
+
|
323
|
+
artifact_list.append(model_artifact_path)
|
324
|
+
|
325
|
+
# Validate deployment container consistency
|
326
|
+
deployment_container = source_model.custom_metadata_list.get(
|
327
|
+
ModelCustomMetadataFields.DEPLOYMENT_CONTAINER,
|
328
|
+
ModelCustomMetadataItem(
|
329
|
+
key=ModelCustomMetadataFields.DEPLOYMENT_CONTAINER
|
330
|
+
),
|
331
|
+
).value
|
332
|
+
|
333
|
+
if deployment_container not in supported_container_families:
|
334
|
+
raise AquaValueError(
|
335
|
+
f"Unsupported deployment container '{deployment_container}' for model '{source_model.id}'. "
|
336
|
+
f"Only '{supported_container_families}' are supported for multi-model deployments."
|
337
|
+
)
|
338
|
+
|
339
|
+
selected_models_deployment_containers.add(deployment_container)
|
340
|
+
|
341
|
+
if not selected_models_deployment_containers:
|
342
|
+
raise AquaValueError(
|
343
|
+
"None of the selected models are associated with a recognized container family. "
|
344
|
+
"Please review the selected models, or select a different group of models."
|
345
|
+
)
|
346
|
+
|
347
|
+
# Check if the all models in the group shares same container family
|
348
|
+
if len(selected_models_deployment_containers) > 1:
|
349
|
+
deployment_container = get_preferred_compatible_family(
|
350
|
+
selected_families=selected_models_deployment_containers
|
351
|
+
)
|
352
|
+
if not deployment_container:
|
353
|
+
raise AquaValueError(
|
354
|
+
"The selected models are associated with different container families: "
|
355
|
+
f"{list(selected_models_deployment_containers)}."
|
356
|
+
"For multi-model deployment, all models in the group must share the same container family."
|
357
|
+
)
|
358
|
+
else:
|
359
|
+
deployment_container = selected_models_deployment_containers.pop()
|
360
|
+
|
361
|
+
# Generate model group details
|
362
|
+
timestamp = datetime.now().strftime("%Y%m%d")
|
363
|
+
model_group_display_name = f"model_group_{timestamp}"
|
364
|
+
combined_models = ", ".join(display_name_list)
|
365
|
+
model_group_description = f"Multi-model grouping using {combined_models}."
|
366
|
+
|
367
|
+
# Add global metadata
|
368
|
+
model_custom_metadata.add(
|
369
|
+
key=ModelCustomMetadataFields.DEPLOYMENT_CONTAINER,
|
370
|
+
value=deployment_container,
|
371
|
+
description=f"Inference container mapping for {model_group_display_name}",
|
372
|
+
category="Other",
|
373
|
+
)
|
374
|
+
model_custom_metadata.add(
|
375
|
+
key=ModelCustomMetadataFields.MULTIMODEL_GROUP_COUNT,
|
376
|
+
value=str(len(models)),
|
377
|
+
description="Number of models in the group.",
|
378
|
+
category="Other",
|
379
|
+
)
|
380
|
+
|
381
|
+
# Combine tags. The `Tags.AQUA_TAG` has been excluded, because we don't want to show
|
382
|
+
# the models created for multi-model purpose in the AQUA models list.
|
383
|
+
tags = {
|
384
|
+
# Tags.AQUA_TAG: "active",
|
385
|
+
Tags.MULTIMODEL_TYPE_TAG: "true",
|
386
|
+
**(freeform_tags or {}),
|
387
|
+
}
|
388
|
+
|
389
|
+
# Create multi-model group
|
390
|
+
custom_model = (
|
391
|
+
DataScienceModel()
|
392
|
+
.with_compartment_id(compartment_id)
|
393
|
+
.with_project_id(project_id)
|
394
|
+
.with_display_name(model_group_display_name)
|
395
|
+
.with_description(model_group_description)
|
396
|
+
.with_freeform_tags(**tags)
|
397
|
+
.with_defined_tags(**(defined_tags or {}))
|
398
|
+
.with_custom_metadata_list(model_custom_metadata)
|
399
|
+
)
|
400
|
+
|
401
|
+
# Attach artifacts
|
402
|
+
for artifact in artifact_list:
|
403
|
+
custom_model.add_artifact(uri=artifact)
|
404
|
+
|
405
|
+
# Finalize creation
|
406
|
+
custom_model.create(model_by_reference=True)
|
407
|
+
|
408
|
+
logger.info(
|
409
|
+
f"Aqua Model '{custom_model.id}' created with models: {', '.join(display_name_list)}."
|
410
|
+
)
|
411
|
+
|
412
|
+
# Create custom metadata for multi model metadata
|
413
|
+
custom_model.create_custom_metadata_artifact(
|
414
|
+
metadata_key_name=ModelCustomMetadataFields.MULTIMODEL_METADATA,
|
415
|
+
artifact_path_or_content=json.dumps(
|
416
|
+
[model.model_dump() for model in models]
|
417
|
+
).encode(),
|
418
|
+
path_type=MetadataArtifactPathType.CONTENT,
|
419
|
+
)
|
420
|
+
|
421
|
+
logger.debug(
|
422
|
+
f"Multi model metadata uploaded for Aqua model: {custom_model.id}."
|
423
|
+
)
|
424
|
+
|
425
|
+
# Track telemetry event
|
426
|
+
self.telemetry.record_event_async(
|
427
|
+
category="aqua/multimodel",
|
428
|
+
action="create",
|
429
|
+
detail=combined_models,
|
430
|
+
)
|
431
|
+
|
432
|
+
return custom_model
|
433
|
+
|
214
434
|
@telemetry(entry_point="plugin=model&action=get", name="aqua")
|
215
435
|
def get(self, model_id: str, load_model_card: Optional[bool] = True) -> "AquaModel":
|
216
436
|
"""Gets the information of an Aqua model.
|
@@ -1448,8 +1668,9 @@ class AquaModelApp(AquaApp):
|
|
1448
1668
|
self, import_model_details: ImportModelDetails = None, **kwargs
|
1449
1669
|
) -> AquaModel:
|
1450
1670
|
"""Loads the model from object storage and registers as Model in Data Science Model catalog
|
1451
|
-
The inference container and finetuning container could be of type Service
|
1452
|
-
If it is custom, full container URI is expected. If it of type SMC, only the container family name is expected
|
1671
|
+
The inference container and finetuning container could be of type Service Managed Container(SMC) or custom.
|
1672
|
+
If it is custom, full container URI is expected. If it of type SMC, only the container family name is expected.\n
|
1673
|
+
For detailed information about CLI flags see: https://github.com/oracle-samples/oci-data-science-ai-samples/blob/main/ai-quick-actions/cli-tips.md#register-model
|
1453
1674
|
|
1454
1675
|
Args:
|
1455
1676
|
import_model_details (ImportModelDetails): Model details for importing the model.
|
@@ -1609,6 +1830,8 @@ class AquaModelApp(AquaApp):
|
|
1609
1830
|
filter_tag = Tags.AQUA_FINE_TUNED_MODEL_TAG
|
1610
1831
|
elif model_type == ModelType.BASE:
|
1611
1832
|
filter_tag = Tags.BASE_MODEL_CUSTOM
|
1833
|
+
# elif model_type == ModelType.MULTIMODEL:
|
1834
|
+
# filter_tag = Tags.MULTIMODEL_TYPE_TAG
|
1612
1835
|
else:
|
1613
1836
|
raise AquaValueError(
|
1614
1837
|
f"Model of type {model_type} is unknown. The values should be in {ModelType.values()}"
|