Skip to content

Commit

Permalink
Add test for Python BLS model loading API (#5980)
Browse files Browse the repository at this point in the history
* Add test for Python BLS model loading API

* Fix up
  • Loading branch information
krishung5 committed Jun 29, 2023
1 parent 4ba3871 commit 438ee53
Show file tree
Hide file tree
Showing 3 changed files with 254 additions and 0 deletions.
92 changes: 92 additions & 0 deletions qa/L0_backend_python/bls/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,98 @@ else
RET=1
fi

# Test model loading API with BLS
rm -fr ./models
mkdir -p models/bls_model_loading/1/
cp ../../python_models/bls_model_loading/model.py models/bls_model_loading/1/
cp ../../python_models/bls_model_loading/config.pbtxt models/bls_model_loading/
cp -fr ${DATADIR}/qa_model_repository/onnx_int32_int32_int32 models/.
# Make only version 2, 3 is valid version directory
rm -rf models/onnx_int32_int32_int32/1

SERVER_LOG="./bls_model_loading_server.log"
SERVER_ARGS="--model-repository=`pwd`/models --backend-directory=${BACKEND_DIR} --model-control-mode=explicit --log-verbose=1"

run_server
if [ "$SERVER_PID" == "0" ]; then
echo -e "\n***\n*** Failed to start $SERVER\n***"
cat $SERVER_LOG
exit 1
fi

export MODEL_NAME='bls_model_loading'

set +e
code=`curl -s -w %{http_code} -X POST localhost:8000/v2/repository/models/${MODEL_NAME}/load`
set -e
if [ "$code" == "400" ]; then
echo -e "\n***\n*** Failed to load model '${MODEL_NAME}'\n***"
RET=1
fi

set +e

python3 $CLIENT_PY >> $CLIENT_LOG 2>&1
if [ $? -ne 0 ]; then
echo -e "\n***\n*** 'bls_model_loading' test FAILED. \n***"
cat $CLIENT_LOG
RET=1
else
check_test_results $TEST_RESULT_FILE $EXPECTED_NUM_TESTS
if [ $? -ne 0 ]; then
cat $CLIENT_LOG
echo -e "\n***\n*** Test Result Verification Failed\n***"
RET=1
fi
fi

set -e

kill $SERVER_PID
wait $SERVER_PID

# Test model loading API with BLS warmup
(cd models/bls_model_loading && \
echo "model_warmup [{" >> config.pbtxt && \
echo " name : \"regular sample\"" >> config.pbtxt && \
echo " batch_size: 1" >> config.pbtxt && \
echo " inputs {" >> config.pbtxt && \
echo " key: \"INPUT0\"" >> config.pbtxt && \
echo " value: {" >> config.pbtxt && \
echo " data_type: TYPE_FP32" >> config.pbtxt && \
echo " dims: 4" >> config.pbtxt && \
echo " zero_data: false" >> config.pbtxt && \
echo " }" >> config.pbtxt && \
echo " }" >> config.pbtxt && \
echo " inputs {" >> config.pbtxt && \
echo " key: \"INPUT1\"" >> config.pbtxt && \
echo " value: {" >> config.pbtxt && \
echo " data_type: TYPE_FP32" >> config.pbtxt && \
echo " dims: 4" >> config.pbtxt && \
echo " zero_data: false" >> config.pbtxt && \
echo " }" >> config.pbtxt && \
echo " }" >> config.pbtxt && \
echo "}]" >> config.pbtxt )

SERVER_LOG="./bls_model_loading_server_warmup.log"
run_server
if [ "$SERVER_PID" == "0" ]; then
echo -e "\n***\n*** Failed to start $SERVER\n***"
cat $SERVER_LOG
exit 1
fi

set +e
code=`curl -s -w %{http_code} -X POST localhost:8000/v2/repository/models/${MODEL_NAME}/load`
set -e
if [ "$code" == "400" ]; then
echo -e "\n***\n*** Failed to load model '${MODEL_NAME}'\n***"
RET=1
fi

kill $SERVER_PID
wait $SERVER_PID

if [ $RET -eq 1 ]; then
cat $CLIENT_LOG
cat $SERVER_LOG
Expand Down
43 changes: 43 additions & 0 deletions qa/python_models/bls_model_loading/config.pbtxt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Copyright 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of NVIDIA CORPORATION nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

name: "bls_model_loading"
backend: "python"

output [
{
name: "OUTPUT0"
data_type: TYPE_BOOL
dims: [ 1 ]
}
]

instance_group [
{
count: 3
kind: KIND_CPU
}
]
119 changes: 119 additions & 0 deletions qa/python_models/bls_model_loading/model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Copyright 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of NVIDIA CORPORATION nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import numpy as np
import unittest
import triton_python_backend_utils as pb_utils


class PBBLSModelLoadingTest(unittest.TestCase):

def setUp(self):
self.model_name = "onnx_int32_int32_int32"

def tearDown(self):
pb_utils.unload_model(self.model_name)

def test_load_unload_model(self):
self.assertFalse(pb_utils.is_model_ready(model_name=self.model_name))
pb_utils.load_model(model_name=self.model_name)
self.assertTrue(pb_utils.is_model_ready(self.model_name))
pb_utils.unload_model(self.model_name)
self.assertFalse(pb_utils.is_model_ready(self.model_name))

def test_load_with_config_override(self):
self.assertFalse(pb_utils.is_model_ready(self.model_name))
pb_utils.load_model(self.model_name)
self.assertTrue(pb_utils.is_model_ready(self.model_name))

# Send the config with the wrong format
wrong_config = "\"parameters\": {\"config\": {{\"backend\":\"onnxruntime\", \"version_policy\":{\"specific\":{\"versions\":[2]}}}}}"
with self.assertRaises(pb_utils.TritonModelException):
pb_utils.load_model(model_name=self.model_name, config=wrong_config)
# The model should not be changed after a failed load model request
for version in ["2", "3"]:
self.assertTrue(pb_utils.is_model_ready(model_name=self.model_name, model_version=version))

# Send the config with the correct format
config = "{\"backend\":\"onnxruntime\", \"version_policy\":{\"specific\":{\"versions\":[2]}}}"
pb_utils.load_model(self.model_name, config=config)
# The model should be changed after a successful load model request
self.assertTrue(pb_utils.is_model_ready(self.model_name, "2"))
self.assertFalse(pb_utils.is_model_ready(self.model_name, "3"))

def test_load_with_file_override(self):
self.assertFalse(pb_utils.is_model_ready(self.model_name))
pb_utils.load_model(self.model_name)
self.assertTrue(pb_utils.is_model_ready(self.model_name))

override_name = "override_model"
config = "{\"backend\":\"onnxruntime\"}"
with open('models/onnx_int32_int32_int32/3/model.onnx', 'rb') as file:
data = file.read()
files = {"file:1/model.onnx": data}

# Request to load the model with override file, should fail without
# providing override config.
with self.assertRaises(pb_utils.TritonModelException):
pb_utils.load_model(self.model_name, "", files)

# Request to load the model with override file and config in a different name
pb_utils.load_model(model_name=override_name, config=config, files=files)
# Sanity check that the model with original name is unchanged
self.assertFalse(pb_utils.is_model_ready(self.model_name, "1"))
self.assertTrue(pb_utils.is_model_ready(self.model_name, "3"))

# Check the override model readiness
self.assertTrue(pb_utils.is_model_ready(override_name, "1"))
self.assertFalse(pb_utils.is_model_ready(override_name, "3"))

# Request to load the model with override file and config in original name
pb_utils.load_model(self.model_name, config, files)
# Check that the model with original name is changed
self.assertTrue(pb_utils.is_model_ready(self.model_name, "1"))
self.assertFalse(pb_utils.is_model_ready(self.model_name, "3"))

# Sanity check readiness of the different named model
self.assertTrue(pb_utils.is_model_ready(override_name, "1"))
self.assertFalse(pb_utils.is_model_ready(override_name, "3"))


class TritonPythonModel:

def initialize(self, args):
# Run the unittest during initialization
test = unittest.main('model', exit=False)
self.result = test.result.wasSuccessful()

def execute(self, requests):
responses = []
for _ in requests:
responses.append(
pb_utils.InferenceResponse([
pb_utils.Tensor('OUTPUT0',
np.array([self.result], dtype=np.float16))
]))
return responses

0 comments on commit 438ee53

Please sign in to comment.