Bento 构建选项

构建选项是指将 BentoML 项目构建成 Bento 的一组运行时规范。您可以在 pyproject.toml 文件中的 [tool.bentoml.build] 部分或 YAML 文件(通常命名为 bentofile.yaml)中定义它们。

重要提示

自 v1.3.20 版本起,BentoML 引入了用于定义运行时规范的新 Python SDK。这提供了使用 pyproject.tomlbentofile.yaml 的程序化替代方案。虽然 BentoML 保持与这些配置文件的兼容性,但我们建议使用新的 Python SDK 来定义您的运行时环境。

可用字段

service

service 是一个必需字段,指向 Service 对象的位置。它通常定义为 service: "service:class-name"

  • service:Python 模块,即 service.py 文件。

  • class-name:在 service.py 中创建的基于类的 Service 的名称,使用 @bentoml.service 装饰器修饰。如果 service.py 中有多个 Services,您可以在配置中指定接收用户请求的主 Service。其他 Services 将与此主 Service 一起启动。

[tool.bentoml.build]
service = "service:MyService"
service: "service:MyService"

description

description 允许您为 Bento 添加相关文档注释,文档可以是纯文本或 Markdown 格式。您可以内联提供描述或引用外部文件。

内联定义描述

[tool.bentoml.build]
service = "service:svc"
description = "This is an inline description for the Service. BentoML is awesome!"

使用文件定义描述

[tool.bentoml.build]
service = "service:svc"
description = "file: ./README.md"

内联定义描述

service: "service:svc"
description: |
    ## Description For My Bento 🍱

    Use **any markdown syntax** here!

    > BentoML is awesome!

使用文件定义描述

service: "service:svc"
description: "file: ./README.md"

对于源自外部文件的描述,您可以使用绝对路径或相对路径。确保在运行 bentoml build 命令时,文件存在于指定的路径。对于相对路径,参考点是 build_ctx,默认情况下是执行 bentoml build 的目录。

labels

labels 是与对象关联的键值对。在 BentoML 中,Bentos 和模型都可以附加标签。这些标签可以用于各种目的,例如在 BentoCloud 中识别或分类 Bentos 和模型。您可以随时添加或修改标签。

[tool.bentoml.build.labels]
owner = "bentoml-team"
stage = "not-ready"
labels:
  owner: bentoml-team
  stage: not-ready

args

定义了Service 的模板参数后,您可以使用 args 参数动态设置相应的值。

例如,您可能有如下模板

service.py
from pydantic import BaseModel
import bentoml

class BentoArgs(BaseModel):
    model_name: str
    gpu: int = 8
    gpu_type: str = "nvidia-h200-141gb"

args = bentoml.use_arguments(BentoArgs)

@bentoml.service(
    resources={
        "gpu": args.gpu,
        "gpu_type": args.gpu_type
    }
)
class LLM:
    model = bentoml.models.HuggingFaceModel(args.model_name)

然后您可以在构建配置中为这些参数提供值

[tool.bentoml.build.args]
model_name = deepseek-ai/DeepSeek-V3
gpu = 4
args:
  model_name: deepseek-ai/DeepSeek-V3
  gpu: 4

include

您可以使用 include 字段在构建 Bento 时包含特定文件。它支持通配符和目录模式匹配。例如,将其设置为 *.py 表示现有 build_ctx 下的所有 Python 文件都将被打包到 Bento 中。

[tool.bentoml.build]
include = ["data/", "**/*.py", "config/*.json", "path/to/a/file.csv"]
include:
  - "data/"
  - "**/*.py"
  - "config/*.json"
  - "path/to/a/file.csv"

如果未指定此字段,BentoML 默认包含 build_ctx 下的所有文件,但 exclude 字段中明确设置的文件除外。

注意

两 个 includeexclude 字段都支持gitignore 风格的模式匹配

exclude

您使用 exclude 字段在构建 Bento 时排除特定文件。当工作目录中有许多文件时,这非常有用,因为您只需要指定要忽略的文件。

设置此字段时,您需要指定相对于 build_ctx 目录的文件路径规范(类似于 .gitignore)。

[tool.bentoml.build]
include = ["data/", "**/*.py"]
exclude = ["tests/", "secrets.key"]
include:
  - "data/"
  - "**/*.py"
exclude:
  - "tests/"
  - "secrets.key"

或者,在 build_ctx 目录中创建 .bentoignore 文件,如下所示

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

注意

exclude 始终在 include 之后应用。

models

您可以使用字符串模型标签或字典来指定用于构建 Bento 的模型。如果您在配置中未定义模型,则使用 Service 中指定的模型来构建 Bento。

[tool.bentoml.build]
models = [
  "summarization-model:latest",
  { tag = "summarization-model:version1", filter = "label:staging", alias = "summarization-model_v1" }
]
models:
  - "summarization-model:latest" # A string model tag
  - tag: "summarization-model:version1"  # A dictionary
    filter: "label:staging"
    alias: "summarization-model_v1"
  • tag:模型的名称和版本,用冒号分隔。

  • filter:此字段使用 BentoCloud 中相同的过滤语法。您可以使用过滤器列出特定模型,例如具有相同标签的模型。您可以为一个模型添加多个逗号分隔的过滤器。

  • alias:模型的别名。如果指定了此项,您可以在代码中直接使用,例如 bentoml.models.BentoModel(alias)

Python 包

您可以使用 python.packages 字段指定给定 Bento 所需的 Python 包。BentoML 允许您指定所需版本,并从自定义 PyPI 源或从 GitHub 仓库安装包。如果某个包没有指定版本,BentoML 会在构建 Bento 时锁定当前平台和 Python 的所有 Python 包版本。

使用 pyproject.toml 文件时,您可以通过 project.dependencies 定义所需的 Python 包

[project]
dependencies = [
  "numpy",
  "matplotlib==3.5.1",
  "package>=0.2,<0.3",
  "torchvision==0.9.2",
  "git+https://github.com/username/mylib.git@main",
]

这等同于使用 python.packages

[tool.bentoml.build.python]
packages = [
  "numpy",
  "matplotlib==3.5.1",
  "package>=0.2,<0.3",
  "torchvision==0.9.2",
  "git+https://github.com/username/mylib.git@main"
]

如果同时指定 project.dependenciestool.bentoml.build.python.packages,则会将依赖项合并。

python:
  packages:
    - "numpy"
    - "matplotlib==3.5.1"
    - "package>=0.2,<0.3"
    - "torchvision==0.9.2"
    - "git+https://github.com/username/mylib.git@main"

注意

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

如果您已经有一个定义项目所需 Python 包的 requirements.txt 文件,您也可以直接提供 requirements.txt 文件的路径

[tool.bentoml.build.python]
requirements_txt = "./project-a/ml-requirements.txt"
python:
  requirements_txt: "./project-a/ml-requirements.txt"

GitHub 仓库

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

[tool.bentoml.build.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",
]
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"

您可以使用 pack_git_packages 选项(默认为 true)来控制是否在构建过程中克隆和打包这些 GitHub 包。这对于通过标准 PyPI 源可能无法获得的依赖项,或直接从 Git 仓库确保依赖项的特定版本(例如,标签和提交)的一致性非常有用。

[tool.bentoml.build.python]
pack_git_packages = true
packages = ["git+https://github.com/username/repository.git@abcdef1234567890abcdef1234567890abcdef12"]
python:
  pack_git_packages: true  # Enable packaging of Git-based packages
  packages:
    - "git+https://github.com/username/repository.git@abcdef1234567890abcdef1234567890abcdef12"

请注意,lock_packages 控制是否在构建 Bento 时锁定所有依赖项的版本,而不仅仅是来自 Git 的依赖项。禁用 pack_git_packages 也会禁用包锁定 (lock_packages),除非明确设置。

注意

BentoML 总是尝试针对 Linux x86_64 平台锁定包版本以匹配部署目标。如果 Bento 包含带有环境标记的依赖项或传递依赖项,它们将针对 Linux x86_64 平台解析。

例如,如果 Bento 需要 torchnvidia-* 包也将被包含到最终的锁定结果中,尽管它们仅适用于 Linux x86_64 平台。

如果您想为不同平台构建 Bento,可以在 bentoml build 命令中传递 --platform 选项,并指定目标平台的名称。例如

$ bentoml build --platform macos

使用私有 GitHub 仓库

  1. 通过 SSH 从仓库包含 Python 包。请确保运行 BentoML 的环境已配置适当的 SSH 密钥,并且这些密钥已添加到 GitHub

    [tool.bentoml.build.python]
    packages = [
        "git+ssh://git@github.com/username/repository.git@branch_name"  # The SSH URL for the repository
    ]
    
    python:
      packages:
        - "git+ssh://git@github.com/username/repository.git@branch_name" # The SSH URL for the repository
    
  2. 确保启用了 pack_git_packages,以便您的私有包可用于构建。

  3. 设置环境变量 BENTOML_ENABLE_FEATURES=no_image

Pip 安装选项

您可以在 python 字段中提供额外的 pip install 参数。如果提供,这些参数将应用于 python.packages 中定义的所有包以及 requirements_txt 文件。

[tool.bentoml.build.python]
requirements_txt = "./requirements.txt"
index_url = "https://my.mirror.com/simple"
no_index = false
trusted_host = ["pypi.python.org", "my.mirror.com"]
find_links = ["https://download.pytorch.org/whl/cu80/stable.html"]
extra_index_url = [
    "https://<other api token>:@my.mirror.com/pypi/simple",
    "https://pypi.python.org/simple"
]
pip_args = "--pre -U --force-reinstall"
python:
  requirements_txt: "./requirements.txt"
  index_url: "https://my.mirror.com/simple"
  no_index: false
  trusted_host:
    - "pypi.python.org"
    - "my.mirror.com"
  find_links:
    - "https://download.pytorch.org/whl/cu80/stable.html"
  extra_index_url:
    - "https://<other api token>:@my.mirror.com/pypi/simple"
    - "https://pypi.python.org/simple"
  pip_args: "--pre -U --force-reinstall"

注意

默认情况下,BentoML 会缓存所有本地镜像构建中的 pip artifacts 以加快构建过程.

如果您想强制重新下载而不是使用缓存,您可以在 bentofile.yaml 文件中指定 pip_args: "--no-cache-dir" 选项,或在 bentoml containerize 命令中使用 --no-cache 选项。例如

$ bentoml containerize my_bento:latest --no-cache

PyPI 包锁定

默认情况下,BentoML 会自动锁定所有包版本及其依赖图中的所有包,并生成一个包含所有包及其确切版本的 requirements.txt 文件。此过程内部使用 uv pip compile

如果您已经为每个包指定了版本或想跳过此过程,您可以通过将 lock_packages 字段设置为 false 来选择性地禁用此行为

[tool.bentoml.build.python]
requirements_txt = "./requirements.txt"
lock_packages = false
python:
  requirements_txt: "./requirements.txt"
  lock_packages: false

Python 选项表

下表提供了 python 字段的完整可用配置列表。

字段

描述

requirements_txt

自定义 requirements.txt 文件的路径

packages

要包含在此 Bento 中的包

lock_packages

是否锁定包

index_url

--index-url pip 参数的输入

no_index

是否包含 --no-index pip 参数

trusted_host

使用 --trusted-host pip 参数作为输入的受信任主机列表

find_links

使用 --find-links pip 参数作为输入的要查找的链接列表

extra_index_url

使用 pip 参数作为输入的额外索引 URL 列表

pip_args

安装包时要添加的任何额外 pip 参数

wheels

要包含在 Bento 中的 wheel 文件的路径列表

envs

环境变量对于以安全灵活的方式管理配置和密钥非常重要。它们允许您配置 BentoML Services,而无需硬编码敏感信息,例如 API 密钥、数据库凭据或在不同环境之间可能更改的可配置参数。

您可以在 bentofile.yaml 文件中的 envs 键下设置环境变量。每个环境变量都使用 namevalue 键定义。例如

[tool.bentoml.build]
envs = [
     { name = "VAR_NAME", value = "value" },
     { name = "API_KEY", value = "your_api_key_here" }
]
envs:
  - name: "VAR_NAME"
    value: "value"
  - name: "API_KEY"
    value: "your_api_key_here"

指定的环境变量将注入到 Bento 容器中。

注意

如果您将 BentoML Service 部署到 BentoCloud,您可以通过配置中的 envs 或在运行 bentoml deploy 时使用 --env 标志来设置环境变量。有关详细信息,请参阅环境变量

conda

可以在 conda 字段下指定 Conda 依赖项。例如

[tool.bentoml.build.conda]
channels = ["default"]
dependencies = ["h2o"]
pip = ["scikit-learn==1.2.0"]
conda:
  channels:
    - default
  dependencies:
    - h2o
  pip:
    - "scikit-learn==1.2.0"
  • channels:要使用的自定义 conda 频道。如果未指定,BentoML 将默认使用社区维护的 conda-forge 频道。

  • dependencies:要包含在环境中的自定义 conda 依赖项。

  • pip:要包含的特定 pip conda 依赖项。

或者,您可以将现有 conda 环境中的所有依赖项导出到 environment.yml 文件中,并在您的 pyproject.tomlbentofile.yaml 文件中提供此文件。如果指定了此文件,它将覆盖任何其他指定的选项。

导出 conda 环境

conda env export > environment.yml

将其添加到配置中

[tool.bentoml.build.conda]
environment_yml = "./environment.yml"
conda:
  environment_yml: "./environment.yml"

注意

与 Python 包不同,BentoML 不支持自动锁定 conda 包版本。我们建议您在配置文件中指定版本。

另请参阅

提供 conda 选项时,BentoML 将选择一个 Docker 基础镜像,该镜像在生成的 Dockerfile 中预装了 Miniconda。请注意,只有 debianalpine 发行版支持 conda。在下面的 docker 部分了解更多信息。

docker

BentoML 可以轻松将 Bento 部署到 Docker 容器。它提供了一组选项,用于自定义从 Bento 生成的 Docker 镜像。

以下 docker 字段包含一些基本的 Docker 配置

[tool.bentoml.build.docker]
distro = "debian"
python_version = "3.11"
system_packages = ["libblas-dev", "liblapack-dev", "gfortran"]
docker:
  distro: debian
  python_version: "3.11"
  system_packages:
    - libblas-dev
    - liblapack-dev
    - gfortran

BentoML 使用BuildKit,这是一个缓存高效的构建工具包,用于将 Bentos 容器化。BuildKit 随附于Docker 18.09。这意味着如果您通过 Docker Desktop 使用 Docker,BuildKit 将默认可用。如果您使用的是独立版本的 Docker,可以按照此处的说明安装 BuildKit。

以下部分提供了特定 Docker 配置的详细说明。

操作系统发行版

BentoML 目前支持以下操作系统发行版

  • debian默认值,类似于 Ubuntu

  • alpine:基于 Alpine Linux 的最小 Docker 镜像

  • ubi8:Red Hat Universal Base Image

  • amazonlinux:Amazon Linux 2

安装脚本

对于高级 Docker 自定义,您还可以使用 setup_script 字段在镜像构建过程中注入任何脚本。例如,对于 NLP 项目,您可以通过设置以下值在镜像中预下载 NLTK 数据。

[tool.bentoml.build.python]
packages = ["nltk"]
[tool.bentoml.build.docker]
setup_script = "./setup.sh"
python:
  packages:
    - "nltk"
docker:
  setup_script: "./setup.sh"

setup.sh 文件中

#!/bin/bash
set -euxo pipefail

echo "Downloading NLTK data.."
python -m nltk.downloader all

构建一个新的 Bento,然后运行 bentoml containerize MY_BENTO --progress plain 查看 Docker 镜像构建进度。新构建的 Docker 镜像将包含预下载的 NLTK 数据集。

提示

处理 bash 脚本时,我们建议您在开头添加 set -euxo pipefail。特别是当缺少 set -e 时,脚本将在 bentoml containerize 期间静默失败,而不会引发异常。了解更多关于Bash Set builtin的信息。

也可以提供 Python 脚本来初始化 Docker 镜像。示例如下

[tool.bentoml.build.python]
packages = ["nltk"]
[tool.bentoml.build.docker]
setup_script = "./setup.py"
python:
  packages:
    - "nltk"
docker:
  setup_script: "./setup.py"

setup.py 文件中

#!/usr/bin/env python

import nltk

print("Downloading NLTK data..")
nltk.download('treebank')

注意

注意上面示例脚本第一行中的 #!/bin/bash#!/usr/bin/env python。它们被称为 Shebang,并且是提供给 BentoML 的安装脚本所必需的。

安装脚本总是在指定的 Python 包、conda 依赖项和系统包安装后执行。因此,您可以在安装脚本中导入和利用这些库进行初始化过程。

Docker 选项表

下表提供了 docker 字段的完整可用配置列表。

字段

描述

distro

Docker 镜像上的操作系统发行版。默认为 debian

python_version

Docker 镜像上的 Python 版本。默认为构建环境中的 Python 版本。

cuda_version

已弃用。用于在 Docker 镜像上运行需要 GPU 的模型的 CUDA 版本。当使用 PyTorch 或 TensorFlow 在 GPU 上运行模型时,我们建议您使用 pip 直接安装它们及其各自的 CUDA 依赖项。这意味着您无需单独配置 cuda_version。有关详细信息,请参阅使用 GPU

system_packages

将安装在容器中的系统包。

setup_script

将在 Docker 构建过程中执行的 Python 或 Shell 脚本。

base_image

用户提供的 Docker 基础镜像。这将覆盖镜像的所有其他自定义属性。

dockerfile_template

通过提供一个扩展默认 Dockerfile 的 Jinja2 模板来自定义生成的 Dockerfile。

自定义构建上下文

对于作为大型代码库一部分并与本地其他 Python 模块交互的项目,或者包含多个 Bentos/Services 的项目,可能无法将所有 Service 定义代码和 pyproject.toml(或 bentofile.yaml)文件放在项目的根目录中。

BentoML 允许将 Service 定义和 pyproject.toml(或 bentofile.yaml)文件放置在项目目录中的任何位置。在这种情况下,在运行 bentoml build 命令时指定 build_ctxbentofile 参数。

  • build_ctx:构建上下文表示 Python 项目的工作目录。在构建过程中,它将被添加到 PYTHONPATH 的前面,确保本地 Python 模块的正确导入。默认情况下,它被设置为执行 bentoml build 命令的当前目录。

  • bentofile:默认情况下,它指向构建上下文中的 pyproject.toml(或 bentofile.yaml)文件。

要自定义它们的值,请使用以下方式

bentoml build -f ./src/my_project_a/bento_fraud_detect.yaml ./src/

结构

默认情况下,所有创建的 Bentos 都存储在 BentoML Bento Store 中,它本质上是一个本地目录。您可以通过运行以下命令进入特定的 Bento 目录

cd $(bentoml get BENTO_TAG -o path)

在目录内部,您可能会看到不同的文件和子目录,具体取决于 pyproject.toml(或 bentofile.yaml)中的配置。一个典型的 Bento 包含以下关键子目录

  • src:包含在 include 字段中指定的文件。这些文件是相对于用户 Python 代码的 CWD(当前工作目录)的,这使得在用户代码内部导入相对模块和文件路径成为可能。

  • apis:包含从 Service 的 API 规范自动生成的 API 定义。

  • env:包含 Bento 初始化相关的环境文件。这些文件是根据 pyproject.toml(或 bentofile.yaml)中指定的构建选项生成的。

警告

我们不建议您直接修改 Bento 中的文件,除非是为了调试目的。