跳到主要内容

将 MLflow 模型部署为本地推理服务器

MLflow 允许您使用单个命令在本地部署模型。这种方法非常适合轻量级应用程序,或者在将模型移至暂存或生产环境之前在本地测试模型。

如果您是 MLflow 模型部署新手,请先阅读MLflow 部署指南,以了解 MLflow 模型和部署的基本概念。

部署推理服务器

部署前,您必须拥有一个 MLflow 模型。如果没有,请按照MLflow 跟踪快速入门创建示例 scikit-learn 模型。请记住记下模型 URI,例如 models:/<model_id>(如果您在MLflow 模型注册表中注册了模型,则为 models:/<model_name>/<model_version>)。

准备好模型后,本地服务器部署将非常简单。使用 mlflow models serve 命令进行一步部署。此命令将启动一个本地服务器,该服务器侦听指定端口并为您提供模型。有关可用选项,请参阅 CLI 参考

mlflow models serve -m runs:/<run_id>/model -p 5000

然后,您可以发送一个测试请求到服务器,如下所示

curl http://127.0.0.1:5000/invocations -H "Content-Type:application/json"  --data '{"inputs": [[1, 2], [3, 4], [5, 6]]}'

有几个命令行选项可用于自定义服务器的行为。例如,--env-manager 选项允许您选择一个特定的环境管理器,如 Anaconda,来创建虚拟环境。mlflow models 模块还提供其他有用的命令,例如构建 Docker 镜像或生成 Dockerfile。有关详细信息,请参阅 MLflow CLI 参考

推理服务器规范

端点

推理服务器提供 4 个端点

  • /invocations:一个推理端点,它接受带有输入数据的 POST 请求并返回预测。

  • /ping:用于健康检查。

  • /health:与 /ping 相同

  • /version:返回 MLflow 版本。

接受的输入格式

/invocations 端点接受 CSV 或 JSON 输入。输入格式必须在 Content-Type 标头中指定为 application/jsonapplication/csv

CSV 输入

CSV 输入必须是有效的 pandas.DataFrame CSV 表示形式。例如

curl http://127.0.0.1:5000/invocations -H 'Content-Type: application/csv' --data '1,2,3,4'

JSON 输入

您可以传递一个与所需模型负载对应的扁平字典,或者用一个字典包装负载,其中一个字典键指定您的负载格式。

包装负载字典

如果上述格式不支持您的模型格式,或者您想避免将输入数据转换为所需的负载格式,则可以使用下面的字典负载结构。

字段描述示例
dataframe_splitPandas DataFrames,以 split 方向表示。
{"dataframe_split": pandas_df.to_dict(orient="split")}
dataframe_recordsPandas DataFrame,以 records 方向表示。我们不建议使用此格式,因为它不能保证保留列顺序。
{"dataframe_records": pandas_df.to_dict(orient="records")}
instancesTensor 输入格式如TF Serving 的 API 文档中所述,其中提供的输入将转换为 Numpy 数组。
{"instances": [1.0, 2.0, 5.0]}
inputsinstances 相同,但键不同。
{"inputs": [["Cheese"], ["and", "Crackers"]]}
示例
# Prerequisite: serve a custom pyfunc OpenAI model (not mlflow.openai) on localhost:5678
# that defines inputs in the below format and params of `temperature` and `max_tokens`

import json
import requests

payload = json.dumps(
{
"inputs": {"messages": [{"role": "user", "content": "Tell a joke!"}]},
"params": {
"temperature": 0.5,
"max_tokens": 20,
},
}
)
response = requests.post(
url=f"https://:5678/invocations",
data=payload,
headers={"Content-Type": "application/json"},
)
print(response.json())

JSON 输入还可以包含一个可选的 params 字段,用于传递附加参数。有效的参数类型为 Union[DataType, List[DataType], None],其中 DataType 是MLflow 数据类型。要传递参数,必须定义具有 params 的有效模型签名

curl http://127.0.0.1:5000/invocations -H 'Content-Type: application/json' -d '{
"inputs": {"question": ["What color is it?"],
"context": ["Some people said it was green but I know that it is pink."]},
"params": {"max_answer_len": 10}
}'
注意

由于 JSON 会丢弃类型信息,MLflow 会将 JSON 输入转换为模型模式中指定的输入类型(如果可用)。如果您的模型对输入类型敏感,建议为模型提供模式,以确保在推理时不会出现类型不匹配错误。特别是,深度学习模型通常对输入类型要求严格,需要模型模式才能正确评分。有关复杂数据类型,请参阅下面的编码复杂数据

原始负载字典

如果您的负载格式是您 mlflow 提供的模型可以接受的格式,并且是下方支持的模型之一,则可以传递原始负载字典。

支持的请求格式描述示例
OpenAI ChatOpenAI 聊天请求负载
{
"messages": [{"role": "user", "content": "Tell a joke!"}], # noqa
"temperature": 0.0,
}

† 请注意,在使用 OpenAI API 时,不应包含 model 参数,因为其配置由 MLflow 模型实例设置。所有其他参数都可以自由使用,前提是它们在记录的模型签名的 params 参数内定义。

示例
# Prerequisite: serve a Pyfunc model accepts OpenAI-compatible chat requests on localhost:5678 that defines
# `temperature` and `max_tokens` as parameters within the logged model signature

import json
import requests

payload = json.dumps(
{
"messages": [{"role": "user", "content": "Tell a joke!"}],
"temperature": 0.5,
"max_tokens": 20,
}
)
requests.post(
url=f"https://:5678/invocations",
data=payload,
headers={"Content-Type": "application/json"},
)
print(requests.json())

编码复杂数据

日期或二进制等复杂数据类型没有原生的 JSON 表示。如果包含模型签名,MLflow 可以自动从 JSON 解码支持的数据类型。支持以下数据类型转换:

  • binary:数据预计为 base64 编码,MLflow 将自动 base64 解码。

  • datetime:数据预计按照 ISO 8601 规范编码为字符串。MLflow 将将其解析为给定平台上的相应日期时间表示。

示例请求

# record-oriented DataFrame input with binary column "b"
curl http://127.0.0.1:5000/invocations -H 'Content-Type: application/json' -d '[
{"a": 0, "b": "dGVzdCBiaW5hcnkgZGF0YSAw"},
{"a": 1, "b": "dGVzdCBiaW5hcnkgZGF0YSAx"},
{"a": 2, "b": "dGVzdCBiaW5hcnkgZGF0YSAy"}
]'

# record-oriented DataFrame input with datetime column "b"
curl http://127.0.0.1:5000/invocations -H 'Content-Type: application/json' -d '[
{"a": 0, "b": "2020-01-01T00:00:00Z"},
{"a": 1, "b": "2020-02-01T12:34:56Z"},
{"a": 2, "b": "2021-03-01T00:00:00Z"}
]'

服务框架

默认情况下,MLflow 使用 FastAPI,一个现代的 Python ASGI Web 应用程序框架,来服务推理端点。FastAPI 异步处理请求,并被认为是速度最快的 Python 框架之一。这个生产就绪的框架非常适合大多数用例。此外,MLflow 还集成了 MLServer 作为替代服务引擎。MLServer 通过利用异步请求/响应范例和工作负载卸载来实现更高的性能和可扩展性。MLServer 还用作 Kubernetes 原生框架(如 Seldon CoreKServe(以前称为 KFServing))中的核心 Python 推理服务器,因此可以开箱即用地提供高级功能,如金丝雀部署和自动伸缩。

用例标准用例,包括本地测试。高规模生产环境。
设置FastAPI 默认随 MLflow 一起安装。需要单独安装。
性能FastAPI 原生支持异步请求处理,使其非常适合 I/O 密集型任务,包括 ML 工作负载。有关 FastAPI 与其他 Python 框架的基准测试和比较,请参阅 FastAPI 基准测试专为高性能 ML 工作负载而设计,通常提供更好的吞吐量和效率。MLServer 支持异步请求/响应范例,通过将 ML 推理工作负载卸载到单独的工作进程池,以便服务器在处理推理时可以继续接受新请求。有关它们如何实现这一点的更多详细信息,请参阅 MLServer 并行推理。此外,MLServer 支持自适应批处理,它可以透明地将请求组合在一起以提高吞吐量和效率。
可扩展性虽然 FastAPI 通常在分布式环境中运行良好,但 MLflow 仅使用 uvicorn 运行它,并且无法开箱即用地支持水平伸缩。除了上述并行推理支持外,MLServer 还用作 Kubernetes 原生框架(如 Seldon CoreKServe(以前称为 KFServing))中的核心推理服务器。通过使用 MLServer 将 MLflow 模型部署到 Kubernetes,您可以利用这些框架的高级功能(如自动伸缩)来实现高可扩展性。

MLServer 通过 /invocations 端点公开相同的评分 API。要使用 MLServer 进行部署,请先使用 pip install mlflow[extras] 安装其他依赖项,然后使用 --enable-mlserver 选项执行部署命令。例如,

mlflow models serve -m runs:/<run_id>/model -p 5000 --enable-mlserver

要详细了解 MLflow 和 MLServer 之间的集成,请查看 MLServer 文档中的端到端示例。您还可以通过将模型部署到 Kubernetes 来查找使用 MLServer 将 MLflow 模型部署到 Kubernetes 集群的指南。

运行批量推理

与运行在线推理端点不同,您可以使用 mlflow models predict 命令在本地文件上执行单个批量推理作业。以下命令在 input.csv 上运行模型预测并将结果输出到 output.csv

mlflow models predict -m models:/<model_id> -i input.csv -o output.csv

故障排除