base.py
1 """ 2 This module contains the base interface implemented by MLflow model deployment plugins. 3 In particular, a valid deployment plugin module must implement: 4 5 1. Exactly one client class subclassed from :py:class:`BaseDeploymentClient`, exposing the primary 6 user-facing APIs used to manage deployments. 7 2. :py:func:`run_local`, for testing deployment by deploying a model locally 8 3. :py:func:`target_help`, which returns a help message describing target-specific URI format 9 and deployment config 10 """ 11 12 import abc 13 14 from mlflow.exceptions import MlflowException 15 from mlflow.utils.annotations import developer_stable 16 17 18 def run_local(target, name, model_uri, flavor=None, config=None): 19 """Deploys the specified model locally, for testing. This function should be defined 20 within the plugin module. Also note that this function has a signature which is very 21 similar to :py:meth:`BaseDeploymentClient.create_deployment` since both does logically 22 similar operation. 23 24 .. Note:: 25 This function is kept here only for documentation purpose and not implementing the 26 actual feature. It should be implemented in the plugin's top level namescope and should 27 be callable with ``plugin_module.run_local`` 28 29 Args: 30 target: Which target to use. This information is used to call the appropriate plugin. 31 name: Unique name to use for deployment. If another deployment exists with the same 32 name, create_deployment will raise a 33 :py:class:`mlflow.exceptions.MlflowException`. 34 model_uri: URI of model to deploy. 35 flavor: (optional) Model flavor to deploy. If unspecified, default flavor is chosen. 36 config: (optional) Dict containing updated target-specific config for the deployment. 37 38 Returns: 39 None 40 """ 41 raise NotImplementedError( 42 "This function should be implemented in the deployment plugin. It is " 43 "kept here only for documentation purpose and shouldn't be used in " 44 "your application" 45 ) 46 47 48 def target_help(): 49 """ 50 .. Note:: 51 This function is kept here only for documentation purpose and not implementing the 52 actual feature. It should be implemented in the plugin's top level namescope and should 53 be callable with ``plugin_module.target_help`` 54 55 Return a string containing detailed documentation on the current deployment target, to be 56 displayed when users invoke the ``mlflow deployments help -t <target-name>`` CLI. This 57 method should be defined within the module specified by the plugin author. 58 The string should contain: 59 60 * An explanation of target-specific fields in the ``config`` passed to ``create_deployment``, 61 ``update_deployment`` 62 * How to specify a ``target_uri`` (e.g. for AWS SageMaker, ``target_uri`` have a scheme of 63 "sagemaker:/<aws-cli-profile-name>", where aws-cli-profile-name is the name of an AWS 64 CLI profile https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) 65 * Any other target-specific details. 66 67 """ 68 raise NotImplementedError( 69 "This function should be implemented in the deployment plugin. It is " 70 "kept here only for documentation purpose and shouldn't be used in " 71 "your application" 72 ) 73 74 75 @developer_stable 76 class BaseDeploymentClient(abc.ABC): 77 """ 78 Base class exposing Python model deployment APIs. 79 80 Plugin implementors should define target-specific deployment logic via a subclass of 81 ``BaseDeploymentClient`` within the plugin module, and customize method docstrings with 82 target-specific information. 83 84 .. Note:: 85 Subclasses should raise :py:class:`mlflow.exceptions.MlflowException` in error cases (e.g. 86 on failure to deploy a model). 87 """ 88 89 def __init__(self, target_uri): 90 self.target_uri = target_uri 91 92 @abc.abstractmethod 93 def create_deployment(self, name, model_uri, flavor=None, config=None, endpoint=None): 94 """ 95 Deploy a model to the specified target. By default, this method should block until 96 deployment completes (i.e. until it's possible to perform inference with the deployment). 97 In the case of conflicts (e.g. if it's not possible to create the specified deployment 98 without due to conflict with an existing deployment), raises a 99 :py:class:`mlflow.exceptions.MlflowException` or an `HTTPError` for remote 100 deployments. See target-specific plugin documentation 101 for additional detail on support for asynchronous deployment and other configuration. 102 103 Args: 104 name: Unique name to use for deployment. If another deployment exists with the same 105 name, raises a :py:class:`mlflow.exceptions.MlflowException` 106 model_uri: URI of model to deploy 107 flavor: (optional) Model flavor to deploy. If unspecified, a default flavor 108 will be chosen. 109 config: (optional) Dict containing updated target-specific configuration for the 110 deployment 111 endpoint: (optional) Endpoint to create the deployment under. May not be supported 112 by all targets 113 114 Returns: 115 Dict corresponding to created deployment, which must contain the 'name' key. 116 117 """ 118 119 @abc.abstractmethod 120 def update_deployment(self, name, model_uri=None, flavor=None, config=None, endpoint=None): 121 """ 122 Update the deployment with the specified name. You can update the URI of the model, the 123 flavor of the deployed model (in which case the model URI must also be specified), and/or 124 any target-specific attributes of the deployment (via `config`). By default, this method 125 should block until deployment completes (i.e. until it's possible to perform inference 126 with the updated deployment). See target-specific plugin documentation for additional 127 detail on support for asynchronous deployment and other configuration. 128 129 Args: 130 name: Unique name of deployment to update. 131 model_uri: URI of a new model to deploy. 132 flavor: (optional) new model flavor to use for deployment. If provided, 133 ``model_uri`` must also be specified. If ``flavor`` is unspecified but 134 ``model_uri`` is specified, a default flavor will be chosen and the 135 deployment will be updated using that flavor. 136 config: (optional) dict containing updated target-specific configuration for the 137 deployment. 138 endpoint: (optional) Endpoint containing the deployment to update. May not be 139 supported by all targets. 140 141 Returns: 142 None 143 144 """ 145 146 @abc.abstractmethod 147 def delete_deployment(self, name, config=None, endpoint=None): 148 """Delete the deployment with name ``name`` from the specified target. 149 150 Deletion should be idempotent (i.e. deletion should not fail if retried on a non-existent 151 deployment). 152 153 Args: 154 name: Name of deployment to delete 155 config: (optional) dict containing updated target-specific configuration for the 156 deployment 157 endpoint: (optional) Endpoint containing the deployment to delete. May not be 158 supported by all targets 159 160 Returns: 161 None 162 """ 163 164 @abc.abstractmethod 165 def list_deployments(self, endpoint=None): 166 """List deployments. 167 168 This method is expected to return an unpaginated list of all 169 deployments (an alternative would be to return a dict with a 'deployments' field 170 containing the actual deployments, with plugins able to specify other fields, e.g. 171 a next_page_token field, in the returned dictionary for pagination, and to accept 172 a `pagination_args` argument to this method for passing pagination-related args). 173 174 Args: 175 endpoint: (optional) List deployments in the specified endpoint. May not be 176 supported by all targets 177 178 Returns: 179 A list of dicts corresponding to deployments. Each dict is guaranteed to 180 contain a 'name' key containing the deployment name. The other fields of 181 the returned dictionary and their types may vary across deployment targets. 182 """ 183 184 @abc.abstractmethod 185 def get_deployment(self, name, endpoint=None): 186 """ 187 Returns a dictionary describing the specified deployment, throwing either a 188 :py:class:`mlflow.exceptions.MlflowException` or an `HTTPError` for remote 189 deployments if no deployment exists with the provided ID. 190 The dict is guaranteed to contain an 'name' key containing the deployment name. 191 The other fields of the returned dictionary and their types may vary across 192 deployment targets. 193 194 Args: 195 name: ID of deployment to fetch. 196 endpoint: (optional) Endpoint containing the deployment to get. May not be 197 supported by all targets. 198 199 Returns: 200 A dict corresponding to the retrieved deployment. The dict is guaranteed to 201 contain a 'name' key corresponding to the deployment name. The other fields of 202 the returned dictionary and their types may vary across targets. 203 """ 204 205 @abc.abstractmethod 206 def predict(self, deployment_name=None, inputs=None, endpoint=None): 207 """Compute predictions on inputs using the specified deployment or model endpoint. 208 209 Note that the input/output types of this method match those of `mlflow pyfunc predict`. 210 211 Args: 212 deployment_name: Name of deployment to predict against. 213 inputs: Input data (or arguments) to pass to the deployment or model endpoint for 214 inference. 215 endpoint: Endpoint to predict against. May not be supported by all targets. 216 217 Returns: 218 A :py:class:`mlflow.deployments.PredictionsResponse` instance representing the 219 predictions and associated Model Server response metadata. 220 221 """ 222 223 def predict_stream(self, deployment_name=None, inputs=None, endpoint=None): 224 """ 225 Submit a query to a configured provider endpoint, and get streaming response 226 227 Args: 228 deployment_name: Name of deployment to predict against. 229 inputs: The inputs to the query, as a dictionary. 230 endpoint: The name of the endpoint to query. 231 232 Returns: 233 An iterator of dictionary containing the response from the endpoint. 234 """ 235 raise NotImplementedError() 236 237 def explain(self, deployment_name=None, df=None, endpoint=None): 238 """ 239 Generate explanations of model predictions on the specified input pandas Dataframe 240 ``df`` for the deployed model. Explanation output formats vary by deployment target, 241 and can include details like feature importance for understanding/debugging predictions. 242 243 Args: 244 deployment_name: Name of deployment to predict against 245 df: Pandas DataFrame to use for explaining feature importance in model prediction 246 endpoint: Endpoint to predict against. May not be supported by all targets 247 248 Returns: 249 A JSON-able object (pandas dataframe, numpy array, dictionary), or 250 an exception if the implementation is not available in deployment target's class 251 """ 252 raise MlflowException( 253 "Computing model explanations is not yet supported for this deployment target" 254 ) 255 256 def create_endpoint(self, name, config=None): 257 """ 258 Create an endpoint with the specified target. By default, this method should block until 259 creation completes (i.e. until it's possible to create a deployment within the endpoint). 260 In the case of conflicts (e.g. if it's not possible to create the specified endpoint 261 due to conflict with an existing endpoint), raises a 262 :py:class:`mlflow.exceptions.MlflowException` or an `HTTPError` for remote 263 deployments. See target-specific plugin documentation 264 for additional detail on support for asynchronous creation and other configuration. 265 266 Args: 267 name: Unique name to use for endpoint. If another endpoint exists with the same 268 name, raises a :py:class:`mlflow.exceptions.MlflowException`. 269 config: (optional) Dict containing target-specific configuration for the 270 endpoint. 271 272 Returns: 273 Dict corresponding to created endpoint, which must contain the 'name' key. 274 275 """ 276 raise MlflowException( 277 "Method is unimplemented in base client. Implementation should be " 278 "provided by specific target plugins." 279 ) 280 281 def update_endpoint(self, endpoint, config=None): 282 """ 283 Update the endpoint with the specified name. You can update any target-specific attributes 284 of the endpoint (via `config`). By default, this method should block until the update 285 completes (i.e. until it's possible to create a deployment within the endpoint). See 286 target-specific plugin documentation for additional detail on support for asynchronous 287 update and other configuration. 288 289 Args: 290 endpoint: Unique name of endpoint to update 291 config: (optional) dict containing target-specific configuration for the 292 endpoint 293 294 Returns: 295 None 296 297 """ 298 raise MlflowException( 299 "Method is unimplemented in base client. Implementation should be " 300 "provided by specific target plugins." 301 ) 302 303 def delete_endpoint(self, endpoint): 304 """ 305 Delete the endpoint from the specified target. Deletion should be idempotent (i.e. deletion 306 should not fail if retried on a non-existent deployment). 307 308 Args: 309 endpoint: Name of endpoint to delete 310 311 Returns: 312 None 313 """ 314 raise MlflowException( 315 "Method is unimplemented in base client. Implementation should be " 316 "provided by specific target plugins." 317 ) 318 319 def list_endpoints(self): 320 """ 321 List endpoints in the specified target. This method is expected to return an 322 unpaginated list of all endpoints (an alternative would be to return a dict with 323 an 'endpoints' field containing the actual endpoints, with plugins able to specify 324 other fields, e.g. a next_page_token field, in the returned dictionary for pagination, 325 and to accept a `pagination_args` argument to this method for passing 326 pagination-related args). 327 328 Returns: 329 A list of dicts corresponding to endpoints. Each dict is guaranteed to 330 contain a 'name' key containing the endpoint name. The other fields of 331 the returned dictionary and their types may vary across targets. 332 """ 333 raise MlflowException( 334 "Method is unimplemented in base client. Implementation should be " 335 "provided by specific target plugins." 336 ) 337 338 def get_endpoint(self, endpoint): 339 """ 340 Returns a dictionary describing the specified endpoint, throwing a 341 py:class:`mlflow.exception.MlflowException` or an `HTTPError` for remote 342 deployments if no endpoint exists with the provided 343 name. 344 The dict is guaranteed to contain an 'name' key containing the endpoint name. 345 The other fields of the returned dictionary and their types may vary across targets. 346 347 Args: 348 endpoint: Name of endpoint to fetch 349 350 Returns: 351 A dict corresponding to the retrieved endpoint. The dict is guaranteed to 352 contain a 'name' key corresponding to the endpoint name. The other fields of 353 the returned dictionary and their types may vary across targets. 354 """ 355 raise MlflowException( 356 "Method is unimplemented in base client. Implementation should be " 357 "provided by specific target plugins." 358 )