使用镜像部署模型#
PAI支持用户使用镜像的方式部署模型,通过镜像,开发者可以自定义模型部署的环境,包括Python、使用的机器学习框架、依赖的第三方库等,能够支持用户灵活的部署需求。详细的介绍可以参考PAI帮助文档:使用镜像部署模型。
PAI Python SDK提供了便利的API,支持用户能够使用自定义镜像,或是PAI提供的预置推理,将一个本地,或是OSS上的模型快捷得部署为模型在线服务。
本文档将介绍,用户如何通过PAI Python SDK通过自定义镜像的方式部署模型。
安装和配置SDK#
我们需要首先安装PAI Python SDK以运行本示例。
!python -m pip install --upgrade alipai
SDK需要配置访问阿里云服务需要的AccessKey,以及当前使用的工作空间和OSS Bucket。在PAI SDK安装之后,通过在 命令行终端 中执行以下命令,按照引导配置密钥、工作空间等信息。
# 以下命令,请在 命令行终端 中执行.
python -m pai.toolkit.config
我们可以通过以下代码验证配置是否已生效。
import pai
from pai.session import get_default_session
print(pai.__version__)
sess = get_default_session()
# 获取配置的工作空间信息
assert sess.workspace_name is not None
print(sess.workspace_name)
部署模型推理服务#
模型在线服务包含了模型的文件、模型的推理服务代码、以及推理服务运行环境。
本示例将使用一个简单的PyTorch
模型,通过Flask
和PAI
提供的PyTorch
基础镜像,部署模型在线服务。
下载示例使用的简单PyTorch模型。
# 下载模型到本地 "model" 目录
!mkdir -p model/
!wget https://pai-sdk.oss-cn-shanghai.aliyuncs.com/pai/resources/toy_model.pt -P model/
准备推理服务代码#
在部署模型之前,我们首先需要准备推理服务的代码,它提供HTTP接口,负责接收预测请求,使用模型进行推理,返回预测结果。
当前示例我们将使用 Flask
编写一个简单的推理服务,保存为 infer_src/app.py
文件。
!mkdir -p infer_src
%%writefile infer_src/app.py
import json
from flask import Flask, request
import os
import torch
import numpy as np
app = Flask(__name__)
model = None
# 默认的模型文件路径
MODEL_PATH = "/eas/workspace/model/"
def load_model():
"""加载模型"""
global model
model = torch.jit.load(os.path.join(MODEL_PATH, "toy_model.pt"))
model.eval()
@app.route("/", methods=["POST"])
def predict():
data = np.asarray(json.loads(request.data)).astype(np.float32)
output_tensor = model(torch.from_numpy(data))
pred_res = output_tensor.detach().cpu().numpy()
return json.dumps(pred_res.tolist())
if __name__ == "__main__":
load_model()
app.run(host="0.0.0.0", port=int(os.environ.get("LISTENING_PORT", 8000)))
获取PAI提供的预置推理镜像#
PAI提供了一系列预置的推理镜像,镜像内预置了机器学习框架、常用的第三方库、Python、NVIDIA CUDA库等。我们可以通过以下代码列出所有的预置镜像。
from pai.image import list_images, ImageScope
data = [
[
"ImageUri",
"FrameworkName",
"FrameworkVersion",
"AcceleratorType",
"PythonVersion",
]
]
# 列出常用的PyTorch推理镜像
for img in list_images(framework_name="PyTorch", image_scope=ImageScope.INFERENCE):
data.append(
[
img.image_uri,
img.framework_name,
img.framework_version,
img.accelerator_type,
img.python_version,
]
)
# 列出常用的TensorFlow推理镜像
for img in list_images(framework_name="TensorFlow", image_scope=ImageScope.INFERENCE):
data.append(
[
img.image_uri,
img.framework_name,
img.framework_version,
img.accelerator_type,
img.python_version,
]
)
from IPython.display import HTML, display
display(
HTML(
"<table><tr>{}</tr></table>".format(
"</tr><tr>".join(
"<td>{}</td>".format("</td><td>".join(str(_) for _ in row))
for row in data
)
)
)
)
通过SDK提供的 pai.image.retrieve
API,可以获取指定框架版本的镜像。在当前示例中,我们将使用PAI提供的PyTorch 1.12版本的CPU推理镜像
from pai.image import retrieve, ImageScope
# # 获取PyTorch 1.10 GPU推理镜像
# print(retrieve(
# framework_name="PyTorch", # 框架名称
# framework_version="latest", # 框架版本
# accelerator_type="gpu", # 选择支持Nvidia CUDA GPU的镜像
# image_scope=ImageScope.INFERENCE, # 镜像类型,推理镜像
# # ).image_uri)
# 获取最新的PyTorch CPU推理镜像
torch_image_uri = retrieve(
framework_name="PyTorch", # 框架名称
framework_version="1.12", # 框架版本,latest表示使用PAI支持的最新版本
# accelerator_type="cpu", # 默认使用CPU镜像
image_scope=ImageScope.INFERENCE, # 镜像类型,推理镜像
).image_uri
print(torch_image_uri)
部署推理服务#
使用以上的推理服务代码,以及PyTorch推理镜像,我们将一个PyTorch模型部署为模型在线服务。
from pai.model import Model, container_serving_spec
m = Model(
model_data="./model/", # 模型文件,可以是一个本地文件或是OSS Bucket路径(例如 oss://<BucketName>/path/to/model ),
inference_spec=container_serving_spec(
image_uri=torch_image_uri, # 推理服务使用的镜像
command="python app.py", # 模型推理服务启动命令
source_dir="./infer_src/", # 推理服务代码所在目录
requirements=["flask==2.0.0", "Werkzeug==2.3.4"], # 推理服务依赖的Python包
),
)
from pai.common.utils import random_str
# 部署模型服务
p = m.deploy(
service_name=f"toy_model_{random_str(6)}", # 模型服务名称, 地域内唯一
instance_type="ecs.c6.large", # 模型服务使用的机器实例规格
)
调用推理服务#
部署服务后返回的pai.predictor.Predictor
对象可以用于调用推理服务,发送预测请求。
import numpy as np
# 构造一个随机数组输入
dummy_input = np.random.rand(1, 10, 10).tolist()
print(dummy_input)
result = p.raw_predict(
data=dummy_input,
)
# 打印推理结果
print(result.json())
在测试完成之后,删除推理服务
p.delete_service()