MLflow 模型中的依赖管理
MLflow 模型 是一种标准格式,它将机器学习模型与其依赖项和其他元数据打包在一起。构建带有依赖项的模型可以提高在各种平台和工具之间的可重现性和可移植性。
当您使用 MLflow Tracking API 创建 MLflow 模型时,例如 mlflow.pytorch.log_model(),MLflow 会自动推断您使用的模型风味所需的依赖项,并将它们记录为模型元数据的一部分。然后,当您部署模型进行预测时,MLflow 会自动在环境中安装这些依赖项。因此,通常情况下,您无需担心 MLflow 模型中依赖项的管理。
但是,在某些情况下,您可能需要添加或修改某些依赖项。本页面将高级别地介绍 MLflow 如何管理依赖项,并为如何根据您的用例自定义依赖项提供指导。
为了提高 MLflow 依赖项推断的准确性,一个技巧是在保存模型时添加 input_example。这使得 MLflow 能够在保存模型之前执行模型预测,从而捕获预测过程中使用的依赖项。有关此参数的更详细用法,请参阅 模型输入示例。
MLflow 如何记录模型依赖项
MLflow 模型保存在一个指定目录中,其结构如下:
my_model/
├── MLmodel
├── model.pkl
├── conda.yaml
├── python_env.yaml
└── requirements.txt
模型依赖项由以下文件定义(有关其他文件,请参阅 存储格式 部分提供的指南):
python_env.yaml- 此文件包含使用 virtualenv 恢复模型环境所需的信息,包括 (1) Python 版本,(2) pip、setuptools 和 wheel 等构建工具,(3) 模型的 pip 要求(指向 requirements.txt)。requirements.txt- 定义运行模型所需的 pip 依赖项集。conda.yaml- 定义运行模型所需的 conda 环境。当您指定conda作为恢复模型环境的环境管理器时,将使用此文件。
请注意,不建议手动编辑这些文件来添加或删除依赖项。它们由 MLflow 自动生成,您手动进行的任何更改在您再次保存模型时都会被覆盖。相反,您应该使用以下章节中描述的推荐方法之一。
使用 MLFLOW_LOCK_MODEL_DEPENDENCIES 锁定模型依赖项
自 MLflow 2.16.0 起可用
MLflow 可以在记录模型时自动将直接和传递的模型依赖项锁定到其精确版本。这通过捕获模型创建时完整的依赖项树来确保可重现性。
要启用依赖项锁定,请设置 MLFLOW_LOCK_MODEL_DEPENDENCIES 环境变量。
export MLFLOW_LOCK_MODEL_DEPENDENCIES=true
启用后,MLflow 将使用 uv(如果已安装)来解析和锁定所有依赖项,包括其传递依赖项。然后,锁定的要求将保存在模型的 requirements.txt 文件中。
无锁定示例(默认)
mlflow==2.9.2
scikit-learn==1.3.2
cloudpickle==3.0.0
启用锁定的示例
mlflow==2.9.2
scikit-learn==1.3.2
cloudpickle==3.0.0
numpy==1.24.3
scipy==1.11.4
joblib==1.3.2
threadpoolctl==3.2.0
# ... other transitive dependencies
依赖项锁定需要安装 uv。如果 uv 不可用,MLflow 将跳过锁定步骤并使用标准的依赖项推断。使用以下命令安装 uv:
pip install uv
锁定依赖项可能会显著增加 requirements.txt 文件的大小,因为它包含了所有传递依赖项。这提供了更好的可重现性,但可能会使环境更加僵化。
示例
以下显示了 MLflow 在使用 mlflow.sklearn.log_model 记录模型时生成的环境文件示例:
python_env.yaml
python: 3.9.8
build_dependencies:
- pip==23.3.2
- setuptools==69.0.3
- wheel==0.42.0
dependencies:
- -r requirements.txt
requirements.txt
mlflow==2.9.2
scikit-learn==1.3.2
cloudpickle==3.0.0
conda.yaml
name: mlflow-env
channels:
- conda-forge
dependencies:
- python=3.9.8
- pip
- pip:
- mlflow==2.9.2
- scikit-learn==1.3.2
- cloudpickle==3.0.0
向 MLflow 模型添加额外的依赖项
MLflow 会推断模型风味库所需的依赖项,但您的模型可能依赖于其他库,例如数据预处理。在这种情况下,您可以通过在记录模型时指定 extra_pip_requirements 参数来向模型添加额外的依赖项。例如:
import mlflow
class CustomModel(mlflow.pyfunc.PythonModel):
def predict(self, context, model_input):
# your model depends on pandas
import pandas as pd
...
return prediction
# Log the model
mlflow.pyfunc.log_model(
python_model=CustomModel(),
name="model",
extra_pip_requirements=["pandas==2.0.3"],
input_example=input_data,
)
这些额外依赖项将添加到 requirements.txt(如下所示,conda.yaml 类似):
mlflow==2.9.2
cloudpickle==3.0.0
pandas==2.0.3 # added
在这种情况下,MLflow 将在为模型提供预测服务时,除了推断出的依赖项之外,还将安装 Pandas 2.0.3。
一旦您记录了带有依赖项的模型,建议在沙盒环境中对其进行测试,以避免在将模型部署到生产环境时出现任何依赖项问题。从 MLflow 2.10.0 开始,您可以使用 mlflow.models.predict() API 在虚拟环境中快速测试您的模型。有关更多详细信息,请参阅 验证预测环境。
完全自行定义所有依赖项
或者,您也可以从头开始定义所有依赖项,而不是添加额外的依赖项。为此,请在记录模型时指定 pip_requirements。例如:
import mlflow
# Log the model
mlflow.sklearn.log_model(
sk_model=model,
name="model",
pip_requirements=[
"mlflow-skinny==2.9.2",
"cloudpickle==2.5.8",
"scikit-learn==1.3.1",
],
)
手动定义的依赖项将覆盖 MLflow 从模型风味库检测到的默认依赖项。
mlflow-skinny==2.9.2
cloudpickle==2.5.8
scikit-learn==1.3.1
请注意,声明与训练期间使用的依赖项不同的依赖项时要小心,这可能会很危险并导致意外行为。确保一致性最安全的方法是依赖 MLflow 推断的默认依赖项。
一旦您记录了带有依赖项的模型,建议在沙盒环境中对其进行测试,以避免在将模型部署到生产环境时出现任何依赖项问题。从 MLflow 2.10.0 开始,您可以使用 mlflow.models.predict() API 在虚拟环境中快速测试您的模型。有关更多详细信息,请参阅 验证预测环境。
将额外的代码依赖项与 MLflow 模型一起保存 - 自动推断
目前仅支持 Python 函数模型的自动代码依赖项推断。未来版本的 MLflow 将支持其他命名模型风味。
在 MLflow 2.13.0 版本中,引入了一种包含自定义依赖代码的新方法,该方法扩展了在保存或记录模型时声明 code_paths 的现有功能。此新功能利用导入依赖项分析,通过检查 Python 模型定义中的引用导入了哪些模块来自动推断模型所需的代码依赖项。
要使用此新功能,您可以在记录模型时将 infer_code_paths 参数(默认为 False)设置为 True。在使用此推断方法时,您无需通过声明 code_paths 目录位置来显式定义文件位置,这与 MLflow 2.13.0 之前的版本不同。
以下示例展示了如何使用此功能,其中我们正在记录一个包含外部依赖项的模型。在第一部分,我们定义了一个名为 custom_code 的外部模块,它存在于不同于我们的模型定义的位置。
from typing import List
iris_types = ["setosa", "versicolor", "viginica"]
def map_iris_types(predictions: int) -> List[str]:
return [iris_types[pred] for pred in predictions]
定义了此 custom_code.py 模块后,它就可以在我们的 Python 模型中使用:
from typing import Any, Dict, List, Optional
from custom_code import map_iris_types # import the external reference
import mlflow
class FlowerMapping(mlflow.pyfunc.PythonModel):
"""Custom model with an external dependency"""
def predict(
self, context, model_input, params: Optional[Dict[str, Any]] = None
) -> List[str]:
predictions = [pred % 3 for pred in model_input]
# Call the external function
return map_iris_types(predictions)
with mlflow.start_run():
model_info = mlflow.pyfunc.log_model(
name="flowers",
python_model=FlowerMapping(),
infer_code_paths=True, # Enabling automatic code dependency inference
)
当 infer_code_paths 设置为 True 时,将分析 map_iris_types 的依赖项,检测到其源代码声明源自 custom_code.py 模块,并将 custom_code.py 中的代码引用与模型工件一起存储。请注意,无需使用 code_paths 参数(在下一节中讨论)来定义外部代码依赖项。
只有当前工作目录中的模块才可访问。依赖项推断无法跨越模块边界,或者如果您的自定义代码定义在完全不同的库中,则无法工作。如果您的代码库结构使得常见模块完全位于您的模型记录代码执行路径之外,则需要使用原始 code_paths 选项来记录这些依赖项,因为 infer_code_paths 依赖项推断将无法捕获这些需求。
infer_code_paths 的限制
在使用 infer_code_paths 进行依赖项推断之前,请确保您的依赖代码模块中没有硬编码敏感数据(例如密码、访问令牌或密钥)。代码推断不会混淆敏感信息,并且会捕获并记录(保存)模块,无论其包含什么内容。
在使用 infer_code_paths 进行代码结构时,一个需要注意的重要方面是避免在代码的主入口点中定义依赖项。当 Python 代码文件被加载为 __main__ 模块时,它无法被推断为代码路径文件。这意味着,如果您直接运行脚本(例如使用 python script.py),则该脚本中定义的函数和类将成为 __main__ 模块的一部分,而其他模块无法轻松访问它们。
如果您的模型依赖于这些类或函数,这可能会带来问题,因为它们不是标准模块命名空间的一部分,因此不易于序列化。要处理这种情况,您应该使用 cloudpickle 来序列化您的模型实例。cloudpickle 是 Python pickle 模块的扩展版本,可以序列化更广泛的 Python 对象,包括在 __main__ 模块中定义的函数和类。
为什么这很重要
- 代码路径推断:MLflow 使用代码路径来理解和记录与您的模型相关的代码。当脚本作为
__main__执行时,无法推断代码路径,这会使 MLflow 实验的跟踪和可重现性变得复杂。 - 序列化:标准的序列化方法,如
pickle,可能无法与__main__模块对象一起使用,这在尝试保存和加载模型时会导致问题。cloudpickle通过启用对这些对象的序列化来提供解决方案,从而确保您的模型能够被正确保存和恢复。
- 代码路径推断:MLflow 使用代码路径来理解和记录与您的模型相关的代码。当脚本作为
最佳实践
- 避免在
__main__模块中定义关键函数和类。相反,将它们放在单独的模块文件中,可以根据需要导入。 - 如果您必须在
__main__模块中定义函数和类,请使用cloudpickle来序列化您的模型,以确保所有依赖项都得到正确处理。
- 避免在
将额外代码与 MLflow 模型一起保存 - 手动声明
MLflow 还支持将您的自定义 Python 代码作为依赖项保存到模型中。当您想要部署用于预测的自定义模块时,这特别有用。为此,请在记录模型时指定 code_paths。例如,如果您的项目具有以下文件结构:
my_project/
├── utils.py
└── train.py
import mlflow
class MyModel(mlflow.pyfunc.PythonModel):
def predict(self, context, model_input):
from utils import my_func
x = my_func(model_input)
# .. your prediction logic
return prediction
# Log the model
with mlflow.start_run() as run:
mlflow.pyfunc.log_model(
python_model=MyModel(),
name="model",
input_example=input_data,
code_paths=["utils.py"],
)
然后 MLflow 会将 utils.py 保存到模型目录下的 code/ 目录中:
model/
├── MLmodel
├── ...
└── code/
└── utils.py
当 MLflow 加载模型进行服务时,code 目录将被添加到系统路径中,因此您可以在模型代码中像 from utils import my_func 一样使用该模块。您还可以将目录路径指定为 code_paths,以保存目录下的多个文件:
为自定义库使用 code_paths 选项
要包含在 PyPI 上不可用的自定义库,在记录模型时可以使用 code_paths 参数。此选项允许您将 .whl 文件或其他依赖项与模型一起上传,确保在服务期间所有必需的库都可用。
以下示例演示了一种用于包含自定义库进行开发的快速方法。不建议在生产环境中使用此方法。对于生产环境,请将库上传到自定义 PyPI 服务器或云存储,以确保可靠且安全的访问。
例如,假设您的项目具有以下文件结构:
my_project/
|── train.py
└── custom_package.whl
然后,以下代码可以记录您的模型以及自定义包:
import mlflow
from custom_package import my_func
class MyModel(mlflow.pyfunc.PythonModel):
def predict(self, context, model_input):
x = my_func(model_input)
# .. your prediction logic
return prediction
# Log the model
with mlflow.start_run() as run:
mlflow.pyfunc.log_model(
python_model=MyModel(),
name="model",
extra_pip_requirements=["code/custom_package.whl"],
input_example=input_data,
code_paths=["custom_package.whl"],
)
code_paths 选项的注意事项
使用 code_paths 选项时,请注意,指定的文件或目录必须与您的模型脚本位于同一目录中。如果指定的文件或目录位于父目录或子目录中,例如 my_project/src/utils.py,则模型服务将因 ModuleNotFoundError 而失败。例如,假设您的项目具有以下文件结构:
my_project/
|── train.py
└── src/
└── utils.py
那么以下模型代码将不起作用:
class MyModel(mlflow.pyfunc.PythonModel):
def predict(self, context, model_input):
from src.utils import my_func
# .. your prediction logic
return prediction
with mlflow.start_run() as run:
mlflow.pyfunc.log_model(
python_model=MyModel(),
name="model",
input_example=input_data,
code_paths=[
"src/utils.py"
], # the file will be saved at code/utils.py not code/src/utils.py
)
# => Model serving will fail with ModuleNotFoundError: No module named 'src'
此限制是由于 MLflow 保存和加载指定文件和目录的方式。当它将 code/ 目标中指定的文件或目录复制时,它不会保留它们最初所在的相对路径。例如,在上面的示例中,MLflow 会将 utils.py 复制到 code/utils.py,而不是 code/src/utils.py。因此,它必须导入为 from utils import my_func,而不是 from src.utils import my_func。然而,这可能并不令人满意,因为导入路径与原始训练脚本不同。
为了解决这个问题,code_paths 应该指定父目录,在本例中是 code_paths=["src"]。这样,MLflow 将整个 src/ 目录复制到 code/ 下,您的模型代码将能够导入 src.utils。
class MyModel(mlflow.pyfunc.PythonModel):
def predict(self, context, model_input):
from src.utils import my_func
# .. your prediction logic
return prediction
with mlflow.start_run() as run:
mlflow.pyfunc.log_model(
python_model=model,
name="model",
input_example=input_data,
code_paths=["src"], # the whole /src directory will be saved at code/src
)
出于同样的原因,code_paths 选项不处理 code_paths=["../src"] 的相对导入。
code_paths 在加载具有相同模块名称但不同实现的多个模型时的限制
code_paths 选项的当前实现存在一个限制,即它不支持在同一 Python 进程中加载依赖于具有相同名称但不同实现的模块的多个模型,如下例所示:
import importlib
import sys
import tempfile
from pathlib import Path
import mlflow
with tempfile.TemporaryDirectory() as tmpdir:
tmpdir = Path(tmpdir)
my_model_path = tmpdir / "my_model.py"
code_template = """
import mlflow
class MyModel(mlflow.pyfunc.PythonModel):
def predict(self, context, model_input):
return [{n}] * len(model_input)
"""
my_model_path.write_text(code_template.format(n=1))
sys.path.insert(0, str(tmpdir))
import my_model
# model 1
model1 = my_model.MyModel()
assert model1.predict(context=None, model_input=[0]) == [1]
with mlflow.start_run():
info1 = mlflow.pyfunc.log_model(
name="model",
python_model=model1,
code_paths=[my_model_path],
)
# model 2
my_model_path.write_text(code_template.format(n=2))
importlib.reload(my_model)
model2 = my_model.MyModel()
assert model2.predict(context=None, model_input=[0]) == [2]
with mlflow.start_run():
info2 = mlflow.pyfunc.log_model(
name="model",
python_model=model2,
code_paths=[my_model_path],
)
# To simulate a fresh Python process, remove the `my_model` module from the cache
sys.modules.pop("my_model")
# Now we have two models that depend on modules with the same name but different implementations.
# Let's load them and check the prediction results.
pred = mlflow.pyfunc.load_model(info1.model_uri).predict([0])
assert pred == [1], pred # passes
# As the `my_model` module was loaded and cached in the previous `load_model` call,
# the next `load_model` call will reuse it and return the wrong prediction result.
assert "my_model" in sys.modules
pred = mlflow.pyfunc.load_model(info2.model_uri).predict([0])
assert pred == [2], pred # doesn't pass, `pred` is [1]
为了解决这个限制,您可以在加载模型之前从缓存中删除该模块。例如:
model1 = mlflow.pyfunc.load_model(info1.model_uri)
sys.modules.pop("my_model")
model2 = mlflow.pyfunc.load_model(info2.model_uri)
另一种解决方法是为不同的实现使用不同的模块名称。例如:
mlflow.pyfunc.log_model(
name="model1",
python_model=model1,
code_paths=["my_model1.py"],
)
mlflow.pyfunc.log_model(
name="model",
python_model=model2,
code_paths=["my_model2.py"],
)
推荐的项目结构
考虑到 code_paths 的这个限制,推荐的项目结构如下:
my_project/
|-- model.py # Defines the custom pyfunc model
|── train.py # Trains and logs the model
|── core/ # Required modules for prediction
| |── preprocessing.py
| └── ...
└── helper/ # Other helper modules used for training, evaluation
|── evaluation.py
└── ...
这样,您就可以使用 code_paths=["core"] 记录模型,以包含预测所需的模块,同时排除仅用于开发的辅助模块。
验证预测环境
在部署之前验证您的模型是确保生产就绪的关键步骤。MLflow 提供了一些方法来在本地测试您的模型,无论是使用虚拟环境还是 Docker 容器。如果您在验证过程中发现任何依赖项问题,请遵循 如何修复模型中的依赖项错误? 中的指南。
使用虚拟环境测试离线预测
您可以使用 MLflow Models 的 predict API(通过 Python 或 CLI)来对模型进行测试预测。这将从模型 URI 加载您的模型,创建一个包含模型依赖项(在 MLflow 模型中定义)的虚拟环境,并使用该模型运行离线预测。有关 predict API 的更详细用法,请参阅 mlflow.models.predict() 或 CLI 参考。
Python API 自 MLflow 2.10.0 起可用。如果您使用的是旧版本,请使用 CLI 选项。
- Python
- Bash
import mlflow
mlflow.models.predict(
model_uri="runs:/<run_id>/model",
input_data="<input_data>",
)
mlflow models predict -m runs:/<run_id>/model-i <input_path>
使用 mlflow.models.predict() API 可以方便地快速测试您的模型和推理环境。但是,它可能不是对服务的一个完美模拟,因为它不会启动在线推理服务器。尽管如此,这是一个很好的方法来测试您的预测输入是否格式正确。
格式化取决于您的已记录模型 predict() 方法支持的类型。如果模型已使用签名记录,则输入数据应可在 MLflow UI 中查看,或通过 mlflow.models.get_model_info() 查看,该函数有一个 signature 字段。
更一般地说,MLflow 能够支持各种特定于风味的输入类型,例如 TensorFlow 张量。MLflow 还支持非特定于给定风类的类型,例如 pandas DataFrame、numpy ndarray、python Dict、python List、scipy.sparse matrix 和 spark data frame。
使用虚拟环境测试在线推理端点
如果您想通过实际运行在线推理服务器来测试您的模型,您可以使用 MLflow serve API。这将创建一个包含您的模型和依赖项的虚拟环境,与 predict API 类似,但会启动推理服务器并公开 REST 端点。然后,您可以发送测试请求并验证响应。有关 serve API 的更详细用法,请参阅 CLI 参考。
mlflow models serve -m runs:/<run_id>/model -p <port>
# In another terminal
curl -X POST -H "Content-Type: application/json" \
--data '{"inputs": [[1, 2], [3, 4]]}' \
https://:<port>/invocations
虽然这是部署前测试模型的可靠方法,但一个缺点是虚拟环境不会吸收您机器与生产环境之间的操作系统级别差异。例如,如果您使用 MacOS 作为本地开发机器,但您的部署目标在 Linux 上运行,您可能会遇到一些在虚拟环境中无法重现的问题。
在这种情况下,您可以使用 Docker 容器来测试您的模型。虽然它不像虚拟机那样提供完整的操作系统级别隔离(例如,我们无法在 Linux 机器上运行 Windows 容器),但 Docker 涵盖了一些常见的测试场景,例如运行不同版本的 Linux 或在 Mac 或 Windows 上模拟 Linux 环境。
使用 Docker 容器测试在线推理端点
MLflow CLI 和 Python 的 build-docker API 能够构建一个基于 Ubuntu 的 Docker 镜像来服务您的模型。该镜像将包含您的模型和依赖项,并且还有一个用于启动推理服务器的入口点。与 serve API 类似,您可以发送测试请求并验证响应。有关 build-docker API 的更详细用法,请参阅 CLI 参考。
mlflow models build-docker -m runs:/<run_id>/model -n <image_name>
docker run -p <port>:8080 <image_name>
# In another terminal
curl -X POST -H "Content-Type: application/json" \
--data '{"inputs": [[1, 2], [3, 4]]}' \
https://:<port>/invocations
故障排除
如何修复模型服务中的依赖项错误
模型部署中最常见的麻烦之一是依赖项问题。在记录或保存模型时,MLflow 会尝试推断模型依赖项并将其作为 MLflow 模型元数据的一部分进行保存。然而,这可能并不总是完整的,并且会遗漏某些依赖项,例如某些库的 [extras] 依赖项。这可能导致模型服务期间出现错误,例如 "ModuleNotFoundError" 或 "ImportError"。以下是一些有助于诊断和修复缺失依赖项错误的步骤。
为了减少出现依赖项错误的可能性,您可以在保存模型时添加 input_example。这使得 MLflow 能够在保存模型之前执行模型预测,从而捕获预测过程中使用的依赖项。有关此参数的更详细用法,请参阅 模型输入示例。
1. 检查缺失的依赖项
错误消息中列出了缺失的依赖项。例如,如果您看到以下错误消息:
ModuleNotFoundError: No module named 'cv2'
2. 尝试使用 predict API 添加依赖项
现在您知道了缺失的依赖项,可以创建一个新的模型版本并包含正确的依赖项。然而,为了尝试新依赖项而创建新模型可能有点繁琐,特别是因为您可能需要多次迭代才能找到正确的解决方案。取而代之的是,您可以使用 mlflow.models.predict() API 来测试您的更改,而无需在排除安装错误时反复重新记录模型。
为此,请使用 pip-requirements-override 选项指定 pip 依赖项,例如 opencv-python==4.8.0。
- Python
- Bash
import mlflow
mlflow.models.predict(
model_uri="runs:/<run_id>/<model_path>",
input_data="<input_data>",
pip_requirements_override=["opencv-python==4.8.0"],
)
mlflow models predict \
-m runs:/<run_id>/<model_path> \
-I <input_path> \
--pip-requirements-override opencv-python==4.8.0
指定的依赖项将安装到虚拟环境中,此外(或代替)模型元数据中定义的依赖项。由于这不会修改模型,因此您可以快速安全地迭代以找到正确的依赖项。
请注意,对于 Python 实现中的 input_data 参数,该函数接受您的模型 predict() 函数支持的 Python 对象。一些示例可能包括特定于风类的输入类型,如 TensorFlow 张量,或更通用的类型,如 pandas DataFrame、numpy ndarray、python Dict 或 python List。在使用 CLI 时,我们无法传递 Python 对象,而是需要传递一个包含输入负载的 CSV 或 JSON 文件的路径。
pip-requirements-override 选项自 MLflow 2.10.0 起可用。
3. 更新模型元数据
一旦找到正确的依赖项,您就可以使用 mlflow.models.update_model_requirements() API 更新已记录模型的依赖项。
import mlflow
mlflow.models.update_model_requirements(
model_uri="runs:/<run_id>/<model_path>",
operation="add",
requirement_list=["opencv-python==4.8.0"],
)
请注意,您也可以利用 CLI 来更新模型要求:
mlflow models update-pip-requirements -m runs:/<run_id>/<model_path> add "opencv-python==4.8.0"
或者,您可以通过在记录模型时指定 extra_pip_requirements 选项来记录带有更新依赖项的新模型。
import mlflow
mlflow.pyfunc.log_model(
name="model",
python_model=python_model,
extra_pip_requirements=["opencv-python==4.8.0"],
input_example=input_data,
)
如何在使用 mlflow.models.predict 时启用安装预发布版本
如果您使用 mlflow.models.predict 在服务前验证模型,并遇到类似以下的错误:
hint: `mlflow-skinny` was requested with a pre-release marker (e.g.,
mlflow-skinny==3.2.0rc0), but pre-releases weren't enabled (try:
`--prerelease=allow`)
您可以通过 extra_envs 字段设置环境变量 UV_PRERELEASE=allow 来解决此问题。这使得 uv 在环境设置期间能够安装预发布包。
mlflow.models.predict(
model_uri=model_info.model_uri,
input_data=["a", "b", "c"],
extra_envs={"UV_PRERELEASE": "allow"},
)
如何迁移 Anaconda 依赖项以更改许可证
Anaconda Inc. 更新了其 anaconda.org 频道的服务条款。根据新的服务条款,如果您依赖 Anaconda 的打包和分发,您可能需要商业许可证。有关更多信息,请参阅 Anaconda Commercial Edition FAQ。您对任何 Anaconda 频道的使用均受其服务条款的约束。
在 MLflow v1.18 之前的版本中记录的 MLflow 模型默认使用 conda defaults 频道(https://repo.anaconda.com/pkgs)作为依赖项。由于这个许可证更改,MLflow 已停止对使用 MLflow v1.18 及更高版本记录的模型使用 defaults 频道。现在记录的默认频道是 conda-forge,它指向社区管理的 https://forge.conda.org.cn。
如果您在 MLflow v1.18 之前记录了一个模型,而没有从该模型的 conda 环境中排除 defaults 频道,则该模型可能存在您可能不希望的 defaults 频道依赖项。要手动确认模型是否具有此依赖项,您可以检查随已记录模型一起打包的 conda.yaml 文件中的 channel 值。例如,一个模型的 conda.yaml 文件,其中包含 defaults 频道依赖项,可能如下所示:
name: mlflow-env
channels:
- defaults
dependencies:
- python=3.8.8
- pip
- pip:
- mlflow==2.3
- scikit-learn==0.23.2
- cloudpickle==1.6.0
如果您想更改模型环境中使用的频道,您可以通过指定 log_model() 的 conda_env 参数,使用新的 conda.yaml 将模型重新注册到模型注册表中。
有关log_model() API的更多信息,请参阅MLflow文档中您正在使用的模型风味,例如mlflow.sklearn.log_model()。