oracle-ads 2.13.11__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.
ads/aqua/app.py CHANGED
@@ -22,7 +22,7 @@ from ads import set_auth
22
22
  from ads.aqua import logger
23
23
  from ads.aqua.common.entities import ModelConfigResult
24
24
  from ads.aqua.common.enums import ConfigFolder, Tags
25
- from ads.aqua.common.errors import AquaRuntimeError, AquaValueError
25
+ from ads.aqua.common.errors import AquaValueError
26
26
  from ads.aqua.common.utils import (
27
27
  _is_valid_mvs,
28
28
  get_artifact_path,
@@ -284,8 +284,11 @@ class AquaApp:
284
284
  logger.info(f"Artifact not found in model {model_id}.")
285
285
  return False
286
286
 
287
+ @cached(cache=TTLCache(maxsize=5, ttl=timedelta(minutes=1), timer=datetime.now))
287
288
  def get_config_from_metadata(
288
- self, model_id: str, metadata_key: str
289
+ self,
290
+ model_id: str,
291
+ metadata_key: str,
289
292
  ) -> ModelConfigResult:
290
293
  """Gets the config for the given Aqua model from model catalog metadata content.
291
294
 
@@ -300,8 +303,9 @@ class AquaApp:
300
303
  ModelConfigResult
301
304
  A Pydantic model containing the model_details (extracted from OCI) and the config dictionary.
302
305
  """
303
- config = {}
306
+ config: Dict[str, Any] = {}
304
307
  oci_model = self.ds_client.get_model(model_id).data
308
+
305
309
  try:
306
310
  config = self.ds_client.get_model_defined_metadatum_artifact_content(
307
311
  model_id, metadata_key
@@ -321,7 +325,7 @@ class AquaApp:
321
325
  )
322
326
  return ModelConfigResult(config=config, model_details=oci_model)
323
327
 
324
- @cached(cache=TTLCache(maxsize=1, ttl=timedelta(minutes=1), timer=datetime.now))
328
+ @cached(cache=TTLCache(maxsize=1, ttl=timedelta(minutes=5), timer=datetime.now))
325
329
  def get_config(
326
330
  self,
327
331
  model_id: str,
@@ -346,8 +350,10 @@ class AquaApp:
346
350
  ModelConfigResult
347
351
  A Pydantic model containing the model_details (extracted from OCI) and the config dictionary.
348
352
  """
349
- config_folder = config_folder or ConfigFolder.CONFIG
353
+ config: Dict[str, Any] = {}
350
354
  oci_model = self.ds_client.get_model(model_id).data
355
+
356
+ config_folder = config_folder or ConfigFolder.CONFIG
351
357
  oci_aqua = (
352
358
  (
353
359
  Tags.AQUA_TAG in oci_model.freeform_tags
@@ -357,9 +363,9 @@ class AquaApp:
357
363
  else False
358
364
  )
359
365
  if not oci_aqua:
360
- raise AquaRuntimeError(f"Target model {oci_model.id} is not an Aqua model.")
366
+ logger.debug(f"Target model {oci_model.id} is not an Aqua model.")
367
+ return ModelConfigResult(config=config, model_details=oci_model)
361
368
 
362
- config: Dict[str, Any] = {}
363
369
  artifact_path = get_artifact_path(oci_model.custom_metadata_list)
364
370
  if not artifact_path:
365
371
  logger.debug(
ads/aqua/cli.py CHANGED
@@ -94,3 +94,18 @@ class AquaCommand:
94
94
  "If you intend to chain a function call to the result, please separate the "
95
95
  "flag and the subsequent function call with separator `-`."
96
96
  )
97
+
98
+ @staticmethod
99
+ def install():
100
+ """Install ADS Aqua Extension from wheel file. Set enviroment variable `AQUA_EXTENSTION_PATH` to change the wheel file path.
101
+
102
+ Return
103
+ ------
104
+ int:
105
+ Installatation status.
106
+ """
107
+ import subprocess
108
+
109
+ wheel_file_path = os.environ.get("AQUA_EXTENSTION_PATH", "/ads/extension/adsjupyterlab_aqua_extension*.whl")
110
+ status = subprocess.run(f"pip install {wheel_file_path}",shell=True)
111
+ return status.check_returncode
@@ -3,7 +3,7 @@
3
3
  # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
4
4
 
5
5
  import re
6
- from typing import Any, Dict, Optional
6
+ from typing import Any, Dict, List, Optional
7
7
 
8
8
  from oci.data_science.models import Model
9
9
  from pydantic import BaseModel, Field, model_validator
@@ -136,6 +136,28 @@ class ComputeShapeSummary(Serializable):
136
136
  return model
137
137
 
138
138
 
139
+ class LoraModuleSpec(Serializable):
140
+ """
141
+ Lightweight descriptor for LoRA Modules used in fine-tuning models.
142
+
143
+ Attributes
144
+ ----------
145
+ model_id : str
146
+ The unique identifier of the fine tuned model.
147
+ model_name : str
148
+ The name of the fine-tuned model.
149
+ model_path : str
150
+ The model-by-reference path to the LoRA Module within the model artifact
151
+ """
152
+
153
+ model_id: Optional[str] = Field(None, description="The fine tuned model OCID to deploy.")
154
+ model_name: Optional[str] = Field(None, description="The name of the fine-tuned model.")
155
+ model_path: Optional[str] = Field(
156
+ None,
157
+ description="The model-by-reference path to the LoRA Module within the model artifact.",
158
+ )
159
+
160
+
139
161
  class AquaMultiModelRef(Serializable):
140
162
  """
141
163
  Lightweight model descriptor used for multi-model deployment.
@@ -157,7 +179,7 @@ class AquaMultiModelRef(Serializable):
157
179
  Optional environment variables to override during deployment.
158
180
  artifact_location : Optional[str]
159
181
  Artifact path of model in the multimodel group.
160
- fine_tune_weights_location : Optional[str]
182
+ fine_tune_weights : Optional[List[LoraModuleSpec]]
161
183
  For fine tuned models, the artifact path of the modified model weights
162
184
  """
163
185
 
@@ -166,15 +188,19 @@ class AquaMultiModelRef(Serializable):
166
188
  gpu_count: Optional[int] = Field(
167
189
  None, description="The gpu count allocation for the model."
168
190
  )
169
- model_task: Optional[str] = Field(None, description="The task that model operates on. Supported tasks are in MultiModelSupportedTaskType")
191
+ model_task: Optional[str] = Field(
192
+ None,
193
+ description="The task that model operates on. Supported tasks are in MultiModelSupportedTaskType",
194
+ )
170
195
  env_var: Optional[dict] = Field(
171
196
  default_factory=dict, description="The environment variables of the model."
172
197
  )
173
198
  artifact_location: Optional[str] = Field(
174
199
  None, description="Artifact path of model in the multimodel group."
175
200
  )
176
- fine_tune_weights_location: Optional[str] = Field(
177
- None, description="For fine tuned models, the artifact path of the modified model weights"
201
+ fine_tune_weights: Optional[List[LoraModuleSpec]] = Field(
202
+ None,
203
+ description="For fine tuned models, the artifact path of the modified model weights",
178
204
  )
179
205
 
180
206
  class Config:
ads/aqua/common/utils.py CHANGED
@@ -870,6 +870,41 @@ def get_combined_params(params1: str = None, params2: str = None) -> str:
870
870
  return " ".join(combined_params)
871
871
 
872
872
 
873
+ def find_restricted_params(
874
+ default_params: Union[str, List[str]],
875
+ user_params: Union[str, List[str]],
876
+ container_family: str,
877
+ ) -> List[str]:
878
+ """Returns a list of restricted params that user chooses to override when creating an Aqua deployment.
879
+ The default parameters coming from the container index json file cannot be overridden.
880
+
881
+ Parameters
882
+ ----------
883
+ default_params:
884
+ Inference container parameter string with default values.
885
+ user_params:
886
+ Inference container parameter string with user provided values.
887
+ container_family: str
888
+ The image family of model deployment container runtime.
889
+
890
+ Returns
891
+ -------
892
+ A list with params keys common between params1 and params2.
893
+
894
+ """
895
+ restricted_params = []
896
+ if default_params and user_params:
897
+ default_params_dict = get_params_dict(default_params)
898
+ user_params_dict = get_params_dict(user_params)
899
+
900
+ restricted_params_set = get_restricted_params_by_container(container_family)
901
+ for key, _items in user_params_dict.items():
902
+ if key in default_params_dict or key in restricted_params_set:
903
+ restricted_params.append(key.lstrip("-"))
904
+
905
+ return restricted_params
906
+
907
+
873
908
  def build_params_string(params: dict) -> str:
874
909
  """Builds params string from params dict
875
910
 
@@ -727,10 +727,11 @@ class AquaEvaluationApp(AquaApp):
727
727
  raise AquaRuntimeError(error_message) from ex
728
728
 
729
729
  # Build the list of valid model names from custom metadata.
730
- model_names = [
731
- AquaMultiModelRef(**metadata).model_name
732
- for metadata in multi_model_metadata
733
- ]
730
+ model_names = []
731
+ for metadata in multi_model_metadata:
732
+ model = AquaMultiModelRef(**metadata)
733
+ model_names.append(model.model_name)
734
+ model_names.extend(ft.model_name for ft in (model.fine_tune_weights or []) if ft.model_name)
734
735
 
735
736
  # Check if the provided model name is among the valid names.
736
737
  if user_model_name not in model_names:
@@ -241,7 +241,7 @@ class AquaHuggingFaceHandler(AquaAPIhandler):
241
241
  aqua_model_app = AquaModelApp()
242
242
  model_ocid = aqua_model_app._find_matching_aqua_model(model_id=model_id_lower)
243
243
  if model_ocid:
244
- return aqua_model_app.get(model_ocid, load_model_card=False)
244
+ return aqua_model_app.get(model_ocid)
245
245
 
246
246
  return None
247
247
 
ads/aqua/model/enums.py CHANGED
@@ -27,6 +27,24 @@ class FineTuningCustomMetadata(ExtendedEnum):
27
27
 
28
28
  class MultiModelSupportedTaskType(ExtendedEnum):
29
29
  TEXT_GENERATION = "text_generation"
30
+ TEXT_GENERATION_INFERENCE = "text_generation_inference"
31
+ TEXT2TEXT_GENERATION = "text2text_generation"
32
+ SUMMARIZATION = "summarization"
33
+ TRANSLATION = "translation"
34
+ CONVERSATIONAL = "conversational"
35
+ FEATURE_EXTRACTION = "feature_extraction"
36
+ SENTENCE_SIMILARITY = "sentence_similarity"
37
+ AUTOMATIC_SPEECH_RECOGNITION = "automatic_speech_recognition"
38
+ TEXT_TO_SPEECH = "text_to_speech"
39
+ TEXT_TO_IMAGE = "text_to_image"
40
+ TEXT_EMBEDDING = "text_embedding"
30
41
  IMAGE_TEXT_TO_TEXT = "image_text_to_text"
31
42
  CODE_SYNTHESIS = "code_synthesis"
32
- EMBEDDING = "text_embedding"
43
+ QUESTION_ANSWERING = "question_answering"
44
+ AUDIO_CLASSIFICATION = "audio_classification"
45
+ AUDIO_TO_AUDIO = "audio_to_audio"
46
+ IMAGE_CLASSIFICATION = "image_classification"
47
+ IMAGE_TO_TEXT = "image_to_text"
48
+ IMAGE_TO_IMAGE = "image_to_image"
49
+ VIDEO_CLASSIFICATION = "video_classification"
50
+ TIME_SERIES_FORECASTING = "time_series_forecasting"
ads/aqua/model/model.py CHANGED
@@ -16,7 +16,7 @@ from oci.data_science.models import JobRun, Metadata, Model, UpdateModelDetails
16
16
 
17
17
  from ads.aqua import logger
18
18
  from ads.aqua.app import AquaApp
19
- from ads.aqua.common.entities import AquaMultiModelRef
19
+ from ads.aqua.common.entities import AquaMultiModelRef, LoraModuleSpec
20
20
  from ads.aqua.common.enums import (
21
21
  ConfigFolder,
22
22
  CustomInferenceContainerTypeFamily,
@@ -89,12 +89,7 @@ from ads.aqua.model.utils import (
89
89
  )
90
90
  from ads.common.auth import default_signer
91
91
  from ads.common.oci_resource import SEARCH_TYPE, OCIResource
92
- from ads.common.utils import (
93
- UNKNOWN,
94
- get_console_link,
95
- is_path_exists,
96
- read_file,
97
- )
92
+ from ads.common.utils import UNKNOWN, get_console_link, is_path_exists, read_file
98
93
  from ads.config import (
99
94
  AQUA_DEPLOYMENT_CONTAINER_CMD_VAR_METADATA_NAME,
100
95
  AQUA_DEPLOYMENT_CONTAINER_METADATA_NAME,
@@ -300,57 +295,73 @@ class AquaModelApp(AquaApp):
300
295
 
301
296
  selected_models_deployment_containers = set()
302
297
 
303
- # Process each model
298
+ # Process each model in the input list
304
299
  for model in models:
300
+ # Retrieve model metadata from the Model Catalog using the model ID
305
301
  source_model = DataScienceModel.from_id(model.model_id)
306
302
  display_name = source_model.display_name
307
303
  model_file_description = source_model.model_file_description
308
- # Update model name in user's input model
304
+ # If model_name is not explicitly provided, use the model's display name
309
305
  model.model_name = model.model_name or display_name
310
306
 
311
- # TODO Uncomment the section below, if only service models should be allowed for multi-model deployment
312
- # if not source_model.freeform_tags.get(Tags.AQUA_SERVICE_MODEL_TAG, UNKNOWN):
313
- # raise AquaValueError(
314
- # f"Invalid selected model {display_name}. "
315
- # "Currently only service models are supported for multi model deployment."
316
- # )
307
+ if not model_file_description:
308
+ raise AquaValueError(
309
+ f"Model '{source_model.display_name}' (ID: {model.model_id}) has no file description. "
310
+ "Please register the model first."
311
+ )
317
312
 
318
- # check if model is a fine-tuned model and if so, add the fine tuned weights path to the fine_tune_weights_location pydantic field
313
+ # Check if the model is a fine-tuned model based on its tags
319
314
  is_fine_tuned_model = (
320
315
  Tags.AQUA_FINE_TUNED_MODEL_TAG in source_model.freeform_tags
321
316
  )
322
317
 
318
+ base_model_artifact_path = ""
319
+ fine_tune_path = ""
320
+
323
321
  if is_fine_tuned_model:
324
- model.model_id, model.model_name = extract_base_model_from_ft(
325
- source_model
326
- )
327
- model_artifact_path, model.fine_tune_weights_location = (
322
+ # Extract artifact paths for the base and fine-tuned model
323
+ base_model_artifact_path, fine_tune_path = (
328
324
  extract_fine_tune_artifacts_path(source_model)
329
325
  )
330
326
 
331
- else:
332
- # Retrieve model artifact for base models
333
- model_artifact_path = source_model.artifact
327
+ # Create a single LoRA module specification for the fine-tuned model
328
+ # TODO: Support multiple LoRA modules in the future
329
+ model.fine_tune_weights = [
330
+ LoraModuleSpec(
331
+ model_id=model.model_id,
332
+ model_name=model.model_name,
333
+ model_path=fine_tune_path,
334
+ )
335
+ ]
334
336
 
335
- display_name_list.append(display_name)
337
+ # Use the LoRA module name as the model's display name
338
+ display_name = model.model_name
336
339
 
337
- self._extract_model_task(model, source_model)
340
+ # Temporarily override model ID and name with those of the base model
341
+ # TODO: Revisit this logic once proper base/FT model handling is implemented
342
+ model.model_id, model.model_name = extract_base_model_from_ft(
343
+ source_model
344
+ )
345
+ else:
346
+ # For base models, use the original artifact path
347
+ base_model_artifact_path = source_model.artifact
348
+ display_name = model.model_name
338
349
 
339
- if not model_artifact_path:
350
+ if not base_model_artifact_path:
351
+ # Fail if no artifact is found for the base model model
340
352
  raise AquaValueError(
341
- f"Model '{display_name}' (ID: {model.model_id}) has no artifacts. "
353
+ f"Model '{model.model_name}' (ID: {model.model_id}) has no artifacts. "
342
354
  "Please register the model first."
343
355
  )
344
356
 
345
- # Update model artifact location in user's input model
346
- model.artifact_location = model_artifact_path
357
+ # Update the artifact path in the model configuration
358
+ model.artifact_location = base_model_artifact_path
359
+ display_name_list.append(display_name)
347
360
 
348
- if not model_file_description:
349
- raise AquaValueError(
350
- f"Model '{display_name}' (ID: {model.model_id}) has no file description. "
351
- "Please register the model first."
352
- )
361
+ # Extract model task metadata from source model
362
+ self._extract_model_task(model, source_model)
353
363
 
364
+ # Track model file description in a validated structure
354
365
  model_file_description_list.append(
355
366
  ModelFileDescription(**model_file_description)
356
367
  )
@@ -480,8 +491,6 @@ class AquaModelApp(AquaApp):
480
491
  ----------
481
492
  model_id: str
482
493
  The model OCID.
483
- load_model_card: (bool, optional). Defaults to `True`.
484
- Whether to load model card from artifacts or not.
485
494
 
486
495
  Returns
487
496
  -------
ads/aqua/model/utils.py CHANGED
@@ -3,9 +3,8 @@
3
3
  # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
4
4
  """AQUA model utils"""
5
5
 
6
- from typing import Dict, Optional, Tuple
6
+ from typing import Tuple
7
7
 
8
- from ads.aqua.common.entities import AquaMultiModelRef
9
8
  from ads.aqua.common.errors import AquaValueError
10
9
  from ads.aqua.common.utils import get_model_by_reference_paths
11
10
  from ads.aqua.finetuning.constants import FineTuneCustomMetadata