部署自定义模型

本文介绍使用 Databricks 模型服务部署自定义模型的支持。 它还提供了有关支持的模型记录选项、计算类型、如何打包用于提供服务的模型依赖项以及创建和缩放终结点的详细信息。

什么是自定义模型?

Model Serving 可以将任何 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外部模型来了解支持的模型和计算产品/服务。

重要

如果依赖于 Anaconda,请查看服务条款通知,了解详细信息。

记录 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())
    

签名和输入示例

建议在 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)

计算类型

注意

GPU Model Serving 为公共预览版。

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

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

部署容器和依赖项

在部署期间,会生成生产级容器并将其部署为终结点。 此容器包括在 MLflow 模型中自动捕获或指定的库。

模型服务容器不包含预安装的依赖项,如果模型中未包含所有必需的依赖项,则可能会导致依赖项错误。 遇到模型部署问题时,Databricks 建议在本地测试模型。

包和代码依赖项

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

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

对于自定义 pyfunc 模型,可以显式添加依赖项。

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

  • 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"],)

依赖项验证

在部署自定义 MLflow 模型之前,最好验证是否能够为模型提供服务。 MLflow 提供了一个 API,可用于验证既模拟部署环境又允许测试修改后的依赖项的模型项目。

有两个预部署验证 API:MLflow Python APIMLflow CLI

可以使用其中任何一个 API 指定以下内容。

  • 部署到模型服务的模型的 model_uri
  • 以下项之一:
    • 对模型进行 mlflow.pyfunc.PyFuncModel.predict() 调用的预期格式的 input_data
    • 定义包含将加载并用于调用 predict 的输入数据的文件的 input_path
  • csvjson 格式的 content_type
  • 用于将预测写入文件的可选 output_path。 如果省略此参数,则预测将输出到 stdout
  • 环境管理器 env_manager,用于生成将提供服务的环境:
    • 默认为 virtualenv。 建议用于服务验证。
    • local 可用,但在进行服务验证时可能会出错。 通常用于快速调试。
  • 是否使用 install_mlflow 通过虚拟环境安装环境中当前版本的 MLflow。 此设置默认设置为 False
  • 是否更新和测试不同版本的包依赖项,以便进行故障排除或调试。 可以使用替代参数 pip_requirements_override 将其指定为一个字符串依赖项替代或添加项列表。

例如:

import mlflow

run_id = "..."
model_uri = f"runs:/{run_id}/model"

mlflow.models.predict(
  model_uri=model_uri,
  input_data={"col1": 34.2, "col2": 11.2, "col3": "green"},
  content_type="json",
  env_manager="virtualenv",
  install_mlflow=False,
  pip_requirements_override=["pillow==10.3.0", "scipy==1.13.0"],
)

依赖项更新

如果已记录模型所指定的依赖项存在任何问题,可以使用 MLflow CLI 或 MLflow Python API 中的 mlflow.models.model.update_model_requirements() 来更新要求,而无需记录另一个模型。

以下示例演示了如何就地更新已记录模型的 pip_requirements.txt

可以使用指定的包版本更新现有定义,或者向 pip_requirements.txt 文件添加不存在的要求。 此文件位于指定 model_uri 位置的 MLflow 模型项目中。

from mlflow.models.model import update_model_requirements

update_model_requirements(
  model_uri=model_uri,
  operation="add",
  requirement_list=["pillow==10.2.0", "scipy==1.12.0"],
)

期望和限制

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

终结点创建和更新预期

注意

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

部署新注册的模型版本涉及打包模型及其模型环境,以及预配模型终结点本身。 此过程可能需要大约 10 分钟。

通过在新模型部署准备就绪之前保持现有终结点配置正常运行,Azure Databricks 可实现终结点的“无停机”更新。 这样做可降低中断使用中的终结点的风险。

如果模型计算耗时超过 120 秒,则请求将超时。如果认为模型计算的耗时会超过 120 秒,请联系 Azure Databricks 客户团队。

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

终结点缩放预期

注意

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

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

  • 预配的并发:系统可以处理的最大并行请求数。 使用以下公式估算所需的并发:预配的并发 = 每秒查询数量 (QPS) * 模型执行时间(秒)。
  • 缩放行为:终结点将会在流量增加时几乎立即纵向扩展,并每五分钟纵向缩减一次,以匹配流量的减少。
  • 缩减为零:终结点可在处于非活动状态 30 分钟后缩减为零。 缩减为零后的第一个请求会经历“冷启动”,从而导致更高的延迟。 对于延迟敏感型应用程序,请考虑可有效管理此功能的策略。

GPU 工作负荷限制

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

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

Anaconda 许可更新

以下通知适用于依赖 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 通道。 若要手动确认模型是否具有此依赖项,可以检查与记录的模型一起打包的 conda.yaml 文件中的 channel 值。 例如,具有 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 将模型重新注册到模型注册表。 为此,可以在 log_model()conda_env 参数中指定该通道。

有关 log_model() API 的详细信息,请参阅所用模型风格的 MLflow 文档,例如用于 scikit-learn 的 log_model

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

其他资源