Docker torchserve 部署模型流程

news2024/11/16 1:50:54

1.拉取官方镜像

地址: https://hub.docker.com/r/pytorch/torchserve/tags

docker pull pytorch/torchserve:0.7.1-gpu

2. docker启动指令

CPU

docker run --rm -it -d -p 8380:8080 -p 8381:8081 --name torch-server -v /path/model-server/extra-files:/home/model-server/extra-files -v /path/model-server/model-store:/home/model-server/model-store pytorch/torchserve:0.7.1-gpu

GPU

docker run --rm -it -d --gpus all -p 8380:8080 -p 8381:8081 --name torch-server -v /path/model-server/extra-files:/home/model-server/extra-files -v /path/model-server/model-store:/home/model-server/model-store pytorch/torchserve:0.7.1-gpu

/home/model-server/model-store 是docker映射地址,不能更改

进入容器,可以发现各个端口的意义,8080是通信访问接口,8081是管理服务配置接口,8082是服务监控接口
在这里插入图片描述

3. 打包模型文件

3.1 使用框架中脚本或者自己写脚本将模型转为torchscript(.pt)

3.2 torchscript转.mar文件

(1) run_hander.py
from xx_model_handler import KnowHandler

_service = KnowHandler()

def handle(data, context):
    try:
        if not _service.initialized:
            print('ENTERING INITIALIZATION')
            _service.initialize(context)
        if data is None:
            return None
        data = _service.preprocess(data)
        data = _service.inference(data)
        data = _service.postprocess(data)
        return data
    except Exception as e:
        raise Exception("Unable to process input data. " + str(e))
(2) xx_model_handler.py
"""
ModelHandler defines a custom model handler.
"""
import torch
import os
import json
import logging
from transformers import BertTokenizer

class KnowHandler(object):
    """
    A custom model handler implementation.
    """

    def __init__(self):
        super(KnowHandler, self).__init__()
        self.initialized = False

    def initialize(self, ctx):
        """
        Initialize model. This will be called during model loading time
        :param context: Initial context contains model server system properties.
        :return:
        """
        self.manifest = ctx.manifest
        properties = ctx.system_properties

        model_dir = properties.get("model_dir")
        serialized_file = self.manifest["model"]["serializedFile"]
        model_pt_path = os.path.join(model_dir, serialized_file)

        self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
        config_path = os.path.join(model_dir, "config.json")
        with open(config_path,"r") as fr:
            setup_config = json.load(fr)
        self.model = torch.jit.load(model_pt_path, map_location=self.device)
        self.tokenizer = BertTokenizer(setup_config["vocab_path"])
        self.max_length = setup_config["max_length"]

        self.initialized = True
        #  load the model, refer 'custom handler class' above for details

    def preprocess(self, data):
        """
        Transform raw input into model input data.
        :param batch: list of raw requests, should match batch size
        :return: list of preprocessed model input data
        """
        # Take the input data and make it inference ready
        preprocessed_data = data[0].get("data")
        if preprocessed_data is None:
            preprocessed_data = data[0].get("body")

        inputs = preprocessed_data.decode('utf-8')
        inputs = json.loads(inputs) # {"text": []}
        return inputs


    def inference(self, model_input):
        """
        Internal inference methods
        :param model_input: transformed model input data
        :return: list of inference output in NDArray
        """
        # Do some inference call to engine here and return output
        text = model_input["text"]
        inputs = self.tokenizer(
            text,
            max_length=self.max_length,
            truncation=True,
            padding='max_length',
            return_tensors='pt'
        )
        #inputs = {k: torch.as_tensor(v, dtype=torch.int64) for k, v in inputs.items()}
        for key, value in inputs.items():
            if isinstance(value, torch.Tensor):
                inputs[key] = value.to(self.device)
        input_ids = inputs['input_ids']
        token_type_ids = inputs['token_type_ids']
        attention_mask = inputs['attention_mask']
        logits = self.model(input_ids,attention_mask,token_type_ids)
        return logits

    def postprocess(self, inference_output):
        """
        Return inference result.
        :param inference_output: list of inference output
        :return: list of predict results
        """
        # Take output from network and post-process to desired format
        postprocess_output = [inference_output.tolist()]
        return postprocess_output


(3) config.json
{
  "threshold": 0.8,
  "max_length": 40
}

torch-model-archiver --model-name {name of model} --version {模型版本} --serialized-file {torchscript文件地址} --export-path {.mar文件存放地址} --handler run_handler.py --extra-files {其它文件如配置文件等} --runtime python3 -f

torch-model-archiver --model-name my_model --version 1.0 --serialized-file /path/mymodel.pt --export-path /home/model-server/model-store --handler run_handler.py --extra-files "xx_model_handler,utils.py,config.json,vocab.txt"  --runtime python -f

–model-name: 模型的名称,后来的接口名称和管理的模型名称都是这个
–serialized-file: 模型环境及代码及参数的打包文件
–export-path: 本次打包文件存放位置
–extra-files: handle.py中需要使用到的其他文件
–handler: 指定handler函数。(模型名:函数名)
-f 覆盖之前导出的同名打包文件

4. torchserver配置接口

(1)查询已注册的模型
curl "http://localhost:8381/models"
(2)注册模型并为模型分配资源

将.mar模型文件注册,注意:.mar文件必须放在model-store文件夹下,即/path/model-server/model-store

curl -X POST "{ip:port}/models?url={.mar文件名}&model_name={model_name}&batch_size=8&max_batch_delay=10&initial_workers=1"

curl -X POST "localhost:8381/models?url=my_model.mar&model_name=my_model&batch_size=8&max_batch_delay=10&initial_workers=1"
(3)查看模型状态
curl http://localhost:8381/models/{model_name}
(4)删除注册模型
curl -X DELETE http://localhost:8381/models/{model_name}/{version}

5. 模型推理

response = requests.post('http://localhost:8380/predictions/{model_name}/{version}',data = data)
# -*- coding: utf-8 -*-
import requests
import json
text = ['xxxxx']
data = {'data':json.dumps({'text':text})}
print(data)
response = requests.post('http://localhost:8380/predictions/my_model',data = data)
print(response)
if response.status_code==200:
    vectors = response.json()
    print(vectors)

参考:
https://blog.51cto.com/u_16213661/8750698
https://blog.csdn.net/wangzitaotao/article/details/131101852
https://pytorch.org/serve/index.html
https://docs.aws.amazon.com/zh_cn/sagemaker/latest/dg/deploy-models-frameworks-torchserve.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2142481.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机毕业设计选题推荐-4S店试驾平台-小程序/App

✨作者主页:IT研究室✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

js 如何代码识别Selenium+Webdriver

Python 的 Selenium 可以模拟用户操作打开浏览器,前端如何去识别是人机还是真人: window.navigator.webdriver Selenium 人机下是这样的: 正常使用:

Makefile语法详解

目录 1 Makefile基本常识1.1 基本格式1.2 makefile规则1.3 伪目标1.4 变量的使用1.5 赋值方式1.6 常用函数 2 Makefile整体编译2.1 编译选项2.2三个.c整体编译2.3 静态库编译2.4 动态库编译 1 Makefile基本常识 1.1 基本格式 如下所示为Makefile的基本格式,特别需…

高等数学 2.5 函数的微分

文章目录 一、微分的定义二、微分的几何意义三、微分运算1、函数和、差、积、商的微分法则2、复合函数的微分法则 四、微分在近似计算中的应用 一、微分的定义 定义 设函数 y f ( x ) y f(x) yf(x) 在某区间内有定义, x 0 x_0 x0​ 及 x 0 Δ x x_0 \Delta x …

大模型时代:普通人如何获利

随着人工智能技术的飞速发展,我们正步入一个以大模型为驱动力的新时代。这些大型语言模型,如GPT-3和BERT,已经在各个领域展现出惊人的能力,包括文本生成、翻译、问答等。这些技术的进步不仅改变了我们的生活,也为普通人…

【数据结构初阶】顺序结构二叉树(堆)接口实现超详解

文章目录 1.树1. 1 树的概念与结构1. 2 树的相关术语1. 3 树的表示1. 4 树形结构实际运用场景 2.二叉树2. 1 概念与结构2. 2 特殊的二叉树2. 2. 1 满二叉树2. 2. 2 完全二叉树 2. 3 二叉树存储结构2. 3. 1 顺序结构2. 3. 2 链式结构 3. 实现顺序结构二叉树(小堆&…

【OJ刷题】双指针问题6

这里是阿川的博客,祝您变得更强 ✨ 个人主页:在线OJ的阿川 💖文章专栏:OJ刷题入门到进阶 🌏代码仓库: 写在开头 现在您看到的是我的结论或想法,但在这背后凝结了大量的思考、经验和讨论 目录 1…

ThreadX源码:Cortex-A7的tx_thread_irq_nesting_start(嵌套中断开始动作).s汇编代码分析

0 参考资料 Cortex M3权威指南(中文).pdf(可以参考ARM指令集用法) 1 前言 tx_thread_irq_nesting_start.s是用来实现Cortex-A7 IRQ嵌套中断的开始函数实现的汇编文件。 2 源码分析 源码如下: 1  IRQ_DISABLE 0x80…

遍历指定的目录a中的所有子目录及所有文件os.walk(root_dir)

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 遍历指定的目录a 中的所有子目录 及所有文件 os.walk(root_dir) [太阳]选择题 已知已经存在的目录和文件情况如下: a目录下有子目录b,有两个文件:a1.txt和…

Flet全平台开发:软件开发界勇士为Python语言补短板的一次极具挑战性的尝试、冲刺和华丽亮相

一、Flet创始人和开发者介绍、开发Flet的背景介绍 Flet 的创始人和开发者 Feodor Fitsner 是俄罗斯人,就职于微软。 Flet 的第一个版本于 2022 年 6 月发布。这是一个相对较新的库,它基于 Flutter 框架,首先支持的是用 Python 语言开发软件…

2024/9/17 pytorch-卷积神经网络

一、torch.nn pytorch有很多接口,其中的torch.nn可以让我们方便的调用以便生成神经网络各层 1.torch.nn.Module 是一个构成神经网络层的一个基本类别,一般生成一个类别来继承nn.module torch.tensor(a)将a初始化为一个tensor类型数据 一般这种已经固…

攻防世界--->hackme

学习笔记。 下载 查壳。 64ida打开。 进入main&#xff1a; 跟进&#xff1a; 这是密文 咋一看这程序感觉很复杂&#xff0c;很复杂&#xff1a; 脚本&#xff1a; #include <stdio.h> #include <string.h> #include <stdlib.h>int main() {unsigned char …

Qt --- 信号和信号槽

前言 Linux信号Signal&#xff0c;系统内部的通知机制&#xff0c;进程间通信方式。 信号源&#xff1a;谁发的信号。 信号的类型&#xff1a;哪种类别的信号。 信号的处理方式&#xff1a;注册信号处理函数&#xff0c;在信号被触发的时候自动调用执行。 Qt中的信号和Lin…

Bugku---密码学---乐谱密码

题目出处&#xff1a;首页 - Bugku CTF ✨打开后发现是一张乐符图 ✨一般我们所熟悉的「Do Re Mi Fa Sol La Si」&#xff0c;若写成音名&#xff0c;即是「C D E F G A B」。不过德国人习惯使用的音名则是「C D E F G A H」&#xff0c;「B」代表 音名B♭ 。 C也就是后面的4&…

Rust练手项目,写个有趣的小工具定时从一言网获取一段有趣的话并推送通知

Rust练手项目&#xff0c;写个有趣的小工具 代码 继续练习Rust, 写个小工具定时从一言网获取一段有趣的话并提示&#xff0c;如下 练习以下Rust点 并发编程 Mutex, Arc指针使用HTTP请求Windows Gui 代码 Cargo.toml [package] name "funny_word" edition "20…

YOLOv8目标检测模型——遥感小目标检测经验分享

小目标检测——YOLOV8 一、引言 背景介绍 &#xff08;1&#xff09;目标检测的重要性 目标检测在许多领域都具有极其重要的作用。在自动驾驶中&#xff0c;目标检测能够识别道路上的障碍物和行人&#xff0c;确保行车安全。在视频监控中&#xff0c;目标检测能够实时发现异…

【matlab】生成 GIF 的函数(已封装可直接调用)

文章目录 前言一、函数输入与输出二、函数代码三、例程&#xff08;可直接运行&#xff09;参考文献 前言 生成 gif 图片时遇到的问题&#xff0c;为了后续调用方便&#xff0c;封装为函数 一、函数输入与输出 输入&#xff1a; cell_figure: cell 数组&#xff0c;数组元素是…

Chainlit集成LlamaIndex并使用通义千问模型实现AI知识库检索网页对话应用增强版

前言 之前使用Chainlit集成LlamaIndex并使用通义千问大语言模型的API接口&#xff0c;实现一个基于文档文档的网页对话应用。 可以点击我的上一篇文章《Chainlit集成LlamaIndex并使用通义千问模型实现AI知识库检索网页对话应用》 查看。 本次针对上一次的代码功能进一步的完善…

Cursor与Copilot:编程界的双雄对决

引子 在技术快速发展的当下&#xff0c;编程几乎成为了现代社会的基础能力。Cursor与Copilot作为当前备受瞩目的编程助手&#xff0c;各自展现出了独特的魅力。它们不仅改变了程序员的工作方式&#xff0c;更是提升了代码编写的效率&#xff0c;成为了编程界的“双雄”。 Curs…

软件安全、逆向分析、加密与解密--crackme2详解

本次使用到的软件有&#xff1a;PEiD、IDA、X32dbg 刚学逆向不久&#xff0c;可能有些地方会有错误&#xff0c;欢迎各位大佬指导 执行 运行程序 点击About 点击确定&#xff0c;输入如图数据 点击try Now 点击确定&#xff0c;回到主界面 点击Exit&#xff0c;退出 查壳&a…