diff options
author | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
---|---|---|
committer | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
commit | 4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch) | |
tree | ee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators | |
parent | cc961e04ba734dd72309fb548a2f97d67d578813 (diff) | |
download | gn-ai-master.tar.gz |
Diffstat (limited to '.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators')
4 files changed, 420 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators/__init__.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators/__init__.py new file mode 100644 index 00000000..dc6af819 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators/__init__.py @@ -0,0 +1,11 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore + +from .code_validator import get_code_configuration_artifacts +from .environment_validator import get_environment_artifacts +from .model_validator import get_model_artifacts + +__all__ = ["get_code_configuration_artifacts", "get_environment_artifacts", "get_model_artifacts"] diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators/code_validator.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators/code_validator.py new file mode 100644 index 00000000..bbe7c971 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators/code_validator.py @@ -0,0 +1,114 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +# pylint: disable=protected-access + +from pathlib import Path +from typing import Optional, Union + +from azure.ai.ml._artifacts._artifact_utilities import download_artifact_from_storage_url +from azure.ai.ml._utils._arm_id_utils import parse_prefixed_name_version +from azure.ai.ml._utils.utils import is_url +from azure.ai.ml.constants._common import ARM_ID_PREFIX +from azure.ai.ml.entities import OnlineDeployment +from azure.ai.ml.entities._deployment.code_configuration import CodeConfiguration +from azure.ai.ml.exceptions import RequiredLocalArtifactsNotFoundError +from azure.ai.ml.operations._code_operations import CodeOperations + + +def get_code_configuration_artifacts( + endpoint_name: str, + deployment: OnlineDeployment, + code_operations: CodeOperations, + download_path: str, +) -> Optional[Union[str, Path]]: + """Validates and returns code artifacts from deployment specification. + + :param endpoint_name: name of endpoint which this deployment is linked to + :type endpoint_name: str + :param deployment: deployment to validate + :type deployment: OnlineDeployment + :param code_operations: The code operations + :type code_operations: CodeOperations + :param download_path: The path to download to + :type download_path: str + :return: local path to code + :rtype: str + :raises: azure.ai.ml._local_endpoints.errors.RequiredLocalArtifactsNotFoundError + :raises: azure.ai.ml._local_endpoints.errors.CloudArtifactsNotSupportedError + """ + # Validate code for local endpoint + if not deployment.code_configuration: + return None + + if not isinstance(deployment.code_configuration, CodeConfiguration): + raise RequiredLocalArtifactsNotFoundError( + endpoint_name=endpoint_name, + required_artifact="code_configuration", + required_artifact_type=str(str), + deployment_name=deployment.name, + ) + + if _code_configuration_contains_cloud_artifacts(deployment=deployment): + return _get_cloud_code_configuration_artifacts( + str(deployment.code_configuration.code), code_operations, download_path + ) + + if not _local_code_path_is_valid(deployment=deployment): + raise RequiredLocalArtifactsNotFoundError( + endpoint_name=endpoint_name, + required_artifact="code_configuration.code", + required_artifact_type=str(str), + deployment_name=deployment.name, + ) + if not _local_scoring_script_is_valid(deployment=deployment): + raise RequiredLocalArtifactsNotFoundError( + endpoint_name=endpoint_name, + required_artifact="code_configuration.scoring_script", + required_artifact_type=str(str), + deployment_name=deployment.name, + ) + return _get_local_code_configuration_artifacts(deployment) + + +def _local_code_path_is_valid(deployment: OnlineDeployment): + return ( + deployment.code_configuration + and deployment.code_configuration.code + and isinstance(deployment.code_configuration.code, str) + and _get_local_code_configuration_artifacts(deployment).exists() + ) + + +def _local_scoring_script_is_valid(deployment: OnlineDeployment): + return deployment.code_configuration and deployment.code_configuration.scoring_script + + +def _code_configuration_contains_cloud_artifacts(deployment: OnlineDeployment): + # If the deployment.code_configuration.code is a string, then it is the cloud code artifact name or full arm ID + + return isinstance(deployment.code_configuration.code, str) and ( # type: ignore[union-attr] + is_url(deployment.code_configuration.code) # type: ignore[union-attr] + or deployment.code_configuration.code.startswith(ARM_ID_PREFIX) # type: ignore[union-attr] + ) + + +def _get_local_code_configuration_artifacts( + deployment: OnlineDeployment, +) -> Path: + return Path( + deployment._base_path, deployment.code_configuration.code # type: ignore[union-attr, arg-type] + ).resolve() + + +def _get_cloud_code_configuration_artifacts(code: str, code_operations: CodeOperations, download_path: str) -> str: + name, version = parse_prefixed_name_version(code) + code_asset = code_operations.get(name=name, version=version) + + return download_artifact_from_storage_url( + blob_url=code_asset.path, + destination=download_path, + datastore_operation=code_operations._datastore_operation, + datastore_name=None, # Use default datastore of current workspace + ) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators/environment_validator.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators/environment_validator.py new file mode 100644 index 00000000..cc739149 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators/environment_validator.py @@ -0,0 +1,202 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +# pylint: disable=protected-access + +import os +from pathlib import Path +from typing import Optional, Tuple, Union + +from azure.ai.ml._artifacts._artifact_utilities import download_artifact_from_storage_url +from azure.ai.ml._utils._arm_id_utils import parse_name_label, parse_name_version +from azure.ai.ml._utils.utils import dump_yaml, is_url +from azure.ai.ml.constants._common import DefaultOpenEncoding +from azure.ai.ml.entities import OnlineDeployment +from azure.ai.ml.entities._assets.environment import BuildContext, Environment +from azure.ai.ml.exceptions import ErrorCategory, ErrorTarget, RequiredLocalArtifactsNotFoundError, ValidationException +from azure.ai.ml.operations._environment_operations import EnvironmentOperations + + +def get_environment_artifacts( + endpoint_name: str, + deployment: OnlineDeployment, + environment_operations: EnvironmentOperations, + download_path: str, +) -> Optional[Tuple]: + """Validates and returns artifacts from environment specification. + + :param endpoint_name: name of endpoint which this deployment is linked to + :type endpoint_name: str + :param deployment: deployment to validate + :type deployment: OnlineDeployment + :param environment_operations: The environment operations + :type environment_operations: EnvironmentOperations + :param download_path: The path to download to + :type download_path: str + :return: (base_image, conda_file_path, conda_file_contents, build_directory, + dockerfile_contents, inference_config) + + Either base_image or build_directory should be None. + :rtype: Union[ + Tuple[str, Optional[Path], str, None, None, Optional[Dict]], + Tuple[None, None, None, Path, str, Optional[Dict]] + ] + :raises: azure.ai.ml._local_endpoints.errors.RequiredLocalArtifactsNotFoundError + :raises: azure.ai.ml._local_endpoints.errors.CloudArtifactsNotSupportedError + """ + # Validate environment for local endpoint + if _environment_contains_cloud_artifacts(deployment=deployment): + if isinstance(deployment.environment, Environment): + environment_asset = deployment.environment + else: + name, version = parse_name_version(deployment.environment) + label = None + if not version: + name, label = parse_name_label(deployment.environment) + environment_asset = environment_operations.get(name=name, version=version, label=label) + + if not _cloud_environment_is_valid(environment=environment_asset): + msg = ( + "Cloud environment must have environment.image " + "or the environment.build.path set to work for local endpoints." + " Note: Curated environments are not supported for local deployments." + ) + raise ValidationException( + message=msg, + no_personal_data_message=msg, + target=ErrorTarget.LOCAL_ENDPOINT, + error_category=ErrorCategory.USER_ERROR, + ) + return _get_cloud_environment_artifacts( + environment_operations=environment_operations, + environment_asset=environment_asset, + download_path=download_path, + ) + if not _local_environment_is_valid(deployment=deployment): + raise RequiredLocalArtifactsNotFoundError( + endpoint_name=endpoint_name, + required_artifact="environment.image or environment.build.path", + required_artifact_type=str(Environment), + deployment_name=deployment.name, + ) + return _get_local_environment_artifacts(deployment.base_path, deployment.environment) # type: ignore[arg-type] + + +def _get_cloud_environment_artifacts( + environment_operations: EnvironmentOperations, + environment_asset: Environment, + download_path: str, +) -> Tuple: + """Retrieves the cloud environment's artifacts + + :param environment_operations: The environment operations + :type environment_operations: EnvironmentOperations + :param environment_asset: The cloud environment + :type environment_asset: Environment + :param download_path: The path to download to + :type download_path: str + :return: (base_image, conda_file_path, conda_file_contents, build_directory, + dockerfile_contents, inference_config) + + Either base_image or build_directory should be None. + :rtype: Union[ + Tuple[str, Optional[Path], str, None, None, Optional[Dict]], + Tuple[None, None, None, Path, str, Optional[Dict]] + ] + """ + if environment_asset.build and environment_asset.build.path and is_url(environment_asset.build.path): + environment_build_directory = download_artifact_from_storage_url( + blob_url=str(environment_asset.build.path), + destination=download_path, + datastore_operation=environment_operations._datastore_operation, + datastore_name="workspaceartifactstore", + ) + dockerfile_path = Path(environment_build_directory, str(environment_asset.build.dockerfile_path)) + dockerfile_contents = dockerfile_path.read_text(encoding=DefaultOpenEncoding.READ) + return ( + None, + None, + None, + environment_build_directory, + dockerfile_contents, + environment_asset.inference_config, + ) + conda_file_contents = dump_yaml(environment_asset.conda_file) if environment_asset.conda_file else None + return ( + environment_asset.image, + environment_asset.id, + conda_file_contents, + None, + None, + environment_asset.inference_config, + ) + + +def _get_local_environment_artifacts(base_path: Union[str, os.PathLike], environment: Environment) -> Optional[Tuple]: + """Retrieves the local environment's artifacts + + :param base_path: The base path + :type base_path: Union[str, os.PathLike] + :param environment: The local environment + :type environment: Environment + :return: (base_image, conda_file_path, conda_file_contents, build_directory, + dockerfile_contents, inference_config) + + Either base_image or build_directory should be None. + :rtype: Union[ + Tuple[str, Optional[Path], str, None, None, Optional[Dict]], + Tuple[None, None, None, Path, str, Optional[Dict]] + ] + """ + if environment.image: + conda_file_contents = dump_yaml(environment.conda_file) + return ( + environment.image, + environment._conda_file_path, + conda_file_contents, + None, + None, + environment.inference_config, + ) + if environment.build and environment.build.dockerfile_path: + absolute_build_directory = Path(base_path, str(environment.build.path)).resolve() + absolute_dockerfile_path = Path(absolute_build_directory, environment.build.dockerfile_path).resolve() + dockerfile_contents = absolute_dockerfile_path.read_text(encoding=DefaultOpenEncoding.READ) + return ( + None, + None, + None, + absolute_build_directory, + dockerfile_contents, + environment.inference_config, + ) + + return None + + +def _local_environment_is_valid(deployment: OnlineDeployment): + return isinstance(deployment.environment, Environment) and ( + deployment.environment.image + or ( + deployment.environment.build is not None + and isinstance(deployment.environment.build, BuildContext) + and _local_build_context_is_valid(deployment.environment.build) + ) + ) + + +def _local_build_context_is_valid(build_context: BuildContext): + return build_context.path is not None + + +def _cloud_environment_is_valid(environment: Environment): + return isinstance(environment, Environment) and ( + environment.image or (environment.build and environment.build.path) + ) + + +def _environment_contains_cloud_artifacts(deployment: OnlineDeployment): + return isinstance(deployment.environment, str) or ( + deployment.environment is not None and deployment.environment.id is not None + ) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators/model_validator.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators/model_validator.py new file mode 100644 index 00000000..40ed2df7 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_local_endpoints/validators/model_validator.py @@ -0,0 +1,93 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +# pylint: disable=protected-access + +from os import PathLike +from pathlib import Path +from typing import Tuple, Union + +from azure.ai.ml._artifacts._artifact_utilities import download_artifact +from azure.ai.ml._utils._arm_id_utils import parse_prefixed_name_version +from azure.ai.ml._utils._storage_utils import AzureMLDatastorePathUri +from azure.ai.ml.entities import OnlineDeployment +from azure.ai.ml.entities._assets import Model +from azure.ai.ml.exceptions import RequiredLocalArtifactsNotFoundError +from azure.ai.ml.operations._model_operations import ModelOperations + + +def get_model_artifacts( + endpoint_name: str, + deployment: OnlineDeployment, + model_operations: ModelOperations, + download_path: str, +) -> Union[str, Tuple]: + """Validates and returns model artifacts from deployment specification. + + :param endpoint_name: name of endpoint which this deployment is linked to + :type endpoint_name: str + :param deployment: deployment to validate + :type deployment: OnlineDeployment + :param model_operations: The model operations + :type model_operations: ModelOperations + :param download_path: The path to download to + :type download_path: str + :return: (model name, model version, the local directory of the model artifact) + :rtype: Tuple[str, str, Path] + :raises: azure.ai.ml._local_endpoints.errors.RequiredLocalArtifactsNotFoundError + :raises: azure.ai.ml._local_endpoints.errors.CloudArtifactsNotSupportedError + """ + # Validate model for local endpoint + if _model_contains_cloud_artifacts(deployment=deployment): + return _get_cloud_model_artifacts( + model_operations=model_operations, + model=str(deployment.model), + download_path=download_path, + ) + if not _local_model_is_valid(deployment=deployment): + raise RequiredLocalArtifactsNotFoundError( + endpoint_name=endpoint_name, + required_artifact="model.path", + required_artifact_type=str, + deployment_name=deployment.name, + ) + _model: Model = deployment.model # type: ignore[assignment] + _model_path: Union[str, PathLike] = _model.path # type: ignore[assignment] + return ( + _model.name, + _model.version, + Path(deployment._base_path, _model_path).resolve().parent, + ) + + +def _local_model_is_valid(deployment: OnlineDeployment): + return deployment.model and isinstance(deployment.model, Model) and deployment.model.path + + +def _model_contains_cloud_artifacts(deployment: OnlineDeployment): + # If the deployment.model is a string, then it is the cloud model name or full arm ID + return isinstance(deployment.model, str) or (deployment.model is not None and deployment.model.id is not None) + + +def _get_cloud_model_artifacts(model_operations: ModelOperations, model: str, download_path: str) -> Tuple: + if isinstance(model, Model): + name = model.name + version = model._version + model_asset = model + else: + name, version = parse_prefixed_name_version(model) + model_asset = model_operations.get(name=name, version=version) + model_uri_path = AzureMLDatastorePathUri(model_asset.path) + path = Path(model_uri_path.path) + starts_with = path if path.is_dir() else path.parent + return ( + name, + version, + download_artifact( + starts_with=starts_with, + destination=download_path, + datastore_operation=model_operations._datastore_operation, + datastore_name=model_uri_path.datastore, + ), + ) |