mlflow.pyfunc
python_function
模型风格作为 MLflow Python 模型的默认接口。任何 MLflow Python 模型都应能够作为 python_function
模型加载。
此外,mlflow.pyfunc
模块定义了一个通用的 文件系统格式 用于 Python 模型,并提供了保存到此格式和从中加载的实用程序。该格式是自包含的,因为它包含了加载和使用模型所需的所有必要信息。依赖项要么直接与模型一起存储,要么通过 Conda 环境引用。
mlflow.pyfunc
模块还定义了用于使用可能未原生包含在 MLflow 中的框架和推理逻辑创建自定义 pyfunc
模型的实用程序。参见 从代码生成自定义模型。
推理 API
Python 函数模型作为 PyFuncModel
的实例加载,这是围绕模型实现和模型元数据(MLmodel 文件)的 MLflow 包装器。你可以通过调用 predict()
方法来评分模型,该方法具有以下签名:
predict(
model_input: [pandas.DataFrame, numpy.ndarray, scipy.sparse.(csc_matrix | csr_matrix),
List[Any], Dict[str, Any], pyspark.sql.DataFrame]
) -> [numpy.ndarray | pandas.(Series | DataFrame) | List | Dict | pyspark.sql.DataFrame]
所有 PyFunc 模型都将支持 pandas.DataFrame 作为输入,而 PyFunc 深度学习模型还将支持以 Dict[str, numpy.ndarray](命名张量)和 `numpy.ndarrays`(未命名张量)形式的张量输入。
以下是一些支持的推理类型的示例,假设我们已经加载了正确的 model
对象。
输入类型 |
示例 |
---|---|
|
import pandas as pd
x_new = pd.DataFrame(dict(x1=[1, 2, 3], x2=[4, 5, 6]))
model.predict(x_new)
|
|
import numpy as np
x_new = np.array([[1, 4][2, 5], [3, 6]])
model.predict(x_new)
|
|
import scipy
x_new = scipy.sparse.csc_matrix([[1, 2, 3], [4, 5, 6]])
model.predict(x_new)
x_new = scipy.sparse.csr_matrix([[1, 2, 3], [4, 5, 6]])
model.predict(x_new)
|
python |
x_new = [[1, 4], [2, 5], [3, 6]]
model.predict(x_new)
|
python |
x_new = dict(x1=[1, 2, 3], x2=[4, 5, 6])
model.predict(x_new)
|
|
from pyspark.sql import SparkSession
spark = SparkSession.builder.getOrCreate()
data = [(1, 4), (2, 5), (3, 6)] # List of tuples
x_new = spark.createDataFrame(data, ["x1", "x2"]) # Specify column name
model.predict(x_new)
|
文件系统格式
Pyfunc 格式定义为一个包含所有必需数据、代码和配置的目录结构:
./dst-path/
./MLmodel: configuration
<code>: code packaged with the model (specified in the MLmodel file)
<data>: data packaged with the model (specified in the MLmodel file)
<env>: Conda environment definition (specified in the MLmodel file)
目录结构可能包含可以通过 MLmodel
配置引用的附加内容。
MLModel 配置
一个 Python 模型在其根目录中包含一个 python_function 格式的 MLmodel
文件,并带有以下参数:
- loader_module [必需]:
可以加载模型的Python模块。预期为模块标识符,例如
mlflow.sklearn
,它将使用importlib.import_module
导入。导入的模块必须包含具有以下签名的函数:_load_pyfunc(path: string) -> <pyfunc model implementation>
路径参数由
data
参数指定,可以指向文件或目录。模型实现应为一个对象,该对象具有以下签名的predict
方法:predict( model_input: [pandas.DataFrame, numpy.ndarray, scipy.sparse.(csc_matrix | csr_matrix), List[Any], Dict[str, Any]], pyspark.sql.DataFrame ) -> [numpy.ndarray | pandas.(Series | DataFrame) | List | Dict | pyspark.sql.DataFrame]
- 代码 [可选]:
包含与此模型一起打包的代码的目录的相对路径。在导入模型加载器之前,此目录中的所有文件和目录都会被添加到 Python 路径中。
- 数据 [可选]:
包含模型数据的文件或目录的相对路径。该路径传递给模型加载器。
- env [可选]:
指向导出的Conda环境的相对路径。如果存在,此环境应在运行模型之前被激活。
可选地,任何解释
pyfunc
格式序列化模型所需的额外参数。
示例
tree example/sklearn_iris/mlruns/run1/outputs/linear-lr
├── MLmodel
├── code
│ ├── sklearn_iris.py
│
├── data
│ └── model.pkl
└── mlflow_env.yml
cat example/sklearn_iris/mlruns/run1/outputs/linear-lr/MLmodel
python_function:
code: code
data: data/model.pkl
loader_module: mlflow.sklearn
env: mlflow_env.yml
main: sklearn_iris
从代码生成自定义模型
小技巧
MLflow 2.12.2 引入了“代码生成模型”功能,这大大简化了通过脚本序列化来序列化和部署自定义模型的过程。强烈建议将自定义模型实现迁移到这个新范式,以避免使用 cloudpickle 进行序列化的限制和复杂性。您可以在 Models From Code Guide 中了解更多关于代码生成模型的信息。
下面的部分展示了使用传统序列化器处理自定义Pyfunc模型的过程。来自代码的模型将为您的模型日志记录提供一个简单得多的体验。
创建自定义 Pyfunc 模型
MLflow 的持久化模块为在多种机器学习框架(如 scikit-learn、Keras、Pytorch 等)中创建带有 pyfunc
风格的模型提供了便利函数;然而,它们并不能覆盖所有使用场景。例如,您可能希望使用 MLflow 不原生支持的框架创建一个带有 pyfunc
风格的 MLflow 模型。或者,您可能希望构建一个在评估查询时执行自定义逻辑的 MLflow 模型,例如预处理和后处理例程。因此,mlflow.pyfunc
提供了从任意代码和模型数据创建 pyfunc
模型的工具。
save_model()
和 log_model()
方法旨在支持多种工作流程,用于创建包含自定义推理逻辑和逻辑可能需要的工件的自定义 pyfunc
模型。
一个 artifact 是一个文件或目录,例如序列化的模型或CSV文件。例如,一个序列化的TensorFlow图是一个artifact。一个MLflow模型目录也是一个artifact。
工作流程
save_model()
和 log_model()
支持以下工作流程:
以编程方式定义一个新的 MLflow 模型,包括其属性和工件。
给定一组工件 URI,
save_model()
和log_model()
可以自动从其 URI 下载工件并创建一个 MLflow 模型目录。在这种情况下,你必须定义一个继承自
PythonModel
的 Python 类,定义predict()
方法,并可选地定义load_context()
方法。这个类的实例通过python_model
参数指定;它会自动作为 Python 类进行序列化和反序列化,包括其所有属性。将现有数据解释为 MLflow 模型。
如果你已经有一个包含模型数据的目录,
save_model()
和log_model()
可以将数据导入为 MLflow 模型。data_path
参数指定了包含模型数据的本地文件系统路径。在这种情况下,您必须提供一个Python模块,称为 加载器模块 。加载器模块定义了一个
_load_pyfunc()
方法,该方法执行以下任务:从指定的
data_path
加载数据。例如,这个过程可能包括反序列化pickled的Python对象或模型,或者解析CSV文件。构建并返回一个与 pyfunc 兼容的模型包装器。与第一个用例一样,此包装器必须定义一个用于评估查询的
predict()
方法。predict()
必须遵守 推理 API。
loader_module
参数指定了你的加载器模块的名称。有关示例加载器模块实现,请参阅 mlflow.sklearn 中的加载器模块实现。
哪种工作流程适合我的使用场景?
我们认为第一个工作流程更加用户友好,并且基于以下原因通常推荐它:
它自动解析并收集指定的模型工件。
它自动序列化和反序列化
python_model
实例及其所有属性,减少了加载模型所需的用户逻辑量。你可以在
__main__
作用域中使用定义的逻辑来创建模型。这允许在交互式环境中构建自定义模型,例如笔记本和 Python REPL。
您可能出于以下原因更喜欢第二种较低级别的流程:
推理逻辑总是作为代码持久化,而不是作为Python对象。这使得逻辑更容易在之后进行检查和修改。
如果你已经将所有模型数据收集到一个位置,第二个工作流程允许它直接以MLflow格式保存,而无需枚举构成的工件。
基于函数的模型 vs 基于类的模型
在创建自定义 PyFunc 模型时,您可以在两种不同的接口之间进行选择:基于函数的模型和基于类的模型。简而言之,基于函数的模型只是一个不接受额外参数的 Python 函数。另一方面,基于类的模型是 PythonModel
的子类,支持多个必需和可选的方法。如果您的用例简单且适合单个预测函数,建议使用基于函数的方法。如果您需要更多功能,例如自定义序列化、自定义数据处理或覆盖其他方法,则应使用基于类的实现。
在查看代码示例之前,重要的是要注意这两种方法都是通过 cloudpickle 进行序列化的。cloudpickle 可以序列化 Python 函数、lambda 函数以及在其他函数内部本地定义的类和函数。这使得 cloudpickle 在需要将代码对象通过网络发送到远程工作节点执行的并行和分布式计算中特别有用,这也是 MLflow 常见的部署模式。
尽管如此,cloudpickle 有一些限制。
环境依赖:cloudpickle 不会捕获完整的执行环境,因此在 MLflow 中我们必须传递
pip_requirements
、extra_pip_requirements
或input_example
,后者用于推断环境依赖。更多信息,请参阅 模型依赖文档。对象支持:cloudpickle 不会序列化 Python 数据模型之外的对象。一些相关的例子包括原始文件和数据库连接。如果你的程序依赖于这些,请确保记录引用这些对象的方法以及你的模型。
基于函数的模型
如果你想序列化一个没有额外依赖方法的简单Python函数,你可以通过关键字参数 python_model
简单地记录一个预测方法。
备注
基于函数的模型仅支持具有单个输入参数的函数。如果您想传递更多参数或额外的推理参数,请使用下面的基于类的模型。
import mlflow
import pandas as pd
# Define a simple function to log
def predict(model_input):
return model_input.apply(lambda x: x * 2)
# Save the function as a model
with mlflow.start_run():
mlflow.pyfunc.log_model("model", python_model=predict, pip_requirements=["pandas"])
run_id = mlflow.active_run().info.run_id
# Load the model from the tracking server and perform inference
model = mlflow.pyfunc.load_model(f"runs:/{run_id}/model")
x_new = pd.Series([1, 2, 3])
prediction = model.predict(x_new)
print(prediction)
基于类的模型
如果你想要序列化一个更复杂的对象,例如一个处理预处理、复杂预测逻辑或自定义序列化的类,你应该继承 PythonModel
类。MLflow 有关于构建自定义 PyFunc 模型的教程,如 这里 所示,因此我们不会重复这些信息,在这个例子中,我们将重新创建上述功能以突出差异。请注意,这个 PythonModel 实现过于复杂,对于这个简单的情况,我们建议使用基于函数的模型。
import mlflow
import pandas as pd
class MyModel(mlflow.pyfunc.PythonModel):
def predict(self, context, model_input, params=None):
return [x * 2 for x in model_input]
# Save the function as a model
with mlflow.start_run():
mlflow.pyfunc.log_model(
"model", python_model=MyModel(), pip_requirements=["pandas"]
)
run_id = mlflow.active_run().info.run_id
# Load the model from the tracking server and perform inference
model = mlflow.pyfunc.load_model(f"runs:/{run_id}/model")
x_new = pd.Series([1, 2, 3])
print(f"Prediction:
{model.predict(x_new)}")
此实现与上述基于函数的实现之间的主要区别在于,预测方法被包装在一个类中,具有 self
参数,并且具有默认值为 None 的 params
参数。请注意,基于函数的模型不支持额外的参数。
总之,当你有一个简单的函数需要序列化时,使用基于函数的模型。如果需要更多功能,使用基于类的模型。
- class mlflow.pyfunc.EnvType[源代码]
基类:
object
- class mlflow.pyfunc.PyFuncModel(model_meta: Model, model_impl: Any, predict_fn: str = 'predict', predict_stream_fn: str | None = None)[源代码]
基类:
object
MLflow ‘python 函数’ 模型。
模型实现和元数据的包装器。这个类不应该直接构造。相反,这个类的实例是通过
load_model()
构造并返回的。model_impl
可以是任何实现 Pyfunc 接口 的 Python 对象,并通过调用模型的loader_module
返回。model_meta
包含从 MLmodel 文件加载的模型元数据。- get_raw_model()[源代码]
备注
实验性功能:此功能可能在未来的版本中无警告地更改或移除。
如果模型包装器实现了 get_raw_model 函数,则获取底层原始模型。
- predict(data: DataFrame | Series | ndarray | csc_matrix | csr_matrix | List[Any] | Dict[str, Any] | datetime | bool | bytes | float | int | str | DataFrame, params: Dict[str, Any] | None = None) DataFrame | Series | ndarray | list | str | DataFrame [源代码]
- predict_stream(data: Dict[str, Any] | bool | bytes | float | int | str, params: Dict[str, Any] | None = None) Iterator[Dict[str, Any] | str] [源代码]
- unwrap_python_model()[源代码]
备注
实验性功能:此功能可能在未来的版本中无警告地更改或移除。
解开底层 Python 模型对象。
这种方法在访问自定义模型函数时非常有用,同时仍然能够通过 predict() 方法利用 MLflow 设计的工作流程。
- 返回:
底层封装的模型对象
import mlflow # define a custom model class MyModel(mlflow.pyfunc.PythonModel): def predict(self, context, model_input, params=None): return self.my_custom_function(model_input, params) def my_custom_function(self, model_input, params=None): # do something with the model input return 0 some_input = 1 # save the model with mlflow.start_run(): model_info = mlflow.pyfunc.log_model(artifact_path="model", python_model=MyModel()) # load the model loaded_model = mlflow.pyfunc.load_model(model_uri=model_info.model_uri) print(type(loaded_model)) # <class 'mlflow.pyfunc.model.PyFuncModel'> unwrapped_model = loaded_model.unwrap_python_model() print(type(unwrapped_model)) # <class '__main__.MyModel'> # does not work, only predict() is exposed # print(loaded_model.my_custom_function(some_input)) print(unwrapped_model.my_custom_function(some_input)) # works print(loaded_model.predict(some_input)) # works # works, but None is needed for context arg print(unwrapped_model.predict(None, some_input))
- mlflow.pyfunc.add_to_model(model, loader_module, data=None, code=None, conda_env=None, python_env=None, model_config=None, model_code_path=None, **kwargs)[源代码]
在模型配置中添加一个
pyfunc
规范。定义
pyfunc
配置模式。调用者可以使用此模式从现有目录结构创建有效的pyfunc
模型风格。例如,其他模型风格可以使用此模式来指定如何将其输出用作pyfunc
。备注
所有路径都是相对于导出的模型根目录的。
- 参数:
model – 现有模型。
loader_module – 用于加载模型的模块。
data – 模型数据的文件路径。
code – 代码依赖的路径。
conda_env – Conda 环境。
python_env – Python 环境。
req – pip 需求文件。
kwargs – 在
pyfunc
风味规范中包含的其他键值对。值必须是可序列化为 YAML 的。model_config – 要应用于模型的模型配置。此配置在模型加载期间可用。 .. 注意:: 实验性:此参数可能在未来的版本中更改或删除,恕不另行通知。
- 返回:
更新了模型配置。
- mlflow.pyfunc.get_model_dependencies(model_uri, format='pip')[源代码]
下载模型依赖项并返回 requirements.txt 或 conda.yaml 文件的路径。
警告
此API将所有模型工件下载到本地文件系统。对于大型模型,这可能需要很长时间。为了避免这种开销,请使用
mlflow.artifacts.download_artifacts("<model_uri>/requirements.txt")
或mlflow.artifacts.download_artifacts("<model_uri>/conda.yaml")
代替。- 参数:
model_uri – 要从中获取依赖项的模型的URI。
format – 返回的依赖文件的格式。如果指定了
"pip"
格式,则返回指向 piprequirements.txt
文件的路径。如果指定了"conda"
格式,则返回指向"conda.yaml"
文件的路径。如果指定了"pip"
格式,但模型未保存带有requirements.txt
文件,则改为提取模型conda.yaml
文件中的pip
部分,并忽略任何额外的 conda 依赖项。默认值为"pip"
。
- 返回:
指定模型依赖关系的本地文件系统路径,可以是pip的``requirements.txt``文件(如果``format=”pip”
)或``conda.yaml``文件(如果``format="conda"
)。
- mlflow.pyfunc.load_model(model_uri: str, suppress_warnings: bool = False, dst_path: str | None = None, model_config: str | Path | Dict[str, Any] | None = None) PyFuncModel [源代码]
加载以Python函数格式存储的模型。
- 参数:
model_uri – MLflow 模型的位置,采用 URI 格式。例如: -
/Users/me/path/to/local/model
-relative/path/to/local/model
-s3://my_bucket/path/to/model
-runs:/<mlflow_run_id>/run-relative/path/to/model
-models:/<model_name>/<model_version>
-models:/<model_name>/<stage>
-mlflow-artifacts:/path/to/model
有关支持的 URI 方案的更多信息,请参阅 引用工件。suppress_warnings – 如果
True
,与模型加载过程相关的非致命警告信息将被抑制。如果False
,这些警告信息将被发出。dst_path – 下载模型工件的本地文件系统路径。此目录必须已经存在。如果未指定,将创建一个本地输出路径。
model_config – 要应用于模型的模型配置。此配置在模型加载期间可用。配置可以作为文件路径传递,或作为带有字符串键的字典传递。.. 注意:: 实验性:此参数可能在未来的版本中更改或删除,而无需警告。
- mlflow.pyfunc.load_pyfunc(model_uri, suppress_warnings=False)[源代码]
警告
mlflow.pyfunc.load_pyfunc
自 1.0 版本起已被弃用。此方法将在未来的版本中被移除。请改用mlflow.pyfunc.load_model
。加载以Python函数格式存储的模型。
- 参数:
model_uri – MLflow 模型的位置,采用 URI 格式。例如: -
/Users/me/path/to/local/model
-relative/path/to/local/model
-s3://my_bucket/path/to/model
-runs:/<mlflow_run_id>/run-relative/path/to/model
-models:/<model_name>/<model_version>
-models:/<model_name>/<stage>
-mlflow-artifacts:/path/to/model
有关支持的 URI 方案的更多信息,请参阅 引用工件。suppress_warnings – 如果
True
,与模型加载过程相关的非致命警告信息将被抑制。如果False
,这些警告信息将被发出。
- mlflow.pyfunc.log_model(artifact_path, loader_module=None, data_path=None, code_path=None, code_paths=None, infer_code_paths=False, conda_env=None, python_model=None, artifacts=None, registered_model_name=None, signature: ModelSignature = None, input_example: DataFrame | ndarray | dict | list | csr_matrix | csc_matrix | str | bytes | tuple = None, await_registration_for=300, pip_requirements=None, extra_pip_requirements=None, metadata=None, model_config=None, example_no_conversion=None, streamable=None, resources: str | List[Resource] | None = None)[源代码]
将具有自定义推理逻辑和可选数据依赖项的 Pyfunc 模型记录为当前运行的 MLflow 工件。
有关此方法支持的工作流程信息,请参阅 创建自定义pyfunc模型的工作流程 和 哪个工作流程适合我的用例?。您不能同时指定第二个工作流程的参数:
loader_module
、data_path
和第一个工作流程的参数:python_model
、artifacts
。- 参数:
artifact_path – 要记录Python模型的运行相对工件路径。
loader_module – 用于从
data_path
加载模型的 Python 模块名称。此模块必须定义一个原型为_load_pyfunc(data_path)
的方法。如果非None
,此模块及其依赖项必须包含在以下位置之一: - MLflow 库。 - 由conda_env
参数指定的模型 Conda 环境中的包。 - 由code_path
参数指定的一个或多个文件。data_path – 包含模型数据的文件或目录的路径。
code_path – 已弃用 用于定义依赖代码的遗留参数。此参数已被
code_paths
取代,并将在 MLflow 的未来版本中移除。code_paths – 一组指向Python文件依赖项(或包含文件依赖项的目录)的本地文件系统路径。这些文件在加载模型时会被*前置*到系统路径中。如果为给定模型声明的依赖文件之间存在导入依赖关系,并且定义了多个文件,则应从公共根路径声明相对导入,以避免加载模型时的导入错误。你可以不设置``code_paths``参数,但将``infer_code_paths``设置为``True``,以让MLflow推断模型代码路径。详见``infer_code_paths``参数文档。有关``code_paths``功能的详细解释、推荐的使用模式和限制,请参阅`code_paths使用指南 <https://mlflow.org/docs/latest/model/dependencies.html?highlight=code_paths#saving-extra-code-with-an-mlflow-model>`_。
infer_code_paths – 如果设置为
True
,MLflow 会自动推断模型代码路径。推断的代码路径文件仅包括必要的 Python 模块文件。只有当前工作目录下的 Python 代码文件可以自动推断。默认值为False
。 .. warning:conda_env –
一个Conda环境的字典表示形式,或Conda环境yaml文件的路径。如果提供,这将描述模型应运行的环境。至少,它应指定包含在
get_default_conda_env()
中的依赖项。如果为None
,则通过mlflow.models.infer_pip_requirements()
推断的pip要求添加一个conda环境到模型中。如果要求推断失败,则回退到使用get_default_pip_requirements()
。来自conda_env
的pip要求被写入一个piprequirements.txt
文件,完整的conda环境被写入conda.yaml
。以下是一个conda环境的字典表示形式的*示例*:{ "name": "mlflow-env", "channels": ["conda-forge"], "dependencies": [ "python=3.8.15", { "pip": [ "scikit-learn==x.y.z" ], }, ], }
python_model –
PythonModel
的子类实例或具有单个参数的可调用对象(参见下面的示例)。传入的对象使用 CloudPickle 库进行序列化。python_model 也可以是定义模型的 PythonModel 文件路径,而不是序列化模型对象。类的任何依赖项应包含在以下位置之一:artifacts –
包含
<name, artifact_uri>
条目的字典。远程工件 URI 被解析为绝对文件系统路径,生成一个<name, absolute_path>
条目的字典。python_model
可以在PythonModel.load_context()
和PythonModel.predict()
的context
参数的artifacts
属性中引用这些解析后的条目。例如,考虑以下artifacts
字典:{"my_file": "s3://my-bucket/path/to/my/file"}
在这种情况下,
"my_file"
工件从 S3 下载。python_model
可以通过context.artifacts["my_file"]
将其作为绝对文件系统路径引用。如果
None
,则不会向模型添加任何工件。registered_model_name – 此参数可能在未来的版本中更改或移除,且不会提前警告。如果提供,将在
registered_model_name
下创建一个模型版本,如果给定名称的注册模型不存在,则同时创建一个注册模型。signature –
ModelSignature
描述了模型的输入和输出Schema
。模型签名可以从具有有效模型输入(例如,省略目标列的训练数据集)和有效模型输出(例如,在训练数据集上生成的模型预测)的数据集中推断
,例如: .. code-block:: pythoninput_example – 一个或多个有效的模型输入实例。输入示例用作提示,指示应向模型提供哪些数据。它将被转换为Pandas DataFrame,然后使用Pandas的面向分割的格式序列化为json,或者是一个numpy数组,其中示例将通过将其转换为列表来序列化为json。字节被base64编码。当``signature``参数为``None``时,输入示例用于推断模型签名。
await_registration_for – 等待模型版本完成创建并处于
READY
状态的秒数。默认情况下,函数等待五分钟。指定 0 或 None 以跳过等待。pip_requirements – 可以是 pip 需求字符串的可迭代对象(例如
["scikit-learn", "-r requirements.txt", "-c constraints.txt"]
),或者是本地文件系统上的 pip 需求文件的字符串路径(例如"requirements.txt"
)。如果提供,这将描述该模型应运行的环境。如果为None
,则通过mlflow.models.infer_pip_requirements()
从当前软件环境中推断出默认的需求列表。如果需求推断失败,则回退到使用get_default_pip_requirements()
。需求和约束都会自动解析并分别写入requirements.txt
和constraints.txt
文件,并作为模型的一部分存储。需求也会写入模型 conda 环境(conda.yaml
)文件的pip
部分。extra_pip_requirements – 可以是 pip 需求字符串的可迭代对象(例如
["pandas", "-r requirements.txt", "-c constraints.txt"]
),或者是本地文件系统上的 pip 需求文件的字符串路径(例如"requirements.txt"
)。如果提供,这将描述附加的 pip 需求,这些需求会被追加到根据用户当前软件环境自动生成的一组默认 pip 需求中。需求和约束会分别自动解析并写入requirements.txt
和constraints.txt
文件,并作为模型的一部分存储。需求也会被写入模型的 conda 环境(conda.yaml
)文件的pip
部分。 .. 警告:: 以下参数不能同时指定: -conda_env
-pip_requirements
-extra_pip_requirements
这个示例 展示了如何使用pip_requirements
和extra_pip_requirements
指定 pip 需求。metadata – 传递给模型并在 MLmodel 文件中存储的自定义元数据字典。
model_config – 要应用于模型的模型配置。此配置在模型加载期间可用。 .. 注意:: 实验性:此参数可能在未来的版本中更改或删除,恕不另行通知。
example_no_conversion – 此参数已被弃用,并将在未来的版本中移除。它不再使用,可以安全地移除。输入示例不再被转换。
resources – 模型资源列表或包含所需资源列表的 resources.yaml 文件。.. 注意:: 实验性:此参数可能在未来的版本中更改或删除,恕不另行通知。
streamable – 一个布尔值,指示模型是否支持流式预测,如果为 None,MLflow 将尝试通过检查 predict_stream 方法是否存在来判断模型是否支持流式预测。默认为 None。
- 返回:
一个包含记录模型元数据的
ModelInfo
实例。
- mlflow.pyfunc.save_model(path, loader_module=None, data_path=None, code_path=None, code_paths=None, infer_code_paths=False, conda_env=None, mlflow_model=None, python_model=None, artifacts=None, signature: ModelSignature = None, input_example: DataFrame | ndarray | dict | list | csr_matrix | csc_matrix | str | bytes | tuple = None, pip_requirements=None, extra_pip_requirements=None, metadata=None, model_config=None, example_no_conversion=None, streamable=None, resources: str | List[Resource] | None = None, **kwargs)[源代码]
将具有自定义推理逻辑和可选数据依赖项的 Pyfunc 模型保存到本地文件系统上的路径。
有关此方法支持的工作流程信息,请参阅 “创建自定义pyfunc模型的流程” 和 “哪个工作流程适合我的用例?”。请注意,第二个工作流程的参数:
loader_module
、data_path
和第一个工作流程的参数:python_model
、artifacts
,不能同时指定。- 参数:
path – 保存Python模型的路径。
loader_module – 用于从
data_path
加载模型的 Python 模块名称。此模块必须定义一个原型为_load_pyfunc(data_path)
的方法。如果非None
,此模块及其依赖项必须包含在以下位置之一: - MLflow 库。 - 由conda_env
参数指定的模型 Conda 环境中的包。 - 由code_path
参数指定的一个或多个文件。data_path – 包含模型数据的文件或目录的路径。
code_path – 已弃用 用于定义依赖代码的遗留参数。此参数已被
code_paths
取代,并将在 MLflow 的未来版本中移除。code_paths – 一组指向Python文件依赖项(或包含文件依赖项的目录)的本地文件系统路径。这些文件在加载模型时会被*前置*到系统路径中。如果为给定模型声明的依赖文件之间存在导入依赖关系,并且定义了多个文件,则应从公共根路径声明相对导入,以避免加载模型时的导入错误。你可以不设置``code_paths``参数,但将``infer_code_paths``设置为``True``,以让MLflow推断模型代码路径。详见``infer_code_paths``参数文档。有关``code_paths``功能的详细解释、推荐的使用模式和限制,请参阅`code_paths使用指南 <https://mlflow.org/docs/latest/model/dependencies.html?highlight=code_paths#saving-extra-code-with-an-mlflow-model>`_。
infer_code_paths – 如果设置为
True
,MLflow 会自动推断模型代码路径。推断的代码路径文件仅包括必要的 Python 模块文件。只有当前工作目录下的 Python 代码文件可以自动推断。默认值为False
。 .. warning:conda_env –
一个Conda环境的字典表示形式,或Conda环境yaml文件的路径。如果提供,这将描述模型应运行的环境。至少,它应指定包含在
get_default_conda_env()
中的依赖项。如果为None
,则通过mlflow.models.infer_pip_requirements()
推断的pip要求添加一个conda环境到模型中。如果要求推断失败,则回退到使用get_default_pip_requirements()
。来自conda_env
的pip要求被写入一个piprequirements.txt
文件,完整的conda环境被写入conda.yaml
。以下是一个conda环境的字典表示形式的*示例*:{ "name": "mlflow-env", "channels": ["conda-forge"], "dependencies": [ "python=3.8.15", { "pip": [ "scikit-learn==x.y.z" ], }, ], }
mlflow_model –
mlflow.models.Model
配置,将 python_function 风格添加到其中。python_model – 一个
PythonModel
子类的实例或一个带有一个参数的可调用对象(见下面的示例)。传入的对象使用 CloudPickle 库进行序列化。python_model 也可以是一个指向 PythonModel 的文件路径,该路径通过代码工件而不是序列化模型对象来定义模型。类的任何依赖项应包含在以下位置之一: - MLflow 库。 - 模型 Conda 环境中列出的包,由conda_env
参数指定。 - 由code_path
参数指定的一个或多个文件。 注意:如果类是从另一个模块导入的,而不是在__main__
作用域中定义的,定义模块也应包含在列出的位置之一。 示例 类模型 .. code-block:: python from typing import List, Dict import mlflow class MyModel(mlflow.pyfunc.PythonModel): def predict(self, context, model_input: List[str], params=None) -> List[str]: return [i.upper() for i in model_input] mlflow.pyfunc.save_model(“model”, python_model=MyModel(), input_example=[“a”]) model = mlflow.pyfunc.load_model(“model”) print(model.predict([“a”, “b”, “c”])) # -> [“A”, “B”, “C”] 函数模型 .. note:: 实验性:函数模型支持是实验性的,可能会在未来的版本中更改或删除,恕不另行通知。 .. code-block:: python from typing import List import mlflow def predict(model_input: List[str]) -> List[str]: return [i.upper() for i in model_input] mlflow.pyfunc.save_model(“model”, python_model=predict, input_example=[“a”]) model = mlflow.pyfunc.load_model(“model”) print(model.predict([“a”, “b”, “c”])) # -> [“A”, “B”, “C”] 代码模型 .. note:: 实验性:代码模型支持是实验性的,可能会在未来的版本中更改或删除,恕不另行通知。 .. code-block:: python # code.py from typing import List import mlflow class MyModel(mlflow.pyfunc.PythonModel): def predict(self, context, model_input: List[str], params=None) -> List[str]: return [i.upper() for i in model_input] mlflow.models.set_model(MyModel()) # log_model.py import mlflow with mlflow.start_run(): model_info = mlflow.pyfunc.log_model( artifact_path=”model”, python_model=”code.py”, ) 如果 predict 方法或函数有类型注解,MLflow 会根据类型注解自动构建模型签名(除非显式指定了signature
参数),并在将输入值传递给函数之前将其转换为指定类型。目前,支持以下类型注解: -List[str]
-List[Dict[str, str]]
artifacts –
包含
<name, artifact_uri>
条目的字典。远程工件 URI 被解析为绝对文件系统路径,生成一个<name, absolute_path>
条目的字典。python_model
可以在PythonModel.load_context()
和PythonModel.predict()
的context
参数的artifacts
属性中引用这些解析后的条目。例如,考虑以下artifacts
字典:{"my_file": "s3://my-bucket/path/to/my/file"}
在这种情况下,
"my_file"
工件从 S3 下载。python_model
可以通过context.artifacts["my_file"]
将其作为绝对文件系统路径引用。如果
None
,则不会向模型添加任何工件。signature –
ModelSignature
描述了模型的输入和输出Schema
。模型签名可以从具有有效模型输入(例如,省略目标列的训练数据集)和有效模型输出(例如,在训练数据集上生成的模型预测)的数据集中推断
,例如: .. code-block:: pythoninput_example – 一个或多个有效的模型输入实例。输入示例用作提示,指示应向模型提供哪些数据。它将被转换为Pandas DataFrame,然后使用Pandas的面向分割的格式序列化为json,或者是一个numpy数组,其中示例将通过将其转换为列表来序列化为json。字节被base64编码。当``signature``参数为``None``时,输入示例用于推断模型签名。
pip_requirements – 可以是 pip 需求字符串的可迭代对象(例如
["scikit-learn", "-r requirements.txt", "-c constraints.txt"]
),或者是本地文件系统上的 pip 需求文件的字符串路径(例如"requirements.txt"
)。如果提供,这将描述该模型应运行的环境。如果为None
,则通过mlflow.models.infer_pip_requirements()
从当前软件环境中推断出默认的需求列表。如果需求推断失败,则回退到使用get_default_pip_requirements()
。需求和约束都会自动解析并分别写入requirements.txt
和constraints.txt
文件,并作为模型的一部分存储。需求也会写入模型 conda 环境(conda.yaml
)文件的pip
部分。extra_pip_requirements – 可以是 pip 需求字符串的可迭代对象(例如
["pandas", "-r requirements.txt", "-c constraints.txt"]
),或者是本地文件系统上的 pip 需求文件的字符串路径(例如"requirements.txt"
)。如果提供,这将描述附加的 pip 需求,这些需求会被追加到根据用户当前软件环境自动生成的一组默认 pip 需求中。需求和约束会分别自动解析并写入requirements.txt
和constraints.txt
文件,并作为模型的一部分存储。需求也会被写入模型的 conda 环境(conda.yaml
)文件的pip
部分。 .. 警告:: 以下参数不能同时指定: -conda_env
-pip_requirements
-extra_pip_requirements
这个示例 展示了如何使用pip_requirements
和extra_pip_requirements
指定 pip 需求。metadata – 传递给模型并在 MLmodel 文件中存储的自定义元数据字典。
model_config – 要应用于模型的模型配置。此配置在模型加载期间可用。 .. 注意:: 实验性:此参数可能在未来的版本中更改或删除,恕不另行通知。
example_no_conversion – 此参数已被弃用,并将在未来的版本中移除。它不再使用,可以安全地移除。输入示例不再被转换。
resources – 模型资源列表或包含所需资源列表的 resources.yaml 文件。.. 注意:: 实验性:此参数可能在未来的版本中更改或删除,恕不另行通知。
streamable – 一个布尔值,指示模型是否支持流式预测,如果为 None,MLflow 将尝试通过检查 predict_stream 方法是否存在来判断模型是否支持流式预测。默认为 None。
kwargs – 额外的关键字参数。
- mlflow.pyfunc.spark_udf(spark, model_uri, result_type=None, env_manager='local', params: Dict[str, Any] | None = None, extra_env: Dict[str, str] | None = None)[源代码]
一个可以用来调用Python函数格式化模型的Spark UDF。
传递给 UDF 的参数会作为 DataFrame 转发给模型,其中列名是序数(0, 1, …)。在某些版本的 Spark(3.0 及以上)中,还可以将输入包装在一个结构体中。在这种情况下,数据将作为 DataFrame 传递,列名由结构体定义给出(例如,当调用 my_udf(struct(‘x’, ‘y’)) 时,模型将获得一个包含两列 ‘x’ 和 ‘y’ 的 pandas DataFrame)。
如果模型包含带有张量规范输入的签名,您需要传递一个数组类型的列作为相应的UDF参数。该列的值必须是一维数组。UDF将以’C’顺序(即使用类似C的索引顺序读/写元素)将列值重塑为所需的形状,并将值转换为所需的张量规范类型。
如果模型包含签名,UDF 可以在不指定列名参数的情况下被调用。在这种情况下,UDF 将使用签名中的列名进行调用,因此评估数据框的列名必须与模型签名的列名匹配。
预测结果被过滤,只包含可以表示为
result_type
的列。如果result_type
是字符串或字符串数组,所有预测结果都会被转换为字符串。如果结果类型不是数组类型,则返回最左边的匹配类型的列。注意:在早期版本的 Spark(2.4 及以下)中,不支持类型为
pyspark.sql.types.DateType
的输入。from pyspark.sql.functions import struct predict = mlflow.pyfunc.spark_udf(spark, "/my/local/model") df.withColumn("prediction", predict(struct("name", "age"))).show()
- 参数:
spark – 一个 SparkSession 对象。
model_uri – MLflow 模型的位置,采用 URI 格式,具有
mlflow.pyfunc
风格。例如: -/Users/me/path/to/local/model
-relative/path/to/local/model
-s3://my_bucket/path/to/model
-runs:/<mlflow_run_id>/run-relative/path/to/model
-models:/<model_name>/<model_version>
-models:/<model_name>/<stage>
-mlflow-artifacts:/path/to/model
有关支持的 URI 方案的更多信息,请参阅 引用工件。result_type – 用户定义函数的返回类型。该值可以是
pyspark.sql.types.DataType
对象或DDL格式的类型字符串。只允许基本类型、基本类型的数组pyspark.sql.types.ArrayType
或包含上述两种类型字段的结构类型。如果未指定,它会尝试从模型签名输出模式推断结果类型,如果模型输出模式不可用,则回退使用double
类型。支持以下结果类型类别: - “int” 或pyspark.sql.types.IntegerType
:适合int32
的最左侧整数,如果没有则抛出异常。 - “long” 或pyspark.sql.types.LongType
:适合int64
的最左侧长整数,如果没有则抛出异常。 -ArrayType(IntegerType|LongType)
:所有适合请求大小的整数列。 - “float” 或pyspark.sql.types.FloatType
:最左侧的数值结果转换为float32
,如果没有则抛出异常。 - “double” 或pyspark.sql.types.DoubleType
:最左侧的数值结果转换为double
,如果没有则抛出异常。 -ArrayType(FloatType|DoubleType)
:所有数值列转换为请求的类型,如果没有数值列则抛出异常。 - “string” 或pyspark.sql.types.StringType
:最左侧的列转换为string
。 - “boolean” 或 “bool” 或pyspark.sql.types.BooleanType
:最左侧的列转换为bool
,如果没有则抛出异常。 -ArrayType(StringType)
:所有列转换为string
。 - “field1 FIELD1_TYPE, field2 FIELD2_TYPE, …”:包含多个字段的结构类型,字段之间用逗号分隔,每个字段类型必须是上述类型之一。env_manager – 用于创建模型推理的Python环境的环境管理器。请注意,环境仅在PySpark UDF的上下文中恢复;UDF外部的软件环境不受影响。默认值为``local``,支持以下值: -
virtualenv
:使用virtualenv恢复用于训练模型的Python环境。 -conda
:(推荐)使用Conda恢复用于训练模型的软件环境。 -local
:使用当前的Python环境进行模型推理,这可能与用于训练模型的环境不同,并可能导致错误或无效的预测。params – 传递给模型进行推理的额外参数。
extra_env – 传递给 UDF 执行器的额外环境变量。
- 返回:
Spark UDF 将模型的
predict
方法应用于数据,并返回由result_type
指定的类型,默认情况下是双精度浮点数。
- mlflow.pyfunc.get_default_pip_requirements()[源代码]
- 返回:
此flavor生成的MLflow Models的默认pip需求列表。对
save_model()
和log_model()
的调用会生成一个pip环境,该环境至少包含这些需求。
- mlflow.pyfunc.get_default_conda_env()[源代码]
- 返回:
当提供用户定义的
PythonModel
子类时,通过调用save_model()
和log_model()
生成的 MLflow 模型的默认 Conda 环境。
- class mlflow.pyfunc.PythonModelContext[源代码]
一组
PythonModel
在进行推理时可以使用的工件。PythonModelContext
对象由save_model()
和log_model()
持久化方法 隐式 创建,使用这些方法的artifacts
参数指定的内容。
- class mlflow.pyfunc.PythonModel[源代码]
表示一个通用的 Python 模型,该模型评估输入并生成与 API 兼容的输出。通过子类化
PythonModel
,用户可以创建具有“python_function”(“pyfunc”)风格的定制 MLflow 模型,利用自定义推理逻辑和工件依赖。- load_context(context)[源代码]
从指定的
PythonModelContext
加载工件,这些工件可以在评估输入时被predict()
使用。当使用load_model()
加载 MLflow 模型时,此方法会在PythonModel
构造时立即被调用。同样的
PythonModelContext
在调用predict()
时也会可用,但覆盖此方法并在模型加载时从上下文中加载工件可能会更高效。- 参数:
context – 一个包含模型可用于执行推理的工件的
PythonModelContext
实例。
- abstract predict(context, model_input, params: Dict[str, Any] | None = None)[源代码]
评估一个与 pyfunc 兼容的输入并生成一个与 pyfunc 兼容的输出。有关 pyfunc 输入/输出 API 的更多信息,请参阅 推理 API。
- 参数:
context – 一个包含模型可用于执行推理的工件的
PythonModelContext
实例。model_input – 模型评估的 pyfunc 兼容输入。
params – 传递给模型进行推理的额外参数。
- predict_stream(context, model_input, params: Dict[str, Any] | None = None)[源代码]
评估一个兼容 pyfunc 的输入并生成一个输出迭代器。有关 pyfunc 输入 API 的更多信息,请参阅 推理 API。
- 参数:
context – 一个包含模型可用于执行推理的工件的
PythonModelContext
实例。model_input – 模型评估的 pyfunc 兼容输入。
params – 传递给模型进行推理的额外参数。
- class mlflow.pyfunc.ChatModel[源代码]
备注
实验性:此类在未来的版本中可能会在没有警告的情况下更改或被移除。
一个
PythonModel
的子类,使得实现与流行的 LLM 聊天 API 兼容的模型更加方便。通过子类化ChatModel
,用户可以创建具有predict()
方法的 MLflow 模型,该方法比通用的PythonModel
API 更适合聊天任务。ChatModels 自动定义输入/输出签名和一个输入示例,因此在调用mlflow.pyfunc.save_model()
时不需要手动指定这些值。有关
ChatModel
API 预期的参数和输出的详细信息,请参阅下面的predict()
方法的文档。- abstract predict(context, messages: List[ChatMessage], params: ChatParams) ChatResponse [源代码]
评估聊天输入并生成聊天输出。
- 参数:
messages (List[
ChatMessage
]) – 表示聊天历史的ChatMessage
对象列表。params (
ChatParams
) – 一个包含各种参数的ChatParams
对象,这些参数用于在推理过程中修改模型行为。
- 返回:
一个包含模型响应(s)以及其他元数据的
ChatResponse
对象。
- predict_stream(context, messages: List[ChatMessage], params: ChatParams) Iterator[ChatResponse] [源代码]
评估聊天输入并生成聊天输出。重写此函数以实现真正的流预测。默认情况下,此函数仅生成 predict 函数的结果。
- 参数:
messages (List[
ChatMessage
]) – 表示聊天历史的ChatMessage
对象列表。params (
ChatParams
) – 一个包含各种参数的ChatParams
对象,这些参数用于在推理过程中修改模型行为。
- 返回:
一个遍历
ChatResponse
对象的迭代器,包含模型的响应以及其他元数据。