Skip to content

[DRCC] Create and Update Metadata artifact content changes #1129

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 25, 2025
18 changes: 1 addition & 17 deletions ads/common/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python

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


Expand Down Expand Up @@ -152,22 +152,6 @@ def oci_key_location():
)


def text_sanitizer(content):
if isinstance(content, str):
return (
content.replace("“", '"')
.replace("”", '"')
.replace("’", "'")
.replace("‘", "'")
.replace("—", "-")
.encode("utf-8", "ignore")
.decode("utf-8", "ignore")
)
if isinstance(content, dict):
return json.dumps(content)
return str(content)


@deprecated(
"2.5.10",
details="Deprecated, use: from ads.common.auth import AuthState; AuthState().oci_config_path",
Expand Down
94 changes: 75 additions & 19 deletions ads/model/datascience_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ class InvalidArtifactType(Exception): # pragma: no cover
pass


class InvalidArtifactPathTypeOrContentError(Exception): # pragma: no cover
def __init__(self, msg="Invalid type of Metdata artifact content"):
super().__init__(msg)


class CustomerNotificationType(ExtendedEnum):
NONE = "NONE"
ALL = "ALL"
Expand Down Expand Up @@ -2238,7 +2243,7 @@ def find_model_idx():
def create_custom_metadata_artifact(
self,
metadata_key_name: str,
artifact_path_or_content: str,
artifact_path_or_content: Union[str, bytes],
path_type: MetadataArtifactPathType = MetadataArtifactPathType.LOCAL,
) -> ModelMetadataArtifactDetails:
"""Creates model custom metadata artifact for specified model.
Expand All @@ -2248,13 +2253,22 @@ def create_custom_metadata_artifact(
metadata_key_name: str
The name of the model custom metadata key

artifact_path_or_content: str
The model custom metadata artifact path to be upload. It can also be the actual content of the custom metadata
artifact_path_or_content: Union[str,bytes]
The model custom metadata artifact path to be uploaded. It can also be the actual content of the custom metadata artifact
The type is string when it represents local path or oss path.
The type is bytes when it represents content itself

path_type: MetadataArtifactPathType
Can be either of MetadataArtifactPathType.LOCAL , MetadataArtifactPathType.OSS , MetadataArtifactPathType.CONTENT
Specifies what type of path is to be provided for metadata artifact.
Can be either local , oss or the actual content itself

Example:
>>> ds_model=DataScienceModel.from_id("ocid1.datasciencemodel.iad.xxyxz...")
>>> ds_model.create_custom_metadata_artifact(
... "README",
... artifact_path_or_content="/Users/<username>/Downloads/README.md",
... path_type=MetadataArtifactPathType.LOCAL
... )

Returns
-------
Expand All @@ -2273,16 +2287,23 @@ def create_custom_metadata_artifact(
}

"""
if path_type == MetadataArtifactPathType.CONTENT and not isinstance(
artifact_path_or_content, bytes
):
raise InvalidArtifactPathTypeOrContentError(
f"Invalid type of artifact content: {type(artifact_path_or_content)}. It should be bytes."
)

return self.dsc_model.create_custom_metadata_artifact(
metadata_key_name=metadata_key_name,
artifact_path=artifact_path_or_content,
artifact_path_or_content=artifact_path_or_content,
path_type=path_type,
)

def create_defined_metadata_artifact(
self,
metadata_key_name: str,
artifact_path_or_content: str,
artifact_path_or_content: Union[str, bytes],
path_type: MetadataArtifactPathType = MetadataArtifactPathType.LOCAL,
) -> ModelMetadataArtifactDetails:
"""Creates model defined metadata artifact for specified model.
Expand All @@ -2292,14 +2313,24 @@ def create_defined_metadata_artifact(
metadata_key_name: str
The name of the model defined metadata key

artifact_path_or_content: str
The model defined metadata artifact path to be upload. It can also be the actual content of the defined metadata
artifact_path_or_content: Union[str,bytes]
The model defined metadata artifact path to be uploaded. It can also be the actual content of the defined metadata
The type is string when it represents local path or oss path.
The type is bytes when it represents content itself

path_type: MetadataArtifactPathType
Can be either of MetadataArtifactPathType.LOCAL , MetadataArtifactPathType.OSS , MetadataArtifactPathType.CONTENT
Specifies what type of path is to be provided for metadata artifact.
Can be either local , oss or the actual content itself

Example:
>>> ds_model=DataScienceModel.from_id("ocid1.datasciencemodel.iad.xxyxz...")
>>> ds_model.create_defined_metadata_artifact(
... "README",
... artifact_path_or_content="oci://path/to/bucket/README.md",
... path_type=MetadataArtifactPathType.OSS
... )

Returns
-------
ModelMetadataArtifactDetails
Expand All @@ -2317,16 +2348,23 @@ def create_defined_metadata_artifact(
}

"""
if path_type == MetadataArtifactPathType.CONTENT and not isinstance(
artifact_path_or_content, bytes
):
raise InvalidArtifactPathTypeOrContentError(
f"Invalid type of artifact content: {type(artifact_path_or_content)}. It should be bytes."
)

return self.dsc_model.create_defined_metadata_artifact(
metadata_key_name=metadata_key_name,
artifact_path=artifact_path_or_content,
artifact_path_or_content=artifact_path_or_content,
path_type=path_type,
)

def update_custom_metadata_artifact(
self,
metadata_key_name: str,
artifact_path_or_content: str,
artifact_path_or_content: Union[str, bytes],
path_type: MetadataArtifactPathType = MetadataArtifactPathType.LOCAL,
) -> ModelMetadataArtifactDetails:
"""Update model custom metadata artifact for specified model.
Expand All @@ -2336,8 +2374,10 @@ def update_custom_metadata_artifact(
metadata_key_name: str
The name of the model custom metadata key

artifact_path_or_content: str
The model custom metadata artifact path. It can also be the actual content of the custom metadata
artifact_path_or_content: Union[str,bytes]
The model custom metadata artifact path to be uploaded. It can also be the actual content of the custom metadata
The type is string when it represents local path or oss path.
The type is bytes when it represents content itself

path_type: MetadataArtifactPathType
Can be either of MetadataArtifactPathType.LOCAL , MetadataArtifactPathType.OSS , MetadataArtifactPathType.CONTENT
Expand All @@ -2361,16 +2401,23 @@ def update_custom_metadata_artifact(
}

"""
if path_type == MetadataArtifactPathType.CONTENT and not isinstance(
artifact_path_or_content, bytes
):
raise InvalidArtifactPathTypeOrContentError(
f"Invalid type of artifact content: {type(artifact_path_or_content)}. It should be bytes."
)

return self.dsc_model.update_custom_metadata_artifact(
metadata_key_name=metadata_key_name,
artifact_path=artifact_path_or_content,
artifact_path_or_content=artifact_path_or_content,
path_type=path_type,
)

def update_defined_metadata_artifact(
self,
metadata_key_name: str,
artifact_path_or_content: str,
artifact_path_or_content: Union[str, bytes],
path_type: MetadataArtifactPathType = MetadataArtifactPathType.LOCAL,
) -> ModelMetadataArtifactDetails:
"""Update model defined metadata artifact for specified model.
Expand All @@ -2380,8 +2427,10 @@ def update_defined_metadata_artifact(
metadata_key_name: str
The name of the model defined metadata key

artifact_path_or_content: str
The model defined metadata artifact path. It can also be the actual content of the defined metadata
artifact_path_or_content: Union[str,bytes]
The model defined metadata artifact path to be uploaded. It can also be the actual content of the defined metadata
The type is string when it represents local path or oss path.
The type is bytes when it represents content itself

path_type: MetadataArtifactPathType
Can be either of MetadataArtifactPathType.LOCAL , MetadataArtifactPathType.OSS , MetadataArtifactPathType.CONTENT
Expand All @@ -2405,9 +2454,16 @@ def update_defined_metadata_artifact(
}

"""
if path_type == MetadataArtifactPathType.CONTENT and not isinstance(
artifact_path_or_content, bytes
):
raise InvalidArtifactPathTypeOrContentError(
f"Invalid type of artifact content: {type(artifact_path_or_content)}. It should be bytes."
)

return self.dsc_model.update_defined_metadata_artifact(
metadata_key_name=metadata_key_name,
artifact_path=artifact_path_or_content,
artifact_path_or_content=artifact_path_or_content,
path_type=path_type,
)

Expand Down Expand Up @@ -2442,7 +2498,7 @@ def get_custom_metadata_artifact(
)
artifact_file_path = os.path.join(target_dir, f"{metadata_key_name}")

if not override and os.path.exists(artifact_file_path):
if not override and is_path_exists(artifact_file_path):
raise FileExistsError(f"File already exists: {artifact_file_path}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we say to use the override param to override?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we can. Will update the error message.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.


with open(artifact_file_path, "wb") as _file:
Expand Down Expand Up @@ -2481,7 +2537,7 @@ def get_defined_metadata_artifact(
)
artifact_file_path = os.path.join(target_dir, f"{metadata_key_name}")

if not override and os.path.exists(artifact_file_path):
if not override and is_path_exists(artifact_file_path):
raise FileExistsError(f"File already exists: {artifact_file_path}")

with open(artifact_file_path, "wb") as _file:
Expand Down
Loading
Loading