tencent cloud

腾讯云 TI 平台

产品简介
产品概述
产品定价
客户价值
应用场景
购买指南
计费概述
购买方式
续费说明
欠费说明
安全合规
数据安全保护机制
监控、审计与日志
安全合规资质
快速入门
平台使用准备
操作指南
大模型广场
任务式建模
开发机
模型管理
模型评测
在线服务
资源组管理
数据源管理
Tikit
GPU 虚拟化
实践教程
LLM 部署及推理
LLM 训练及评测
内置训练镜像列表
自定义训练镜像规范
Angel 训练加速功能介绍
基于标签实现子用户间资源隔离
相关协议
TI Platform 隐私协议
TI Platform 数据处理和安全协议
开源软件信息
联系我们
文档腾讯云 TI 平台操作指南在线服务模型推理文件简介和示例

模型推理文件简介和示例

PDF
聚焦模式
字号
最后更新时间: 2025-05-09 17:47:19

TI 内置推理框架 tiinfer 介绍

tiinfer 是腾讯云 TI-ONE 模型服务使用的推理框架。基于mosec 提供的基础能力,tiinfer 提供了以下功能:
高性能的 HTTP 服务
自由编排计算过程

安装

tiinfer 支持 Gnu/Linux 系统,依赖 python 3.8 及以上版本。需要使用以下命令安装 PyPI 包:
pip install -i https://mirrors.cloud.tencent.com/pypi/simple tiinfer

HelloWorld!

以下代码展示了一个最简单的 HelloWorld 示例:
from typing import Dict
import tiinfer

### 日志相关代码 ###
# 增加以下代码,才能将框架记录的请求日志打印到终端
import logging
import sys
logger_formatter = "%(asctime)s %(levelname)s    %(module)s:%(lineno)d    %(message)s"
logging.basicConfig(stream=sys.stdout, format=logger_formatter, level=logging.DEBUG)
### 日志相关代码 ###

# tiinfer支持原生的mosec.Worker
class 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
其中,配置项timeout值表示Web服务超时时间,单位为毫秒。模型拉起后,会在8501端口启动一个 HTTP 服务,请求地址为/v1/models/m:predict。用以下命令可以访问:
> curl -X POST -d '{"key": "values"}' http://127.0.0.1:8501/v1/models/m:predict
{
"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 tiinfer
from mosec import Worker
from typing import Dict, Any


class 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后处理Worker
tiinfer.append_worker(MyPreprocess, 1)
tiinfer.append_worker(MyPredict, 2)
tiinfer.append_worker(MyPostprocess, 1)

model_service.py 简介

对 model_service.py 的要求

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

分类模型推理脚本 Pytorch 实现示例


import logging
import os
import time
from typing import Dict, List
from urllib.request import urlretrieve

import cv2  # type: ignore
import numpy as np  # type: ignore

import torch  # type: ignore

import tiinfer
import tiinfer.utils
import 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
检测

TI-ACC 推理加速函数介绍

tiacc_inference.load()

TI-ONE 的 Detectron2 或者 MMDetection 格式优化后的模型,需要使用 tiacc-inference.load() 函数对模型进行加载,其他格式无需使用tiacc_inference 的 load,使用原生格式 load 即可。
MMDetection 原生示例:
from mmdet.apis import init_detector
model = init_detector(config, checkpoint, device=device)
优化后使用示例:
import tiacc_inference
model = tiacc_inference.load('tiacc.pt') #tiacc.pt是模型优化后生成的新模型
Detectro2(对于 Detectron2 导出的 PyTorch 模型) 原生示例:
import torch
model = torch.load(checkpoint) #.pth模型文件
优化后使用示例:
import tiacc_inference
model = tiacc_inference.load('tiacc.pt') #tiacc.pt是模型优化后生成的新模型
Detectro2(对于通过 Detectron2.modeling.build_model 构造的模型) 原生示例:
from detectron2.config import get_cfg
from detectron2.modeling import build_model
cfg = get_cfg()
cfg.MODEL.DEVICE = device
cfg.MODEL.WEIGHTS = checkpoint
model = build_model(cfg)
优化后使用示例:
import tiacc_inference
model = tiacc_inference.load('tiacc.pt') #tiacc.pt是模型优化后生成的新模型


帮助和支持

本页内容是否解决了您的问题?

填写满意度调查问卷,共创更好文档体验。

文档反馈