- 人工智能
- 大模型
- 预训练
- 微调
- LoRA
- RLHF
- 强化学习
- 分布式训练
【免费下载链接】PaddleNLP
Easy-to-use and powerful LLM and SLM library with awesome model zoo.
PaddleNLP 多标签分类应用(slm/applications/text_classification/multi_label)提供了从数据标注、模型训练、模型分析、模型压缩到预测部署的端到端方案。本文聚焦其中基于Paddle Serving的在线服务化部署环节:从环境准备、inference 静态图模型转换,到 pipeline 服务启动与 RPC/HTTP 客户端验证,完整覆盖将训练好的多标签模型上线为可对外提供预测能力的 HTTP 服务的全过程。读完本文,你将掌握 PaddleNLP 多标签模型转 Paddle Serving 格式的命令、服务端config.yml的每项参数含义、service.py内部 tokenizer 预处理与 sigmoid 阈值后处理逻辑,以及如何用 rpc_client 与 http_client 完成在线请求验证。
适用前提:本指南面向已经完成多标签模型训练并导出了静态图 inference 模型的场景。训练与静态图导出步骤详见 多标签分类指南,部署目录中同时提供基于 ONNXRuntime 的离线部署方案、SimpleServing 方案 与 Triton 方案,本文仅讲解 Paddle Serving 路线。
目录
- 环境准备
- 模型转换
- 部署模型
环境准备
在线服务化部署需要同时具备 PaddleNLP 运行环境和 Paddle Serving 运行环境,版本要求如下:
- python >= 3.6
- paddlepaddle >= 2.3
- paddlenlp >= 2.4
安装 PaddlePaddle
环境中paddlepaddle-gpu或paddlepaddle版本应大于或等于 2.3。请根据自己机器情况(操作系统、是否使用 GPU、CUDA 版本等)选择合适的安装命令,具体可参考飞桨官方快速安装文档。
安装 PaddleNLP
安装 PaddleNLP 默认开启百度镜像源以加速下载;如果你使用 HTTP 代理,可以删去-i https://mirror.baidu.com/pypi/simple:
python3 -m pip install --upgrade paddlenlp -i https://mirror.baidu.com/pypi/simple安装 Paddle Serving
Paddle Serving 的安装拆分为三部分:
- client 与 serving app:用于向服务发送请求(RPC/HTTP 客户端依赖),例如本文后续用到的
rpc_client.py依赖paddle_serving_server.pipeline.PipelineClient,http_client.py通过 HTTP 请求访问服务:
pip install paddle_serving_app paddle_serving_client- serving server:用于启动服务,需根据服务器设备选择 CPU server 或 GPU server:
- 安装 CPU server:
pip install paddle_serving_server- 安装 GPU server(注意选择与本地环境一致的 CUDA/Cudnn/TensorRT 版本组合):
# CUDA10.2 + Cudnn7 + TensorRT6 pip install paddle-serving-server-gpu==0.8.3.post102 -i https://pypi.tuna.tsinghua.edu.cn/simple # CUDA10.1 + TensorRT6 pip install paddle-serving-server-gpu==0.8.3.post101 -i https://pypi.tuna.tsinghua.edu.cn/simple # CUDA11.2 + TensorRT8 pip install paddle-serving-server-gpu==0.8.3.post112 -i https://pypi.tuna.tsinghua.edu.cn/simpleNOTE:
- 默认开启国内清华镜像源加速下载,如果你使用 HTTP 代理可以去掉
-i https://pypi.tuna.tsinghua.edu.cn/simple; - 更多 wheel 包版本请参考 Paddle Serving 官方文档的 Latest Packages 说明。
模型转换
使用 Paddle Serving 做服务化部署时,需要先将保存的 inference 静态图模型转换为 serving 易于部署的模型格式。
第一步:导出静态图模型
在进入本文部署环节之前,需要先完成动态图参数到静态图参数的导出。多标签分类应用提供 静态图导出脚本,运行方式如下:
python export_model.py --params_path ./checkpoint/ --output_path ./export若使用多语言模型 ERNIE M 作为预训练模型,需追加--multilingual参数(此时输入规格只包含input_ids):
python export_model.py --params_path ./checkpoint/ --output_path ./export --multilingual从 export_model.py 的源码可以看到,导出过程通过paddle.jit.to_static将动态图模型转换为静态图:
- 非多语言模型定义两个输入
InputSpec(shape=[None, None], dtype="int64", name="input_ids")与token_type_ids; - 多语言模型仅保留
input_ids一个输入; - 最终通过
paddle.jit.save(model, save_path)将模型保存到output_path下的float32前缀文件中(如float32.pdiparams、float32.pdiparams.info、float32.pdmodel)。
第二步:转换为 Serving 格式
用已安装的paddle_serving_client将静态图参数模型转换成 serving 格式。命令中的--dirname填模型地址(export目录),--model_filename与--params_filename根据实际导出的模型文件名填写即可:
python -m paddle_serving_client.convert --dirname ../../export --model_filename float32.pdmodel --params_filename float32.pdiparams原文档中该命令位于
deploy/paddle_serving/目录下执行,故../../export指向 multi_label 应用 下的export目录;如你已将模型放在其他位置,请相应调整--dirname。
可通过以下命令查看convert各参数含义:
python -m paddle_serving_client.convert --help转换成功后的目录结构如下:
paddle_serving/ ├── serving_server │ ├── float32.pdiparams │ ├── float32.pdmodel │ ├── serving_server_conf.prototxt │ └── serving_server_conf.stream.prototxt └── serving_client ├── serving_client_conf.prototxt └── serving_client_conf.stream.prototxtserving_server目录用于启动服务端;serving_client目录中的serving_client_conf.prototxt记录了模型输入输出节点(fetch var 的 alias_name),后面配置config.yml的fetch_list时需以它为准。
部署模型
Paddle Serving 部署目录(slm/applications/text_classification/multi_label/deploy/paddle_serving/)中包含了启动 pipeline 服务和发送预测请求的代码与模型,结构如下:
serving/ ├── serving_server │ ├── float32.pdiparams │ ├── float32.pdmodel │ ├── serving_server_conf.prototxt │ └── serving_server_conf.stream.prototxt ├── config.yml # 分类任务启动服务端的配置文件 ├── rpc_client.py # 分类任务发送 pipeline 预测请求的脚本 └── service.py # 分类任务启动服务端的脚本实际部署时,需要把上一步转换得到的serving_server目录放入此目录(替换或覆盖),并保证service.py、config.yml、rpc_client.py、http_client.py与本模型配套。
修改配置文件
目录中的 config.yml 是启动服务端的核心配置,文件内注释解释了每个参数的含义。下面结合该文件逐项说明,并给出常用修改示例:
# 修改模型目录为下载的模型目录或自己的模型目录: model_config: serving_server => model_config: ernie-3.0-tiny/serving_server # 修改 rpc 端口号 rpc_port: 10231 => rpc_port: 9998 # 修改使用 GPU 推理为使用 CPU 推理: device_type: 1 => device_type: 0 # 开启 MKLDNN 加速 # use_mkldnn: False => use_mkldnn: True # Fetch 结果列表,以 serving_client/serving_client_conf.prototxt 中 fetch_var 的 alias_name 为准 fetch_list: ["linear_147.tmp_1"] => fetch_list: ["linear_75.tmp_1"]config.yml 的完整参数清单及含义如下:
| 配置项 | 取值示例 | 含义 |
|---|---|---|
rpc_port | 18090 | RPC 端口;rpc_port和http_port不允许同时为空。当rpc_port为空且http_port不为空时,会自动将rpc_port设置为http_port+1 |
http_port | 9878 | HTTP 端口;当rpc_port可用且http_port为空时,不会自动生成http_port |
worker_num | 1 | 最大并发数。当build_dag_each_worker=True时,框架会创建worker_num个进程,每个进程内构建 grpcServer 和 DAG;当为False时,框架会设置主线程 grpc 线程池的max_workers=worker_num |
build_dag_each_worker | false | False时框架在进程内创建一条 DAG;True时框架会在每个进程内创建多个独立的 DAG |
dag.is_thread_op | False | op 资源类型,True为线程模型,False为进程模型 |
dag.retry | 1 | 重试次数 |
dag.use_profile | false | 是否使用性能分析,True会生成 Timeline 性能数据,对性能有一定影响 |
dag.tracer.interval_s | 10 | 性能采样的时间间隔(秒) |
op.seq_cls.concurrency | 1 | op 并发数,is_thread_op=True时为线程并发,否则为进程并发 |
op.seq_cls.local_service_conf.client_type | local_predictor | client 类型,包括brpc、grpc和local_predictor;local_predictor不启动 Serving 服务,在进程内直接预测 |
op.seq_cls.local_service_conf.model_config | serving_server | 模型路径,即转换得到的serving_server目录 |
op.seq_cls.local_service_conf.fetch_list | ["linear_75.tmp_1"] | Fetch 结果列表,以 client_config 中 fetch_var 的 alias_name 为准(不同模型输出节点名不同,详见下文) |
op.seq_cls.local_service_conf.device_type | 1 | 推理设备类型:0=cpu,1=gpu,2=tensorRT,3=arm cpu,4=kunlun xpu |
op.seq_cls.local_service_conf.devices | "0" | 计算硬件 ID;为空或不写时为 CPU 预测;为"0"、"0,1,2"等时为 GPU 预测,表示使用的 GPU 卡 |
op.seq_cls.local_service_conf.use_mkldnn | True | 是否开启 MKLDNN 加速(CPU 推理场景下通常开启) |
op.seq_cls.local_service_conf.thread_num | 12 | 推理线程数 |
op.seq_cls.local_service_conf.ir_optim | True | 是否开启 IR 图优化 |
op.seq_cls.local_service_conf.min_subgraph_size | 10(注释示例) | 开启 TensorRT 后,进行优化的子图包含的最少节点数 |
关于fetch_list的取值:不同预训练模型导出的静态图输出节点名不同。service.py 中内置了一张模型名到输出节点名的映射表FETCH_NAME_MAP,部署时请按实际使用的模型选择对应节点名,例如:
ernie-3.0-medium-zh、ernie-3.0-mini-zh→linear_75.tmp_1ernie-3.0-base-zh、ernie-2.0-base-en、ernie-m-base→linear_147.tmp_1ernie-1.0-large-zh-cw、ernie-2.0-large-en、ernie-m-large→linear_291.tmp_1ernie-3.0-micro-zh、ernie-3.0-nano-zh→linear_51.tmp_1
最稳妥的方式是直接查看serving_server/serving_server_conf.prototxt中记录的输出节点名,与 service.py 注释中的说明一致。
分类任务
启动服务
修改好配置文件后,执行下面命令启动服务:
python service.py --max_seq_length 128 --model_name "ernie-3.0-medium-zh"可支持的参数:
max_seq_length:分词器 tokenizer 使用的最大序列长度,ERNIE 模型最大不能超过 2048。请根据文本长度选择,通常推荐 128、256 或 512,若出现显存不足,请适当调低这一参数;默认为 128。model_name:选择预训练模型,可选ernie-1.0-large-zh-cw、ernie-3.0-xbase-zh、ernie-3.0-base-zh、ernie-3.0-medium-zh、ernie-3.0-micro-zh、ernie-3.0-mini-zh、ernie-3.0-nano-zh、ernie-2.0-base-en、ernie-2.0-large-en、ernie-m-base、ernie-m-large;默认为ernie-3.0-medium-zh,请根据实际使用的预训练模型选择。
从 service.py 源码可以看到服务端的完整工作流:
- 服务架构:
Service继承自paddle_serving_server.web_service.WebService,通过service.prepare_pipeline_config("config.yml")读取 pipeline 配置,service.run_service()启动服务;get_pipeline_response将读取节点read_op与分类节点Op(name="seq_cls", input_ops=[read_op])串联成一条 pipeline(这与config.yml中op.seq_cls的配置一一对应)。 - preprocess(预处理):使用
AutoTokenizer.from_pretrained(args.model_name, use_fast=True)加载与训练时一致的 tokenizer;对输入句子按max_seq_length做padding=True, truncation=True处理,并转为int64的 numpy 数组作为模型输入。 - postprocess(后处理):对模型输出的 logits 逐项施加 sigmoid 变换
result = 1 / (1 + np.exp(-result)),将概率大于 0.5 的类别索引收集为多标签结果,用逗号拼接返回{"label": labels}。这一 0.5 阈值判多标签的机制与离线预测脚本 predict.py 及训练评估脚本 utils.py 中F.sigmoid(logits)的判定逻辑完全一致。
启动成功后,输出打印如下:
[DAG] Succ init [PipelineServicer] succ init ...... --- Running analysis [ir_graph_to_program_pass] I0625 16:44:36.563802 40218 analysis_predictor.cc:1007] ======= optimize end ======= I0625 16:44:36.571702 40218 naive_executor.cc:102] --- skip [feed], feed -> token_type_ids I0625 16:44:36.571728 40218 naive_executor.cc:102] --- skip [feed], feed -> input_ids I0625 16:44:36.574352 40218 naive_executor.cc:102] --- skip [linear_147.tmp_1], fetch -> fetch [2022-06-25 16:44:37,546] [ INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load 'ernie-3.0-medium-zh'. [2022-06-25 16:44:37,546] [ INFO] - Already cached /root/.paddlenlp/models/ernie-3.0-medium-zh/ernie_3.0_base_zh_vocab.txt [OP Object] init success W0625 16:45:40.312942 40218 gpu_context.cc:278] Please NOTE: device: 3, GPU Compute Capability: 7.0, Driver API Version: 11.2, Runtime API Version: 10.2 W0625 16:45:40.316538 40218 gpu_context.cc:306] device: 3, cuDNN Version: 8.1.日志中的skip [feed]、skip [fetch]表示静态图推理的输入输出节点已正确衔接;[OP Object] init success表示 pipeline 中的分类 op 初始化完成。
启动 rpc client 测试
Paddle Serving 提供 RPC 客户端脚本 rpc_client.py。注意执行客户端请求时需关闭代理,并根据实际情况修改server_url地址(即启动服务所在机器的地址,脚本默认127.0.0.1:18090,需与config.yml中的rpc_port一致):
python rpc_client.py从源码看,rpc_client.py 通过PipelineClient()连接服务端,将文本列表编码为 numpy 数组后调用client.predict(feed_dict={"sentence": sentence})发起预测;返回结果中每个样本是逗号分隔的类别索引,脚本再通过label_list将索引映射回中文标签名打印。示例输出如下:
data: 五松新村房屋是被告婚前购买的; label: 婚前个人财产 -------------------- data: 被告于2016年3月将车牌号为皖B×××××出售了2.7万元,被告通过原告偿还了齐荷花人民币2.6万元,原、被告尚欠齐荷花2万元。 label: 有夫妻共同财产,有夫妻共同债务 -------------------- data: 2、判令被告返还借婚姻索取的现金33万元,婚前个人存款10万元; label: 婚前个人财产 -------------------- data: 一、判决原告于某某与被告杨某某离婚; label: 准予离婚,法定离婚可以看到模型对一个样本输出了多个标签(如有夫妻共同财产,有夫妻共同债务),这正是多标签分类与单标签分类的差异所在——每个类别独立做 sigmoid 判定,多个类别可以同时成立。
启动 http client 测试
Paddle Serving 还提供 HTTP 客户端脚本 http_client.py。同样注意执行客户端请求时关闭代理,并根据实际情况修改server_url地址(脚本默认http://127.0.0.1:9878/seq_cls/prediction,其中9878需与config.yml中的http_port一致,/seq_cls/prediction为服务名拼接的预测路径):
python http_client.py从源码看,http_client.py 将句子列表包装为{"key": ["sentence"], "value": [sentence]}的 JSON 通过requests.post发送,解析返回的value[0]后同样借助label_list还原为中文标签。输出打印如下:
data: 五松新村房屋是被告婚前购买的; label: 婚前个人财产 -------------------- data: 被告于2016年3月将车牌号为皖B×××××出售了2.7万元,被告通过原告偿还了齐荷花人民币2.6万元,原、被告尚欠齐荷花2万元。 label: 有夫妻共同财产,有夫妻共同债务 -------------------- data: 2、判令被告返还借婚姻索取的现金33万元,婚前个人存款10万元; label: 婚前个人财产 -------------------- data: 一、判决原告于某某与被告杨某某离婚; label: 准予离婚,法定离婚小结
至此,一条完整的 Paddle Serving 多标签分类在线部署链路已经打通:训练导出静态图(export_model.py)→ 转换为 serving 格式(paddle_serving_client.convert)→ 修改config.yml→service.py启动 pipeline 服务 → RPC/HTTP 客户端验证。部署过程中需要重点注意三处与模型强相关的配置:
model_config指向转换后的serving_server目录;fetch_list使用与当前模型输出节点一致的 alias_name(可查serving_client_conf.prototxt或 service.py 的FETCH_NAME_MAP);rpc_port/http_port与客户端脚本中的server_url保持一致。
如需进一步提升在线推理性能,可结合 多标签分类指南 中的模型裁剪方案(prune.py)压缩模型体积后再走本文的部署流程;需要离线批量推理时,则可参考同目录下的离线部署方案。
- 人工智能
- 大模型
- 预训练
- 微调
- LoRA
- RLHF
- 强化学习
- 分布式训练
【免费下载链接】PaddleNLP
Easy-to-use and powerful LLM and SLM library with awesome model zoo.
相关推荐
PaddleDetection 模型 Python Serving 服务化部署实战:基于 Paddle Serving Pipeline 框架的完整部署指南
PaddleDetection 模型 Python Serving 服务化部署实战:基于 Paddle Serving Pipeline 框架的完整部署指南 导
人工智能深度学习计算机视觉PaddleDetection C++ Serving 预测部署实战:基于 Paddle Serving 的高性能服务化推理
PaddleDetection C++ Serving 预测部署实战:基于 Paddle Serving 的高性能服务化推理 Paddle Serving 是飞
人工智能深度学习计算机视觉InsightFace ArcFace-Paddle 基于 PaddleServing 的 Pipeline 在线服务部署实战指南
InsightFace ArcFace Paddle 基于 PaddleServing 的 Pipeline 在线服务部署实战指南 导读 本文以 Insight
人工智能计算机视觉深度学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考