定义运行时环境

自v1.3.20版本起,BentoML引入了一个新的Python SDK,用于配置Bento的运行时环境。你可以在service.py文件中与BentoML Service代码一起进行设置。

本质上,运行时环境包含一组Bento构建选项,例如:

  • Python版本

  • 操作系统(发行版)

  • 系统软件包

  • Python软件包

  • 软件包安装选项

  • 自定义命令

重要提示

我们建议你使用新的Python SDK来配置运行时环境。它允许你将所有构建配置集成到单个文件中,并利用Python的动态特性(如子类化)实现更多定制。如果你更喜欢之前使用bentofile.yamlpyproject.toml的方法,请参阅Bento构建选项文档。

基本用法

创建一个具有所需配置的Image实例,并将其附加到你的Service:

import bentoml

my_image = bentoml.images.Image(python_version='3.11') \
    .python_packages("torch", "transformers")

@bentoml.service(image=my_image)
class MyService:
    # Service implementation

此示例指定:

  • 使用Python 3.11作为运行时版本

  • 安装PyTorch和Transformers库

注意

目前,尚无法为多Service Bento部署中的每个Service定义唯一的运行时环境,但这已在我们的路线图上。目前,你只需配置入口Service(即调用其他Service作为依赖项的Service)的运行时镜像即可。

构造函数参数

你可以使用以下参数初始化一个Image实例:

  • python_version: 要使用的Python版本。如果未指定,则默认为当前构建环境中的Python版本。

  • distro: 基础镜像的Linux发行版。默认为debian

  • base_image: 自定义Docker基础镜像,它会覆盖镜像的所有其他属性。

  • lock_python_packages: 是否锁定所有软件包版本和依赖项。默认为True。如果你已经为所有软件包指定了版本,则可以将其设置为False

示例用法:

import bentoml

# Specify Python version and distro
image_two = bentoml.images.Image(python_version='3.11', distro='alpine')

# Specify a custom base image and disable version locking
image_one = bentoml.images.Image(base_image="python:3.11-slim-buster", lock_python_packages=False)

配置方法

Image类提供了多种方法来定制构建过程。

python_packages()

通过直接列出特定的Python依赖项来安装它们。它支持版本约束。

import bentoml

image = bentoml.images.Image(python_version='3.11') \
    .python_packages(
        "numpy>=1.20.0",
        "pandas",
        "scikit-learn==1.2.0",
        "git+https://github.com/username/mylib.git@main"
    )

注意

你无需在此字段中指定BentoML作为依赖项,因为当前版本的BentoML将默认添加到列表中。但是,你可以通过指定不同的BentoML版本来覆盖此设置。

GitHub软件包

要包含来自GitHub仓库的软件包,请使用pip requirements文件格式。你可以指定要安装的仓库URL、分支、标签或提交,以及Python软件包不在仓库根目录下的子目录。

import bentoml

image = bentoml.images.Image(python_version='3.11') \
    .python_packages(
        "git+https://github.com/username/repository.git@branch_name",
        "git+https://github.com/username/repository.git@v1.0.0",
        "git+https://github.com/username/repository.git@abcdef1234567890abcdef1234567890abcdef12",
        "git+https://github.com/username/repository.git@branch_name#subdirectory=package_dir"
    )

如果你的项目依赖于私有GitHub仓库,你可以通过SSH包含该仓库中的Python软件包。请确保运行BentoML的环境配置了适当的SSH密钥,并且这些密钥已添加到GitHub

import bentoml

image = bentoml.images.Image(python_version='3.11') \
    .python_packages("git+ssh://git@github.com/username/repository.git@branch_name")

预构建的whl文件

将预构建的whl文件放在项目内的wheels/目录中,然后将其作为本地路径在.python_packages()列表中指定,即可将其包含在你的Bento中。

import bentoml

image = bentoml.images.Image(python_version='3.11') \
    .python_packages("./wheels/foo-0.1.0-py3-none-any.whl")

你也可以在requirements.txt文件中列出本地whl文件的路径。参见下方的requirements_file()

PyPI软件包

要配置PyPI索引和其他pip选项(例如自定义软件包源和私有仓库):

import bentoml

# Using custom PyPI index
image = bentoml.images.Image(python_version='3.11') \
    .python_packages(
        "--index-url https://download.pytorch.org/whl/cpu",
        "torch",
        "torchvision",
        "torchaudio"
    )

# Configuring multiple PyPI options, including a private repository
image = bentoml.images.Image(python_version='3.11') \
    .python_packages(
        "--index-url https://pypi.ac.cn/simple", # Default PyPI index
        "--extra-index-url https://my.private.pypi/simple", # Additional private repository
        "--trusted-host my.private.pypi", # Mark the private host as trusted
        "my-private-package"
    )

如果你的私有软件包需要认证:

import bentoml

# Securely configure authentication for a private PyPI repository
image = bentoml.images.Image(python_version='3.11') \
    .python_packages(
        # Use environment variables for security
        "--extra-index-url https://${USERNAME}:${PASSWORD}@my.private.pypi/simple",
        "my-private-package"
    )

@bentoml.service(
    image=image,
    envs=[
        {"name": "USERNAME"},  # You can omit value and set it when deploying the Service
        {"name": "PASSWORD"},
    ]
)
class MyService:
   ...

requirements_file()

你也可以从requirements.txt文件安装Python依赖项,而不是使用.python_packages()

import bentoml

image = bentoml.images.Image(python_version='3.11') \
    .requirements_file("./path/to/requirements.txt")

system_packages()

在运行时环境中安装系统级依赖项。

import bentoml

image = bentoml.images.Image(python_version='3.11') \
    .system_packages("curl", "git")

run()

在构建过程中运行自定义命令。它支持与其他方法链式调用。这意味着你可以自由组合上述所有方法来创建自定义的运行时环境。

这是一个示例:

import bentoml

image = bentoml.images.Image(python_version='3.11') \
    .run('echo "Starting build process..."') \
    .system_packages("curl", "git") \
    .run('echo "System packages installed"') \
    .python_packages("pillow", "fastapi") \
    .run('echo "Python packages installed"')

run()是上下文相关的。例如,放在.python_packages()之前的命令在安装Python依赖项之前执行,而放在之后的命令则在安装之后执行。这允许你以正确的顺序执行某些任务。

run_script()

在构建过程中运行脚本文件。它支持与其他方法链式调用。这对于执行更复杂的逻辑或第三方CLI(例如下载模型或设置配置文件)非常有用。

例如,你可以编写一个shell脚本如下:

scripts/setup.sh
#!/bin/bash
huggingface-cli download lukbl/LaTeX-OCR --repo-type space --local-dir models

重要提示

Shebang行(第一行以#!开头)非常重要,因为它告诉构建过程如何执行脚本。例如,对于Python脚本,你可以使用#!/usr/bin/env python。脚本的执行方式是:

./scripts/setup.sh

要在镜像构建过程中包含此脚本:

import bentoml

image = bentoml.images.Image(python_version='3.11') \
    .python_packages("torch", "pillow") \
    .run_script("scripts/setup.sh")

排除文件

你可以定义一个.bentoignore文件,以便在构建Bento时排除特定文件。它使用标准的pathspec模式,指定的路径应相对于build_ctx目录(通常,这是与service.py文件所在的同一目录)。这有助于减小Bento的大小,并保持你的运行时干净和高效。

这是一个示例:

.bentoignore
__pycache__/
*.py[cod]
*$py.class
.ipynb_checkpoints/
training_data/
venv/

下一步

配置完环境规范后,你可以构建Bento将你的Service部署到BentoCloud