Add UT for Azure Ops during packaging (#502)

* set before-test

* test cmd

* clean in yml

* restore toml

* add ut for triton endpoints

* reset working path

* rename suffix

* install ort

* pip install

* make env

* add extra env

* make executable

* set dir for linux

* add switch

* set env default

* skip tests

* simplify env

* clean env for official

---------

Co-authored-by: Randy Shuai <rashuai@microsoft.com>
Co-authored-by: Wenbing Li <10278425+wenbingl@users.noreply.github.com>
This commit is contained in:
RandySheriffH 2023-08-02 17:01:09 -07:00 коммит произвёл GitHub
Родитель 922b7cc387
Коммит 9e7f8e5b1d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
19 изменённых файлов: 331 добавлений и 39 удалений

Просмотреть файл

@ -16,13 +16,10 @@ parameters: # parameters are shown up in ADO UI in a build queue time
type: boolean
default: false
- name: BuildAzureOp
displayName: 'Build and test AzureEP ops'
- name: ExtraEnv
displayName: 'Extra env variable set to CIBW_ENVIRONMENT'
type: string
values:
- '0'
- '1'
default: '0'
default: 'None=None'
variables:
CDP_DEFINITION_BUILD_COUNT: $[counter('', 0)]
@ -35,7 +32,7 @@ variables:
CIBW_BUILD: cp3{8,9,10,11}-*amd64
CIBW_ARCHS: AMD64
DEBIAN_FRONTEND: noninteractive
CIBW_ENVIRONMENT: "OCOS_ENABLE_AZURE=${{ parameters.BuildAzureOp }}"
CIBW_ENVIRONMENT: "${{ parameters.ExtraEnv }}"
resources:
repositories:
@ -107,6 +104,7 @@ extends:
python -m pip install --upgrade pip
python -m pip install cibuildwheel numpy
python -m cibuildwheel --platform windows --archs AMD64 --output-dir $(REPOROOT)\out
tools\install_deps.bat uninstall
displayName: Build wheels
- task: SDLNativeRules@3
inputs:

Просмотреть файл

@ -16,13 +16,10 @@ parameters: # parameters are shown up in ADO UI in a build queue time
type: boolean
default: false
- name: BuildAzureOp
displayName: 'Build and test AzureEP ops'
- name: ExtraEnv
displayName: 'Extra env variable set to CIBW_ENVIRONMENT'
type: string
values:
- '0'
- '1'
default: '0'
default: 'None=None'
variables:
CDP_DEFINITION_BUILD_COUNT: $[counter('', 0)]
@ -36,7 +33,7 @@ variables:
CIBW_ARCHS: AMD64
CIBW_BUILD_VERBOSITY: 1
DEBIAN_FRONTEND: noninteractive
CIBW_ENVIRONMENT: "OCOS_ENABLE_AZURE=${{ parameters.BuildAzureOp }}"
CIBW_ENVIRONMENT: "${{ parameters.ExtraEnv }}"
resources:
repositories:
@ -108,6 +105,7 @@ extends:
python -m pip install --upgrade pip
python -m pip install cibuildwheel numpy
python -m cibuildwheel --platform windows --archs AMD64 --output-dir $(REPOROOT)\out
tools\install_deps.bat uninstall
displayName: Build wheels
- task: SDLNativeRules@3
inputs:

Просмотреть файл

@ -1,11 +1,8 @@
parameters:
- name: BuildAzureOp
displayName: 'Build and test AzureEP ops'
- name: ExtraEnv
displayName: 'Extra env variable set to CIBW_ENVIRONMENT'
type: string
values:
- '0'
- '1'
default: '0'
default: 'None=None'
jobs:
- job: linux
@ -13,7 +10,7 @@ jobs:
pool: {name: 'Azure-Pipelines-EO-Ubuntu-2004-aiinfra'}
variables:
CIBW_BUILD: "cp3{8,9,10,11}-*"
CIBW_ENVIRONMENT: "OCOS_ENABLE_AZURE=${{ parameters.BuildAzureOp }}"
CIBW_ENVIRONMENT: "${{ parameters.ExtraEnv }}"
steps:
- task: UsePythonVersion@0

Просмотреть файл

@ -379,12 +379,6 @@ if(OCOS_ENABLE_BLINGFIRE)
endif()
if(OCOS_ENABLE_AZURE)
if ($ENV{TEST_AZURE_INVOKERS_AS_CPU_OP} MATCHES "ON")
message(STATUS "Azure inovkers will be testable as cpu ops")
add_compile_definitions(TEST_AZURE_INVOKERS_AS_CPU_OP)
endif()
# Azure endpoint invokers
include(triton)
file(GLOB TARGET_SRC_AZURE "operators/azure/*.cc" "operators/azure/*.h*")

Просмотреть файл

@ -374,7 +374,7 @@ struct Variadic : public TensorBase {
tensor = std::make_unique<Custom::Tensor<int64_t>>(api, ctx, ith_input, true);
break;
case ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING:
tensor = std::make_unique<Custom::Tensor<std::string_view>>(api, ctx, ith_input, true);
tensor = std::make_unique<Custom::Tensor<std::string>>(api, ctx, ith_input, true);
break;
default:
ORTX_CXX_API_THROW("unknow input type", ORT_RUNTIME_EXCEPTION);

Просмотреть файл

@ -343,11 +343,15 @@ void AzureTritonInvoker::Compute(const ortc::Variadic& inputs, ortc::Variadic& o
triton_input_vec.emplace_back(triton_input);
triton_inputs.push_back(triton_input);
// todo - test string
const float* data_raw = reinterpret_cast<const float*>(inputs[ith_input]->DataRaw());
size_t size_in_bytes = inputs[ith_input]->SizeInBytes();
err = triton_input->AppendRaw(reinterpret_cast<const uint8_t*>(data_raw), size_in_bytes);
CHECK_TRITON_ERR(err, "failed to append raw data to input");
if ("BYTES" == triton_data_type) {
const auto* string_tensor = reinterpret_cast<const ortc::Tensor<std::string>*>(inputs[ith_input].get());
triton_input->AppendFromString(string_tensor->Data());
} else {
const float* data_raw = reinterpret_cast<const float*>(inputs[ith_input]->DataRaw());
size_t size_in_bytes = inputs[ith_input]->SizeInBytes();
err = triton_input->AppendRaw(reinterpret_cast<const uint8_t*>(data_raw), size_in_bytes);
CHECK_TRITON_ERR(err, "failed to append raw data to input");
}
}
for (size_t ith_output = 0; ith_output < output_names_.size(); ++ith_output) {
@ -411,15 +415,11 @@ const std::vector<const OrtCustomOp*>& AzureInvokerLoader() {
static OrtOpLoader op_loader(CustomAzureStruct("AzureAudioInvoker", AzureAudioInvoker),
CustomAzureStruct("AzureTritonInvoker", AzureTritonInvoker),
CustomAzureStruct("AzureAudioInvoker", AzureAudioInvoker),
CustomAzureStruct("AzureTextInvoker", AzureTextInvoker)
#ifdef TEST_AZURE_INVOKERS_AS_CPU_OP
,
CustomAzureStruct("AzureTextInvoker", AzureTextInvoker),
CustomCpuStruct("AzureAudioInvoker", AzureAudioInvoker),
CustomCpuStruct("AzureTritonInvoker", AzureTritonInvoker),
CustomCpuStruct("AzureAudioInvoker", AzureAudioInvoker),
CustomCpuStruct("AzureTextInvoker", AzureTextInvoker)
#endif
);
return op_loader.GetCustomOps();
}

Просмотреть файл

@ -11,6 +11,7 @@ line-length = 120
[[tool.cibuildwheel.overrides]]
select = "*-manylinux*x86_64*"
before-all = "./tools/install_deps.sh many64"
test-command = "{project}/tools/test_cibuildwheel.sh {project}"
[[tool.cibuildwheel.overrides]]
select = "*-manylinux*i686*"
@ -23,4 +24,4 @@ before-all = "./tools/install_deps.sh musl"
[[tool.cibuildwheel.overrides]]
select = "*win*"
before-build = "tools\\install_deps.bat install"
after-build = "tools\\install_deps.bat uninstall"
test-command = "{project}\\tools\\test_cibuildwheel.bat {project}"

Двоичные данные
test/data/azure/openai_audio.onnx Normal file

Двоичный файл не отображается.

Двоичные данные
test/data/azure/openai_chat.onnx Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,17 @@
:…

auth_token
text embeddingembedding_invoker"AzureTextInvoker*4
model_uri"$https://api.openai.com/v1/embeddings *
verbose :ai.onnx.contribgraphZ!
auth_token

ÿÿÿÿÿÿÿÿÿZ
text

ÿÿÿÿÿÿÿÿÿb
embedding

ÿÿÿÿÿÿÿÿÿB

Двоичные данные
test/data/azure/test16.wav Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,24 @@

Ò
auth_token
X
YZtriton_invoker"AzureTritonInvoker*
model_name"addf *G
model_uri"7https://endpoint-5095584.westus2.inference.ml.azure.com *
model_version"1 *
verbose"1 :ai.onnx.contribgraphZ!
auth_token

ÿÿÿÿÿÿÿÿÿZ
X

ÿÿÿÿÿÿÿÿÿZ
Y

ÿÿÿÿÿÿÿÿÿb
Z

ÿÿÿÿÿÿÿÿÿB

Просмотреть файл

@ -0,0 +1,24 @@

Ó
auth_token
X
YZtriton_invoker"AzureTritonInvoker*
model_name"addf8 *G
model_uri"7https://endpoint-3586177.westus2.inference.ml.azure.com *
model_version"1 *
verbose"1 :ai.onnx.contribgraphZ!
auth_token

ÿÿÿÿÿÿÿÿÿZ
X
 
ÿÿÿÿÿÿÿÿÿZ
Y
 
ÿÿÿÿÿÿÿÿÿb
Z
 
ÿÿÿÿÿÿÿÿÿB

Просмотреть файл

@ -0,0 +1,24 @@

Ó
auth_token
X
YZtriton_invoker"AzureTritonInvoker*
model_name"addi4 *G
model_uri"7https://endpoint-9231153.westus2.inference.ml.azure.com *
model_version"1 *
verbose"1 :ai.onnx.contribgraphZ!
auth_token

ÿÿÿÿÿÿÿÿÿZ
X

ÿÿÿÿÿÿÿÿÿZ
Y

ÿÿÿÿÿÿÿÿÿb
Z

ÿÿÿÿÿÿÿÿÿB

Просмотреть файл

@ -0,0 +1,24 @@

Ñ
auth_token
X
YZtriton_invoker"AzureTritonInvoker*
model_name"and *G
model_uri"7https://endpoint-5911162.westus2.inference.ml.azure.com *
model_version"1 *
verbose"1 :ai.onnx.contribgraphZ!
auth_token

ÿÿÿÿÿÿÿÿÿZ
X
 
ÿÿÿÿÿÿÿÿÿZ
Y
 
ÿÿÿÿÿÿÿÿÿb
Z
 
ÿÿÿÿÿÿÿÿÿB

Просмотреть файл

@ -0,0 +1,23 @@

ä
auth_token
str_instr_out1str_out2triton_invoker"AzureTritonInvoker*
model_name"str *G
model_uri"7https://endpoint-7270363.westus2.inference.ml.azure.com *
model_version"1 *
verbose"1 :ai.onnx.contribgraphZ!
auth_token

ÿÿÿÿÿÿÿÿÿZ
str_in

ÿÿÿÿÿÿÿÿÿb
str_out1

ÿÿÿÿÿÿÿÿÿb
str_out2

ÿÿÿÿÿÿÿÿÿB

152
test/test_azure_ops.py Normal file
Просмотреть файл

@ -0,0 +1,152 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
import os
import unittest
import numpy as np
from onnx import checker, helper, onnx_pb as onnx_proto
from onnxruntime_extensions import PyOrtFunction, util, get_library_path
from onnxruntime import *
script_dir = os.path.dirname(os.path.realpath(__file__))
ort_ext_root = os.path.abspath(os.path.join(script_dir, ".."))
test_data_dir = os.path.join(ort_ext_root, "test", "data", "azure")
class TestAzureOps(unittest.TestCase):
def __init__(self, config):
super().__init__(config)
self.__enabled = os.getenv('OCOS_ENABLE_AZURE','') == '1'
if self.__enabled:
self.__opt = SessionOptions()
self.__opt.register_custom_ops_library(get_library_path())
def test_addf(self):
if self.__enabled:
sess = InferenceSession(os.path.join(test_data_dir, "triton_addf.onnx"),
self.__opt, providers=["CPUExecutionProvider"])
auth_token = np.array([os.getenv('ADDF', '')])
x = np.array([1,2,3,4]).astype(np.float32)
y = np.array([4,3,2,1]).astype(np.float32)
ort_inputs = {
"auth_token": auth_token,
"X": x,
"Y": y
}
out = sess.run(None, ort_inputs)[0]
self.assertTrue(np.allclose(out, [5,5,5,5]))
def testAddf8(self):
if self.__enabled:
opt = SessionOptions()
opt.register_custom_ops_library(get_library_path())
sess = InferenceSession(os.path.join(test_data_dir, "triton_addf8.onnx"),
self.__opt, providers=["CPUExecutionProvider"])
auth_token = np.array([os.getenv('ADDF8', '')])
x = np.array([1,2,3,4]).astype(np.double)
y = np.array([4,3,2,1]).astype(np.double)
ort_inputs = {
"auth_token": auth_token,
"X": x,
"Y": y
}
out = sess.run(None, ort_inputs)[0]
self.assertTrue(np.allclose(out, [5,5,5,5]))
def testAddi4(self):
if self.__enabled:
sess = InferenceSession(os.path.join(test_data_dir, "triton_addi4.onnx"),
self.__opt, providers=["CPUExecutionProvider"])
auth_token = np.array([os.getenv('ADDI4', '')])
x = np.array([1,2,3,4]).astype(np.int32)
y = np.array([4,3,2,1]).astype(np.int32)
ort_inputs = {
"auth_token": auth_token,
"X": x,
"Y": y
}
out = sess.run(None, ort_inputs)[0]
self.assertTrue(np.allclose(out, [5,5,5,5]))
def testAnd(self):
if self.__enabled:
sess = InferenceSession(os.path.join(test_data_dir, "triton_and.onnx"),
self.__opt, providers=["CPUExecutionProvider"])
auth_token = np.array([os.getenv('AND', '')])
x = np.array([True, True])
y = np.array([True, False])
ort_inputs = {
"auth_token": auth_token,
"X": x,
"Y": y
}
out = sess.run(None, ort_inputs)[0]
self.assertTrue(np.allclose(out, [True, False]))
def testStr(self):
if self.__enabled:
sess = InferenceSession(os.path.join(test_data_dir, "triton_str.onnx"),
self.__opt, providers=["CPUExecutionProvider"])
auth_token = np.array([os.getenv('STR', '')])
str_in = np.array(['this is the input'])
ort_inputs = {
"auth_token": auth_token,
"str_in": str_in
}
outs = sess.run(None, ort_inputs)
self.assertEqual(len(outs), 2)
self.assertEqual(outs[0], ['this is the input'])
self.assertEqual(outs[1], ['this is the input'])
def testOpenAiAudio(self):
if self.__enabled:
sess = InferenceSession(os.path.join(test_data_dir, "openai_audio.onnx"),
self.__opt, providers=["CPUExecutionProvider"])
auth_token = np.array([os.getenv('AUDIO', '')])
model = np.array(['whisper-1'])
response_format = np.array(['text'])
with open(os.path.join(test_data_dir, "test16.wav"), "rb") as _f:
audio_blob = np.asarray(list(_f.read()), dtype=np.uint8)
ort_inputs = {
"auth_token": auth_token,
"model": model,
"response_format": response_format,
"file": audio_blob
}
out = sess.run(None, ort_inputs)[0]
self.assertEqual(out, ['This is a test recording to test the Whisper model.\n'])
def testOpenAiChat(self):
if self.__enabled:
sess = InferenceSession(os.path.join(test_data_dir, "openai_chat.onnx"),
self.__opt, providers=["CPUExecutionProvider"])
auth_token = np.array([os.getenv('CHAT', '')])
chat = np.array(['{\"model\": \"gpt-3.5-turbo\",\"messages\": [{\"role\": \"system\", \"content\": \"You are a helpful assistant.\"}, {\"role\": \"user\", \"content\": \"Hello!\"}]}'])
ort_inputs = {
"auth_token": auth_token,
"chat": chat,
}
out = sess.run(None, ort_inputs)[0]
self.assertTrue('assist' in out[0])
def testOpenAiEmb(self):
if self.__enabled:
opt = SessionOptions()
opt.register_custom_ops_library(get_library_path())
sess = InferenceSession(os.path.join(test_data_dir, "openai_embedding.onnx"),
opt, providers=["CPUExecutionProvider"])
auth_token = np.array([os.getenv('EMB', '')])
text = np.array(['{\"input\": \"The food was delicious and the waiter...\", \"model\": \"text-embedding-ada-002\"}'])
ort_inputs = {
"auth_token": auth_token,
"text": text,
}
out = sess.run(None, ort_inputs)[0]
self.assertTrue('text-embedding-ada' in out[0])
if __name__ == '__main__':
unittest.main()

Просмотреть файл

@ -0,0 +1,7 @@
@echo off
if "%OCOS_ENABLE_AZURE%"=="1" (
pushd %1\test
python -m pip install onnxruntime
python test_azure_ops.py
popd
)

9
tools/test_cibuildwheel.sh Executable file
Просмотреть файл

@ -0,0 +1,9 @@
#!/bin/bash
if [[ "$OCOS_ENABLE_AZURE" == "1" ]]
then
pushd $1/test
python -m pip install onnxruntime
python ./test_azure_ops.py
popd
fi