Skip to content

Latest commit

 

History

History
207 lines (181 loc) · 9.52 KB

server.md

File metadata and controls

207 lines (181 loc) · 9.52 KB

PaddleNLP SimpleSevring

PaddleNLP SimpleServing 是基于 unicorn 封装的模型部署服务化工具,该服务化工具具备灵活、易用的特性,可以简易部署预训练模型和预训练模型工具Taskflow,PaddleNLP SimpleServing 具备以下两个特性:

  • 易用:一行代码即可部署预训练模型和预训练工具Taskflow
  • 灵活:Handler机制可以快速定制化服务化部署方式

Tasflow部署

Taskflow 是 PaddleNLP 预训练模型工具,具备开箱即用的特性,同时 Taskflow 可以支持加载微调后的模型,基于 Taskflow 的服务化方式可以进一步降低使用者的部署难度。PaddleNLP SimpleServing 基于这样的设计需求,设计了一套基于Taskflow的快速部署方式。下面从 server 搭建,client 发送请求来详细介绍使用方式。

server 搭建

下面是 Taskflow 搭建服务的简易代码

schema = ['出发地', '目的地', '费用', '时间']
uie = Taskflow("information_extraction", schema=schema)
app = SimpleServer()
app.register_taskflow('taskflow/uie', uie)

这里主要是使用 SimpleServer 服务类来注册 Taskflow Server,下面我们具体介绍一下 register_taskflow 相关参数

def register_taskflow(
    task_name,
    task,
    taskflow_handler=None)

task_name(str):
      服务化的名称,最终的服务化的URL: https://host:port/{task_name}
task(paddlenlp.Taskflow or list(paddlenlp.Taskflow)):
      Taskflow的实例对象,将想要注册的Taskflow任务注册进去,可以是多个Taskflow实例来支持多卡服务化
taskflow_handler(paddlenlp.server.BaseTaskflowHandler, 可选):
      Taskflow句柄处理类,可以自定义处理类来定制化Taskflow服务,默认为None,是默认的TaskflowHandler

多卡服务化(可选)

在机器环境里面如果有多卡,那就可以register taskflow服务化时,可以注册多个Taskflow实例,在服务化处理请求的过程中做了负载均衡,保证机器设备利用率充分利用,下面是具体的使用例子

schema = ['出发地', '目的地', '费用', '时间']
uie1 = Taskflow("information_extraction", schema=schema, device_id=0)
uie2 = Taskflow("information_extraction", schema=schema, device_id=1)
app = SimpleServer()
app.register_taskflow('uie', [uie1, uie2])

启动服务化

执行代码的即可启动服务

paddlenlp server server:app --host 0.0.0.0 --port 8189 --workers 1

服务化整体参数配置如下:

--host: 启动服务化的IP地址,通常可以设置成 0.0.0.0
--port:启动服务化的网络端口
--workers: 接收服务化的进程数,默认为1
--log_level:服务化输出日志的级别,默认为 info 级别
--limit_concurrency:服务化能接受的并发数目,默认为None, 没有限制
--timeout_keep_alive:保持服务化连接的时间,默认为15s
--app_dir:服务化本地的路径,默认为服务化启动的位置
--reload: 当 app_dir的服务化相关配置和代码发生变化时,是否重启server,默认为False

client 发送

import requests
import json

url = "http://0.0.0.0:8189/taskflow/uie"
headers = {"Content-Type": "application/json"}
texts = ["城市内交通费7月5日金额114广州至佛山", "5月9日交通费29元从北苑到望京搜后"]
data = {
    "data": {
        "text": texts,
    }
}
r = requests.post(url=url, headers=headers, data=json.dumps(data))
datas = json.loads(r.text)
print(datas)

通过上述代码配置即可发送POST请求,同时注意在data这个key填入相关请求

同时可以支持定义 schema 传入到client请求中,可以快速切换 schema

import requests
import json

url = "http://0.0.0.0:8189/taskflow/uie"
headers = {"Content-Type": "application/json"}
texts = ["城市内交通费7月5日金额114广州至佛山", "5月9日交通费29元从北苑到望京搜后"]
data = {
    "data": {
        "text": texts,
    },
    "parameters": {
        "schema": [] # 自定义schema
    }
}
r = requests.post(url=url, headers=headers, data=json.dumps(data))
datas = json.loads(r.text)
print(datas)

预训练模型部署

PaddleNLP SimpleServing 除了能支持Taskflow的服务化部署,也能支持预训练模型的部署,通过简单的配置即可加载预训练模型来进行服务化,同时在接口层面也能支持服务化的扩展,支持模型前后处理的定制化需求。

server 搭建

下面是预训练模型的搭建的简易代码

from paddlenlp import SimpleServer
from paddlenlp.server import CustomModelHandler, MultiClassificationPostHandler

app = SimpleServer()
app.register('cls_multi_class',
             model_path="./export",
             tokenizer_name='ernie-3.0-medium-zh',
             model_handler=CustomModelHandler,
             post_handler=MultiClassificationPostHandler)

这里主要是使用 SimpleServer 服务类来注册 Transformers Server,下面我们具体介绍一下 register 相关参数

def register(task_name,
             model_path,
             tokenizer_name,
             model_handler,
             post_handler,
             precision='fp32',
             device_id=0)
task_name(str):
      服务化的名称,最终的服务化的URL: https://host:port/{task_name}
model_path(str):
      需要部署的模型路径,这里的路径必须是动转静后的模型路径
model_handler(paddlenlp.server.BaseModelHandler):
      模型前置处理以及模型预测的Handler类别名字,这里可以继承 BaseModelHandler 自定义处理逻辑
 post_handler(paddlenlp.server.BasePostHandler):
      模型后置处理的Handler类别名字,这里可以继承 BasePostHandler 自定义处理逻辑
precision(str):
      模型的预测精度,默认为fp32;可选fp16,fp16的支持需要以下条件 1) **硬件**: V100、T4、A10、A100/GA100、Jetson AGX Xavier 、3080、3080、2080、2090 等显卡 2)**CUDA环境**:确保 CUDA >= 11.2,cuDNN >= 8.1.1 3) **安装依赖**:安装 onnx、 onnxruntime-gpu
device_id(int, list(int)):
       GPU设备,device_id默认为0,同时如果有多张显卡,可以设置成list,例如[0, 1]就可以支持多卡服务化;CPU设备,不用设置。
  • BaseModelHandler继承类:主要是 CustomModelHandler,该类的实现可以参考链接, 绝大多数语义理解模型均可使用该继承类
  • BasePostHandler继承类:主要是文本分类 MultiClassificationPostHandlerMultiLabelClassificationPostHandler 来支持多分类、多标签分类,实现代码部分可以参考链接TokenClsModelHandler 支持 序列标注任务,实现代码部分可以参考链接

启动服务化

执行代码的即可启动服务

paddlenlp server server:app --host 0.0.0.0 --port 8189 --workers 1

服务化整体参数配置如下:

--host: 启动服务化的IP地址,通常可以设置成 0.0.0.0
--port:启动服务化的网络端口,注意和已有网络端口冲突
--workers: 接收服务化的进程数,默认为1
--log_level:服务化输出日志的级别,默认为 info 级别
--limit_concurrency:服务化能接受的并发数目,默认为None, 没有限制
--timeout_keep_alive:保持服务化连接的时间,默认为15s
--app_dir:服务化本地的路径,默认为服务化启动的位置
--reload: 当 app_dir的服务化相关配置和代码发生变化时,是否重启server,默认为False

多卡服务化(可选)

在机器环境里面如果有多卡,通过简单设置 device_id 即可实现多卡服务化,保证机器设备利用率充分利用,下面是具体的使用例子

from paddlenlp import SimpleServer
from paddlenlp.server import CustomModelHandler, MultiClassificationPostHandler

app = SimpleServer()
app.register('models/cls_multi_class',
             model_path="../../export",
             tokenizer_name='ernie-3.0-medium-zh',
             model_handler=CustomModelHandler,
             post_handler=MultiClassificationPostHandlerdevice_id=[0,1]) # device_id是0,1 两张卡

client 发送

import requests
import json

texts = [
        '黑苦荞茶的功效与作用及食用方法', '交界痣会凸起吗', '检查是否能怀孕挂什么科', '鱼油怎么吃咬破吃还是直接咽下去',
        '幼儿挑食的生理原因是'
    ]
    data = {
        'data': {
            'text': texts,
        },
        'parameters': {
            'max_seq_len': 128,
            'batch_size': 2
        }
    }
    r = requests.post(url=url, headers=headers, data=json.dumps(data))
    result_json = json.loads(r.text)
    print(result_json)

在Client发送请求的过程中可以一些参数来控制服务化处理逻辑,例如上面的 max_seq_lenbatch_size 均可以控制服务化处理时的序列长度和处理batch_size 。

参考示例