/ mlflow / deployments / base.py
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          )