oracle-ads 2.13.2__py3-none-any.whl → 2.13.3__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 (24) hide show
  1. ads/aqua/app.py +2 -1
  2. ads/aqua/evaluation/evaluation.py +11 -10
  3. ads/aqua/finetuning/finetuning.py +2 -3
  4. ads/opctl/operator/lowcode/anomaly/model/base_model.py +3 -3
  5. ads/opctl/operator/lowcode/anomaly/model/randomcutforest.py +1 -1
  6. ads/opctl/operator/lowcode/anomaly/utils.py +1 -1
  7. ads/opctl/operator/lowcode/common/transformations.py +5 -1
  8. ads/opctl/operator/lowcode/common/utils.py +7 -2
  9. ads/opctl/operator/lowcode/forecast/model/arima.py +15 -10
  10. ads/opctl/operator/lowcode/forecast/model/automlx.py +31 -9
  11. ads/opctl/operator/lowcode/forecast/model/autots.py +7 -5
  12. ads/opctl/operator/lowcode/forecast/model/base_model.py +127 -101
  13. ads/opctl/operator/lowcode/forecast/model/forecast_datasets.py +14 -6
  14. ads/opctl/operator/lowcode/forecast/model/ml_forecast.py +2 -2
  15. ads/opctl/operator/lowcode/forecast/model/neuralprophet.py +46 -32
  16. ads/opctl/operator/lowcode/forecast/model/prophet.py +82 -29
  17. ads/opctl/operator/lowcode/forecast/model_evaluator.py +136 -54
  18. ads/opctl/operator/lowcode/forecast/operator_config.py +29 -3
  19. ads/opctl/operator/lowcode/forecast/whatifserve/deployment_manager.py +103 -58
  20. {oracle_ads-2.13.2.dist-info → oracle_ads-2.13.3.dist-info}/METADATA +1 -1
  21. {oracle_ads-2.13.2.dist-info → oracle_ads-2.13.3.dist-info}/RECORD +24 -24
  22. {oracle_ads-2.13.2.dist-info → oracle_ads-2.13.3.dist-info}/WHEEL +0 -0
  23. {oracle_ads-2.13.2.dist-info → oracle_ads-2.13.3.dist-info}/entry_points.txt +0 -0
  24. {oracle_ads-2.13.2.dist-info → oracle_ads-2.13.3.dist-info}/licenses/LICENSE.txt +0 -0
ads/aqua/app.py CHANGED
@@ -225,6 +225,7 @@ class AquaApp:
225
225
  model_taxonomy_metadata: Union[ModelTaxonomyMetadata, Dict],
226
226
  compartment_id: str,
227
227
  project_id: str,
228
+ defined_tags: Dict = None,
228
229
  **kwargs,
229
230
  ) -> DataScienceModel:
230
231
  model = (
@@ -237,7 +238,7 @@ class AquaApp:
237
238
  .with_custom_metadata_list(model_custom_metadata)
238
239
  .with_defined_metadata_list(model_taxonomy_metadata)
239
240
  .with_provenance_metadata(ModelProvenanceMetadata(training_id=UNKNOWN))
240
- # TODO: decide what parameters will be needed
241
+ .with_defined_tags(**(defined_tags or {})) # Create defined tags when a model is created.
241
242
  .create(
242
243
  **kwargs,
243
244
  )
@@ -260,6 +260,10 @@ class AquaEvaluationApp(AquaApp):
260
260
  **create_aqua_evaluation_details.model_parameters,
261
261
  )
262
262
 
263
+ evaluation_model_defined_tags = (
264
+ create_aqua_evaluation_details.defined_tags or {}
265
+ )
266
+
263
267
  target_compartment = (
264
268
  create_aqua_evaluation_details.compartment_id or COMPARTMENT_OCID
265
269
  )
@@ -311,9 +315,7 @@ class AquaEvaluationApp(AquaApp):
311
315
  create_aqua_evaluation_details.experiment_description
312
316
  )
313
317
  .with_freeform_tags(**evaluation_mvs_freeform_tags)
314
- .with_defined_tags(
315
- **(create_aqua_evaluation_details.defined_tags or {})
316
- )
318
+ .with_defined_tags(**evaluation_model_defined_tags)
317
319
  # TODO: decide what parameters will be needed
318
320
  .create(**kwargs)
319
321
  )
@@ -358,6 +360,7 @@ class AquaEvaluationApp(AquaApp):
358
360
  .with_custom_metadata_list(evaluation_model_custom_metadata)
359
361
  .with_defined_metadata_list(evaluation_model_taxonomy_metadata)
360
362
  .with_provenance_metadata(ModelProvenanceMetadata(training_id=UNKNOWN))
363
+ .with_defined_tags(**evaluation_model_defined_tags)
361
364
  # TODO uncomment this once the evaluation container will get the updated version of the ADS
362
365
  # .with_input_schema(create_aqua_evaluation_details.to_dict())
363
366
  # TODO: decide what parameters will be needed
@@ -390,7 +393,7 @@ class AquaEvaluationApp(AquaApp):
390
393
  .with_shape_name(create_aqua_evaluation_details.shape_name)
391
394
  .with_block_storage_size(create_aqua_evaluation_details.block_storage_size)
392
395
  .with_freeform_tag(**evaluation_job_freeform_tags)
393
- .with_defined_tag(**(create_aqua_evaluation_details.defined_tags or {}))
396
+ .with_defined_tag(**evaluation_model_defined_tags)
394
397
  )
395
398
  if (
396
399
  create_aqua_evaluation_details.memory_in_gbs
@@ -429,7 +432,9 @@ class AquaEvaluationApp(AquaApp):
429
432
  metrics=create_aqua_evaluation_details.metrics,
430
433
  inference_configuration=eval_inference_configuration or {},
431
434
  )
432
- ).create(**kwargs) ## TODO: decide what parameters will be needed
435
+ ).create(
436
+ **kwargs
437
+ ) ## TODO: decide what parameters will be needed
433
438
  logger.debug(
434
439
  f"Successfully created evaluation job {evaluation_job.id} for {create_aqua_evaluation_details.evaluation_source_id}."
435
440
  )
@@ -437,7 +442,7 @@ class AquaEvaluationApp(AquaApp):
437
442
  evaluation_job_run = evaluation_job.run(
438
443
  name=evaluation_model.display_name,
439
444
  freeform_tags=evaluation_job_freeform_tags,
440
- defined_tags=(create_aqua_evaluation_details.defined_tags or {}),
445
+ defined_tags=evaluation_model_defined_tags,
441
446
  wait=False,
442
447
  )
443
448
  logger.debug(
@@ -461,16 +466,12 @@ class AquaEvaluationApp(AquaApp):
461
466
  Tags.AQUA_EVALUATION: Tags.AQUA_EVALUATION,
462
467
  **(create_aqua_evaluation_details.freeform_tags or {}),
463
468
  }
464
- evaluation_model_defined_tags = (
465
- create_aqua_evaluation_details.defined_tags or {}
466
- )
467
469
 
468
470
  self.ds_client.update_model(
469
471
  model_id=evaluation_model.id,
470
472
  update_model_details=UpdateModelDetails(
471
473
  custom_metadata_list=updated_custom_metadata_list,
472
474
  freeform_tags=evaluation_model_freeform_tags,
473
- defined_tags=evaluation_model_defined_tags,
474
475
  ),
475
476
  )
476
477
 
@@ -263,6 +263,7 @@ class AquaFineTuningApp(AquaApp):
263
263
  compartment_id=target_compartment,
264
264
  project_id=target_project,
265
265
  model_by_reference=True,
266
+ defined_tags=create_fine_tuning_details.defined_tags
266
267
  )
267
268
 
268
269
  ft_job_freeform_tags = {
@@ -382,14 +383,12 @@ class AquaFineTuningApp(AquaApp):
382
383
  Tags.AQUA_FINE_TUNED_MODEL_TAG: f"{source.id}#{source.display_name}",
383
384
  **(create_fine_tuning_details.freeform_tags or {}),
384
385
  }
385
- model_defined_tags = create_fine_tuning_details.defined_tags or {}
386
386
 
387
387
  self.update_model(
388
388
  model_id=ft_model.id,
389
389
  update_model_details=UpdateModelDetails(
390
390
  custom_metadata_list=updated_custom_metadata_list,
391
391
  freeform_tags=model_freeform_tags,
392
- defined_tags=model_defined_tags,
393
392
  ),
394
393
  )
395
394
  logger.debug(
@@ -490,7 +489,7 @@ class AquaFineTuningApp(AquaApp):
490
489
  "finetuning_source": source.id,
491
490
  "finetuning_experiment_id": experiment_model_version_set_id,
492
491
  **model_freeform_tags,
493
- **model_defined_tags,
492
+ **(create_fine_tuning_details.defined_tags or {}),
494
493
  },
495
494
  parameters=ft_parameters,
496
495
  )
@@ -71,7 +71,7 @@ class AnomalyOperatorBaseModel(ABC):
71
71
  try:
72
72
  anomaly_output = self._build_model()
73
73
  except Exception as e:
74
- logger.warn(f"Found exception: {e}")
74
+ logger.warning(f"Found exception: {e}")
75
75
  if self.spec.datetime_column:
76
76
  anomaly_output = self._fallback_build_model()
77
77
  raise e
@@ -347,7 +347,7 @@ class AnomalyOperatorBaseModel(ABC):
347
347
  storage_options=storage_options,
348
348
  )
349
349
 
350
- logger.warn(
350
+ logger.warning(
351
351
  f"The report has been successfully "
352
352
  f"generated and placed to the: {unique_output_dir}."
353
353
  )
@@ -356,7 +356,7 @@ class AnomalyOperatorBaseModel(ABC):
356
356
  """
357
357
  Fallback method for the sub model _build_model method.
358
358
  """
359
- logger.warn(
359
+ logger.warning(
360
360
  f"The build_model method has failed for the model: {self.spec.model}. "
361
361
  "A fallback model will be built."
362
362
  )
@@ -95,7 +95,7 @@ class RandomCutForestOperatorModel(AnomalyOperatorBaseModel):
95
95
 
96
96
  anomaly_output.add_output(target, anomaly, score)
97
97
  except Exception as e:
98
- logger.warn(f"Encountered Error: {e}. Skipping series {target}.")
98
+ logger.warning(f"Encountered Error: {e}. Skipping series {target}.")
99
99
 
100
100
  return anomaly_output
101
101
 
@@ -44,7 +44,7 @@ def _build_metrics_df(y_true, y_pred, column_name):
44
44
  # Throws exception if y_true has only one class
45
45
  metrics[SupportedMetrics.ROC_AUC] = roc_auc_score(y_true, y_pred)
46
46
  except Exception as e:
47
- logger.warn(f"An exception occurred: {e}")
47
+ logger.warning(f"An exception occurred: {e}")
48
48
  metrics[SupportedMetrics.ROC_AUC] = None
49
49
  precision, recall, thresholds = precision_recall_curve(y_true, y_pred)
50
50
  metrics[SupportedMetrics.PRC_AUC] = auc(recall, precision)
@@ -98,7 +98,11 @@ class Transformations(ABC):
98
98
  return clean_df
99
99
 
100
100
  def _remove_trailing_whitespace(self, df):
101
- return df.apply(lambda x: x.str.strip() if x.dtype == "object" else x)
101
+ return df.apply(
102
+ lambda x: x.str.strip()
103
+ if hasattr(x, "dtype") and x.dtype == "object"
104
+ else x
105
+ )
102
106
 
103
107
  def _clean_column_names(self, df):
104
108
  """
@@ -3,6 +3,7 @@
3
3
  # Copyright (c) 2024, 2025 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 json
6
7
  import logging
7
8
  import os
8
9
  import shutil
@@ -12,7 +13,6 @@ from typing import List, Union
12
13
 
13
14
  import fsspec
14
15
  import oracledb
15
- import json
16
16
  import pandas as pd
17
17
 
18
18
  from ads.common.object_storage_details import ObjectStorageDetails
@@ -142,6 +142,11 @@ def write_data(data, filename, format, storage_options=None, index=False, **kwar
142
142
  )
143
143
 
144
144
 
145
+ def write_json(json_dict, filename, storage_options=None):
146
+ with fsspec.open(filename, mode="w", **storage_options) as f:
147
+ f.write(json.dumps(json_dict))
148
+
149
+
145
150
  def write_simple_json(data, path):
146
151
  if ObjectStorageDetails.is_oci_path(path):
147
152
  storage_options = default_signer()
@@ -265,7 +270,7 @@ def find_output_dirname(output_dir: OutputDirectory):
265
270
  while os.path.exists(unique_output_dir):
266
271
  unique_output_dir = f"{output_dir}_{counter}"
267
272
  counter += 1
268
- logger.warn(
273
+ logger.warning(
269
274
  f"Since the output directory was not specified, the output will be saved to {unique_output_dir} directory."
270
275
  )
271
276
  return unique_output_dir
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python
2
2
 
3
- # Copyright (c) 2023, 2024 Oracle and/or its affiliates.
3
+ # Copyright (c) 2023, 2025 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
6
  import logging
@@ -132,13 +132,14 @@ class ArimaOperatorModel(ForecastOperatorBaseModel):
132
132
 
133
133
  logger.debug("===========Done===========")
134
134
  except Exception as e:
135
- self.errors_dict[s_id] = {
135
+ new_error = {
136
136
  "model_name": self.spec.model,
137
137
  "error": str(e),
138
138
  "error_trace": traceback.format_exc(),
139
139
  }
140
- logger.warn(f"Encountered Error: {e}. Skipping.")
141
- logger.warn(traceback.format_exc())
140
+ self.errors_dict[s_id] = new_error
141
+ logger.warning(f"Encountered Error: {e}. Skipping.")
142
+ logger.warning(traceback.format_exc())
142
143
 
143
144
  def _build_model(self) -> pd.DataFrame:
144
145
  full_data_dict = self.datasets.get_data_by_series()
@@ -166,7 +167,7 @@ class ArimaOperatorModel(ForecastOperatorBaseModel):
166
167
  sec5_text = rc.Heading("ARIMA Model Parameters", level=2)
167
168
  blocks = [
168
169
  rc.Html(
169
- m['model'].summary().as_html(),
170
+ m["model"].summary().as_html(),
170
171
  label=s_id if self.target_cat_col else None,
171
172
  )
172
173
  for i, (s_id, m) in enumerate(self.models.items())
@@ -201,11 +202,15 @@ class ArimaOperatorModel(ForecastOperatorBaseModel):
201
202
  self.formatted_local_explanation = aggregate_local_explanations
202
203
 
203
204
  if not self.target_cat_col:
204
- self.formatted_global_explanation = self.formatted_global_explanation.rename(
205
- {"Series 1": self.original_target_column},
206
- axis=1,
205
+ self.formatted_global_explanation = (
206
+ self.formatted_global_explanation.rename(
207
+ {"Series 1": self.original_target_column},
208
+ axis=1,
209
+ )
210
+ )
211
+ self.formatted_local_explanation.drop(
212
+ "Series", axis=1, inplace=True
207
213
  )
208
- self.formatted_local_explanation.drop("Series", axis=1, inplace=True)
209
214
 
210
215
  # Create a markdown section for the global explainability
211
216
  global_explanation_section = rc.Block(
@@ -235,7 +240,7 @@ class ArimaOperatorModel(ForecastOperatorBaseModel):
235
240
  local_explanation_section,
236
241
  ]
237
242
  except Exception as e:
238
- logger.warn(f"Failed to generate Explanations with error: {e}.")
243
+ logger.warning(f"Failed to generate Explanations with error: {e}.")
239
244
  logger.debug(f"Full Traceback: {traceback.format_exc()}")
240
245
 
241
246
  model_description = rc.Text(
@@ -184,13 +184,18 @@ class AutoMLXOperatorModel(ForecastOperatorBaseModel):
184
184
  "selected_model_params": model.selected_model_params_,
185
185
  }
186
186
  except Exception as e:
187
- self.errors_dict[s_id] = {
187
+ new_error = {
188
188
  "model_name": self.spec.model,
189
189
  "error": str(e),
190
190
  "error_trace": traceback.format_exc(),
191
191
  }
192
- logger.warn(f"Encountered Error: {e}. Skipping.")
193
- logger.warn(traceback.format_exc())
192
+ if s_id in self.errors_dict:
193
+ self.errors_dict[s_id]["model_fitting"] = new_error
194
+ else:
195
+ self.errors_dict[s_id] = {"model_fitting": new_error}
196
+ logger.warning(f"Encountered Error: {e}. Skipping.")
197
+ logger.warning(f"self.errors_dict[s_id]: {self.errors_dict[s_id]}")
198
+ logger.warning(traceback.format_exc())
194
199
 
195
200
  logger.debug("===========Forecast Generated===========")
196
201
 
@@ -257,7 +262,9 @@ class AutoMLXOperatorModel(ForecastOperatorBaseModel):
257
262
  )
258
263
 
259
264
  self.formatted_global_explanation.rename(
260
- columns={self.spec.datetime_column.name: ForecastOutputColumns.DATE},
265
+ columns={
266
+ self.spec.datetime_column.name: ForecastOutputColumns.DATE
267
+ },
261
268
  inplace=True,
262
269
  )
263
270
 
@@ -312,7 +319,7 @@ class AutoMLXOperatorModel(ForecastOperatorBaseModel):
312
319
  local_explanation_section,
313
320
  ]
314
321
  except Exception as e:
315
- logger.warn(f"Failed to generate Explanations with error: {e}.")
322
+ logger.warning(f"Failed to generate Explanations with error: {e}.")
316
323
  logger.debug(f"Full Traceback: {traceback.format_exc()}")
317
324
 
318
325
  model_description = rc.Text(
@@ -462,14 +469,27 @@ class AutoMLXOperatorModel(ForecastOperatorBaseModel):
462
469
  index="row", columns="Feature", values="Attribution"
463
470
  )
464
471
  explanations_df = explanations_df.reset_index(drop=True)
465
-
472
+ explanations_df[ForecastOutputColumns.DATE] = (
473
+ self.datasets.get_horizon_at_series(
474
+ s_id=s_id
475
+ )[self.spec.datetime_column.name].reset_index(drop=True)
476
+ )
466
477
  # Store the explanations in the local_explanation dictionary
467
478
  self.local_explanation[s_id] = explanations_df
468
479
 
469
480
  self.global_explanation[s_id] = dict(
470
481
  zip(
471
- self.local_explanation[s_id].columns,
472
- np.nanmean(np.abs(self.local_explanation[s_id]), axis=0),
482
+ self.local_explanation[s_id]
483
+ .drop(ForecastOutputColumns.DATE, axis=1)
484
+ .columns,
485
+ np.nanmean(
486
+ np.abs(
487
+ self.local_explanation[s_id].drop(
488
+ ForecastOutputColumns.DATE, axis=1
489
+ )
490
+ ),
491
+ axis=0,
492
+ ),
473
493
  )
474
494
  )
475
495
  else:
@@ -478,7 +498,9 @@ class AutoMLXOperatorModel(ForecastOperatorBaseModel):
478
498
  except Exception as e:
479
499
  if s_id in self.errors_dict:
480
500
  self.errors_dict[s_id]["explainer_error"] = str(e)
481
- self.errors_dict[s_id]["explainer_error_trace"] = traceback.format_exc()
501
+ self.errors_dict[s_id]["explainer_error_trace"] = (
502
+ traceback.format_exc()
503
+ )
482
504
  else:
483
505
  self.errors_dict[s_id] = {
484
506
  "model_name": self.spec.model,
@@ -211,8 +211,8 @@ class AutoTSOperatorModel(ForecastOperatorBaseModel):
211
211
  "error": str(e),
212
212
  "error_trace": traceback.format_exc(),
213
213
  }
214
- logger.warn(f"Encountered Error: {e}. Skipping.")
215
- logger.warn(traceback.format_exc())
214
+ logger.warning(f"Encountered Error: {e}. Skipping.")
215
+ logger.warning(traceback.format_exc())
216
216
 
217
217
  logger.debug("===========Done===========")
218
218
 
@@ -242,7 +242,7 @@ class AutoTSOperatorModel(ForecastOperatorBaseModel):
242
242
  self.models.df_wide_numeric, series=s_id
243
243
  ),
244
244
  self.datasets.list_series_ids(),
245
- target_category_column=self.target_cat_col
245
+ target_category_column=self.target_cat_col,
246
246
  )
247
247
  section_1 = rc.Block(
248
248
  rc.Heading("Forecast Overview", level=2),
@@ -260,7 +260,9 @@ class AutoTSOperatorModel(ForecastOperatorBaseModel):
260
260
  )
261
261
 
262
262
  except KeyError:
263
- logger.warn("Issue generating Model Parameters Table Section. Skipping")
263
+ logger.warning(
264
+ "Issue generating Model Parameters Table Section. Skipping"
265
+ )
264
266
  sec2 = rc.Text("Error generating model parameters.")
265
267
 
266
268
  section_2 = rc.Block(sec2_text, sec2)
@@ -268,7 +270,7 @@ class AutoTSOperatorModel(ForecastOperatorBaseModel):
268
270
  all_sections = [section_1, section_2]
269
271
 
270
272
  if self.spec.generate_explanations:
271
- logger.warn("Explanations not yet supported for the AutoTS Module")
273
+ logger.warning("Explanations not yet supported for the AutoTS Module")
272
274
 
273
275
  # Model Description
274
276
  model_description = rc.Text(