Skip to content

Commit 8094d70

Browse files
committed
Merge branch 'main' of github.com:oracle/accelerated-data-science into fix_report_title
2 parents 09a31ae + 93a3281 commit 8094d70

File tree

28 files changed

+1140
-166
lines changed

28 files changed

+1140
-166
lines changed

CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
* @darenr @mayoor @mrDzurb @VipulMascarenhas @qiuosier @ahosler
1+
* @mayoor @mrDzurb @VipulMascarenhas @lu-ohai @smfirmin @sambitkumohanty

ads/aqua/modeldeployment/deployment.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env python
2-
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
2+
# Copyright (c) 2024, 2026 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

55

@@ -1007,6 +1007,13 @@ def _create(
10071007

10081008
env_var.update({"AQUA_TELEMETRY_BUCKET_NS": AQUA_TELEMETRY_BUCKET_NS})
10091009
env_var.update({"AQUA_TELEMETRY_BUCKET": AQUA_TELEMETRY_BUCKET})
1010+
# TODO: remove this once dsc model deployment propagates compartment id in the container runtime
1011+
env_var.update(
1012+
{
1013+
"MD_COMPARTMENT_OCID": create_deployment_details.compartment_id
1014+
or COMPARTMENT_OCID
1015+
}
1016+
)
10101017

10111018
logger.info(f"Env vars used for deploying {aqua_model.id} :{env_var}")
10121019

@@ -1053,6 +1060,13 @@ def _create_multi(
10531060
"""
10541061
model_name_list = []
10551062
env_var = {**(create_deployment_details.env_var or UNKNOWN_DICT)}
1063+
# TODO: remove this once dsc model deployment propagates compartment id in the container runtime
1064+
env_var.update(
1065+
{
1066+
"MD_COMPARTMENT_OCID": create_deployment_details.compartment_id
1067+
or COMPARTMENT_OCID
1068+
}
1069+
)
10561070

10571071
container_type_key = self._get_container_type_key(
10581072
model=aqua_model_group,

ads/aqua/version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"aqua": "2.0.0"
2+
"aqua": "2.0.1"
33
}

ads/common/model_artifact.py

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

4-
# Copyright (c) 2020, 2023 Oracle and/or its affiliates.
3+
# Copyright (c) 2020, 2026 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 warnings
@@ -21,34 +20,46 @@
2120
import json
2221
import os
2322
import re
24-
import git
2523
import shutil
2624
import subprocess
2725
import sys
2826
import textwrap
2927
import uuid
30-
import python_jsonschema_objects as pjs
3128
from enum import Enum
3229
from pathlib import Path
3330
from typing import Dict, Optional, Union
3431

35-
import ads.dataset.factory as factory
3632
import fsspec
33+
import git
3734
import numpy as np
3835
import oci.data_science
3936
import oci.exceptions
4037
import pandas as pd
41-
import pkg_resources
38+
import python_jsonschema_objects as pjs
4239
import yaml
40+
from oci.data_science.models import ModelProvenance
4341

44-
from ads.common.decorator.runtime_dependency import (
45-
runtime_dependency,
46-
OptionalDependency,
47-
)
48-
from ads.common import logger, utils
4942
from ads.common import auth as authutil
43+
from ads.common import logger, utils
5044
from ads.common.data import ADSData
45+
from ads.common.decorator.deprecate import deprecated
5146
from ads.common.error import ChangesNotCommitted
47+
from ads.common.object_storage_details import (
48+
InvalidObjectStoragePath,
49+
ObjectStorageDetails,
50+
)
51+
from ads.common.utils import DATA_SCHEMA_MAX_COL_NUM
52+
from ads.config import (
53+
JOB_RUN_COMPARTMENT_OCID,
54+
JOB_RUN_OCID,
55+
NB_SESSION_COMPARTMENT_OCID,
56+
NB_SESSION_OCID,
57+
PROJECT_OCID,
58+
)
59+
from ads.dataset import factory
60+
from ads.feature_engineering.schema import DataSizeTooWide, Schema, SchemaSizeTooLarge
61+
from ads.model.common.utils import fetch_manifest_from_conda_location
62+
from ads.model.extractor.model_info_extractor_factory import ModelInfoExtractorFactory
5263
from ads.model.model_introspect import (
5364
TEST_STATUS,
5465
Introspectable,
@@ -66,33 +77,12 @@
6677
ModelTaxonomyMetadata,
6778
UseCaseType,
6879
)
69-
from ads.common.object_storage_details import (
70-
InvalidObjectStoragePath,
71-
ObjectStorageDetails,
72-
)
73-
from ads.common.utils import DATA_SCHEMA_MAX_COL_NUM
74-
from ads.config import (
75-
JOB_RUN_COMPARTMENT_OCID,
76-
JOB_RUN_OCID,
77-
NB_SESSION_COMPARTMENT_OCID,
78-
NB_SESSION_OCID,
79-
PROJECT_OCID,
80-
)
81-
from ads.common.decorator.deprecate import deprecated
82-
from ads.feature_engineering.schema import DataSizeTooWide, Schema, SchemaSizeTooLarge
83-
from ads.model.extractor.model_info_extractor_factory import ModelInfoExtractorFactory
8480
from ads.model.model_version_set import ModelVersionSet
85-
from ads.model.common.utils import fetch_manifest_from_conda_location
86-
from git import InvalidGitRepositoryError, Repo
87-
88-
from oci.data_science.models import ModelProvenance
8981

9082
try:
9183
from yaml import CDumper as dumper
92-
from yaml import CLoader as loader
9384
except:
9485
from yaml import Dumper as dumper
95-
from yaml import Loader as loader
9686

9787
MODEL_ARTIFACT_VERSION = "3.0"
9888
INPUT_SCHEMA_FILE_NAME = "input_schema.json"
@@ -102,7 +92,7 @@
10292
_COMPARTMENT_OCID = NB_SESSION_COMPARTMENT_OCID or JOB_RUN_COMPARTMENT_OCID
10393

10494

105-
class InvalidDataType(Exception): # pragma: no cover
95+
class InvalidDataType(Exception): # pragma: no cover
10696
"""Invalid Data Type."""
10797

10898
pass
@@ -119,7 +109,7 @@ class InvalidDataType(Exception): # pragma: no cover
119109
"""
120110

121111

122-
class ConflictStrategy(object):
112+
class ConflictStrategy:
123113
IGNORE = "IGNORE"
124114
UPDATE = "UPDATE"
125115
CREATE = "CREATE"
@@ -305,7 +295,7 @@ def __fetch_training_env_details(self, training_info):
305295
os.path.join(os.path.expanduser("~"), "conda", "config.yaml")
306296
):
307297
with open(
308-
(os.path.join(os.path.expanduser("~"), "conda", "config.yaml"))
298+
os.path.join(os.path.expanduser("~"), "conda", "config.yaml")
309299
) as conf:
310300
user_config = yaml.load(conf, Loader=yaml.FullLoader)
311301
pack_bucket = user_config["bucket_info"]["name"]
@@ -327,7 +317,7 @@ def __fetch_training_env_details(self, training_info):
327317
if manifest_type == PACK_TYPE.USER_CUSTOM_PACK.value:
328318
if self.data_science_env:
329319
raise Exception(
330-
f"For Published conda environments, assign the path of the environment in "
320+
"For Published conda environments, assign the path of the environment in "
331321
+ "Object Storage to the `inference_conda_env` parameter and set the "
332322
+ "parameter `data_science_env` to `False`."
333323
)
@@ -338,16 +328,15 @@ def __fetch_training_env_details(self, training_info):
338328
)
339329
if self.ignore_deployment_error:
340330
logger.warn(error_message)
341-
else:
342-
if not self.inference_conda_env:
343-
logger.error(error_message)
344-
logger.info(
345-
"Provide a URI to the conda environment that you wish to use with the model "
346-
"deployment service if you do not want to publish the current training environment."
347-
)
348-
raise Exception(
349-
f"Could not resolve the path in the Object Storage for the conda environment: {conda_prefix}"
350-
)
331+
elif not self.inference_conda_env:
332+
logger.error(error_message)
333+
logger.info(
334+
"Provide a URI to the conda environment that you wish to use with the model "
335+
"deployment service if you do not want to publish the current training environment."
336+
)
337+
raise Exception(
338+
f"Could not resolve the path in the Object Storage for the conda environment: {conda_prefix}"
339+
)
351340
else:
352341
logger.warn(
353342
f"Could not resolve the Object Storage destination of {conda_prefix}. Correct "
@@ -416,15 +405,15 @@ def _generate_empty_runtime_yaml(
416405
f"The inference conda environment is {inference_conda_env} and the Python version is {inference_python_version}."
417406
)
418407
if inference_conda_env:
419-
content["MODEL_DEPLOYMENT"]["INFERENCE_CONDA_ENV"][
420-
"INFERENCE_ENV_SLUG"
421-
] = ""
422-
content["MODEL_DEPLOYMENT"]["INFERENCE_CONDA_ENV"][
423-
"INFERENCE_ENV_TYPE"
424-
] = ""
425-
content["MODEL_DEPLOYMENT"]["INFERENCE_CONDA_ENV"][
426-
"INFERENCE_ENV_PATH"
427-
] = inference_conda_env
408+
content["MODEL_DEPLOYMENT"]["INFERENCE_CONDA_ENV"]["INFERENCE_ENV_SLUG"] = (
409+
""
410+
)
411+
content["MODEL_DEPLOYMENT"]["INFERENCE_CONDA_ENV"]["INFERENCE_ENV_TYPE"] = (
412+
""
413+
)
414+
content["MODEL_DEPLOYMENT"]["INFERENCE_CONDA_ENV"]["INFERENCE_ENV_PATH"] = (
415+
inference_conda_env
416+
)
428417
if inference_python_version:
429418
content["MODEL_DEPLOYMENT"]["INFERENCE_CONDA_ENV"][
430419
"INFERENCE_PYTHON_VERSION"
@@ -511,7 +500,7 @@ def _generate_runtime_yaml(self, model_file_name="model.onnx"):
511500
if (
512501
not self.inference_conda_env
513502
and not self.data_science_env
514-
and inference_info.INFERENCE_ENV_TYPE == PACK_TYPE.SERVICE_PACK.value
503+
and PACK_TYPE.SERVICE_PACK.value == inference_info.INFERENCE_ENV_TYPE
515504
and training_env_info.TRAINING_ENV_PATH == inference_info.INFERENCE_ENV_PATH
516505
):
517506
error_message = (
@@ -526,7 +515,7 @@ def _generate_runtime_yaml(self, model_file_name="model.onnx"):
526515

527516
if not inference_info.INFERENCE_ENV_PATH and not self.inference_conda_env:
528517
error_message = (
529-
f"The inference conda environment is missing. Set the `inference_conda_env` parameter "
518+
"The inference conda environment is missing. Set the `inference_conda_env` parameter "
530519
+ "or publish the conda environment and run the `.prepare()` method."
531520
)
532521
if not self.ignore_deployment_error:
@@ -808,7 +797,7 @@ def save(
808797

809798
runtime_yaml_file = os.path.join(self.artifact_dir, "runtime.yaml")
810799
if os.path.exists(runtime_yaml_file):
811-
with open(runtime_yaml_file, "r") as mfile:
800+
with open(runtime_yaml_file) as mfile:
812801
runtime_prep_info = yaml.load(mfile, Loader=yaml.FullLoader)
813802
# runtime_info['pack-info'] = deployment_pack_info
814803
else:
@@ -982,8 +971,11 @@ def install_requirements(self, conflict_strategy=ConflictStrategy.IGNORE):
982971
IGNORE: Use the installed version in case of a conflict.
983972
UPDATE: Force update dependency to the version required by model artifact in case of conflict.
984973
"""
985-
importlib.reload(pkg_resources)
986-
from pkg_resources import DistributionNotFound, VersionConflict
974+
from importlib.metadata import PackageNotFoundError
975+
from importlib.metadata import version as get_version
976+
977+
from packaging.markers import default_environment
978+
from packaging.requirements import Requirement
987979

988980
if self.version.split(".")[0] not in ["0", "1"] and os.path.exists(
989981
Path(os.path.join(self.artifact_dir), "requirements.txt")
@@ -1010,19 +1002,43 @@ def install_requirements(self, conflict_strategy=ConflictStrategy.IGNORE):
10101002
)
10111003

10121004
version_conflicts = {}
1005+
env = default_environment()
10131006
for requirement in requirements:
1007+
req_line = requirement.strip()
1008+
if not req_line or req_line.startswith("#"):
1009+
continue
1010+
# Skip include or index options lines
1011+
if req_line.startswith(("-", "--")):
1012+
continue
1013+
try:
1014+
req = Requirement(req_line)
1015+
except Exception:
1016+
# If the requirement line cannot be parsed, attempt to install it as-is.
1017+
pip_install(req_line)
1018+
continue
1019+
1020+
# Evaluate environment markers, if any
1021+
if req.marker and not req.marker.evaluate(environment=env):
1022+
continue
1023+
1024+
package_name = req.name
1025+
spec = req.specifier # SpecifierSet
1026+
10141027
try:
1015-
pkg_resources.require(requirement)
1016-
except VersionConflict as vc:
1028+
installed_version = get_version(package_name)
1029+
except PackageNotFoundError:
1030+
# Not installed; install the requirement as written
1031+
pip_install(req_line)
1032+
continue
1033+
1034+
if spec and installed_version not in spec:
10171035
if conflict_strategy == ConflictStrategy.UPDATE:
1018-
pip_install("%s%s" % (vc.req.name, vc.req.specifier), "-U")
1036+
pip_install(f"{package_name}{spec}", "-U")
10191037
elif conflict_strategy == ConflictStrategy.IGNORE:
1020-
version_conflicts[
1021-
"%s==%s" % (vc.dist.key, vc.dist.parsed_version)
1022-
] = "%s%s" % (vc.req.name, vc.req.specifier)
1023-
except DistributionNotFound as dnf:
1024-
pip_install(requirement)
1025-
# distributions_not_found.add('%s%s' % (dnf.req.name, dnf.req.specifier))
1038+
version_conflicts[f"{package_name}=={installed_version}"] = (
1039+
f"{package_name}{spec}"
1040+
)
1041+
10261042
if len(version_conflicts) > 0:
10271043
print(
10281044
"\033[93m"
@@ -1308,21 +1324,15 @@ def _populate_metadata_custom(self):
13081324
)
13091325
)
13101326
try:
1311-
env_type = (
1312-
self._runtime_info.MODEL_DEPLOYMENT.INFERENCE_CONDA_ENV.INFERENCE_ENV_TYPE._value
1313-
)
1327+
env_type = self._runtime_info.MODEL_DEPLOYMENT.INFERENCE_CONDA_ENV.INFERENCE_ENV_TYPE._value
13141328
except:
13151329
env_type = None
13161330
try:
1317-
slug_name = (
1318-
self._runtime_info.MODEL_DEPLOYMENT.INFERENCE_CONDA_ENV.INFERENCE_ENV_SLUG._value
1319-
)
1331+
slug_name = self._runtime_info.MODEL_DEPLOYMENT.INFERENCE_CONDA_ENV.INFERENCE_ENV_SLUG._value
13201332
except:
13211333
slug_name = None
13221334
try:
1323-
env_path = (
1324-
self._runtime_info.MODEL_DEPLOYMENT.INFERENCE_CONDA_ENV.INFERENCE_ENV_PATH._value
1325-
)
1335+
env_path = self._runtime_info.MODEL_DEPLOYMENT.INFERENCE_CONDA_ENV.INFERENCE_ENV_PATH._value
13261336
except:
13271337
env_path = None
13281338

@@ -1467,7 +1477,6 @@ def _save_from_local_file(
14671477
self._save_data_path(", ".join(oci_storage_paths), data_type)
14681478

14691479
def _save_data_path(self, oci_storage_path, data_type):
1470-
14711480
key = (
14721481
MetadataCustomKeys.TRAINING_DATASET
14731482
if data_type == "training"
@@ -1728,7 +1737,7 @@ def from_model_catalog(
17281737
return result_artifact
17291738

17301739

1731-
class VersionConflictWarning(object):
1740+
class VersionConflictWarning:
17321741
def __init__(self, version_conflicts):
17331742
self.version_conflicts = version_conflicts
17341743

0 commit comments

Comments
 (0)