Files
wehub-resource-sync 2aaeece67c
Codestyle Check / Lint (push) Has been cancelled
Codestyle Check / Check bypass (push) Has been cancelled
Pipelines-Test / Pipelines-Test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:37:14 +08:00

208 lines
9.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PaddleNLP SimpleSevring
PaddleNLP SimpleServing 是基于 unicorn 封装的模型部署服务化工具,该服务化工具具备灵活、易用的特性,可以简易部署预训练模型和预训练模型工具 TaskflowPaddleNLP SimpleServing 具备以下两个特性:
- 易用:一行代码即可部署预训练模型和预训练工具 Taskflow
- 灵活:Handler 机制可以快速定制化服务化部署方式
## Tasflow 部署
Taskflow 是 PaddleNLP 预训练模型工具,具备开箱即用的特性,同时 Taskflow 可以支持加载微调后的模型,基于 Taskflow 的服务化方式可以进一步降低使用者的部署难度。PaddleNLP SimpleServing 基于这样的设计需求,设计了一套基于 Taskflow 的快速部署方式。下面从 server 搭建,client 发送请求来详细介绍使用方式。
### server 搭建
下面是 Taskflow 搭建服务的简易代码
```python
schema = ['出发地', '目的地', '费用', '时间']
uie = Taskflow("information_extraction", schema=schema)
app = SimpleServer()
app.register_taskflow('taskflow/uie', uie)
```
这里主要是使用 `SimpleServer` 服务类来注册 Taskflow Server,下面我们具体介绍一下 `register_taskflow` 相关参数
```text
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 实例,在服务化处理请求的过程中做了负载均衡,保证机器设备利用率充分利用,下面是具体的使用例子
```python
schema = ['出发地', '目的地', '费用', '时间']
uie1 = Taskflow("information_extraction", schema=schema, device_id=0)
uie2 = Taskflow("information_extraction", schema=schema, device_id=1)
app = SimpleServer()
app.register_taskflow('taskflow/uie', [uie1, uie2])
```
### 启动服务化
执行代码的即可启动服务
```
paddlenlp server server:app --host 0.0.0.0 --port 8189 --workers 1
```
服务化整体参数配置如下:
```text
--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 发送
```python
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`
```python
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 搭建
下面是预训练模型的搭建的简易代码
```python
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` 相关参数
```text
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.2cuDNN >= 8.1.1 3) **安装依赖**:安装 onnx、 onnxruntime-gpu
device_id(int, list(int)):
GPU设备,device_id默认为0,同时如果有多张显卡,可以设置成list,例如[0, 1]就可以支持多卡服务化;CPU设备,不用设置。
```
- BaseModelHandler 继承类:主要是 `CustomModelHandler`,该类的实现可以参考[链接](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/paddlenlp/server/handlers/custom_model_handler.py), 绝大多数语义理解模型均可使用该继承类
- BasePostHandler 继承类:主要是文本分类 `MultiClassificationPostHandler``MultiLabelClassificationPostHandler` 来支持多分类、多标签分类,实现代码部分可以参考[链接](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/paddlenlp/server/handlers/cls_post_handler.py)`TokenClsModelHandler` 支持 序列标注任务,实现代码部分可以参考[链接](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/paddlenlp/server/handlers/token_model_handler.py)
### 启动服务化
执行代码的即可启动服务
```
paddlenlp server server:app --host 0.0.0.0 --port 8189 --workers 1
```
服务化整体参数配置如下:
```text
--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 即可实现多卡服务化,保证机器设备利用率充分利用,下面是具体的使用例子
```python
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=MultiClassificationPostHandler
device_id=[0,1]) # device_id是0,1 两张卡
```
### client 发送
```python
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_len``batch_size` 均可以控制服务化处理时的序列长度和处理 batch_size 。
## 参考示例
- [UIE 服务化部署](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/slm/model_zoo/uie/deploy/serving/simple_serving)
- [文本分类服务化部署](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/slm/applications/text_classification/multi_class/deploy/simple_serving)
- [预训练模型定制化 post_handler](https://github.com/PaddlePaddle/PaddleNLP/blob/release/2.8/model_zoo/ernie-health/cblue/deploy/serving/simple_serving)