oracle-ads 2.13.10rc0__py3-none-any.whl → 2.13.12__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 (31) hide show
  1. ads/aqua/app.py +13 -7
  2. ads/aqua/cli.py +15 -0
  3. ads/aqua/common/entities.py +31 -5
  4. ads/aqua/common/utils.py +35 -0
  5. ads/aqua/config/container_config.py +0 -1
  6. ads/aqua/evaluation/evaluation.py +5 -4
  7. ads/aqua/extension/deployment_handler.py +4 -1
  8. ads/aqua/extension/model_handler.py +1 -1
  9. ads/aqua/model/enums.py +19 -1
  10. ads/aqua/model/model.py +45 -36
  11. ads/aqua/model/utils.py +1 -2
  12. ads/aqua/modeldeployment/config_loader.py +815 -0
  13. ads/aqua/modeldeployment/constants.py +4 -1
  14. ads/aqua/modeldeployment/deployment.py +100 -124
  15. ads/aqua/modeldeployment/entities.py +4 -178
  16. ads/aqua/modeldeployment/model_group_config.py +240 -0
  17. ads/aqua/modeldeployment/utils.py +0 -539
  18. ads/common/work_request.py +39 -38
  19. ads/jobs/builders/infrastructure/dsc_job.py +121 -24
  20. ads/jobs/builders/infrastructure/dsc_job_runtime.py +71 -24
  21. ads/jobs/builders/runtimes/base.py +7 -5
  22. ads/jobs/builders/runtimes/pytorch_runtime.py +6 -8
  23. ads/jobs/templates/driver_pytorch.py +486 -172
  24. ads/jobs/templates/driver_utils.py +27 -11
  25. ads/model/service/oci_datascience_model_deployment.py +6 -11
  26. ads/telemetry/client.py +4 -4
  27. {oracle_ads-2.13.10rc0.dist-info → oracle_ads-2.13.12.dist-info}/METADATA +2 -2
  28. {oracle_ads-2.13.10rc0.dist-info → oracle_ads-2.13.12.dist-info}/RECORD +31 -29
  29. {oracle_ads-2.13.10rc0.dist-info → oracle_ads-2.13.12.dist-info}/WHEEL +0 -0
  30. {oracle_ads-2.13.10rc0.dist-info → oracle_ads-2.13.12.dist-info}/entry_points.txt +0 -0
  31. {oracle_ads-2.13.10rc0.dist-info → oracle_ads-2.13.12.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env python
2
- # Copyright (c) 2024 Oracle and/or its affiliates.
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
4
 
5
5
  """
@@ -8,3 +8,6 @@ aqua.modeldeployment.constants
8
8
 
9
9
  This module contains constants used in Aqua Model Deployment.
10
10
  """
11
+
12
+ DEFAULT_WAIT_TIME = 12000
13
+ DEFAULT_POLL_INTERVAL = 10
@@ -2,10 +2,12 @@
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
4
 
5
+
5
6
  import json
6
7
  import shlex
8
+ import threading
7
9
  from datetime import datetime, timedelta
8
- from typing import Dict, List, Optional, Union
10
+ from typing import Dict, List, Optional
9
11
 
10
12
  from cachetools import TTLCache, cached
11
13
  from oci.data_science.models import ModelDeploymentShapeSummary
@@ -17,20 +19,15 @@ from ads.aqua.common.entities import (
17
19
  ComputeShapeSummary,
18
20
  ContainerPath,
19
21
  )
20
- from ads.aqua.common.enums import (
21
- InferenceContainerTypeFamily,
22
- ModelFormat,
23
- Tags,
24
- )
22
+ from ads.aqua.common.enums import InferenceContainerTypeFamily, ModelFormat, Tags
25
23
  from ads.aqua.common.errors import AquaRuntimeError, AquaValueError
26
24
  from ads.aqua.common.utils import (
27
25
  DEFINED_METADATA_TO_FILE_MAP,
28
- build_params_string,
29
26
  build_pydantic_error_message,
27
+ find_restricted_params,
30
28
  get_combined_params,
31
29
  get_container_params_type,
32
30
  get_ocid_substring,
33
- get_params_dict,
34
31
  get_params_list,
35
32
  get_resource_name,
36
33
  get_restricted_params_by_container,
@@ -55,22 +52,29 @@ from ads.aqua.model.utils import (
55
52
  extract_base_model_from_ft,
56
53
  extract_fine_tune_artifacts_path,
57
54
  )
55
+ from ads.aqua.modeldeployment.config_loader import (
56
+ AquaDeploymentConfig,
57
+ ConfigurationItem,
58
+ ModelDeploymentConfigSummary,
59
+ MultiModelDeploymentConfigLoader,
60
+ )
61
+ from ads.aqua.modeldeployment.constants import DEFAULT_POLL_INTERVAL, DEFAULT_WAIT_TIME
58
62
  from ads.aqua.modeldeployment.entities import (
59
63
  AquaDeployment,
60
- AquaDeploymentConfig,
61
64
  AquaDeploymentDetail,
62
- ConfigurationItem,
63
65
  ConfigValidationError,
64
66
  CreateModelDeploymentDetails,
65
- ModelDeploymentConfigSummary,
66
67
  )
67
- from ads.aqua.modeldeployment.utils import MultiModelDeploymentConfigLoader
68
+ from ads.aqua.modeldeployment.model_group_config import ModelGroupConfig
68
69
  from ads.common.object_storage_details import ObjectStorageDetails
69
70
  from ads.common.utils import UNKNOWN, get_log_links
71
+ from ads.common.work_request import DataScienceWorkRequest
70
72
  from ads.config import (
71
73
  AQUA_DEPLOYMENT_CONTAINER_CMD_VAR_METADATA_NAME,
72
74
  AQUA_DEPLOYMENT_CONTAINER_METADATA_NAME,
73
75
  AQUA_DEPLOYMENT_CONTAINER_URI_METADATA_NAME,
76
+ AQUA_TELEMETRY_BUCKET,
77
+ AQUA_TELEMETRY_BUCKET_NS,
74
78
  COMPARTMENT_OCID,
75
79
  PROJECT_OCID,
76
80
  )
@@ -486,7 +490,7 @@ class AquaDeploymentApp(AquaApp):
486
490
  f"with deployment without parameter overrides."
487
491
  )
488
492
 
489
- restricted_params = self._find_restricted_params(
493
+ restricted_params = find_restricted_params(
490
494
  params, user_params, container_type_key
491
495
  )
492
496
  if restricted_params:
@@ -508,6 +512,9 @@ class AquaDeploymentApp(AquaApp):
508
512
  if key not in env_var:
509
513
  env_var.update(env)
510
514
 
515
+ env_var.update({"AQUA_TELEMETRY_BUCKET_NS": AQUA_TELEMETRY_BUCKET_NS})
516
+ env_var.update({"AQUA_TELEMETRY_BUCKET": AQUA_TELEMETRY_BUCKET})
517
+
511
518
  logger.info(f"Env vars used for deploying {aqua_model.id} :{env_var}")
512
519
 
513
520
  tags = {**tags, **(create_deployment_details.freeform_tags or {})}
@@ -553,7 +560,6 @@ class AquaDeploymentApp(AquaApp):
553
560
  AquaDeployment
554
561
  An Aqua deployment instance.
555
562
  """
556
- model_config = []
557
563
  model_name_list = []
558
564
  env_var = {**(create_deployment_details.env_var or UNKNOWN_DICT)}
559
565
 
@@ -566,80 +572,14 @@ class AquaDeploymentApp(AquaApp):
566
572
 
567
573
  container_params = container_spec.cli_param if container_spec else UNKNOWN
568
574
 
569
- for model in create_deployment_details.models:
570
- user_params = build_params_string(model.env_var)
571
- if user_params:
572
- restricted_params = self._find_restricted_params(
573
- container_params, user_params, container_type_key
574
- )
575
- if restricted_params:
576
- selected_model = model.model_name or model.model_id
577
- raise AquaValueError(
578
- f"Parameters {restricted_params} are set by Aqua "
579
- f"and cannot be overridden or are invalid."
580
- f"Select other parameters for model {selected_model}."
581
- )
582
-
583
- # replaces `--served-model-name`` with user's model name
584
- container_params_dict = get_params_dict(container_params)
585
- container_params_dict.update({"--served-model-name": model.model_name})
586
- # replaces `--tensor-parallel-size` with model gpu count
587
- container_params_dict.update({"--tensor-parallel-size": model.gpu_count})
588
- params = build_params_string(container_params_dict)
589
-
590
- deployment_config = model_config_summary.deployment_config.get(
591
- model.model_id, AquaDeploymentConfig()
592
- ).configuration.get(
593
- create_deployment_details.instance_shape, ConfigurationItem()
594
- )
595
-
596
- # finds the corresponding deployment parameters based on the gpu count
597
- # and combines them with user's parameters. Existing deployment parameters
598
- # will be overriden by user's parameters.
599
- params_found = False
600
- for item in deployment_config.multi_model_deployment:
601
- if (
602
- model.gpu_count
603
- and item.gpu_count
604
- and item.gpu_count == model.gpu_count
605
- ):
606
- config_parameters = item.parameters.get(
607
- get_container_params_type(container_type_key), UNKNOWN
608
- )
609
- params = f"{params} {get_combined_params(config_parameters, user_params)}".strip()
610
- params_found = True
611
- break
612
-
613
- if not params_found and deployment_config.parameters:
614
- config_parameters = deployment_config.parameters.get(
615
- get_container_params_type(container_type_key), UNKNOWN
616
- )
617
- params = f"{params} {get_combined_params(config_parameters, user_params)}".strip()
618
- params_found = True
619
-
620
- # if no config parameters found, append user parameters directly.
621
- if not params_found:
622
- params = f"{params} {user_params}".strip()
623
-
624
- artifact_path_prefix = model.artifact_location.rstrip("/")
625
- if ObjectStorageDetails.is_oci_path(artifact_path_prefix):
626
- os_path = ObjectStorageDetails.from_path(artifact_path_prefix)
627
- artifact_path_prefix = os_path.filepath.rstrip("/")
628
-
629
- # override by-default completion/ chat endpoint with other endpoint (embedding)
630
- config_data = {"params": params, "model_path": artifact_path_prefix}
631
- if model.model_task:
632
- config_data["model_task"] = model.model_task
633
-
634
- if model.fine_tune_weights_location:
635
- config_data["fine_tune_weights_location"] = (
636
- model.fine_tune_weights_location
637
- )
638
-
639
- model_config.append(config_data)
640
- model_name_list.append(model.model_name)
575
+ multi_model_config = ModelGroupConfig.from_create_model_deployment_details(
576
+ create_deployment_details,
577
+ model_config_summary,
578
+ container_type_key,
579
+ container_params,
580
+ )
641
581
 
642
- env_var.update({AQUA_MULTI_MODEL_CONFIG: json.dumps({"models": model_config})})
582
+ env_var.update({AQUA_MULTI_MODEL_CONFIG: multi_model_config.model_dump_json()})
643
583
 
644
584
  env_vars = container_spec.env_vars if container_spec else []
645
585
  for env in env_vars:
@@ -788,9 +728,21 @@ class AquaDeploymentApp(AquaApp):
788
728
 
789
729
  deployment_id = deployment.id
790
730
  logger.info(
791
- f"Aqua model deployment {deployment_id} created for model {aqua_model_id}."
731
+ f"Aqua model deployment {deployment_id} created for model {aqua_model_id}. Work request Id is {deployment.dsc_model_deployment.workflow_req_id}"
792
732
  )
793
733
 
734
+ progress_thread = threading.Thread(
735
+ target=self.get_deployment_status,
736
+ args=(
737
+ deployment_id,
738
+ deployment.dsc_model_deployment.workflow_req_id,
739
+ model_type,
740
+ model_name,
741
+ ),
742
+ daemon=True,
743
+ )
744
+ progress_thread.start()
745
+
794
746
  # we arbitrarily choose last 8 characters of OCID to identify MD in telemetry
795
747
  telemetry_kwargs = {"ocid": get_ocid_substring(deployment_id, key_len=8)}
796
748
 
@@ -1231,7 +1183,7 @@ class AquaDeploymentApp(AquaApp):
1231
1183
  container_spec = container_config.spec if container_config else UNKNOWN
1232
1184
  cli_params = container_spec.cli_param if container_spec else UNKNOWN
1233
1185
 
1234
- restricted_params = self._find_restricted_params(
1186
+ restricted_params = find_restricted_params(
1235
1187
  cli_params, params, container_type_key
1236
1188
  )
1237
1189
 
@@ -1242,41 +1194,6 @@ class AquaDeploymentApp(AquaApp):
1242
1194
  )
1243
1195
  return {"valid": True}
1244
1196
 
1245
- @staticmethod
1246
- def _find_restricted_params(
1247
- default_params: Union[str, List[str]],
1248
- user_params: Union[str, List[str]],
1249
- container_family: str,
1250
- ) -> List[str]:
1251
- """Returns a list of restricted params that user chooses to override when creating an Aqua deployment.
1252
- The default parameters coming from the container index json file cannot be overridden.
1253
-
1254
- Parameters
1255
- ----------
1256
- default_params:
1257
- Inference container parameter string with default values.
1258
- user_params:
1259
- Inference container parameter string with user provided values.
1260
- container_family: str
1261
- The image family of model deployment container runtime.
1262
-
1263
- Returns
1264
- -------
1265
- A list with params keys common between params1 and params2.
1266
-
1267
- """
1268
- restricted_params = []
1269
- if default_params and user_params:
1270
- default_params_dict = get_params_dict(default_params)
1271
- user_params_dict = get_params_dict(user_params)
1272
-
1273
- restricted_params_set = get_restricted_params_by_container(container_family)
1274
- for key, _items in user_params_dict.items():
1275
- if key in default_params_dict or key in restricted_params_set:
1276
- restricted_params.append(key.lstrip("-"))
1277
-
1278
- return restricted_params
1279
-
1280
1197
  @telemetry(entry_point="plugin=deployment&action=list_shapes", name="aqua")
1281
1198
  @cached(cache=TTLCache(maxsize=1, ttl=timedelta(minutes=5), timer=datetime.now))
1282
1199
  def list_shapes(self, **kwargs) -> List[ComputeShapeSummary]:
@@ -1313,3 +1230,62 @@ class AquaDeploymentApp(AquaApp):
1313
1230
  )
1314
1231
  for oci_shape in oci_shapes
1315
1232
  ]
1233
+
1234
+ def get_deployment_status(
1235
+ self,
1236
+ model_deployment_id: str,
1237
+ work_request_id: str,
1238
+ model_type: str,
1239
+ model_name: str,
1240
+ ) -> None:
1241
+ """Waits for the data science model deployment to be completed and log its status in telemetry.
1242
+
1243
+ Parameters
1244
+ ----------
1245
+
1246
+ model_deployment_id: str
1247
+ The id of the deployed aqua model.
1248
+ work_request_id: str
1249
+ The work request Id of the model deployment.
1250
+ model_type: str
1251
+ The type of aqua model to be deployed. Allowed values are: `custom`, `service` and `multi_model`.
1252
+
1253
+ Returns
1254
+ -------
1255
+ AquaDeployment
1256
+ An Aqua deployment instance.
1257
+ """
1258
+ ocid = get_ocid_substring(model_deployment_id, key_len=8)
1259
+ telemetry_kwargs = {"ocid": ocid}
1260
+
1261
+ data_science_work_request: DataScienceWorkRequest = DataScienceWorkRequest(
1262
+ work_request_id
1263
+ )
1264
+
1265
+ try:
1266
+ data_science_work_request.wait_work_request(
1267
+ progress_bar_description="Creating model deployment",
1268
+ max_wait_time=DEFAULT_WAIT_TIME,
1269
+ poll_interval=DEFAULT_POLL_INTERVAL,
1270
+ )
1271
+ except Exception:
1272
+ if data_science_work_request._error_message:
1273
+ error_str = ""
1274
+ for error in data_science_work_request._error_message:
1275
+ error_str = error_str + " " + error.message
1276
+
1277
+ self.telemetry.record_event(
1278
+ category=f"aqua/{model_type}/deployment/status",
1279
+ action="FAILED",
1280
+ detail=error_str,
1281
+ value=model_name,
1282
+ **telemetry_kwargs,
1283
+ )
1284
+
1285
+ else:
1286
+ self.telemetry.record_event_async(
1287
+ category=f"aqua/{model_type}/deployment/status",
1288
+ action="SUCCEEDED",
1289
+ value=model_name,
1290
+ **telemetry_kwargs,
1291
+ )
@@ -13,6 +13,10 @@ from ads.aqua.common.enums import Tags
13
13
  from ads.aqua.config.utils.serializer import Serializable
14
14
  from ads.aqua.constants import UNKNOWN_DICT
15
15
  from ads.aqua.data import AquaResourceIdentifier
16
+ from ads.aqua.modeldeployment.config_loader import (
17
+ ConfigurationItem,
18
+ ModelDeploymentConfigSummary,
19
+ )
16
20
  from ads.common.serializer import DataClassSerializable
17
21
  from ads.common.utils import UNKNOWN, get_console_link
18
22
 
@@ -213,184 +217,6 @@ class AquaDeploymentDetail(AquaDeployment, DataClassSerializable):
213
217
  extra = "allow"
214
218
 
215
219
 
216
- class ShapeInfoConfig(Serializable):
217
- """Describes how many memory and cpu to this model for specific shape.
218
-
219
- Attributes:
220
- memory_in_gbs (float, optional): The number of memory in gbs to this model of the shape.
221
- ocpu (float, optional): The number of ocpus to this model of the shape.
222
- """
223
-
224
- memory_in_gbs: Optional[float] = Field(
225
- None,
226
- description="The number of memory in gbs to this model of the shape.",
227
- )
228
- ocpu: Optional[float] = Field(
229
- None,
230
- description="The number of ocpus to this model of the shape.",
231
- )
232
-
233
- class Config:
234
- extra = "allow"
235
-
236
-
237
- class DeploymentShapeInfo(Serializable):
238
- """Describes the shape information to this model for specific shape.
239
-
240
- Attributes:
241
- configs (List[ShapeInfoConfig], optional): A list of memory and cpu number details to this model of the shape.
242
- type (str, optional): The type of the shape.
243
- """
244
-
245
- configs: Optional[List[ShapeInfoConfig]] = Field(
246
- default_factory=list,
247
- description="A list of memory and cpu number details to this model of the shape.",
248
- )
249
- type: Optional[str] = Field(
250
- default_factory=str, description="The type of the shape."
251
- )
252
-
253
- class Config:
254
- extra = "allow"
255
-
256
-
257
- class MultiModelConfig(Serializable):
258
- """Describes how many GPUs and the parameters of specific shape for multi model deployment.
259
-
260
- Attributes:
261
- gpu_count (int, optional): Number of GPUs count to this model of this shape.
262
- parameters (Dict[str, str], optional): A dictionary of parameters (e.g., VLLM_PARAMS) to
263
- configure the behavior of a particular GPU shape.
264
- """
265
-
266
- gpu_count: Optional[int] = Field(
267
- default_factory=int, description="The number of GPUs allocated to the model."
268
- )
269
- parameters: Optional[Dict[str, str]] = Field(
270
- default_factory=dict,
271
- description="Key-value pairs for GPU shape parameters (e.g., VLLM_PARAMS).",
272
- )
273
-
274
- class Config:
275
- extra = "allow"
276
-
277
-
278
- class ConfigurationItem(Serializable):
279
- """Holds key-value parameter pairs for a specific GPU or CPU shape.
280
-
281
- Attributes:
282
- parameters (Dict[str, str], optional): A dictionary of parameters (e.g., VLLM_PARAMS) to
283
- configure the behavior of a particular GPU shape.
284
- multi_model_deployment (List[MultiModelConfig], optional): A list of multi model configuration details.
285
- shape_info (DeploymentShapeInfo, optional): The shape information to this model for specific CPU shape.
286
- """
287
-
288
- parameters: Optional[Dict[str, str]] = Field(
289
- default_factory=dict,
290
- description="Key-value pairs for shape parameters.",
291
- )
292
- multi_model_deployment: Optional[List[MultiModelConfig]] = Field(
293
- default_factory=list, description="A list of multi model configuration details."
294
- )
295
- shape_info: Optional[DeploymentShapeInfo] = Field(
296
- default_factory=DeploymentShapeInfo,
297
- description="The shape information to this model for specific shape",
298
- )
299
-
300
- class Config:
301
- extra = "allow"
302
-
303
-
304
- class AquaDeploymentConfig(Serializable):
305
- """Represents multi model's shape list and detailed configuration.
306
-
307
- Attributes:
308
- shape (List[str], optional): A list of shape names (e.g., BM.GPU.A10.4).
309
- configuration (Dict[str, ConfigurationItem], optional): Maps each shape to its configuration details.
310
- """
311
-
312
- shape: Optional[List[str]] = Field(
313
- default_factory=list, description="List of supported shapes for the model."
314
- )
315
- configuration: Optional[Dict[str, ConfigurationItem]] = Field(
316
- default_factory=dict, description="Configuration details keyed by shape."
317
- )
318
-
319
- class Config:
320
- extra = "allow"
321
-
322
-
323
- class GPUModelAllocation(Serializable):
324
- """Describes how many GPUs are allocated to a particular model.
325
-
326
- Attributes:
327
- ocid (str, optional): The unique identifier of the model.
328
- gpu_count (int, optional): Number of GPUs allocated to this model.
329
- """
330
-
331
- ocid: Optional[str] = Field(
332
- default_factory=str, description="The unique model OCID."
333
- )
334
- gpu_count: Optional[int] = Field(
335
- default_factory=int, description="The number of GPUs allocated to the model."
336
- )
337
-
338
- class Config:
339
- extra = "allow"
340
-
341
-
342
- class GPUShapeAllocation(Serializable):
343
- """
344
- Allocation details for a specific GPU shape.
345
-
346
- Attributes:
347
- models (List[GPUModelAllocation], optional): List of model GPU allocations for this shape.
348
- total_gpus_available (int, optional): The total number of GPUs available for this shape.
349
- """
350
-
351
- models: Optional[List[GPUModelAllocation]] = Field(
352
- default_factory=list, description="List of model allocations for this shape."
353
- )
354
- total_gpus_available: Optional[int] = Field(
355
- default_factory=int, description="Total GPUs available for this shape."
356
- )
357
-
358
- class Config:
359
- extra = "allow"
360
-
361
-
362
- class ModelDeploymentConfigSummary(Serializable):
363
- """Top-level configuration model for OCI-based deployments.
364
-
365
- Attributes:
366
- deployment_config (Dict[str, AquaDeploymentConfig], optional): Deployment configurations
367
- keyed by model OCID.
368
- gpu_allocation (Dict[str, GPUShapeAllocation], optional): GPU allocations keyed by GPU shape.
369
- error_message (str, optional): Error message if GPU allocation is not possible.
370
- """
371
-
372
- deployment_config: Optional[Dict[str, AquaDeploymentConfig]] = Field(
373
- default_factory=dict,
374
- description=(
375
- "Deployment configuration details for each model, including supported shapes "
376
- "and shape-specific parameters."
377
- ),
378
- )
379
- gpu_allocation: Optional[Dict[str, GPUShapeAllocation]] = Field(
380
- default_factory=dict,
381
- description=(
382
- "Details on how GPUs are allocated per shape, including the total "
383
- "GPUs available for each shape."
384
- ),
385
- )
386
- error_message: Optional[str] = Field(
387
- default=None, description="Error message if GPU allocation is not possible."
388
- )
389
-
390
- class Config:
391
- extra = "allow"
392
-
393
-
394
220
  class CreateModelDeploymentDetails(BaseModel):
395
221
  """Class for creating Aqua model deployments."""
396
222