Skip to content

Commit 38e9645

Browse files
authored
[Serving] add ppdet serving example (PaddlePaddle#641)
* serving support ppdet * Update README.md update ppadet/README
1 parent 2cb4882 commit 38e9645

18 files changed

+996
-1
lines changed

examples/vision/classification/paddleclas/serving/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ tar -xvf ResNet50_vd_infer.tgz
1313
wget https://gitee.com/paddlepaddle/PaddleClas/raw/release/2.4/deploy/images/ImageNet/ILSVRC2012_val_00000010.jpeg
1414

1515
# 将配置文件放入预处理目录
16-
mv ResNet50_vd_infer/inference_cls.yaml models/preprocess/1/
16+
mv ResNet50_vd_infer/inference_cls.yaml models/preprocess/1/inference_cls.yaml
1717

1818
# 将模型放入 models/runtime/1目录下, 并重命名为model.pdmodel和model.pdiparams
1919
mv ResNet50_vd_infer/inference.pdmodel models/runtime/1/model.pdmodel

examples/vision/detection/paddledetection/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@
4747

4848
- [Python部署](python)
4949
- [C++部署](cpp)
50+
- [服务化部署](serving)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import json
16+
import numpy as np
17+
import time
18+
19+
import fastdeploy as fd
20+
21+
# triton_python_backend_utils is available in every Triton Python model. You
22+
# need to use this module to create inference requests and responses. It also
23+
# contains some utility functions for extracting information from model_config
24+
# and converting Triton input/output types to numpy types.
25+
import triton_python_backend_utils as pb_utils
26+
27+
28+
class TritonPythonModel:
29+
"""Your Python model must use the same class name. Every Python model
30+
that is created must have "TritonPythonModel" as the class name.
31+
"""
32+
33+
def initialize(self, args):
34+
"""`initialize` is called only once when the model is being loaded.
35+
Implementing `initialize` function is optional. This function allows
36+
the model to intialize any state associated with this model.
37+
Parameters
38+
----------
39+
args : dict
40+
Both keys and values are strings. The dictionary keys and values are:
41+
* model_config: A JSON string containing the model configuration
42+
* model_instance_kind: A string containing model instance kind
43+
* model_instance_device_id: A string containing model instance device ID
44+
* model_repository: Model repository path
45+
* model_version: Model version
46+
* model_name: Model name
47+
"""
48+
# You must parse model_config. JSON string is not parsed here
49+
self.model_config = json.loads(args['model_config'])
50+
print("model_config:", self.model_config)
51+
52+
self.input_names = []
53+
for input_config in self.model_config["input"]:
54+
self.input_names.append(input_config["name"])
55+
print("postprocess input names:", self.input_names)
56+
57+
self.output_names = []
58+
self.output_dtype = []
59+
for output_config in self.model_config["output"]:
60+
self.output_names.append(output_config["name"])
61+
dtype = pb_utils.triton_string_to_numpy(output_config["data_type"])
62+
self.output_dtype.append(dtype)
63+
print("postprocess output names:", self.output_names)
64+
65+
self.postprocess_ = fd.vision.detection.PaddleDetPostprocessor()
66+
67+
def execute(self, requests):
68+
"""`execute` must be implemented in every Python model. `execute`
69+
function receives a list of pb_utils.InferenceRequest as the only
70+
argument. This function is called when an inference is requested
71+
for this model. Depending on the batching configuration (e.g. Dynamic
72+
Batching) used, `requests` may contain multiple requests. Every
73+
Python model, must create one pb_utils.InferenceResponse for every
74+
pb_utils.InferenceRequest in `requests`. If there is an error, you can
75+
set the error argument when creating a pb_utils.InferenceResponse.
76+
Parameters
77+
----------
78+
requests : list
79+
A list of pb_utils.InferenceRequest
80+
Returns
81+
-------
82+
list
83+
A list of pb_utils.InferenceResponse. The length of this list must
84+
be the same as `requests`
85+
"""
86+
responses = []
87+
for request in requests:
88+
infer_outputs = []
89+
for name in self.input_names:
90+
infer_output = pb_utils.get_input_tensor_by_name(request, name)
91+
if infer_output:
92+
infer_output = infer_output.as_numpy()
93+
infer_outputs.append(infer_output)
94+
95+
results = self.postprocess_.run(infer_outputs)
96+
r_str = fd.vision.utils.fd_result_to_json(results)
97+
98+
r_np = np.array(r_str, dtype=np.object)
99+
out_tensor = pb_utils.Tensor(self.output_names[0], r_np)
100+
inference_response = pb_utils.InferenceResponse(
101+
output_tensors=[out_tensor, ])
102+
responses.append(inference_response)
103+
return responses
104+
105+
def finalize(self):
106+
"""`finalize` is called only once when the model is being unloaded.
107+
Implementing `finalize` function is optional. This function allows
108+
the model to perform any necessary clean ups before exit.
109+
"""
110+
print('Cleaning up...')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: "postprocess"
2+
backend: "python"
3+
4+
input [
5+
{
6+
name: "post_input1"
7+
data_type: TYPE_FP32
8+
dims: [ -1, 6 ]
9+
},
10+
{
11+
name: "post_input2"
12+
data_type: TYPE_INT32
13+
dims: [ -1 ]
14+
}
15+
]
16+
17+
output [
18+
{
19+
name: "post_output"
20+
data_type: TYPE_STRING
21+
dims: [ -1 ]
22+
}
23+
]
24+
25+
instance_group [
26+
{
27+
count: 1
28+
kind: KIND_CPU
29+
}
30+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
backend: "python"
2+
3+
input [
4+
{
5+
name: "post_input1"
6+
data_type: TYPE_FP32
7+
dims: [ -1, 6 ]
8+
},
9+
{
10+
name: "post_input2"
11+
data_type: TYPE_INT32
12+
dims: [ -1 ]
13+
},
14+
{
15+
name: "post_input3"
16+
data_type: TYPE_INT32
17+
dims: [ -1, -1, -1 ]
18+
}
19+
]
20+
21+
output [
22+
{
23+
name: "post_output"
24+
data_type: TYPE_STRING
25+
dims: [ -1 ]
26+
}
27+
]
28+
29+
instance_group [
30+
{
31+
count: 1
32+
kind: KIND_CPU
33+
}
34+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# PaddleDetection Pipeline
2+
3+
The pipeline directory does not have model files, but a version number directory needs to be maintained.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
platform: "ensemble"
2+
3+
input [
4+
{
5+
name: "INPUT"
6+
data_type: TYPE_UINT8
7+
dims: [ -1, -1, -1, 3 ]
8+
}
9+
]
10+
output [
11+
{
12+
name: "DET_RESULT"
13+
data_type: TYPE_STRING
14+
dims: [ -1 ]
15+
}
16+
]
17+
ensemble_scheduling {
18+
step [
19+
{
20+
model_name: "preprocess"
21+
model_version: 1
22+
input_map {
23+
key: "preprocess_input"
24+
value: "INPUT"
25+
}
26+
output_map {
27+
key: "preprocess_output1"
28+
value: "RUNTIME_INPUT1"
29+
}
30+
output_map {
31+
key: "preprocess_output2"
32+
value: "RUNTIME_INPUT2"
33+
}
34+
output_map {
35+
key: "preprocess_output3"
36+
value: "RUNTIME_INPUT3"
37+
}
38+
},
39+
{
40+
model_name: "runtime"
41+
model_version: 1
42+
input_map {
43+
key: "image"
44+
value: "RUNTIME_INPUT1"
45+
}
46+
input_map {
47+
key: "scale_factor"
48+
value: "RUNTIME_INPUT2"
49+
}
50+
input_map {
51+
key: "im_shape"
52+
value: "RUNTIME_INPUT3"
53+
}
54+
output_map {
55+
key: "concat_12.tmp_0"
56+
value: "RUNTIME_OUTPUT1"
57+
}
58+
output_map {
59+
key: "concat_8.tmp_0"
60+
value: "RUNTIME_OUTPUT2"
61+
}
62+
},
63+
{
64+
model_name: "postprocess"
65+
model_version: 1
66+
input_map {
67+
key: "post_input1"
68+
value: "RUNTIME_OUTPUT1"
69+
}
70+
input_map {
71+
key: "post_input2"
72+
value: "RUNTIME_OUTPUT2"
73+
}
74+
output_map {
75+
key: "post_output"
76+
value: "DET_RESULT"
77+
}
78+
}
79+
]
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
platform: "ensemble"
2+
3+
input [
4+
{
5+
name: "INPUT"
6+
data_type: TYPE_UINT8
7+
dims: [ -1, -1, -1, 3 ]
8+
}
9+
]
10+
output [
11+
{
12+
name: "DET_RESULT"
13+
data_type: TYPE_STRING
14+
dims: [ -1 ]
15+
}
16+
]
17+
ensemble_scheduling {
18+
step [
19+
{
20+
model_name: "preprocess"
21+
model_version: 1
22+
input_map {
23+
key: "preprocess_input"
24+
value: "INPUT"
25+
}
26+
output_map {
27+
key: "preprocess_output1"
28+
value: "RUNTIME_INPUT1"
29+
}
30+
output_map {
31+
key: "preprocess_output2"
32+
value: "RUNTIME_INPUT2"
33+
}
34+
output_map {
35+
key: "preprocess_output3"
36+
value: "RUNTIME_INPUT3"
37+
}
38+
},
39+
{
40+
model_name: "runtime"
41+
model_version: 1
42+
input_map {
43+
key: "image"
44+
value: "RUNTIME_INPUT1"
45+
}
46+
input_map {
47+
key: "scale_factor"
48+
value: "RUNTIME_INPUT2"
49+
}
50+
input_map {
51+
key: "im_shape"
52+
value: "RUNTIME_INPUT3"
53+
}
54+
output_map {
55+
key: "concat_9.tmp_0"
56+
value: "RUNTIME_OUTPUT1"
57+
}
58+
output_map {
59+
key: "concat_5.tmp_0"
60+
value: "RUNTIME_OUTPUT2"
61+
},
62+
output_map {
63+
key: "tmp_109"
64+
value: "RUNTIME_OUTPUT3"
65+
}
66+
},
67+
{
68+
model_name: "postprocess"
69+
model_version: 1
70+
input_map {
71+
key: "post_input1"
72+
value: "RUNTIME_OUTPUT1"
73+
}
74+
input_map {
75+
key: "post_input2"
76+
value: "RUNTIME_OUTPUT2"
77+
}
78+
input_map {
79+
key: "post_input3"
80+
value: "RUNTIME_OUTPUT3"
81+
}
82+
output_map {
83+
key: "post_output"
84+
value: "DET_RESULT"
85+
}
86+
}
87+
]
88+
}

0 commit comments

Comments
 (0)