这是我的第404篇原创文章。

一、引言

Triton Inference Server是一款开源的推理服务框架,它的核心库基于C++编写的,旨在在生产环境中提供快速且可扩展的AI推理能力,具有以下优势:

  • 支持多种深度学习框架:包括PyTorch,Tensorflow,TensorRT,ONNX,OpenVINO等产出的模型文件

  • 支持多种机器学习框架:支持对树模型的部署,包括XGBoost,LightGBM等

  • 支持多种推理协议:支持HTTP,GRPC推理协议

  • 服务端支持模型前后处理:提供后端API,支持将数据的前处理和模型推理的后处理在服务端实现

  • 支持模型并发推理:支持多个模型或者同一模型的多个实例在同一系统上并行执行

  • 支持动态批处理(Dynamic batching):支持将一个或多个推理请求合并成一个批次,以最大化吞吐量

  • 支持多模型的集成流水线:支持将多个模型进行连接组合,将其视作一个整体进行调度管理

图片

二、实现过程

2.1 训练模型并保存模型文件(夹)

这里我直接用开源的模型,下载后,四个模型文件如下:

图片

2.2 构建模型仓库

Triton Inference Server将模型统一放置在一个目录下进行管理,该目录下记录了每个模型的名称,配置,后端代码,模型文件等。

我们创建该目录为model_repository:

图片

并且在其下创建两个模型目录,命名为paraformer_funasr和SeAcoParaformer,该命名是自定义的,但是在后续的配置文件和请求中要保持命名统一。

图片

这里我仅以paraformer_funasr这个模型为例。

2.3 构建模型推理配置

进入paraformer_funasr目录,创建一个文件夹命名为official_models:

图片

下面放入模型文件(夹),所有版本共用该模型文件,如下:

图片

进入paraformer_funasr目录,创建模型的推理配置文件命名为config.pbtxt,所有版本共用该配置,

图片

配置如下:

图片

基本信息:

name:模型服务的名称,这里设置paraformer_funasr。

backend:指定模型使用的后端,这里设置python,表示模型是一个python脚本。

max_batch_size:模型的最大批处理大小,这里设置为6,意味着单词请求最多可以处理6个输入。

输入定义:

input:定义模型的输入。包括DATA和PARAMS两个字段。

DATA:data_type表示数据类型为TYPE_STRING,即字符串类型。dims表示输入维度为[1],表示每个输入是一个一维的字符串。

PARAMS:data_type表示数据类型为TYPE_STRING,即字符串类型。dims表示输入维度为[1],表示每个输入是一个一维的字符串。optional设置为true,表示这个输入是可选的。

输出定义:

output:定义模型的输入。包括RESULTS和PARAMS两个字段。

DATA:data_type表示数据类型为TYPE_STRING,即字符串类型。dim表示输入维度为[1],表示每个输入是一个一维的字符串。

PARAMS:data_type表示数据类型为TYPE_STRING,即字符串类型。dim表示输入维度为[1],表示每个输入是一个一维的字符串。

实例组:

instance_group:定义模型实例组。

count:实例的数量,设置为3,表示将创建3个模型实例。

kind:实例的类型,设置为KIND_GPU,表示这些实例运行在GPU上。

gpus:指定使用的GPU设备,这里设置为[0],表示使用编号为0的GPU。

动态批处理:

dynamic:定义动态批处理的配置。

preferred_batch_size:优选的批处理大小,设置为【3,6】,表示优先使用3或6的批处理大小。

max_queue_delay_microseconds:最大队列延迟时间,设置500微秒,表示在达到最大批处理大小之前,最多等待500微秒。

2.4 构建服务端代码

服务端代码负责读取模型,并且在其中实现数据的前处理,模型推理,后处理的逻辑。Triton Inference Server提供了服务端代码模板TritonPythonModel,只需要略微修改即可,

进入paraformer_funasr目录,创建一个文件夹命名为1,代表是paraformer_funasr的第一个版本。

图片

本例的服务端代码如下:此处略。

其中initialize方法实现了模型的初始化,execute方法实现了模型的推理逻辑,并且包装了返回。

我们将该Python脚本保存命名为model.py,放置在文件1下。

图片

2.5 启动服务端

拉镜像:

docker pull nvcr.io/nvdia/tritonserver:24.05-py3
# 删除镜像:docker rmi nvcr.io/nvdia/tritonserver:24.05-py3
# 镜像=项目源码+运行环境

图片

查镜像

docker images |grep triton

图片

启容器(容器=环境+项目源码):

docker run -itd --gpus all --name triton_test_wq-v /app/wenqiang/triton-wq:/app/wenqiang -p 18999:8000 -p 18998:8001 -p 18997:8002 ngc.nju.edu.cn/nvidia/tritonserver:24.05-py3

图片

查容器运行情况:

docker ps -a |grep triton
重启:docker restart triton_test_wq
删除: docker rm triton_test_wq
停止运行:docker stop triton_test_wq

图片

进入这个容器:

docker exec -it triton_test_wq bash
退出容器:exit

可见已经进入了容器,当前在/opt/tritonserver目录:

图片

服务器上的/app/wenqiang/triton-wq已经被映射进来了,等于容器中/app/wenqiang:

图片

执行triton命令,启动部署的模型:

tritonserver --model-repository=/app/wenqiang/model_repository

图片

可以看到容器里面没有funasr:

图片

在容器里面安装这个包:

pip install funasr -i http://maven.suningbank.com/repository/pypi/simple/ --trusted-host maven.suningbank.com

图片

同样容器里么有torch:

图片

先看下容器的CUDA版本:

图片

安装:

pip install torch
pip install torchaudio

再次执行triton命令,启动部署的模型:

tritonserver --model-repository=/app/wenqiang/model_repository

图片

可见,模型仓库下面的两个模型都已经启动。

2.6 客户端调用

客户端调用可以用triton使用request进行客户端调用的代码:

图片

图片

pyload包含inputs和outputs,name和配置文件的定义的输入一致。其中data就是模型的输入。

# url = f"{base_url}?singleFlag={singleFlag}&iccVoiceId={iccVoiceId}&iccVoiceDate={iccVoiceDate}&downLoadFileName={downLoadFileName}&authorization={authorization}"
# response = requests.get(url, verify=False)
# file = response.content
with open(audio_file_path, "rb") as f:
      audio_data = f.read()
file = audio_data

response结果:

图片

response是一个字典字符串,有model_name,model_version,outputs。其中outputs的值是一个列表,每个元素是一个字典,name和配置文件定义的输出一致,还有datatype、shape、data等字段。其中data就是模型推理的输出。

作者简介:

读研期间发表6篇SCI数据挖掘相关论文,现在某研究院从事数据算法相关科研工作,结合自身科研实践经历不定期分享关于Python、机器学习、深度学习、人工智能系列基础知识与应用案例。致力于只做原创,以最简单的方式理解和学习,关注我一起交流成长。需要数据集和源码的小伙伴可以关注底部公众号添加作者微信。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐