自定义模型概述

本文介绍使用马赛克 AI 模型服务自定义模型的支持。 它提供有关支持的模型日志记录选项和计算类型、如何打包模型依赖项以提供服务的详细信息,以及终结点创建和缩放的预期。

什么是自定义模型?

模型服务可以使用 CPU 或 GPU 计算资源将任何 Python 模型或 自定义代码 部署为生产级 API。 Databricks 将此类模型称为“自定义模型”。 这些 ML 模型可以使用 scikit-learn、XGBoost、PyTorch 和 HuggingFace 转换器等标准 ML 库进行训练,并且可以包含任何 Python 代码。

若要部署自定义模型

  1. 使用原生 MLflow 内置风格pyfunc 记录 MLflow 格式的模型或代码。
  2. 记录模型后,在 Unity Catalog(建议)或工作区注册表中注册该模型。
  3. 在这里,你可以创建一个模型服务终结点来部署和查询模型。
    1. 请参阅 创建自定义模型服务终结点
    2. 请参阅 自定义模型的查询服务终结点

有关如何在 Databricks 上提供自定义模型的完整教程,请参阅 模型服务教程

Databricks 还支持为生成式 AI 应用程序提供基础模型,请参阅 基础模型 API外部模型 ,了解支持的模型和计算产品/服务。

记录 ML 模型

有不同的方法来记录 ML 模型,以便提供模型服务。 以下列表汇总了受支持的方法和示例。

  • 自动记录:此方法在使用用于 ML 的 Databricks Runtime 时自动启用。

    import mlflow
    from sklearn.ensemble import RandomForestRegressor
    from sklearn.datasets import load_iris
    
    iris = load_iris()
    model = RandomForestRegressor()
    model.fit(iris.data, iris.target)
    
  • 使用 MLflow 的内置类型进行日志记录。 如果要手动记录模型以实现更详细的控制,可以使用此方法。

    import mlflow
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.datasets import load_iris
    
    iris = load_iris()
    model = RandomForestClassifier()
    model.fit(iris.data, iris.target)
    
    with mlflow.start_run():
        mlflow.sklearn.log_model(model, "random_forest_classifier")
    
  • 使用 pyfunc 进行自定义记录。 可以使用此方法来部署任意 Python 代码模型,也可以随模型一起部署其他代码。

      import mlflow
      import mlflow.pyfunc
    
      class Model(mlflow.pyfunc.PythonModel):
          def predict(self, context, model_input):
              return model_input * 2
    
      with mlflow.start_run():
          mlflow.pyfunc.log_model("custom_model", python_model=Model())
    
  • 从 HuggingFace 下载。 可以直接从 Hugging Face 下载模型,并记录该模型以供使用。 有关示例,请参阅 Notebook 示例

签名和输入示例

建议在 MLflow 中添加签名和输入示例。 将模型记录到 Unity Catalog 时需要签名。

下面是一个签名示例:

from mlflow.models.signature import infer_signature

signature = infer_signature(training_data, model.predict(training_data))
mlflow.sklearn.log_model(model, "model", signature=signature)

下面是一个输入示例:


input_example = {"feature1": 0.5, "feature2": 3}
mlflow.sklearn.log_model(model, "model", input_example=input_example)

计算类型

Mosaic AI 模型服务提供了各种用于部署模型的 CPU 和 GPU 选项。 使用 GPU 进行部署时,必须确保设置了代码,以便使用框架提供的方法在 GPU 上运行预测。 对于使用 PyTorch 或 Transformers 风格记录的模型,MLflow 会自动执行此操作。

工作负荷类型 GPU 实例 内存
CPU 每个并发 4GB
GPU_SMALL 1xT4 16GB
GPU_LARGE 1xA100 80GB
GPU_LARGE_2 2xA100 160GB
GPU_LARGE_4 4xA100 320GB

部署容器和依赖项

在部署期间,会生成生产级容器并将其部署为终结点。 此容器包括在 MLflow 模型中自动捕获或指定的库。 基本映像可能包含一些系统级依赖项,但必须在 MLflow 模型中显式指定应用程序级依赖项。

如果模型中不包含所有必需的依赖项,则可能会在部署过程中遇到依赖项错误。 遇到模型部署问题时,Databricks 建议在本地测试模型。

包和代码依赖项

自定义库或专用库均可添加到部署中。 请参阅 将自定义 Python 库与模型服务配合使用

对于 MLflow 原生风格模型,系统会自动捕获必要的包依赖项。

对于自定义 pyfunc 模型,可以显式添加依赖项。 有关日志记录要求和最佳做法的详细信息,请参阅 MLflow 模型文档MLflow Python API 参考

你可以使用以下方法添加包依赖项:

  • pip_requirements 参数:

    mlflow.sklearn.log_model(model, "sklearn-model", pip_requirements = ["scikit-learn", "numpy"])
    
  • conda_env 参数:

    
    conda_env = {
        'channels': ['defaults'],
        'dependencies': [
            'python=3.7.0',
            'scikit-learn=0.21.3'
        ],
        'name': 'mlflow-env'
    }
    
    mlflow.sklearn.log_model(model, "sklearn-model", conda_env = conda_env)
    
  • 若要包含自动捕获内容之外的其他要求,请使用 extra_pip_requirements

    mlflow.sklearn.log_model(model, "sklearn-model", extra_pip_requirements = ["sklearn_req"])
    

如果有代码依赖项,可以使用 code_path 指定这些依赖项。

  mlflow.sklearn.log_model(model, "sklearn-model", code_path=["path/to/helper_functions.py"],)

有关在部署前验证和更新依赖项的信息,请参阅 模型部署验证检查之前

期望和限制

注意

本节中的信息不适用于为基础模型或外部模型提供服务的终结点。

以下部分介绍使用 Model Serving 就自定义模型提供服务的已知预期和限制。

终结点创建和更新预期

  • 部署时间:部署新注册的模型版本涉及打包模型及其模型环境以及预配模型终结点本身。 此过程可能需要大约 10 分钟,但可能需要更长的时间,具体取决于模型复杂性、大小和依赖项。
  • 零停机更新:Azure Databricks 通过将现有终结点配置保持为就绪状态,对终结点执行零停机更新。 这样做可降低中断使用中的终结点的风险。 在此更新过程中,需要为旧终结点配置和新终结点配置付费,直到转换完成。
  • 请求超时:如果模型计算花费的时间超过 297 秒,则请求将超时。

重要

Databricks 偶尔对现有模型服务终结点执行零停机系统更新和维护。 在维护期间,Databricks 会重新加载模型。 如果模型无法重新加载,终结点更新将标记为失败,并且现有终结点配置将继续为请求提供服务。 确保自定义模型是可靠的且随时能够重新加载。

终结点缩放预期

服务终结点会自动根据流量和预配的并发单位的容量进行缩放。

  • 预配的并发:系统可以处理的最大并行请求数。 使用以下公式估算所需的并发:预配的并发 = 每秒查询数量 (QPS) * 模型执行时间(秒)。 若要验证并发配置,请参阅 用于服务端点的负载测试
  • 缩放行为:终结点将会在流量增加时几乎立即纵向扩展,并每五分钟纵向缩减一次,以匹配流量的减少。
  • 缩放到零: 缩放到零是终结点的可选功能,允许在 30 分钟处于非活动状态后将其缩减为零。 缩放到零后的第一个请求会经历“冷启动”,从而导致更高的延迟。 从零纵向扩展通常需要 10-20 秒,但有时可能需要几分钟时间。 从零延迟进行缩放时,没有 SLA。
  • 路由优化: 对于高 QPS 和低延迟用例, 路由优化 是提高性能的最佳建议选项。

警告

缩放到零不应用于需要一致运行时间或保证响应时间的生产工作负荷。 对于需要持续可用性的延迟敏感应用程序或终结点,请禁用“缩放至零”功能。

GPU 工作负荷限制

以下是为具有 GPU 工作负载的终结点提供服务的限制:

  • GPU 服务的容器映像创建时间比 CPU 服务的映像创建时间长,这是由于模型大小以及在 GPU 上服务的模型安装要求的增加。
  • 部署非常大的模型时,如果容器生成和模型部署超过 60 分钟,则部署过程可能会超时。
  • GPU 服务的自动缩放比 CPU 服务花费的时间长。
  • 缩放到零时,无法保证 GPU 容量。 GPU 终结点在缩放到零后,第一个请求可能需要额外的高延迟。

Anaconda 旧模型许可信息通知

注意

本部分仅适用于使用 MLflow v1.17 或更早版本(Databricks Runtime 8.3 ML 或更早版本)记录的模型。 如果使用的是较新版本,可以跳过本部分。

以下通知适用于使用旧模型依赖 Anaconda 的客户。

重要

Anaconda Inc. 更新了 anaconda.org 渠道 的服务条款 。 根据新的服务条款,如果依赖 Anaconda 的打包和分发,则可能需要商业许可证。 有关详细信息,请参阅 Anaconda Commercial Edition 常见问题解答 。 对任何 Anaconda 通道的使用都受其服务条款的约束。

v1.18 (Databricks Runtime 8.3 ML 或更早版本)之前记录的 MLflow 模型默认以 conda defaults 通道 (https://repo.anaconda.com/pkgs/) 作为依赖项进行记录。 由于此许可证更改,Databricks 已停止对使用 MLflow v1.18 及更高版本记录的模型使用 defaults 通道。 记录的默认通道现在为 conda-forge,它指向社区管理的 https://conda-forge.org/

如果在 MLflow v1.18 之前记录了一个模型,但没有从模型的 conda 环境中排除 defaults 通道,则该模型可能依赖于你可能没有预期到的 defaults 通道。 若要手动确认模型是否具有此依赖项,可以检查与记录的模型一起打包的 channel 文件中的 conda.yaml 值。 例如,具有 conda.yaml 通道依赖项的模型 defaults 可能如下所示:

channels:
- defaults
dependencies:
- python=3.8.8
- pip
- pip:
    - mlflow
    - scikit-learn==0.23.2
    - cloudpickle==1.6.0
      name: mlflow-env

由于 Databricks 无法确定是否允许你根据你与 Anaconda 的关系使用 Anaconda 存储库来与模型交互,因此 Databricks 不会强制要求其客户进行任何更改。 如果允许你根据 Anaconda 的条款通过 Databricks 使用 Anaconda.com 存储库,则你不需要采取任何措施。

若要更改模型环境中使用的通道,可以使用新的 conda.yaml 将模型重新注册到模型注册表。 为此,可以在 conda_envlog_model() 参数中指定该通道。

有关 log_model() API 的详细信息,请参阅你正在使用的模型类型的 MLflow 文档,例如,用于 scikit-learn 的 log_model

有关 conda.yaml 文件的详细信息,请参阅 MLflow 文档

其他资源