
ZenML 集成 BentoML Model Deployer 实战从 Bento 构建到本地 HTTP 与容器化模型部署【免费下载链接】zenmlZenML : One AI Platform from Pipelines to Agents. https://zenml.io.项目地址: https://gitcode.com/GitHub_Trending/ze/zenml本文以 ZenML 官方文档《BentoML》为骨架系统讲解如何借助 ZenML 的 BentoML 集成将训练完成的模型打包为 Bento 制品并通过bentoml_model_deployer_step以本地 HTTP 服务器或容器化服务两种方式部署上线同时结合仓库源码剖析底层实现帮助你在实际项目中快速落地一套标准化、可持续演进的模型服务方案。BentoML 与 ZenML 的集成定位BentoML 是一个开源的机器学习模型服务框架可用于在本地环境、云环境或 Kubernetes 环境中部署模型。在 ZenML 中BentoML Model Deployer 是 Model Deployer 栈组件众多 flavor风味实现之一随 BentoML 集成一起提供。它能够在本地运行的 HTTP 服务器上部署并管理 BentoML 模型或 Bento 制品。在 ZenML 的模型部署体系中BentoML 集成支持两条部署路径本地 HTTP 服务器将 Bento 作为守护进程在本地持续运行适合本地开发与快速测试容器化服务将 Bento 构建为 Docker 镜像并推送到 ZenML Stack 的容器注册中心再以容器方式在本地运行镜像可以进一步被带到任何远程环境执行。⚠️ 需要注意在 BentoML 生态中Yatai与bentoctl才是负责把 Bento 部署到 Kubernetes 集群和云平台的工具。其中bentoctl目前已废弃可能无法兼容最新的 BentoML 版本。而 ZenML 的 BentoML 集成负责在本地开发与生产场景下完成前两条路径的部署。从源码结构看该集成位于src/zenml/integrations/bentoml/包含以下核心模块flavors/bentoml_model_deployer_flavor.py定义BentoMLModelDeployerConfig与 flavor 注册信息model_deployers/bentoml_model_deployer.pyBentoMLModelDeployer栈组件实现负责服务的创建、启动、停止与删除services/bentoml_local_deployment.py、services/bentoml_container_deployment.py两种部署模式的服务类services/deployment_type.py定义BentoMLDeploymentType枚举local/containersteps/bento_builder.py、steps/bentoml_deployer.py内置的 Bento 构建步骤与部署步骤constants.pyDEFAULT_BENTO_FILENAME、默认端口、健康检查路径等常量。何时使用 BentoML Model Deployer官方文档建议在以下场景选择 BentoML Model Deployer希望在组织内部标准化模型的部署方式让所有模型以一致的方式进入生产环境希望以简单的方式完成模型部署同时保留在合适的时机将模型平滑升级为生产级解决方案的能力如果期望用 Kubernetes 等方案部署模型则可以参考 ZenML 提供的其他 Model Deployer Flavors例如 Seldon Core、MLflow 等。此外BentoML 也支持更复杂的生产级部署形态将 ZenML 管道中构建好的 Bento通过bentoctl部署到 AWS Lambda、AWS SageMaker、Google Cloud Functions、Google Cloud AI Platform、Azure Functions 等云环境。需要说明的是官方文档同时标注bentoctl集成实现仍在推进中且该 CLI 目前已废弃可能无法兼容最新 BentoML 版本请以实际使用的 BentoML 版本为准。 补充提示ZenML 官方文档Model Deployers 总览已给出弃用说明——Model Deployer 栈组件正逐步被更灵活的 Deployer 组件与 Pipeline Deployments 范式取代。但 Model Deployer 集成仍保持向后兼容可用BentoML 这一实现适合作为理解模型服务化与学习 ZenML 部署抽象的入口。安装与注册快速启用 BentoML 集成安装集成包要在本地机器上部署模型首先需要安装 BentoML 集成所需的 Python 包zenml integration install bentoml -y该命令会安装bentoml及相关依赖并在 ZenML 中注册 BentoML 集成提供的 flavor、步骤与服务实现。注册 Model Deployer 栈组件安装完成后通过以下命令注册 BentoML model deployerzenml model-deployer register bentoml_deployer --flavorbentoml注册完成后ZenML 集成会以守护进程方式在后台启动一个本地 HTTP 部署服务器持续为最新的模型和 Bento 提供服务。组件配置项service_path从 flavors/bentoml_model_deployer_flavor.py 源码可以看到BentoMLModelDeployerConfig暴露了一个可选配置字段service_path默认BentoML 服务目录的路径。若不提供则使用默认服务路径。在 model_deployers/bentoml_model_deployer.py 中local_path属性决定了部署守护进程配置的存放位置如果用户配置了service_path则优先使用否则按组件 ID 生成本地默认路径GlobalConfiguration().local_stores_path下的子目录并自动创建目录。也就是说不传service_path也能开箱即用它主要用于自定义部署服务元数据的落盘位置。在 CLI 注册时如需指定可写作zenml model-deployer register bentoml_deployer --flavorbentoml --service_path/your/custom/path注册后将该组件加入你的 Stack 即可在管道中使用zenml stack register local_bentoml -m default -a default -o default -d bentoml_deployer --set使用流程总览官方文档推荐的标准使用流程分为三步创建 BentoML Service定义模型服务的核心逻辑输入、输出、预处理与推理 API构建 Bento既可以使用内置的bento_builder_step将模型与 Service 打包成 Bento 制品也可以自行调用bentos.build自定义构建部署 Bento通过bentoml_model_deployer_step将 Bento 部署到本地 HTTP 服务器或容器化服务。下面逐一展开。第一步创建 BentoML ServiceService 是 BentoML 中定义模型如何被服务的核心逻辑。以下示例展示了一个用于服务 torch 模型的基础 Bento Service以 MNIST 手写数字识别为例import bentoml from bentoml.validators import DType, Shape from bentoml.io import PILImage import numpy as np import torch from typing import Annotated # Note: SERVICE_NAME and MODEL_NAME would be defined elsewhere # Note: to_numpy() would be a custom function to convert tensors to numpy arrays bentoml.service( nameSERVICE_NAME, ) class MNISTService: def __init__(self): # load model self.model bentoml.pytorch.load_model(MODEL_NAME) self.model.eval() bentoml.api() async def predict_ndarray( self, inp: Annotated[np.ndarray, DType(float32), Shape((28, 28))] ) - np.ndarray: inp np.expand_dims(inp, (0, 1)) output_tensor await self.model(torch.tensor(inp)) return to_numpy(output_tensor) bentoml.api() async def predict_image(self, f: PILImage) - np.ndarray: assert isinstance(f, PILImage) arr np.array(f) / 255.0 assert arr.shape (28, 28) arr np.expand_dims(arr, (0, 1)).astype(float32) output_tensor await self.model(torch.tensor(arr)) return to_numpy(output_tensor)要点说明bentoml.service(name...)声明一个 Bento Servicename需要与后续构建 Bento 时使用的 Service 名称一致__init__中通过bentoml.pytorch.load_model(MODEL_NAME)加载保存在 BentoML 模型仓库中的模型并置为 eval 模式每个bentoml.api()装饰的方法都暴露为一个 HTTP 推理 API例如predict_ndarray、predict_image参数注解用于声明输入输出的类型与校验规则如DType(float32)校验数据类型、Shape((28, 28))校验张量形状PILImage用于接收图像输入。关于 API 输入输出类型与校验器的完整用法可参考 BentoML 官方 I/O 类型文档。第二步构建 Bento 制品方式一自行构建 Bentobento_builder_step只是为了让生活更简单而存在——你完全可以自己构建 Bento然后在部署步骤中使用它。文档给出的自建思路如下理解它有助于你对 Bento 构建过程做更高度的定制# 1. use the step context to get the output artifact uri context get_step_context() # 2. you can save the model and bento uri as part of the bento labels labels labels or {} labels[model_uri] model.uri labels[bento_uri] os.path.join( context.get_output_artifact_uri(), DEFAULT_BENTO_FILENAME ) # 3. Load the model from the model artifact model load_artifact_from_response(model) # 4. Save the model to a BentoML model based on the model type try: module importlib.import_module(f.{model_type}, bentoml) module.save_model(model_name, model, labelslabels) except importlib.metadata.PackageNotFoundError: bentoml.picklable_model.save_model( model_name, model, ) # 5. Build the BentoML bundle. You can use any of the parameters supported by the bentos.build function. bento bentos.build( serviceservice, models[model_name], versionversion, labelslabels, descriptiondescription, includeinclude, excludeexclude, pythonpython, dockerdocker, build_ctxworking_dir or source_utils.get_source_root(), )这里的model_name应是你保存到 BentoML 时使用的模型名称通常通过下面两种方式之一保存bentoml.MODEL_TYPE.save_model(model_name, model, labelslabels) # or bentoml.picklable_model.save_model( model_name, model, )基于上述思路一个自定义的 builder step 大致长这样from zenml import step step def my_bento_builder(model) - bento.Bento: ... # Load the model from the model artifact model load_artifact_from_response(model) # save to bentoml bentoml.pytorch.save_model(model_name, model) # Build the BentoML bundle. You can use any of the parameters supported by the bentos.build function. bento bentos.build( ... ) return bento构建完成后你就可以按需使用这个 Bento 制品了。方式二使用内置的bento_builder_step一旦定义好 Bento Service就可以在 ZenML 管道中调用内置的bento_builder_step来构建 Bento 制品。请确保 Bento Service 文件位于仓库根目录层级并在service参数中填入正确的类名。from zenml import pipeline, step from zenml.integrations.bentoml.steps import bento_builder_step pipeline def bento_builder_pipeline(): model ... bento bento_builder_step( modelmodel, model_namepytorch_mnist, # Name of the model model_typepytorch, # Type of the model (pytorch, tensorflow, sklearn, xgboost..) serviceservice.py:CLASS_NAME, # Path to the service file within zenml repo labels{ # Labels to be added to the bento bundle framework: pytorch, dataset: mnist, zenml_version: 0.21.1, }, exclude[data], # Exclude files from the bento bundle python{ packages: [zenml, torch, torchvision], }, # Python package requirements of the model )参数详解依据 steps/bento_builder.py 源码签名参数类型说明modelUnmaterializedArtifact上一个步骤产出的已训练/已加载模型制品必填model_namestr保存到 BentoML 时使用的模型名称必填model_typestr模型类型如pytorch、tensorflow、sklearn、xgboost等必填用于选择bentoml.model_type.save_model对应的保存器servicestrBentoML Service 文件在仓库内的路径及类名格式path/to/service.py:ClassName必填versionOptional[str]模型/Bento 的版本号不传则由 BentoML 自动生成labelsOptional[Dict[str, str]]附加到 Bento 制品的标签可用于元数据追踪descriptionOptional[str]Bento 的描述信息includeOptional[List[str]]需要打进 Bento 包的文件列表excludeOptional[List[str]]需要从 Bento 包排除的文件列表pythonOptional[Dict[str, Any]]Bento 的 Python 依赖配置如{packages: [...]}dockerOptional[Dict[str, Any]]Bento 容器镜像的配置working_dirOptional[str]Bento 构建的工作目录默认取source_utils.get_source_root()源码级实现细节src/zenml/integrations/bentoml/steps/bento_builder.py步骤首先通过get_step_context()获取输出制品 URI并把model_uri与bento_uri写入 labels 中——部署步骤正是从 Bento 的info.labels里读取这两个 URI 来做追溯的通过load_artifact_from_response(model)从 ZenML 制品仓库中加载模型实例保存模型时先尝试importlib.import_module(f.{model_type}, bentoml)动态导入对应的 BentoML 模块如bentoml.pytorch若因对应框架包未安装抛出PackageNotFoundError则回退到bentoml.picklable_model.save_model使用可序列化方式保存最后调用bentos.build(...)生成 Bento 制品并作为步骤输出返回其build_ctx默认使用source_utils.get_source_root()。Bento Builder 步骤可以在你用 ZenML 创建的任何编排管道中使用。该步骤会构建 Bento 制品并保存到当前使用的 Artifact Store之后既可以用 BentoML Model Deployer 步骤在本地或容器化环境中服务模型也可以在远程环境中配合bentoctl或 Yatai 使用——这让模型打包方式对不同的部署场景都保持就绪。第三步使用bentoml_model_deployer_step部署构建好 Bento 制品后就可以使用内置的bentoml_model_deployer_step把它部署到本地 HTTP 服务器或本地机器上的容器化服务。 提示bentoml_model_deployer_step只能运行在本地环境。但使用容器化部署时该步骤创建的 Docker 镜像会自动推送到 ZenML Stack 的容器注册中心你可以把镜像带到远程环境部署模型。本地部署Local Deployment以下示例把 Bento 部署到本地 HTTP 服务器from zenml import pipeline, step from zenml.integrations.bentoml.steps import bentoml_model_deployer_step pipeline def bento_deployer_pipeline(): bento ... deployed_model bentoml_model_deployer_step( bentobento model_namepytorch_mnist, # Name of the model port3001, # Port to be used by the http server )容器化部署Containerized Deployment以下示例把 Bento 部署到本地机器上运行的容器化服务。请确保本地已安装dockerCLI以便构建镜像并运行容器。你可以为镜像指定名称和标签镜像会被构建并推送到 ZenML Stack 的容器注册中心。默认情况下使用 Bento 的 tag 作为镜像名如果你提供自定义镜像名务必在镜像名前加上正确的注册中心名称作为前缀否则镜像推送会失败。from zenml import pipeline, step from zenml.integrations.bentoml.steps import bentoml_model_deployer_step pipeline def bento_deployer_pipeline(): bento ... deployed_model bentoml_model_deployer_step( bentobento model_namepytorch_mnist, # Name of the model port3001, # Port to be used by the http server deployment_typecontainer, imagemy-custom-image, image_tagmy-custom-image-tag, platformlinux/amd64, )该步骤会为 Bento 构建 Docker 镜像并推送到容器注册中心在本地运行该 Docker 镜像使其可被调用进行推理。部署后可以用以下命令查看本机镜像与运行中的容器docker images docker ps由于镜像同时被推送到 ZenML Stack 的容器注册中心你可以把它运行在任何环境中例如docker run -it --rm -p 3000:3000 image:image-tag serve部署步骤参数详解根据 steps/bentoml_deployer.py 的源码签名bentoml_model_deployer_step支持以下参数参数类型 / 默认值说明bentobento.Bento要部署的 Bento 制品必填model_namestr部署的模型名称必填portint预测服务使用的端口必填deployment_typeBentoMLDeploymentType.LOCAL部署类型local或container对应 services/deployment_type.py 中的枚举deploy_decisionbool True是否执行部署若为False且有已存在的等价服务则复用上一次部署的服务可用于质量门控只有模型达标才部署新版本workersOptional[int] 1预测服务使用的 worker 进程数backlogOptional[int] 2048拒绝请求前允许排队等待的请求数productionbool False是否以生产模式运行服务working_dirOptional[str] None预测服务的工作目录hostOptional[str] None服务监听的主机地址imageOptional[str] None容器部署时的镜像名image_tagOptional[str] None容器部署时的镜像标签platformOptional[str] None构建镜像的目标平台如linux/amd64ssl_certfile/ssl_keyfile/ssl_keyfile_password/ssl_version/ssl_cert_reqs/ssl_ca_certs/ssl_ciphersOptional[...] None本地部署启用 HTTPS 时的 SSL 参数对应 services/bentoml_local_deployment.py 的SSLBentoMLParametersConfigtimeoutint 30等待服务启动/停止的超时秒数部署步骤的底层行为结合 model_deployers/bentoml_model_deployer.py 源码可以看清部署步骤的执行逻辑通过BentoMLModelDeployer.get_active_model_deployer()获取当前激活的 model deployer 栈组件并从get_step_context()取得管道名与步骤名从 Bento 的info.labels中读取model_uri、bento_uri通过bentoml.load解析出 Service 暴露的所有 API 路径service_apis组装成部署配置根据deployment_type选择BentoMLLocalDeploymentConfig含 SSL 与 production 参数或BentoMLContainerDeploymentConfig含 image、image_tag、platform 参数调用find_model_server查找同管道名、同步骤名、同模型名的既有服务若deploy_decision为False且存在既有服务则直接复用并返回保证服务不中断否则以replaceTrue调用deploy_model创建新服务并替换旧服务——两个部署服务被视为等价的条件是拥有相同的pipeline_name、pipeline_step_name与model_name即它们服务于由同一管道步骤部署的同一模型的多个版本若找到多个等价服务随机选一个更新其余删除。在本地模式下服务以守护进程运行BentoMLLocalDeploymentService启动时会依据 BentoML 版本分支调用serve_http_productionBentoML 1.2或_bentoml_impl.server.serve_httpBentoML 1.2并内置健康检查路径readyz见 constants.py默认端口为3000。在容器模式下服务会调用bentoml.container.build构建镜像没有容器注册中心时会以 Bento tag 直接命名镜像并给出警告。组合管道训练、构建、部署一体化定义好所有步骤后就可以创建 ZenML 管道并运行了。注意两个前置条件bento_builder_step期望接收训练好的模型作为输入因此需要有一个前置步骤训练模型并输出或从之前的运行中加载模型bentoml_model_deployer_step期望接收 Bento 制品作为输入因此需要有一个前置步骤构建 Bento或从之前的运行/外部来源加载 Bento。端到端一体化管道下面的例子创建了一条训练模型、构建 Bento、为它创建并运行 Docker 镜像并推送到容器注册中心的管道之后你可以另建一条管道拉取该镜像并部署到远程环境# Import the pipeline to use the pipeline decorator from zenml.pipelines import pipeline # Pipeline definition pipeline def bentoml_pipeline( importer, trainer, evaluator, deployment_trigger, bento_builder, deployer, ): Link all the steps and artifacts together train_dataloader, test_dataloader importer() model trainer(train_dataloader) accuracy evaluator(test_dataloadertest_dataloader, modelmodel) decision deployment_trigger(accuracyaccuracy) bento bento_builder(modelmodel) deployer(deploy_decisiondecision, bentobento, deployment_typecontainer)这里deployment_trigger是一个质量门控步骤只有当模型准确率等指标达标时才产出deploy_decisionTrue避免把劣化模型部署上线。远程训练 本地/云端部署分离在更复杂的场景中你可能希望在远程环境训练模型并构建 Bento然后由另一条管道拉取 Bento 制品部署到本地 HTTP 服务器或云平台。下面两个管道分别完成这两件事# Import the pipeline to use the pipeline decorator from zenml.pipelines import pipeline # Pipeline definition pipeline def remote_train_pipeline( importer, trainer, evaluator, bento_builder, ): Link all the steps and artifacts together train_dataloader, test_dataloader importer() model trainer(train_dataloader) accuracy evaluator(test_dataloadertest_dataloader, modelmodel) bento bento_builder(modelmodel) pipeline def local_deploy_pipeline( bento_loader, deployer, ): Link all the steps and artifacts together bento bento_loader() deployer(deploy_decisiondecision, bentobento)与本地已部署模型交互发起预测模型部署完成后ZenML 会自动为你创建 BentoML 客户端。你只需调用服务对象的predict方法传入输入数据与 API 函数名即可向已部署模型发送请求step def predictor( inference_data: Dict[str, List], service: BentoMLDeploymentService, ) - None: Run an inference request against the BentoML prediction service. Args: service: The BentoML service. data: The data to predict. service.start(timeout10) # should be a NOP if already started for img, data in inference_data.items(): prediction service.predict(predict_ndarray, np.array(data)) result to_labels(prediction[0]) rich_print(fPrediction for {img} is {result})从 services/bentoml_local_deployment.py 源码看predict(api_endpoint, data, syncTrue)会首先检查服务是否在运行未运行则抛出异常根据sync参数选择SyncHTTPClient或AsyncHTTPClient指向服务的prediction_url调用client.call(api_endpoint, data)完成推理请求。容器化服务的predict则使用bentoml.client.Client.from_url建立连接见 services/bentoml_container_deployment.py。此外服务还暴露prediction_url与prediction_apis_urls属性分别给出 HTTP 服务地址与各个推理 API 的完整 URL 列表。本地部署与测试是起步和验证模型的好方式。但真实业务场景往往需要把模型部署到远程环境你可以在部署步骤中将deployment_type设置为container以生成容器镜像然后在远程环境中使用该镜像也可以借助bentoctl或 Yatai 把 Bento 部署到云环境。从本地走向云端bentoctl⚠️ 警告bentoctlCLI 目前已废弃可能无法兼容最新的 BentoML 版本使用前请确认你所依赖的 BentoML 版本。bentoctl帮助把任意机器学习模型作为生产级 API 端点部署到云端它是一个命令行工具提供了管理 BentoML 制品包的简单接口。bentoctlCLI 提供了一系列operators与云服务交互的插件包括AWS LambdaAWS SageMakerAWS EC2Google Cloud RunGoogle Compute EngineAzure Container InstancesHeroku它的典型用法是从 ZenML 管道中取出已构建的 Bento再用bentoctl将其部署到上述云环境之一。关于bentoctl工具的更多信息可查看其官方 GitHub 仓库关于 BentoML Model Deployer 全部可配置属性的完整说明可查阅 ZenML SDK Docs 中的zenml.integrations.bentoml模块文档。总结ZenML 的 BentoML 集成把「模型训练 → 制品打包 → 本地/容器部署 → 推理调用」串成一条标准化的流水线通过zenml integration install bentoml与zenml model-deployer register完成环境准备用自定义 Service 或内置bento_builder_step把模型与推理逻辑封装为 Bento再用bentoml_model_deployer_step一键完成本地 HTTP 服务或容器化部署配合deploy_decision、workers、production、SSL 等参数满足从开发到生产的多种场景需求。源码层面部署步骤的等价服务查找与替换机制保证了持续部署工作流不会为每个模型版本都新起一个服务从而实现模型版本的无缝滚动更新。想要继续深入可以阅读仓库中以下关键文件部署步骤实现steps/bentoml_deployer.pyBento 构建步骤实现steps/bento_builder.py栈组件实现model_deployers/bentoml_model_deployer.py本地服务实现services/bentoml_local_deployment.py容器服务实现services/bentoml_container_deployment.pyFlavor 定义flavors/bentoml_model_deployer_flavor.pyModel Deployer 总览与其余 flavorsdocs/book/component-guide/model-deployers/README.md【免费下载链接】zenmlZenML : One AI Platform from Pipelines to Agents. https://zenml.io.项目地址: https://gitcode.com/GitHub_Trending/ze/zenml创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考