server部署
更新时间:2022-01-25
简介
本文以文本分类任务为例介绍如何搭建HttpServer,提供模型在线预测服务。本文假定用户已经完成模型训练,有模型文件保存。
部署流程
- 进入文本分类任务目录,模型部署server脚本是inference_server.py,配置文件为examplse目录下的以api为后缀的json配置文件,这里以./examples/cls_cnn_ch_api.json举例,编辑./examples/cls_cnn_ch_api.json文件,设置模型保存路径inference_model_path字段:
cd tasks/text_classification
# 修改inference_model_path字段,模型保存路径为output目录下详细的模型路径为准
vim ./examples/cls_cnn_ch_api.json
- 启动模型部署服务,HttpServer基于bottle + gevent框架搭建:
# 这里port参数指定服务监听端口,这里即启动了以8801为端口的server服务
# param_path参数指定配置文件路径
python inference_server.py --port 8801 --param_path ./examples/cls_cnn_ch_api.json
- client发送请求:
# 这里的ip使用上面启动模型部署服务对应机器的ip地址,port使用启动模型部署服务设置的端口,例如上面采用的是8801
curl -d '{"text": [["内容 一般 ,纸张 还行 吧 , 字 大 , 太 浪费 了"], ["材质 很好 , 重量 不 重, 键盘 也 很大 , 电池 也 很 耐用"]]}' 'http://ip:port/wenxin/inference'
json配置格式说明
这里以分类任务举例说明:
{
"dataset_reader": {
"predict_reader": {
"config": {
"batch_size": 8,
"data_path": "",
"epoch": 1,
"sampling_rate": 1.0,
"shuffle": false
},
"fields": [
{
"data_type": "string",
"embedding": null,
"max_seq_len": 512,
"name": "text_a",
"need_convert": true,
"padding_id": 0,
"reader": {
"type": "CustomTextFieldReader"
},
"tokenizer": {
"params": null,
"split_char": " ",
"type": "CustomTokenizer",
"unk_token": "[UNK]"
},
"truncation_type": 0,
"vocab_path": "./dict/vocab.txt"
}
],
"name": "predict_reader",
"type": "BasicDataSetReader"
}
},
"predictor": {
# 使用使用GPU预测
"PADDLE_USE_GPU": 0,
# 是否使用ERNIE预训练模型,由于序列标注对输出结果解析逻辑不一致,需要用到该字段
"is_ernie": 0,
# 模型保存路径
"inference_model_path": "./output/cls_cnn_ch/save_inference_model/inference_step_251",
# 分类类别数
"num_labels": 2,
# 预测线程数,CPU模型下生效
"thread_num": 4
}
}
请求格式说明
- 请求数据要求是UTF-8编码。
- client统一使用post + json接口方式发送请求,输入使用text字段,支持批量输入。
- text的内容是json数组格式,数组的每个值也是一个json数组格式,对应一个输入文本:
-
文本分类:
- 文本分类为单query任务,每条请求只有一个文本,对应于json输入,就是子数组里只能有一个string类型的字符串。
- 未使用预训练模型ERNIE的任务:要求输入是已经切好词,词与词之间空格分隔。切词可以使用文心里的分词与词表生成工具对要预测的输入文本进行切词。请求示例:
curl -d '{"text": [["内容 一般 ,纸张 还行 吧 , 字 大 , 太 浪费 了"], ["材质 很好 , 重量 不 重, 键盘 也 很大 , 电池 也 很 耐用"]]}' 'http://ip:port/wenxin/inference'
- 使用预训练模型ERNIE的任务:文心内部会进行切单字处理,只需要传入原始的输入文本即可。请求示例:
curl -d '{"text": [["内容一般,纸张还行吧,字大,太浪费了"], ["材质很好, 重量不重,键盘也很大, 电池也很耐用"]]}' 'http://ip:port/wenxin/inference'
-
文本匹配:
- 文本匹配任务为query对任务,每条请求需要有两个文本,对应于json输入,就是子数组需要有两个string类型的字符串。
- 未使用预训练模型ERNIE的任务:要求输入是已经切好词,词与词之间空格分隔。切词可以使用文心里的分词与词表生成工具对要预测的输入文本进行切词。请求示例:
curl -d '{"text": [["谁 有 狂三 这张 高清 的", "这张 高清图,谁有"], ["英雄 联盟 什么 英雄 最好", "英雄 联盟 最好 英雄 是什么"]]}' 'http://ip:port/wenxin/inference'
- 使用预训练模型ERNIE的任务:文心内部会进行切单字处理,只需要传入原始的输入文本即可。请求示例:
curl -d '{"text": [["谁有狂三这张高清的", "这张高清图,谁有"], ["英雄联盟什么英雄最好", "英雄联盟最好英雄是什么"]]}' 'http://10.12.46.6:8263/wenxin/inference'
-
序列标注
- 序列标注为单query任务,每条请求只有一个文本,对应于json输入,就是子数组里只能有一个string类型的字符串。
- 序列标注统一要求用户输入的文本为已经切好单字的,请求示例:
curl -d '{"text": [["叶 利 钦 随 即 签 署 命 令 , 正 式 任 命 他 为 俄 罗 斯 联 邦 政 府 总 理 "], ["英 雄 联 盟 什 么 英 雄"]]}' 'http://ip:port/wenxin/inference'
返回格式说明
- 返回参数
参数名称 | 类型 | 必需 | 详细说明 |
---|---|---|---|
ret | int | 是 | 错误码 |
msg | string | 否 | 返回失败时的错误信息 |
content | array of objects | 否 | 返回预测结果,数组里每个子数组对应于一个输入文本。 |
- 错误码:
错误码 | 含义 |
---|---|
200 | 成功 |
201 | 输入json格式错误 |
202 | 输入字段错误 |
- 返回示例
{"content": [[0.4901733696460724, 0.50982666015625], [0.49466341733932495, 0.5053365230560303]], "ret": 200}