bert_service.md 12.4 KB
Newer Older
走神的阿圆's avatar
走神的阿圆 已提交
1
# Bert Service  
走神的阿圆's avatar
走神的阿圆 已提交
2 3 4
## 简介
### 什么是Bert Service
`Bert Service`是基于[Paddle Serving](https://github.com/PaddlePaddle/Serving)框架的快速部署模型远程计算服务方案,可将embedding过程通过调用API接口的方式实现,减少了对机器资源的依赖。使用PaddleHub可在服务器上一键部署`Bert Service`服务,在另外的普通机器上通过客户端接口即可轻松的获取文本对应的embedding数据。  
走神的阿圆's avatar
走神的阿圆 已提交
5

走神的阿圆's avatar
走神的阿圆 已提交
6 7 8 9
整体流程图如下:  

<div align="center">  

走神的阿圆's avatar
走神的阿圆 已提交
10
<img src="../demo/serving/bert_service/img/bs.png" aligh="center" width="100%" alt="BS流程图" />  
走神的阿圆's avatar
走神的阿圆 已提交
11 12 13

</div>  

走神的阿圆's avatar
走神的阿圆 已提交
14
### 为什么使用Bert Service  
走神的阿圆's avatar
走神的阿圆 已提交
15 16
* 算力有限的集群环境中,可利用一台或几台高性能机器部署`Bert Service`服务端,为全部机器提供在线embedding功能。  

走神的阿圆's avatar
走神的阿圆 已提交
17
* 实际的生产服务器不适宜承担大批量embedding工作,通过API接口可减少资源占用。  
走神的阿圆's avatar
走神的阿圆 已提交
18 19

* 专注下游深度学习任务,可利用PaddleHub的`Bert Service`大幅减少embedding代码。  
走神的阿圆's avatar
走神的阿圆 已提交
20

走神的阿圆's avatar
走神的阿圆 已提交
21
`Bert Service`具有几个突出的优点:  
走神的阿圆's avatar
走神的阿圆 已提交
22 23

* 代码精短,易于使用。简单的pip安装方式,服务端仅需一行命令即可启动,客户端仅需一行代码即可获取embedding结果。  
走神的阿圆's avatar
走神的阿圆 已提交
24 25 26

* 更高性能,更高效率。通过Paddle AnalysisPredictor API对模型的计算图进行优化,提升了计算速度并减小了显存占用。

走神的阿圆's avatar
走神的阿圆 已提交
27
* 随"机"应变,灵活扩展。可根据机器资源选择不同数量的服务端,并根据实际需求快速、灵活地进行增减,同时支持各张显卡执行不同的模型计算任务。  
走神的阿圆's avatar
走神的阿圆 已提交
28 29

* 删繁就简,专注任务。`Bert Service`基于PaddlePaddle和PaddleHub开发,将模型的下载和安装等管理工作交由PaddleHub,开发者可以专注于主要任务,还可以无缝对接PaddleHub继续进行文本分类、序列标注等下游任务。
走神的阿圆's avatar
走神的阿圆 已提交
30

走神的阿圆's avatar
走神的阿圆 已提交
31
使用Bert Service搭建服务主要分为下面三个步骤:
走神的阿圆's avatar
走神的阿圆 已提交
32

走神的阿圆's avatar
走神的阿圆 已提交
33 34
## Step1:环境准备
### 环境要求  
走神的阿圆's avatar
走神的阿圆 已提交
35
下表是使用`Bert Service`的环境要求,带有*号标志项为非必需依赖,可根据实际使用需求选择安装。  
走神的阿圆's avatar
走神的阿圆 已提交
36 37 38 39

|项目|版本|说明|  
|:-:|:-:|:-:|  
|操作系统|Linux|目前仅支持Linux操作系统|  
走神的阿圆's avatar
走神的阿圆 已提交
40 41
|PaddleHub|>=1.4.0|无|  
|PaddlePaddle|>=1.6.1|若使用GPU计算,则对应使用PaddlePaddle-gpu版本|  
走神的阿圆's avatar
走神的阿圆 已提交
42 43
|GCC|>=4.8|无|  
|CUDA*|>=8|若使用GPU,需使用CUDA8以上版本|  
走神的阿圆's avatar
走神的阿圆 已提交
44 45
|paddle-gpu-serving*|>=0.8.0|在`Bert Service`服务端需依赖此包|  
|ujson*|>=1.35|在`Bert Service`客户端需依赖此包|  
走神的阿圆's avatar
走神的阿圆 已提交
46

走神的阿圆's avatar
走神的阿圆 已提交
47
### 安装步骤
走神的阿圆's avatar
走神的阿圆 已提交
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
a) 安装PaddlePaddle,利用pip下载CPU版本命令如下。GPU版本、Docker方式安装等其他更具体的安装过程见[开始使用PaddlePaddle](https://paddlepaddle.org.cn/install/quick)
```shell
$ # 安装paddlepaddle的CPU版本
$ pip install paddlepaddle
```
b) 安装PaddleHub
```shell
$ pip install paddlehub
```
c) server端,需另外安装`paddle-gpu-serving`,以获取快速部署服务的能力
```shell
$ pip install paddle-gpu-serving
```  
d) client端,需另外安装ujson
```shell
$ pip install ujson
```


走神的阿圆's avatar
走神的阿圆 已提交
67
### 支持模型
走神的阿圆's avatar
走神的阿圆 已提交
68 69 70 71
目前`Bert Service`支持的语义模型如下表,可根据需要选择模型进行部署embedding服务,未来还将支持更多模型。  

|模型|网络|
|:-|:-:|
72
|[ernie](https://paddlepaddle.org.cn/hubdetail?name=ERNIE&en_category=SemanticModel)|ERNIE|
走神的阿圆's avatar
走神的阿圆 已提交
73 74 75 76 77 78 79 80 81 82 83 84
|[ernie_tiny](https://paddlepaddle.org.cn/hubdetail?name=ernie_tiny&en_category=SemanticModel)|ERNIE|
|[ernie_v2_eng_large](https://paddlepaddle.org.cn/hubdetail?name=ernie_v2_eng_large&en_category=SemanticModel)|ERNIE|
|[ernie_v2_eng_base](https://paddlepaddle.org.cn/hubdetail?name=ernie_v2_eng_base&en_category=SemanticModel)|ERNIE|
|[roberta_wwm_ext_chinese_L-12_H-768_A-12](https://paddlepaddle.org.cn/hubdetail?name=roberta_wwm_ext_chinese_L-12_H-768_A-12&en_category=SemanticModel)|BERT|
|[roberta_wwm_ext_chinese_L-24_H-1024_A-16](https://paddlepaddle.org.cn/hubdetail?name=roberta_wwm_ext_chinese_L-24_H-1024_A-16&en_category=SemanticModel)|BERT|
|[bert_wwm_ext_chinese_L-12_H-768_A-12](https://paddlepaddle.org.cn/hubdetail?name=bert_wwm_ext_chinese_L-12_H-768_A-12&en_category=SemanticModel)|BERT|
|[bert_uncased_L-12_H-768_A-12](https://paddlepaddle.org.cn/hubdetail?name=bert_uncased_L-12_H-768_A-12&en_category=SemanticModel)|BERT|
|[bert_uncased_L-24_H-1024_A-16](https://paddlepaddle.org.cn/hubdetail?name=bert_uncased_L-24_H-1024_A-16&en_category=SemanticModel)|BERT|
|[bert_cased_L-12_H-768_A-12](https://paddlepaddle.org.cn/hubdetail?name=bert_cased_L-12_H-768_A-12&en_category=SemanticModel)|BERT|
|[bert_cased_L-24_H-1024_A-16](https://paddlepaddle.org.cn/hubdetail?name=bert_cased_L-24_H-1024_A-16&en_category=SemanticModel)|BERT|
|[bert_multi_cased_L-12_H-768_A-12](https://paddlepaddle.org.cn/hubdetail?name=bert_multi_cased_L-12_H-768_A-12&en_category=SemanticModel)|BERT|
|[bert_chinese_L-12_H-768_A-12](https://paddlepaddle.org.cn/hubdetail?name=bert_chinese_L-12_H-768_A-12&en_category=SemanticModel)|BERT|
走神的阿圆's avatar
走神的阿圆 已提交
85 86


走神的阿圆's avatar
走神的阿圆 已提交
87 88
## Step2:服务端(server)
### 简介
走神的阿圆's avatar
走神的阿圆 已提交
89 90 91 92
server端接收client端发送的数据,执行模型计算过程并将计算结果返回给client端。  

server端启动时会按照指定的模型名称从PaddleHub获取对应的模型文件进行加载,无需提前下载模型或指定模型路径,对模型的管理工作由PaddleHub负责。在加载模型后在指定的端口启动`BRPC`服务,保持端口监听,当接收到数据后便执行模型计算,并将计算结果通过`BRPC`返回并发送至client端。

走神的阿圆's avatar
走神的阿圆 已提交
93
### 启动  
走神的阿圆's avatar
走神的阿圆 已提交
94
使用PaddleHub的命令行工具可一键启动`Bert Service`,命令如下:
走神的阿圆's avatar
走神的阿圆 已提交
95
```shell
走神的阿圆's avatar
走神的阿圆 已提交
96
$ hub serving start bert_service -m ernie_tiny -p 8866 --use_gpu --gpu 0
走神的阿圆's avatar
走神的阿圆 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
```
启动成功则显示  
```shell
Server[baidu::paddle_serving::predictor::bert_service::BertServiceImpl] is serving on port=8866.
```
整个启动过程如下图:


<div align="center">  

&emsp;&emsp;<img src="https://github.com/ShenYuhan/ml-python/blob/master/short_start_fast.gif" aligh="center" width="70%" alt="启动BS" />  

</div>  


其中各参数说明如下表:

<div align="center">

|参数|说明|是否必填|  
|:--:|:--:|:----:|  
走神的阿圆's avatar
走神的阿圆 已提交
118
|hub serving start bert_service|启动`Bert Service`服务端。|必填项|  
走神的阿圆's avatar
走神的阿圆 已提交
119 120 121 122 123 124 125
|--module/-m|指定启动的模型,如果指定的模型不存在,则自动通过PaddleHub下载指定模型。|必填项|  
|--port/-p|指定启动的端口,每个端口对应一个模型,可基于不同端口进行多次启动,以实现多个模型的服务部署。|必填项|  
|--use_gpu|若指定此项则使用GPU进行工作,反之仅使用CPU。注意需安装GPU版本的PaddlePaddle。|非必填项,默认为不指定|  
|--gpu|指定使用的GPU卡号,如未指定use_gpu则填写此项无效,每个服务对应一张卡,部署多个服务时需指定不同卡|非必填项,默认为0号显卡|  

</div>

走神的阿圆's avatar
走神的阿圆 已提交
126
### 关闭
走神的阿圆's avatar
走神的阿圆 已提交
127
通过在启动服务端的命令行页面使用Ctrl+C终止`Bert Service`运行,关闭成功则显示:
走神的阿圆's avatar
走神的阿圆 已提交
128 129 130 131 132
```shell
Paddle Inference Server exit successfully!
```


走神的阿圆's avatar
走神的阿圆 已提交
133 134
## Step3:客户端(client)  
### 简介
走神的阿圆's avatar
走神的阿圆 已提交
135 136 137
client端接收文本数据,并获取server端返回的模型计算的embedding结果。  

client端利用PaddleHub的语义理解任务将原始文本按照不同模型的数据预处理方案将文本ID化,并生成对应的sentence type、position、input masks数据,将这些信息封装成json数据,通过http协议按照指定的IP端口信息发送至server端,等待并获取模型生成结果。
走神的阿圆's avatar
走神的阿圆 已提交
138
### 启动
走神的阿圆's avatar
走神的阿圆 已提交
139
服务端类BSClient初始化方法原型为:
走神的阿圆's avatar
走神的阿圆 已提交
140
```python
走神的阿圆's avatar
走神的阿圆 已提交
141 142 143 144 145 146 147 148 149
BSClient.__init__(self,
             module_name,
             server,
             max_seq_len=20,
             show_ids=False,
             do_lower_case=True,
             retry=3)
# 获取embedding方法原型为
BSClient.get_result(self, input_text)  
走神的阿圆's avatar
走神的阿圆 已提交
150 151 152 153 154
```  
其中各参数说明如下表:  

|参数|说明|类型|样例|  
|:--:|:--:|:--:|:--:|  
走神的阿圆's avatar
走神的阿圆 已提交
155 156
|module_name|指定使用的模型名称|string|"ernie"|  
|server|要访问的server地址,包括ip地址及端口号|string|"127.0.0.1:8866"|  
走神的阿圆's avatar
走神的阿圆 已提交
157 158 159
|max_seq_len|计算时的样例长度,样例长度不足时采用补零策略,超出此参数则超出部分会被截断|int|128|  
|show_ids|是否展现数据预处理后的样例信息,指定为True则显示样例信息,反之则不显示|bool|False|  
|do_lower_case|是否将英文字母转换成小写,指定为True则将所有英文字母转换为小写,反之则保持原状|bool|True|
走神的阿圆's avatar
走神的阿圆 已提交
160 161
|retry|连接失败后的最大重试次数|int|3|  
|input_text|输入文本,要获取embedding的原始文本|二维list类型,内部元素为string类型的文本|[['样例1'],['样例2']]|
走神的阿圆's avatar
走神的阿圆 已提交
162

走神的阿圆's avatar
走神的阿圆 已提交
163
## Demo-利用Bert Service部署ernie_tiny在线embedding服务
走神的阿圆's avatar
走神的阿圆 已提交
164
在这里,我们将展示一个实际场景中可能使用的demo,我们利用PaddleHub在一台GPU机器上部署`ernie_tiny`模型服务,并在另一台CPU机器上尝试访问,获取一首七言绝句的embedding。
走神的阿圆's avatar
走神的阿圆 已提交
165
### Step1:安装环境依赖
走神的阿圆's avatar
走神的阿圆 已提交
166 167
首先需要安装环境依赖,根据第2节内容分别在两台机器上安装相应依赖。  

走神的阿圆's avatar
走神的阿圆 已提交
168
### Step2:启动Bert Service服务端
走神的阿圆's avatar
走神的阿圆 已提交
169
确保环境依赖安装正确后,在要部署服务的GPU机器上使用PaddleHub命令行工具启动`Bert Service`服务端,命令如下:
走神的阿圆's avatar
走神的阿圆 已提交
170
```shell
走神的阿圆's avatar
走神的阿圆 已提交
171
$ hub serving start bert_service -m ernie_tiny --use_gpu --gpu 0 --port 8866
走神的阿圆's avatar
走神的阿圆 已提交
172 173 174 175 176
```
启动成功后打印
```shell
Server[baidu::paddle_serving::predictor::bert_service::BertServiceImpl] is serving on port=8866.
```  
走神的阿圆's avatar
走神的阿圆 已提交
177
这样就启动了`ernie_tiny`的在线服务,监听8866端口,并在0号GPU上进行任务。
走神的阿圆's avatar
走神的阿圆 已提交
178
### Step3:使用Bert Service客户端进行远程调用  
走神的阿圆's avatar
走神的阿圆 已提交
179
部署好服务端后,就可以用普通机器作为客户端测试在线embedding功能。
走神的阿圆's avatar
走神的阿圆 已提交
180

走神的阿圆's avatar
走神的阿圆 已提交
181 182
首先导入客户端依赖。  
```python
走神的阿圆's avatar
走神的阿圆 已提交
183
from paddlehub.serving.bert_serving import bs_client
走神的阿圆's avatar
走神的阿圆 已提交
184
```
走神的阿圆's avatar
走神的阿圆 已提交
185 186 187 188 189 190 191

接着启动并初始化`bert service`客户端`BSClient`(这里的server为虚拟地址,需根据自己实际ip设置)
```python
bc = bs_client.BSClient(module_name="ernie_tiny", server="127.0.0.1:8866")
```

然后输入文本信息。
走神的阿圆's avatar
走神的阿圆 已提交
192 193 194
```python
input_text = [["西风吹老洞庭波"], ["一夜湘君白发多"], ["醉后不知天在水"], ["满船清梦压星河"], ]
```
走神的阿圆's avatar
走神的阿圆 已提交
195 196

最后利用客户端接口`get_result`发送文本到服务端,以获取embedding结果。
走神的阿圆's avatar
走神的阿圆 已提交
197
```python
走神的阿圆's avatar
走神的阿圆 已提交
198
result = bc.get_result(input_text=input_text)
走神的阿圆's avatar
走神的阿圆 已提交
199 200 201 202 203
```
最后即可得到embedding结果(此处只展示部分结果)。
```python
[[0.9993321895599361, 0.9994612336158751, 0.9999646544456481, 0.732795298099517, -0.34387934207916204, ... ]]
```
走神的阿圆's avatar
走神的阿圆 已提交
204
客户端代码demo文件见[示例](../paddlehub/serving/bert_serving/bert_service.py)
走神的阿圆's avatar
走神的阿圆 已提交
205 206
运行命令如下:  
```shell
走神的阿圆's avatar
走神的阿圆 已提交
207
$ python bert_service_client.py
走神的阿圆's avatar
走神的阿圆 已提交
208 209 210 211 212 213 214 215 216 217
```  

运行过程如下图:

<div align="center">  

&emsp;&emsp;<img src="https://github.com/ShenYuhan/ml-python/blob/master/short_client_fast.gif" aligh="center" width="70%" alt="启动BS" />  

</div>  

走神的阿圆's avatar
走神的阿圆 已提交
218
### Step4:关闭Bert Service服务端
走神的阿圆's avatar
走神的阿圆 已提交
219
如要停止`Bert Service`服务端程序,可在其启动命令行页面使用Ctrl+C方式关闭,关闭成功会打印如下日志:
走神的阿圆's avatar
走神的阿圆 已提交
220 221 222
```shell
Paddle Inference Server exit successfully!
```
走神的阿圆's avatar
走神的阿圆 已提交
223
这样,我们就利用一台GPU机器就完成了`Bert Service`的部署,并利用另一台普通机器进行了测试,可见通过`Bert Service`能够方便地进行在线embedding服务的快速部署。  
走神的阿圆's avatar
走神的阿圆 已提交
224

走神的阿圆's avatar
走神的阿圆 已提交
225 226 227 228 229 230 231
## FAQ  
Q : 如何在一台服务器部署多个模型?  
A : 可通过多次启动`Bert Service`,分配不同端口实现。如果使用GPU,需要指定不同的显卡。如同时部署`ernie``bert_chinese_L-12_H-768_A-12`,分别执行命令如下:  
```shell
$ hub serving start bert_service -m ernie -p 8866
$ hub serving start bert_service -m bert_chinese_L-12_H-768_A-12 -p 8867
```
走神的阿圆's avatar
走神的阿圆 已提交
232

走神的阿圆's avatar
走神的阿圆 已提交
233
Q : 启动时显示"Check out http://yq01-gpu-255-129-12-00.epc.baidu.com:8887 in web
走神的阿圆's avatar
走神的阿圆 已提交
234
 browser.",这个页面有什么作用。  
走神的阿圆's avatar
走神的阿圆 已提交
235 236 237 238 239 240 241 242 243 244
A : 这是`BRPC`的内置服务,主要用于查看请求数、资源占用等信息,可对server端性能有大致了解,具体信息可查看[BRPC内置服务](https://github.com/apache/incubator-brpc/blob/master/docs/cn/builtin_service.md)

Q : 为什么输入文本的格式为[["文本1"], ["文本2"], ],而不是["文本1", "文本2", ]?  
A : 因为Bert模型可以对一轮对话生成向量表示,例如[["问题1","回答1"],["问题2","回答2"]],为了防止使用时混乱,每个样本使用一个list表示,一个样本list内部可以是1条string或2条string,如下面的文本:  
```python
input_text = [
   ["你今天吃饭了吗","我已经吃过饭了"],
   ["今天天气怎么样","今天天气不错"],
]
```