腾讯云大模型训推平台TI-ONE 模型推理文件简介和示例

tiinfer 是腾讯云 TI-ONE 模型服务使用的推理框架。基于 mosec 提供的基础能力,tiinfer 提供了以下功能。

相关产品
腾讯云大模型训推平台TI-ONE 产品页,含版本规格、价格与购买入口。

一、TI 内置推理框架 tiinfer 介绍

·高性能的 HTTP 服务

·自由编排计算过程

二、安装

tiinfer 支持 Gnu/Linux 系统,依赖 python 3.8 及以上版本。需要使用以下命令安装 PyPI 包:

pip install tencent_tiinferpip install mosec

三、HelloWorld!

以下代码展示了一个最简单的 HelloWorld 示例:

from typing import Dictimport tiinferimport mosec### 日志相关代码 #### 增加以下代码,才能将框架记录的请求日志打印到终端import loggingimport syslogger_formatter = "%(asctime)s %(levelname)s %(module)s:%(lineno)d %(message)s"logging.basicConfig(stream=sys.stdout, format=logger_formatter, level=logging.DEBUG)### 日志相关代码 #### tiinfer支持原生的mosec.Workerclass HelloWorld(mosec.Worker): def forward(self, req: Dict) -> Dict: return {"hello": f"world. raw req is {req}"}# 启动两个进程同时处理请求tiinfer.append_worker(HelloWorld, num=2)

将上述代码保存为 model_service.py 文件。执行以下命令可以拉起整个推理服务:

TI_MODEL_DIR=`pwd` python3 -m tiinfer –timeout 30000 –port 8501

其中,配置项 timeout 值表示 Web 服务超时时间,单位为毫秒。模型拉起后,会在8501端口启动一个 HTTP 服务,请求地址为/v1/models/m:predict。用以下命令可以访问:

> curl -X POST -d '{"key": "values"}' http://localhost:8501/inference{ "hello": "world. raw is {'key': 'values'}"}

四、tiinfer 的架构

为了降低模型的上线难度,平台提供的 tiinfer 镜像已经打包了诸多流行的推理引擎,会读取客户提供的 model_service.py 文件,自动拉起 HTTP 服务。具体的服务启动过程如下所示:

1. 使用 pip 安装 requirements.txt 文件中填写的 python 依赖。

2. 读取 model_service.py 并实例化几个处理过程的进程。

3. 启动 HTTP 服务。

五、框架内置环境变量

框架默认为单进程模式,用户可根据需要调整框架内置环境变量,启用多进程模式,充分利用资源。

环境变量 说明 默认值
TI_MODEL_DIR 模型路径 /data/model/
TI_PREPROCESS_NUMS 预处理进程数 0
TI_INFERENCE_NUMS 推理进程数 1
TI_POSTPROCESS_NUMS 后处理进程数 0
TI_INFERENCE_MAX_BATCH_SIZE 推理 Batch 数 1

注意:说明:

注意:1. 当TI_PREPROCESS_NUMS==0且TI_POSTPROCESS_NUMS==0时

注意:model_service.py 文件中 preprocess,predict,postpress 函数在一个进程中执行。

注意:2. 否则,model_service.py 文件中preprocess, predict ,postpress 函数分别处于不同进程中执行。

注意:3. load 函数与 predict 函数处于同一进程。

注意:4. 注意 TI_INFERENCE_MAX_BATCH_SIZE 的值的调整,避免引发 GPU OOM。

六、自定义推理Worker

每一个处理 Worker 需要继承 mosec.Worker 来定义处理逻辑:

1. 可选:覆写__init__函数,进行一些初始化工作。只在必要的时候覆写,注意必须先调用super.__init__()以完成父类初始化。

2. 必须:自定义 forward 函数,提供处理能力。通常在 forward 中完成数据的处理工作。

class Worker: def __init__(self) def forward(data)

在完成定义推理 Worker 后,需要调用tiinfer.append_worker()函数来进行编排:

def append_worker( worker: Type[mosec.Worker], num: int = 1, start_method: str = "spawn", env: Union[None, List[Dict[str, str]]] = None,) -> None""" worker: 继承mosec.Worker并实现了forward方法的处理Worker num: 并行计算的进程数(>=1) start_method: 进程启动方法("spawn" 或 "fork") env: 进程启动前的一些环境变量"""

完整的推理过程中,一般需要对输入进行预处理,再输入到模型进行推理,并对推理结果进行后处理,最终才返回给调用方。推理过程通常是在 GPU 上完成的,而预处理、后处理往往是 CPU 计算甚至是一些 IO 处理。如果将预处理、后处理同推理放在同一个进程中处理,启动的进程数目主要受限于 GPU 的显存及算力。此时,将预处理、后处理同推理进程剥离,能够充分利用 CPU 的处理能力,参考以下代码片段:

import tiinferfrom mosec import Workerfrom typing import Dict, Anyclass MyPreprocess(Worker): def forward(self, data: Dict) -> Any: # 输入是json转化来的Dict,进行一些必要的预处理 class MyPredict(Worker): def __int__(self): super.__init__() # 读取并加载模型 def forward(self, data: Any) -> Any: # 输入是预处理的结果,通过调用模型推理后,得到推理结果class MyPostprocess(Worker): def forward(self, data: Any) -> Dict: # 输入为推理结果,通过一些后处理手段转化为Dict作为Json返回给调用方 # 编排处理过程: 1x预处理Worker -> 2x推理Worker -> 1x后处理Workertiinfer.append_worker(MyPreprocess, 1)tiinfer.append_worker(MyPredict, 2)tiinfer.append_worker(MyPostprocess, 1)

七、对 model_service.py 的要求

参考上文 tiinfer 介绍中的相关章节。

八、分类模型推理脚本 PyTorch 实现示例

import loggingimport osimport timefrom typing import Dict, Listfrom urllib.request import urlretrieveimport cv2 # type: ignoreimport numpy as np # type: ignoreimport torch # type: ignoreimport tiinferimport tiinfer.utilsimport mosec### 日志相关代码 #### 增加以下代码,才能将框架记录的请求日志打印到终端logger = logging.getLogger()logger.setLevel(logging.DEBUG)formatter = logging.Formatter( "%(asctime)s – %(process)d – %(levelname)s – %(filename)s:%(lineno)s – %(message)s")sh = logging.StreamHandler()sh.setFormatter(formatter)logger.addHandler(sh)### 日志相关代码 #### 预处理过程对输入的base64字符串进行解码,并按照模型要求做一些缩放操作class Pre(mosec.Worker): def forward(self, req: Dict) -> cv2.Mat: # 预处理的输入数据是json转化而来的Dict img_base64_bytes = req["image"] img = tiinfer.utils.image_to_cv2_mat(img_base64_bytes) # bgr -> rgb img = img[:, :, ::-1] # 对图片做一些预处理 img = cv2.resize(img, (256, 256)) crop_img = ( img[16 : 16 + 224, 16 : 16 + 224].astype(np.float32) / 255 ) # center crop crop_img -= [0.485, 0.456, 0.406] crop_img /= [0.229, 0.224, 0.225] crop_img = np.transpose(crop_img, (2, 0, 1)) return crop_img# 加载模型,并对预处理后的结果做推理操作,并转换为最终结果传给调用方·class Infer(mosec.Worker): def __init__(self) -> None: super().__init__() # 获取当前所在目录,需要据此加载模型 self.root_path = tiinfer.TI_MODEL_DIR # 优先使用GPU self.device = ( torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu") ) ### 非加速模型的加载 开始### # 模型存在model目录下面 model_file = os.path.join(self.root_path, "model/resNet50.pt") ### 非加速模型的加载 结束### ### 加速模型的加载 开始### # #加速模型需要额外导入tiacc_inference # import tiacc_inference # model_file = os.path.join(self.root_path, "model/tiacc.pt") ### 加速模型的加载 结束### # 加载模型 self.model = torch.jit.load(model_file) self.model.eval() # 分类需要知道最终的类别 self.categories = load_categories() def forward(self, img: cv2.Mat) -> Dict: with torch.no_grad(): batch = torch.stack( [torch.tensor(arr, device=self.device) for arr in [img]] ) pred_results = self.model(batch) prob = torch.nn.functional.softmax(pred_results, dim=1) top1_prob, top1_catid = torch.topk(prob, 1) return [ { "confidence": top1_prob[i].tolist()[0], "pred": self.categories[top1_catid[i].tolist()[0]], } for i in range(top1_prob.size(0)) ][0]# 从标签文件中读取标签id对应的类别信息def load_categories() -> List[str]: logging.info("loading categories file…") local_filename = "imagenet_classes.txt" if not os.path.exists("imagenet_classes.txt"): local_filename, _ = urlretrieve( "https://raw.githubusercontent.com/pytorch/hub/master/imagenet_classes.txt" ) with open(local_filename, encoding="utf8") as file: return list(map(lambda x: x.strip(), file.readlines()))# 编排处理过程:2个进程进行预处理 -> 1个进程进行推理tiinfer.append_worker(Pre, 2)tiinfer.append_worker(Infer, 1)

九、Demo 下载

平台提供了针对各类模型的 Demo,下载地址详见下表:

格式 场景 下载地址
TorchScript 分类 单击下载
TorchScript 检测 单击下载
TorchScript NLP 单击下载
TorchScript OCR 单击下载
Detectron2 检测 单击下载
MMDetection 检测 单击下载
HuggingFace NLP 单击下载
SavedModel NLP 单击下载
SavedModel 推荐 单击下载
FrozenGraph NLP 单击下载
ONNX 检测 单击下载

十、tiacc_inference.load()

TI-ONE 的 Detectron2 或者 MMDetection 格式优化后的模型,需要使用 tiacc-inference.load() 函数对模型进行加载,其他格式无需使用tiacc_inference 的 load,使用原生格式 load 即可。

·MMDetection
原生示例:

from mmdet.apis import init_detectormodel = init_detector(config, checkpoint, device=device)

优化后使用示例:

import tiacc_inferencemodel = tiacc_inference.load('tiacc.pt') #tiacc.pt是模型优化后生成的新模型

·Detectron2(对于 Detectron2 导出的 PyTorch 模型)

·原生示例:

import torchmodel = torch.load(checkpoint) #.pth模型文件

优化后使用示例:

import tiacc_inferencemodel = tiacc_inference.load('tiacc.pt') #tiacc.pt是模型优化后生成的新模型

·Detectron2(对于通过 Detectron2.modeling.build_model 构造的模型)

·原生示例:

from detectron2.config import get_cfgfrom detectron2.modeling import build_modelcfg = get_cfg()cfg.MODEL.DEVICE = devicecfg.MODEL.WEIGHTS = checkpointmodel = build_model(cfg)

优化后使用示例:

import tiacc_inferencemodel = tiacc_inference.load('tiacc.pt') #tiacc.pt是模型优化后生成的新模型

赞 (0)
上一篇 4天前
下一篇 4天前