|
| 1 | +# --------------------------------------------------------- |
| 2 | +# Copyright (c) Microsoft Corporation. All rights reserved. |
| 3 | +# --------------------------------------------------------- |
| 4 | + |
| 5 | +# pylint: disable=protected-access,no-value-for-parameter,disable=docstring-missing-return,docstring-missing-param,docstring-missing-rtype,ungrouped-imports,line-too-long,too-many-statements |
| 6 | + |
| 7 | +from os import PathLike |
| 8 | +from typing import Any, Dict, Iterable, Optional, Union, cast |
| 9 | +from azure.ai.ml._restclient.v2021_10_01_dataplanepreview import ( |
| 10 | + AzureMachineLearningWorkspaces as ServiceClient102021Dataplane, |
| 11 | +) |
| 12 | +from azure.ai.ml._restclient.v2023_08_01_preview import ( |
| 13 | + AzureMachineLearningWorkspaces as ServiceClient082023Preview, |
| 14 | +) |
| 15 | +from azure.ai.ml._restclient.v2023_08_01_preview.models import ( |
| 16 | + ListViewType, |
| 17 | +) |
| 18 | +from azure.ai.ml._scope_dependent_operations import ( |
| 19 | + OperationConfig, |
| 20 | + OperationsContainer, |
| 21 | + OperationScope, |
| 22 | + _ScopeDependentOperations, |
| 23 | +) |
| 24 | +from azure.ai.ml._telemetry import ActivityType, monitor_with_activity |
| 25 | +from azure.ai.ml._utils._logger_utils import OpsLogger |
| 26 | +from azure.ai.ml._utils.utils import ( |
| 27 | + _get_evaluator_properties, |
| 28 | + _is_evaluator, |
| 29 | +) |
| 30 | +from azure.ai.ml.entities._assets import Model |
| 31 | +from azure.ai.ml.entities._assets.workspace_asset_reference import ( |
| 32 | + WorkspaceAssetReference, |
| 33 | +) |
| 34 | +from azure.ai.ml.exceptions import ( |
| 35 | + UnsupportedOperationError, |
| 36 | +) |
| 37 | +from azure.ai.ml.operations._datastore_operations import DatastoreOperations |
| 38 | +from azure.core.exceptions import ResourceNotFoundError |
| 39 | + |
| 40 | +from azure.ai.ml.operations._model_operations import ModelOperations |
| 41 | + |
| 42 | +ops_logger = OpsLogger(__name__) |
| 43 | +module_logger = ops_logger.module_logger |
| 44 | + |
| 45 | + |
| 46 | +class EvaluatorOperations(_ScopeDependentOperations): |
| 47 | + """EvaluatorOperations. |
| 48 | +
|
| 49 | + You should not instantiate this class directly. Instead, you should create an MLClient instance that instantiates it |
| 50 | + for you and attaches it as an attribute. |
| 51 | +
|
| 52 | + :param operation_scope: Scope variables for the operations classes of an MLClient object. |
| 53 | + :type operation_scope: ~azure.ai.ml._scope_dependent_operations.OperationScope |
| 54 | + :param operation_config: Common configuration for operations classes of an MLClient object. |
| 55 | + :type operation_config: ~azure.ai.ml._scope_dependent_operations.OperationConfig |
| 56 | + :param service_client: Service client to allow end users to operate on Azure Machine Learning Workspace |
| 57 | + resources (ServiceClient082023Preview or ServiceClient102021Dataplane). |
| 58 | + :type service_client: typing.Union[ |
| 59 | + azure.ai.ml._restclient.v2023_04_01_preview._azure_machine_learning_workspaces.AzureMachineLearningWorkspaces, |
| 60 | + azure.ai.ml._restclient.v2021_10_01_dataplanepreview._azure_machine_learning_workspaces. |
| 61 | + AzureMachineLearningWorkspaces] |
| 62 | + :param datastore_operations: Represents a client for performing operations on Datastores. |
| 63 | + :type datastore_operations: ~azure.ai.ml.operations._datastore_operations.DatastoreOperations |
| 64 | + :param all_operations: All operations classes of an MLClient object. |
| 65 | + :type all_operations: ~azure.ai.ml._scope_dependent_operations.OperationsContainer |
| 66 | + """ |
| 67 | + |
| 68 | + # pylint: disable=unused-argument |
| 69 | + def __init__( |
| 70 | + self, |
| 71 | + operation_scope: OperationScope, |
| 72 | + operation_config: OperationConfig, |
| 73 | + service_client: Union[ServiceClient082023Preview, ServiceClient102021Dataplane], |
| 74 | + datastore_operations: DatastoreOperations, |
| 75 | + all_operations: Optional[OperationsContainer] = None, |
| 76 | + **kwargs, |
| 77 | + ): |
| 78 | + super(EvaluatorOperations, self).__init__(operation_scope, operation_config) |
| 79 | + |
| 80 | + ops_logger.update_info(kwargs) |
| 81 | + self._model_op = ModelOperations( |
| 82 | + operation_scope=operation_scope, |
| 83 | + operation_config=operation_config, |
| 84 | + service_client=service_client, |
| 85 | + datastore_operations=datastore_operations, |
| 86 | + all_operations=all_operations, |
| 87 | + **{ModelOperations._IS_EVALUATOR: True}, |
| 88 | + **kwargs, |
| 89 | + ) |
| 90 | + self._operation_scope = self._model_op._operation_scope |
| 91 | + self._datastore_operation = self._model_op._datastore_operation |
| 92 | + |
| 93 | + @monitor_with_activity(ops_logger, "Evaluator.CreateOrUpdate", ActivityType.PUBLICAPI) |
| 94 | + def create_or_update( # type: ignore |
| 95 | + self, model: Union[Model, WorkspaceAssetReference] |
| 96 | + ) -> Model: # TODO: Are we going to implement job_name? |
| 97 | + """Returns created or updated model asset. |
| 98 | +
|
| 99 | + :param model: Model asset object. |
| 100 | + :type model: ~azure.ai.ml.entities.Model |
| 101 | + :raises ~azure.ai.ml.exceptions.AssetPathException: Raised when the Model artifact path is |
| 102 | + already linked to another asset |
| 103 | + :raises ~azure.ai.ml.exceptions.ValidationException: Raised if Model cannot be successfully validated. |
| 104 | + Details will be provided in the error message. |
| 105 | + :raises ~azure.ai.ml.exceptions.EmptyDirectoryError: Raised if local path provided points to an empty directory. |
| 106 | + :return: Model asset object. |
| 107 | + :rtype: ~azure.ai.ml.entities.Model |
| 108 | + """ |
| 109 | + model.properties.update(_get_evaluator_properties()) |
| 110 | + return self._model_op.create_or_update(model) |
| 111 | + |
| 112 | + def _raise_if_not_evaluator(self, properties: Optional[Dict[str, Any]], message: str) -> None: |
| 113 | + """ |
| 114 | + :param properties: The properties of a model. |
| 115 | + :type properties: dict[str, str] |
| 116 | + :param message: The message to be set on exception. |
| 117 | + :type message: str |
| 118 | + :raises ~azure.ai.ml.exceptions.ValidationException: Raised if model is not an |
| 119 | + evaluator. |
| 120 | + """ |
| 121 | + if properties is not None and not _is_evaluator(properties): |
| 122 | + raise ResourceNotFoundError( |
| 123 | + message=message, |
| 124 | + response=None, |
| 125 | + ) |
| 126 | + |
| 127 | + @monitor_with_activity(ops_logger, "Evaluator.Get", ActivityType.PUBLICAPI) |
| 128 | + def get(self, name: str, version: Optional[str] = None, label: Optional[str] = None) -> Model: |
| 129 | + """Returns information about the specified model asset. |
| 130 | +
|
| 131 | + :param name: Name of the model. |
| 132 | + :type name: str |
| 133 | + :param version: Version of the model. |
| 134 | + :type version: str |
| 135 | + :param label: Label of the model. (mutually exclusive with version) |
| 136 | + :type label: str |
| 137 | + :raises ~azure.ai.ml.exceptions.ValidationException: Raised if Model cannot be successfully validated. |
| 138 | + Details will be provided in the error message. |
| 139 | + :return: Model asset object. |
| 140 | + :rtype: ~azure.ai.ml.entities.Model |
| 141 | + """ |
| 142 | + model = self._model_op.get(name, version, label) |
| 143 | + |
| 144 | + properties = None if model is None else model.properties |
| 145 | + self._raise_if_not_evaluator( |
| 146 | + properties, |
| 147 | + f"Evaluator {name} with version {version} not found.", |
| 148 | + ) |
| 149 | + |
| 150 | + return model |
| 151 | + |
| 152 | + @monitor_with_activity(ops_logger, "Evaluator.Download", ActivityType.PUBLICAPI) |
| 153 | + def download(self, name: str, version: str, download_path: Union[PathLike, str] = ".") -> None: |
| 154 | + """Download files related to a model. |
| 155 | +
|
| 156 | + :param name: Name of the model. |
| 157 | + :type name: str |
| 158 | + :param version: Version of the model. |
| 159 | + :type version: str |
| 160 | + :param download_path: Local path as download destination, defaults to current working directory of the current |
| 161 | + user. Contents will be overwritten. |
| 162 | + :type download_path: Union[PathLike, str] |
| 163 | + :raises ResourceNotFoundError: if can't find a model matching provided name. |
| 164 | + """ |
| 165 | + self._model_op.download(name, version, download_path) |
| 166 | + |
| 167 | + @monitor_with_activity(ops_logger, "Evaluator.List", ActivityType.PUBLICAPI) |
| 168 | + def list( |
| 169 | + self, |
| 170 | + name: str, |
| 171 | + stage: Optional[str] = None, |
| 172 | + *, |
| 173 | + list_view_type: ListViewType = ListViewType.ACTIVE_ONLY, |
| 174 | + ) -> Iterable[Model]: |
| 175 | + """List all model assets in workspace. |
| 176 | +
|
| 177 | + :param name: Name of the model. |
| 178 | + :type name: str |
| 179 | + :param stage: The Model stage |
| 180 | + :type stage: Optional[str] |
| 181 | + :keyword list_view_type: View type for including/excluding (for example) archived models. |
| 182 | + Defaults to :attr:`ListViewType.ACTIVE_ONLY`. |
| 183 | + :paramtype list_view_type: ListViewType |
| 184 | + :return: An iterator like instance of Model objects |
| 185 | + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.ml.entities.Model] |
| 186 | + """ |
| 187 | + properties_str = "is-promptflow=true,is-evaluator=true" |
| 188 | + if name: |
| 189 | + return cast( |
| 190 | + Iterable[Model], |
| 191 | + ( |
| 192 | + self._model_op._model_versions_operation.list( |
| 193 | + name=name, |
| 194 | + registry_name=self._model_op._registry_name, |
| 195 | + cls=lambda objs: [Model._from_rest_object(obj) for obj in objs], |
| 196 | + properties=properties_str, |
| 197 | + **self._model_op._scope_kwargs, |
| 198 | + ) |
| 199 | + if self._registry_name |
| 200 | + else self._model_op._model_versions_operation.list( |
| 201 | + name=name, |
| 202 | + workspace_name=self._model_op._workspace_name, |
| 203 | + cls=lambda objs: [Model._from_rest_object(obj) for obj in objs], |
| 204 | + list_view_type=list_view_type, |
| 205 | + properties=properties_str, |
| 206 | + stage=stage, |
| 207 | + **self._model_op._scope_kwargs, |
| 208 | + ) |
| 209 | + ), |
| 210 | + ) |
| 211 | + # ModelContainer object does not carry properties. |
| 212 | + raise UnsupportedOperationError("list on evaluation operations without name provided") |
| 213 | + # TODO: Implement filtering of the ModelContainerOperations list output |
| 214 | + # return cast( |
| 215 | + # Iterable[Model], ( |
| 216 | + # self._model_container_operation.list( |
| 217 | + # registry_name=self._registry_name, |
| 218 | + # cls=lambda objs: [Model._from_container_rest_object(obj) for obj in objs], |
| 219 | + # list_view_type=list_view_type, |
| 220 | + # **self._scope_kwargs, |
| 221 | + # ) |
| 222 | + # if self._registry_name |
| 223 | + # else self._model_container_operation.list( |
| 224 | + # workspace_name=self._workspace_name, |
| 225 | + # cls=lambda objs: [Model._from_container_rest_object(obj) for obj in objs], |
| 226 | + # list_view_type=list_view_type, |
| 227 | + # **self._scope_kwargs, |
| 228 | + # ) |
| 229 | + # ) |
| 230 | + # ) |
0 commit comments