当前位置: 首页 > 工具软件 > Bento > 使用案例 >

快速入门统一模型部署(Model Serving)框架 BentoML

洪飞白
2023-12-01

简述

BentoML 是一个用于机器学习模型服务的开源框架,旨在弥合数据科学和 DevOps 之间的差距(gap)。

数据科学家可以使用 BentoMl 轻松打包使用任何 ML 框架训练的模型,并重现该模型以用于生产。

BentoML 协助管理 BentoML 格式打包的模型,并允许 DevOps 将它们部署为任何云平台上的在线 API 服务端点或离线批量推理作业。

为什么选择 BentoML

  • 将您的 ML 模型转换为生产就绪 API 非常简单。
  • 高性能模型服务,并且全部使用 Python。
  • 标准化模型打包和 ML 服务定义以简化部署。
  • 支持所有主流的机器学习训练框架。
  • 通过Yatai在 Kubernetes 上大规模部署和运行 ML 服务。

下面将演示了如何使用 BentoML 通过 REST API 服务为 sklearn 模型提供服务,然后将模型服务容器化以进行生产部署。

依赖库安装

BentoML 需要 Python 3.6 或更高版本,然后,通过 pip 安装依赖项:

# 安装本教程需要的依赖包,包括BentoML
pip install -q bentoml==v1.0.0-a6
pip install -q 'scikit-learn>=0.23.2' 'pandas>=1.1.1'

训练模型及保存模型

我们预先准备一个训练的模型来使用 BentoML 提供服务。 模型训练完成后,使用我们的工具将特定框架训练的模型保存为 BentoML 标准格式。

首先,在鸢尾花(Iris)数据集上训练一个分类模型:

# train.py
from sklearn import svm
from sklearn import datasets
import bentoml

# Load training data
iris = datasets.load_iris()
X, y = iris.data, iris.target

# Model Training
clf = svm.SVC(gamma='scale')
clf.fit(X, y)

# 调用`bentoml.<FRAMEWORK>.save(<MODEL_NAME>, model)` 为了在本地模型存储中保存为 BentoML 的标准格式
bentoml.sklearn.save("iris_clf", clf)

运行结果:

$ python train.py

03/31/22 16:15:13 INFO     [cli] Successfully saved Model(tag="iris_clf:wdqpqfvqzk32yhqa", path="/Users/liguodong/bentoml/models/iris_clf/wdqpqfvqzk32yhqa/") 

bentoml.sklearn.save()会将 Iris 分类模型保存到由 BentoML 管理的本地模型存储中。 目前所有受支持的建模库,请参阅ML framework specific API

查看 BentoML 本地模型仓库的模型

模型也可以通过 bentoml models CLI 命令进行管理。 更多信息请使用 bentoml models --help

$ bentoml models list

 Tag                        Module           Path                                                       Size      Creation Time       
 iris_clf:wdqpqfvqzk32yhqa  bentoml.sklearn  /Users/liguodong/bentoml/models/iris_clf/wdqpqfvqzk32yhqa  5.64 KiB  2022-03-31 08:15:13 

然后,您可以使用bentoml.<FRAMEWORK>.load(<TAG>) 加载要在线运行的模型。同时,您也可以使用 bentoml.<FRAMEWORK>.load_runner(<TAG>) API 使用性能优化的运行器。

验证模型是否可以作为运行器加载

# verify.py

import bentoml

runner = bentoml.sklearn.load_runner("iris_clf:latest")

print(runner.run([5.9, 3., 5.1, 1.8]))  # => array(2)

使用 BentoML 定义和调试 ML 预测服务

服务是 BentoML 的核心组件,其中定义了服务逻辑。

通过保存在模型仓库中的模型,我们可以创建 Python 文件 service.py 来定义服务,其内容如下:

# service.py
import numpy as np
import bentoml
from bentoml.io import NumpyNdarray

# 加载我们刚刚保存的最新 ScikitLearn 模型的运行器
iris_clf_runner = bentoml.sklearn.load_runner("iris_clf:latest")

# 使用 ScikitLearn 运行器创建 iris_classifier 服务
# 如果需要,可以在runners数组中指定多个运行器
# 当包装为bento时,运行器(runners)也会被包括在里面
svc = bentoml.Service("iris_classifier", runners=[iris_clf_runner])


# 使用“svc”注解创建具有预处理和后处理逻辑的 API 函数
@svc.api(input=NumpyNdarray(), output=NumpyNdarray())
def classify(input_series: np.ndarray) -> np.ndarray:
    # 定义预处理逻辑
    result = iris_clf_runner.run(input_series)
    # 定义后处理逻辑
    return result

在此示例中,我们将输入和输出类型定义为 numpy.ndarray。 还支持更多选项,例如 pandas.DataFramePIL.image。 要查看所有支持的选项,请参阅API 和 IO 描述。

到此为止,我们现在拥有了满足第一个请求所需要的一切。

在本地启动一个 API server 进行测试

我们通过在当前工作目录中运行 bentoml serve 命令以调试模式启动服务。使用 --reload 选项允许服务显示对 service.py 模块所做的任何更改,而无需重新启动(热更新):

$ bentoml serve ./service.py:svc --reload

03/31/22 17:00:54 INFO     [cli] Starting development BentoServer from "./service.py:svc" running on http://127.0.0.1:3000 (Press CTRL+C to quit)                           
03/31/22 17:00:55 INFO     [dev_api_server] Service imported from source: bentoml.Service(name="iris_classifier", import_str="service:svc",                                 
                           working_dir="/Users/liguodong/work/gitee/sample-all-py3/mlops/bentoml/bento_deploy")                                                             
03/31/22 17:00:55 INFO     [dev_api_server] Will watch for changes in these directories: ['/Users/liguodong/work/gitee/sample-all-py3/mlops/bentoml/bento_deploy']          
03/31/22 17:00:55 INFO     [dev_api_server] Started reloader process [54356] using statreload                                                                               
03/31/22 17:00:56 INFO     [cli] Started server process [54359]                                                                                                             
03/31/22 17:00:56 INFO     [cli] Waiting for application startup.                                                                                                           
03/31/22 17:00:56 INFO     [cli] Application startup complete.                                                                                                              
03/31/22 17:05:36 WARNING  [dev_api_server] StatReload detected file change in 'service.py'. Reloading...                                                                   
03/31/22 17:05:36 INFO     [cli] Shutting down                                                                                                                              
03/31/22 17:05:36 INFO     [cli] Waiting for application shutdown.                                                                                                          
03/31/22 17:05:36 INFO     [cli] Application shutdown complete.                                                                                                             
03/31/22 17:05:36 INFO     [cli] Finished server process [54359]                                                                                                            
03/31/22 17:05:37 INFO     [cli] Started server process [54372]                                                                                                             
03/31/22 17:05:37 INFO     [cli] Waiting for application startup.                                                                                                           
03/31/22 17:05:37 INFO     [cli] Application startup complete.                                                                                                              
03/31/22 17:08:13 INFO     [cli] 127.0.0.1:56051 (scheme=http,method=POST,path=/classify,type=application/json,length=9) (status=200,type=application/json,length=1) 3.123ms
                           (trace=108811182904080858968430329246303376687,span=3358824710013532286,sampled=0)                                                               

然后,我们可以使用任何 HTTP 客户端向新启动的服务发送请求。比如,通过python http request 请求:

# http_request.py
import requests
print(requests.post(
    "http://127.0.0.1:3000/classify",
    headers={"content-type": "application/json"},
    data="[5,4,3,2]").text)

或者通过curl请求:

> curl \
  -X POST \
  -H "content-type: application/json" \
  --data "[5,4,3,2]" \
  http://127.0.0.1:3000/classify

BentoML 可以以多种方式优化您的服务,例如,BentoML 使用了两个最快的 Python Web 框架 Starlette 和 Uvicorn,以便大规模高效地为您的模型提供服务。

有关性能优化的更多信息,请参阅 BentoServer

构建和部署 Bentos

一旦我们对服务定义感到满意,我们就可以将模型和服务构建成bento。 Bentos 是服务的分发格式,包含运行或部署这些服务所需的所有信息,例如模型和依赖项。 有关构建bento的更多信息,请参阅Building Bentos

要构建 Bento,首先在项目目录中创建一个名为 bentofile.yaml 的文件:

# bentofile.yaml
service: "service.py:svc"  # 定位服务的约定:<YOUR_SERVICE_PY>:<YOUR_SERVICE_ANNOTATION>
description: "file: ./README.md"
labels:
    owner: bentoml-team
    stage: demo
include:
 - "*.py"  # 用于匹配要包含在bento中的文件的格式
python:
  packages:
   - scikit-learn==0.23.2  # bento中将包含的其他的依赖库
   - pandas>=1.1.1

接下来,在同样的目录中的bentoml build CLI 命令来构建一个bento。

$ bentoml build

03/31/22 17:41:06 INFO     [cli] Building BentoML service "iris_classifier:v7eedwvq22c5ahqa" from build context                                                             
                           "/Users/liguodong/work/gitee/sample-all-py3/mlops/bentoml/bento_deploy"                                                                          
03/31/22 17:41:06 INFO     [cli] Packing model "iris_clf:wdqpqfvqzk32yhqa" from "/Users/liguodong/bentoml/models/iris_clf/wdqpqfvqzk32yhqa"                                 
03/31/22 17:41:06 INFO     [cli] Successfully saved Model(tag="iris_clf:wdqpqfvqzk32yhqa",                                                                                  
                           path="/var/folders/_7/b59dvhj56lq3lr4jpsx2h7t80000gn/T/tmpfekkt4b3bentoml_bento_iris_classifier/models/iris_clf/wdqpqfvqzk32yhqa/")              
03/31/22 17:41:06 INFO     [cli] Locking PyPI package versions..                                                                                                            
03/31/22 17:47:00 INFO     [cli]                                                                                                                                            
                           ██████╗░███████╗███╗░░██╗████████╗░█████╗░███╗░░░███╗██╗░░░░░                                                                                    
                           ██╔══██╗██╔════╝████╗░██║╚══██╔══╝██╔══██╗████╗░████║██║░░░░░                                                                                    
                           ██████╦╝█████╗░░██╔██╗██║░░░██║░░░██║░░██║██╔████╔██║██║░░░░░                                                                                    
                           ██╔══██╗██╔══╝░░██║╚████║░░░██║░░░██║░░██║██║╚██╔╝██║██║░░░░░                                                                                    
                           ██████╦╝███████╗██║░╚███║░░░██║░░░╚█████╔╝██║░╚═╝░██║███████╗                                                                                    
                           ╚═════╝░╚══════╝╚═╝░░╚══╝░░░╚═╝░░░░╚════╝░╚═╝░░░░░╚═╝╚══════╝                                                                                    
                                                                                                                                                                            
03/31/22 17:47:00 INFO     [cli] Successfully built Bento(tag="iris_classifier:v7eedwvq22c5ahqa") at "/Users/liguodong/bentoml/bentos/iris_classifier/v7eedwvq22c5ahqa/" 

构建的Bentos将保存在本地bento商店中,您可以使用bentoml list CLI 命令查看。

$ bentoml list

 Tag                               Service      Path                                                              Size       Creation Time       
 iris_classifier:v7eedwvq22c5ahqa  service:svc  /Users/liguodong/bentoml/bentos/iris_classifier/v7eedwvq22c5ahqa  15.21 KiB  2022-03-31 09:47:00 

我们可以使用bentoml serve --production CLI 命令从bento商店提供bentos服务。其中,--production 选项将在生产模式下提供bento服务。

$ bentoml serve iris_classifier:veshoxfq3wzyqhqa --production

03/31/22 18:02:41 INFO     [cli] Service loaded from Bento store: bentoml.Service(tag="iris_classifier:v7eedwvq22c5ahqa",                                                   
                           path="/Users/liguodong/bentoml/bentos/iris_classifier/v7eedwvq22c5ahqa")                                                                         
03/31/22 18:02:41 INFO     [cli] Starting production BentoServer from "bento_identifier" running on http://0.0.0.0:3000 (Press CTRL+C to quit)                              
03/31/22 18:02:42 INFO     [api_server] Service loaded from Bento store: bentoml.Service(tag="iris_classifier:v7eedwvq22c5ahqa",                                            
                           path="/Users/liguodong/bentoml/bentos/iris_classifier/v7eedwvq22c5ahqa")                                                                         
03/31/22 18:02:42 INFO     [iris_clf] Service loaded from Bento store: bentoml.Service(tag="iris_classifier:v7eedwvq22c5ahqa",                                              
                           path="/Users/liguodong/bentoml/bentos/iris_classifier/v7eedwvq22c5ahqa")                                                                         
03/31/22 18:02:42 INFO     [iris_clf] Started server process [54672]                                                                                                        
03/31/22 18:02:42 INFO     [iris_clf] Waiting for application startup.                                                                                                      
03/31/22 18:02:42 INFO     [api_server] Started server process [54673]                                                                                                      
03/31/22 18:02:42 INFO     [api_server] Waiting for application startup.                                                                                                    
03/31/22 18:02:42 INFO     [api_server] Application startup complete.                                                                                                       
03/31/22 18:02:45 INFO     [iris_clf] Application startup complete.       

Bento 目录说明

Bento 目录包含运行此服务所需的所有代码、文件、模型和配置。 BentoML 标准化了这个文件结构,使服务运行时和部署工具能够建立在它之上。 默认情况下,Bentos 在~/bentoml/bentos 目录下进行管理:

$ cd ~/bentoml/bentos/iris_classifier && cd $(cat latest)

$ tree

.
├── README.md
├── apis
│   └── openapi.yaml
├── bento.yaml
├── env
│   ├── docker
│   │   ├── Dockerfile
│   │   ├── entrypoint.sh
│   │   └── init.sh
│   └── python
│       ├── requirements.lock.txt
│       ├── requirements.txt
│       └── version.txt
├── models
│   └── iris_clf
│       ├── latest
│       └── y3f4ijcxj3i6zo6x2ie5eubhd
│           ├── model.yaml
│           └── saved_model.pkl
└── src
    ├── iris_classifier.py
    └── train.py

8 directories, 14 files

将 Bento 容器化以进行部署

最后,我们可以使用bentoml containerize CLI 命令将 bentos 容器化为Docker 镜像,并使用模型和 bento 管理服务 来大规模管理bentos。

首先,需确保您已安装 docker 并运行了 docker deamon,以下命令将使用您的本地 docker 环境构建一个新的 docker 镜像,并包含来自此 Bento 的模型服务配置。

$ bentoml containerize iris_classifier:veshoxfq3wzyqhqa

# 运行容器测试镜像的构建
$ docker run -p 5000:5000 iris_classifier:invwzzsw7li6zckb2ie5eubhd 

总结

BentoML 是一个开放平台,可简化 ML 模型部署并使您能够在几分钟内以生产规模为模型提供服务。

 类似资料: