Skip to content

Commit f10ac55

Browse files
Merge branch 'main' into feature/oss-bucket-config-dependency
2 parents eb88b11 + ead37f6 commit f10ac55

File tree

16 files changed

+139
-59
lines changed

16 files changed

+139
-59
lines changed

README-development.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
The Oracle Accelerated Data Science (ADS) SDK used by data scientists and analysts for
55
data exploration and experimental machine learning to democratize machine learning and
66
analytics by providing easy-to-use,
7-
performant, and user friendly tools that
7+
performant, and user-friendly tools that
88
brings together the best of data science practices.
99

1010
The ADS SDK helps you connect to different data sources, perform exploratory data analysis,
@@ -176,7 +176,7 @@ pip install -r test-requirements.txt
176176
```
177177

178178
### Step 2: Create local .env files
179-
Running the local JuypterLab server requires setting OCI authentication, proxy, and OCI namespace parameters. Adapt this .env file with your specific OCI profile and OCIDs to set these variables.
179+
Running the local JupyterLab server requires setting OCI authentication, proxy, and OCI namespace parameters. Adapt this .env file with your specific OCI profile and OCIDs to set these variables.
180180

181181
```
182182
CONDA_BUCKET_NS="your_conda_bucket"

ads/aqua/common/enums.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
33
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
44

5+
from typing import Dict, List
6+
57
from ads.common.extended_enum import ExtendedEnum
68

79

@@ -106,3 +108,15 @@ class ModelFormat(ExtendedEnum):
106108
class Platform(ExtendedEnum):
107109
ARM_CPU = "ARM_CPU"
108110
NVIDIA_GPU = "NVIDIA_GPU"
111+
112+
113+
# This dictionary defines compatibility groups for container families.
114+
# The structure is:
115+
# - Key: The preferred container family to use when multiple compatible families are selected.
116+
# - Value: A list of all compatible families (including the preferred one).
117+
CONTAINER_FAMILY_COMPATIBILITY: Dict[str, List[str]] = {
118+
InferenceContainerTypeFamily.AQUA_VLLM_V1_CONTAINER_FAMILY: [
119+
InferenceContainerTypeFamily.AQUA_VLLM_V1_CONTAINER_FAMILY,
120+
InferenceContainerTypeFamily.AQUA_VLLM_CONTAINER_FAMILY,
121+
],
122+
}

ads/aqua/common/utils.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
from ads.aqua.common.entities import GPUShapesIndex
3939
from ads.aqua.common.enums import (
40+
CONTAINER_FAMILY_COMPATIBILITY,
4041
InferenceContainerParamType,
4142
InferenceContainerType,
4243
RqsAdditionalDetails,
@@ -1245,3 +1246,40 @@ def load_gpu_shapes_index(
12451246
)
12461247

12471248
return GPUShapesIndex(**data)
1249+
1250+
1251+
def get_preferred_compatible_family(selected_families: set[str]) -> str:
1252+
"""
1253+
Determines the preferred container family from a given set of container families.
1254+
1255+
This method is used in the context of multi-model deployment to handle cases
1256+
where models selected for deployment use different, but compatible, container families.
1257+
1258+
It checks the input `families` set against the `CONTAINER_FAMILY_COMPATIBILITY` map.
1259+
If a compatibility group exists that fully includes all the families in the input,
1260+
the corresponding key (i.e., the preferred family) is returned.
1261+
1262+
Parameters
1263+
----------
1264+
families : set[str]
1265+
A set of container family identifiers.
1266+
1267+
Returns
1268+
-------
1269+
Optional[str]
1270+
The preferred container family if all families are compatible within one group;
1271+
otherwise, returns `None` indicating that no compatible family group was found.
1272+
1273+
Example
1274+
-------
1275+
>>> get_preferred_compatible_family({"odsc-vllm-serving", "odsc-vllm-serving-v1"})
1276+
'odsc-vllm-serving-v1'
1277+
1278+
>>> get_preferred_compatible_family({"odsc-vllm-serving", "odsc-tgi-serving"})
1279+
None # Incompatible families
1280+
"""
1281+
for preferred, compatible_list in CONTAINER_FAMILY_COMPATIBILITY.items():
1282+
if selected_families.issubset(set(compatible_list)):
1283+
return preferred
1284+
1285+
return None

ads/aqua/model/model.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
generate_tei_cmd_var,
3939
get_artifact_path,
4040
get_hf_model_info,
41+
get_preferred_compatible_family,
4142
list_os_files_with_extension,
4243
load_config,
4344
upload_folder,
@@ -343,15 +344,25 @@ def create_multi(
343344

344345
selected_models_deployment_containers.add(deployment_container)
345346

346-
# Check if the all models in the group shares same container family
347-
if len(selected_models_deployment_containers) > 1:
347+
if not selected_models_deployment_containers:
348348
raise AquaValueError(
349-
"The selected models are associated with different container families: "
350-
f"{list(selected_models_deployment_containers)}."
351-
"For multi-model deployment, all models in the group must share the same container family."
349+
"None of the selected models are associated with a recognized container family. "
350+
"Please review the selected models, or select a different group of models."
352351
)
353352

354-
deployment_container = selected_models_deployment_containers.pop()
353+
# Check if the all models in the group shares same container family
354+
if len(selected_models_deployment_containers) > 1:
355+
deployment_container = get_preferred_compatible_family(
356+
selected_families=selected_models_deployment_containers
357+
)
358+
if not deployment_container:
359+
raise AquaValueError(
360+
"The selected models are associated with different container families: "
361+
f"{list(selected_models_deployment_containers)}."
362+
"For multi-model deployment, all models in the group must share the same container family."
363+
)
364+
else:
365+
deployment_container = selected_models_deployment_containers.pop()
355366

356367
# Generate model group details
357368
timestamp = datetime.now().strftime("%Y%m%d")

ads/dataset/recommendation.py

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
#!/usr/bin/env python
2-
# -*- coding: utf-8; -*-
32

4-
# Copyright (c) 2020, 2022 Oracle and/or its affiliates.
3+
# Copyright (c) 2020, 2025 Oracle and/or its affiliates.
54
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
65

76
import copy
87
import importlib
98

109
from ads.common.decorator.runtime_dependency import (
11-
runtime_dependency,
1210
OptionalDependency,
11+
runtime_dependency,
1312
)
1413
from ads.dataset import logger
1514

@@ -59,11 +58,10 @@ def on_action_change(change):
5958
if change["type"] == "change" and change["name"] == "value":
6059
if change["new"] == "Fill missing values with constant":
6160
self._show_constant_fill_widget(column)
62-
else:
63-
if change["old"] == "Fill missing values with constant":
64-
text = self.fill_nan_dict.pop(column, None)
65-
if text is not None:
66-
text.close()
61+
elif change["old"] == "Fill missing values with constant":
62+
text = self.fill_nan_dict.pop(column, None)
63+
if text is not None:
64+
text.close()
6765
self.reco_dict[recommendation_type][column]["Selected Action"] = change[
6866
"new"
6967
]
@@ -151,7 +149,6 @@ def show_in_notebook(self):
151149
@runtime_dependency(module="IPython", install_from=OptionalDependency.NOTEBOOK)
152150
@runtime_dependency(module="ipywidgets", install_from=OptionalDependency.NOTEBOOK)
153151
def _display(self):
154-
155152
from IPython.core.display import display
156153

157154
if self.recommendation_type_index != len(self.recommendation_types):
@@ -164,11 +161,7 @@ def _display(self):
164161
]
165162
if self.recommendation_type_index == 0:
166163
for column in recommendation:
167-
print(
168-
"Column '{0}' is constant and will be dropped".format(
169-
column
170-
)
171-
)
164+
print(f"Column '{column}' is constant and will be dropped")
172165
self.recommendation_type_index += 1
173166
self._display()
174167
return
@@ -184,17 +177,17 @@ def _display(self):
184177
self.recommendation_type_labels[
185178
self.recommendation_type_index
186179
]
187-
)
180+
),
181+
layout=ipywidgets.Layout(display="flex"),
188182
),
189-
layout=ipywidgets.Layout(display="flex"),
190183
)
191184
self.action_list[
192185
self.recommendation_types[self.recommendation_type_index]
193186
] = []
194187
self.column_list = []
195188
self.message_list = []
196189
self.extra_info_list = []
197-
for column in recommendation.keys():
190+
for column in recommendation:
198191
messages = ipywidgets.Label(
199192
recommendation[column]["Message"],
200193
layout=ipywidgets.Layout(
@@ -240,9 +233,7 @@ def _display(self):
240233
self.column_list.append(
241234
ipywidgets.Label(
242235
column
243-
+ "(type: {0})".format(
244-
self.ds.sampled_df[column].dtype
245-
),
236+
+ f"(type: {self.ds.sampled_df[column].dtype})",
246237
layout=ipywidgets.Layout(flex="auto"),
247238
color="grey",
248239
)

ads/opctl/operator/lowcode/pii/model/report.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22

3-
# Copyright (c) 2023, 2024 Oracle and/or its affiliates.
3+
# Copyright (c) 2023, 2025 Oracle and/or its affiliates.
44
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
55

66

@@ -123,7 +123,6 @@ def make_model_card(model_name="", readme_path=""):
123123
)
124124
return rc.Group(
125125
rc.Text("-"),
126-
columns=1,
127126
)
128127

129128
try:
@@ -156,7 +155,6 @@ def make_model_card(model_name="", readme_path=""):
156155
return rc.Group(
157156
rc.Text(text),
158157
eval_res_tb,
159-
columns=2,
160158
)
161159

162160

@@ -216,7 +214,7 @@ def build_entity_df(entites, id) -> pd.DataFrame:
216214
"Type": "-",
217215
"Redacted To": "-",
218216
}
219-
df = df.append(df2, ignore_index=True)
217+
df = pd.concat([df, pd.DataFrame([df2])], ignore_index=True)
220218
return df
221219

222220

@@ -232,7 +230,6 @@ def build_report(self) -> rc.Group:
232230
self._make_stats_card(),
233231
self._make_text_card(),
234232
],
235-
type=rc.SelectType.TABS,
236233
),
237234
label="Row Id: " + str(self.spec.id),
238235
)
@@ -256,7 +253,7 @@ def _make_stats_card(self):
256253
index=True,
257254
)
258255
)
259-
return rc.Group(stats, label="STATS")
256+
return rc.Group(*stats, label="STATS")
260257

261258
def _make_text_card(self):
262259
annotations = []
@@ -277,7 +274,7 @@ def _make_text_card(self):
277274
},
278275
return_html=True,
279276
)
280-
return rc.Group(rc.HTML(render_html), label="TEXT")
277+
return rc.Group(rc.Html(render_html), label="TEXT")
281278

282279

283280
class PIIOperatorReport:
@@ -292,7 +289,7 @@ def __init__(self, report_spec: PiiReportSpec, report_uri: str):
292289
RowReportFields(r, report_spec.run_summary.show_sensitive_info)
293290
for r in rows
294291
]
295-
292+
self.report_sections = None
296293
self.report_uri = report_uri
297294

298295
def make_view(self):
@@ -317,7 +314,6 @@ def make_view(self):
317314
label="Details",
318315
),
319316
],
320-
type=rc.SelectType.TABS,
321317
)
322318
)
323319
self.report_sections = [title_text, report_description, time_proceed, structure]
@@ -331,7 +327,8 @@ def save_report(
331327
disable_print()
332328
with rc.ReportCreator("My Report") as report:
333329
report.save(
334-
rc.Block(report_sections or self.report_sections), report_local_path
330+
rc.Block(*(report_sections or self.report_sections)),
331+
report_local_path,
335332
)
336333
enable_print()
337334

@@ -354,7 +351,6 @@ def _build_summary_page(self):
354351
self._make_yaml_card(),
355352
self._make_model_card(),
356353
],
357-
type=rc.SelectType.TABS,
358354
),
359355
)
360356

@@ -367,7 +363,6 @@ def _build_details_page(self):
367363
blocks=[
368364
row.build_report() for row in self.rows_details
369365
], # RowReportFields
370-
type=rc.SelectType.DROPDOWN,
371366
label="Details",
372367
),
373368
)
@@ -414,7 +409,6 @@ def _make_summary_stats_card(self) -> rc.Group:
414409
self.report_spec.run_summary.elapsed_time
415410
),
416411
),
417-
columns=2,
418412
),
419413
rc.Heading("Entities Distribution", level=3),
420414
plot_pie(self.report_spec.run_summary.statics),
@@ -423,7 +417,7 @@ def _make_summary_stats_card(self) -> rc.Group:
423417
entites_df = self._build_total_entity_df()
424418
summary_stats.append(rc.Heading("Resolved Entities", level=3))
425419
summary_stats.append(rc.DataTable(entites_df, index=True))
426-
return rc.Group(summary_stats, label="STATS")
420+
return rc.Group(*summary_stats, label="STATS")
427421

428422
def _make_yaml_card(self) -> rc.Group:
429423
"""Shows the full pii config yaml."""
@@ -449,13 +443,12 @@ def _make_model_card(self) -> rc.Group:
449443

450444
if len(model_cards) <= 1:
451445
return rc.Group(
452-
model_cards,
446+
*model_cards,
453447
label="MODEL CARD",
454448
)
455449
return rc.Group(
456450
rc.Select(
457451
model_cards,
458-
type=rc.SelectType.TABS,
459452
),
460453
label="MODEL CARD",
461454
)

docs/source/release_notes.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22
Release Notes
33
=============
44

5+
2.13.6
6+
-------
7+
Release date: April 7, 2025
8+
9+
* Fixed PII operator report generator script to use the latest code from ``report-creator``.
10+
* AI Quick Actions: Enhance the container family validation for multi-model deployment.
11+
* AI Quick Actions: Removing OSS bucket config dependency.
12+
13+
514
2.13.5
615
-------
716
Release date: April 3, 2025

docs/source/user_guide/configuration/configuration.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ encryption keys.
296296

297297
Master encryption keys can be generated internally by the Vault service
298298
or imported to the service from an external source. Once a master
299-
encryption key has been created, the Oracle Cloud Infrastruture API can
299+
encryption key has been created, the Oracle Cloud Infrastructure API can
300300
be used to generate data encryption keys that the Vault service returns
301301
to you. by default, a wrapping key is included with each vault. A
302302
wrapping key is a 4096-bit asymmetric encryption key pair based on the
@@ -673,7 +673,7 @@ prints it. This shows that the password was actually updated.
673673
wait_for_states=[oci.vault.models.Secret.LIFECYCLE_STATE_ACTIVE]).data
674674
675675
# The secret OCID does not change.
676-
print("Orginal Secret OCID: {}".format(secret_id))
676+
print("Original Secret OCID: {}".format(secret_id))
677677
print("Updated Secret OCID: {}".format(secret_update.id))
678678
679679
### Read a secret's value.
@@ -685,7 +685,7 @@ prints it. This shows that the password was actually updated.
685685
686686
.. parsed-literal::
687687
688-
Orginal Secret OCID: ocid1.vaultsecret.oc1.iad.amaaaaaav66vvnia2bmkbroin34eu2ghmubvmrtjdgo4yr6daewakacwuk4q
688+
Original Secret OCID: ocid1.vaultsecret.oc1.iad.amaaaaaav66vvnia2bmkbroin34eu2ghmubvmrtjdgo4yr6daewakacwuk4q
689689
Updated Secret OCID: ocid1.vaultsecret.oc1.iad.amaaaaaav66vvnia2bmkbroin34eu2ghmubvmrtjdgo4yr6daewakacwuk4q
690690
{'database': 'datamart', 'username': 'admin', 'password': 'UpdatedPassword'}
691691

0 commit comments

Comments
 (0)