From 4a6e6b05619e839bb86b0b821671722f85c0530c Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Fri, 20 Aug 2021 16:09:06 +0200 Subject: [PATCH 01/28] Make numpy methods public --- mlserver/codecs/base.py | 4 ++-- mlserver/codecs/numpy.py | 2 +- mlserver/codecs/pandas.py | 4 ++-- tests/codecs/test_numpy.py | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mlserver/codecs/base.py b/mlserver/codecs/base.py index 5d3e6f7f5..ee2d05b93 100644 --- a/mlserver/codecs/base.py +++ b/mlserver/codecs/base.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional, Type +from typing import Any, ClassVar, Dict, Optional, Type from ..errors import MLServerError from ..types import InferenceRequest, InferenceResponse, RequestInput, ResponseOutput @@ -18,7 +18,7 @@ class InputCodec: interface instead. """ - ContentType: Optional[str] = None + ContentType: ClassVar[str] = "" @classmethod def encode(cls, name: str, payload: Any) -> ResponseOutput: diff --git a/mlserver/codecs/numpy.py b/mlserver/codecs/numpy.py index 06429a0cd..403343d22 100644 --- a/mlserver/codecs/numpy.py +++ b/mlserver/codecs/numpy.py @@ -42,7 +42,7 @@ def _to_dtype(request_input: RequestInput) -> "np.dtype": return np.dtype(dtype) -def _to_datatype(dtype: np.dtype) -> str: +def to_datatype(dtype: np.dtype) -> str: as_str = str(dtype) if as_str not in _NumpyToDatatype: diff --git a/mlserver/codecs/pandas.py b/mlserver/codecs/pandas.py index 10fc9baba..47c481514 100644 --- a/mlserver/codecs/pandas.py +++ b/mlserver/codecs/pandas.py @@ -3,7 +3,7 @@ import numpy as np from .base import RequestCodec, register_request_codec -from .numpy import _to_datatype +from .numpy import to_datatype from .utils import get_decoded_or_raw from ..types import InferenceRequest, InferenceResponse, RequestInput, ResponseOutput @@ -22,7 +22,7 @@ def _to_response_output(series: pd.Series) -> ResponseOutput: name=series.name, shape=list(series.shape), data=series.tolist(), - datatype=_to_datatype(series.dtype), + datatype=to_datatype(series.dtype), ) diff --git a/tests/codecs/test_numpy.py b/tests/codecs/test_numpy.py index 114199dbb..167a794be 100644 --- a/tests/codecs/test_numpy.py +++ b/tests/codecs/test_numpy.py @@ -1,7 +1,7 @@ import pytest import numpy as np -from mlserver.codecs.numpy import NumpyCodec, _to_datatype +from mlserver.codecs.numpy import NumpyCodec, to_datatype from mlserver.types import RequestInput @@ -61,5 +61,5 @@ def test_numpy_codec(request_input, payload): def test_to_datatype(dtype, datatype): dtype = np.dtype(dtype) - obtained_datatype = _to_datatype(dtype) + obtained_datatype = to_datatype(dtype) assert datatype == obtained_datatype From e65633942a31301568adb7658af8316eac42e3fa Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Fri, 20 Aug 2021 16:09:47 +0200 Subject: [PATCH 02/28] Add signature to MLflow test model --- runtimes/mlflow/tests/conftest.py | 18 ++++++++++++++++-- runtimes/mlflow/tests/test_encoding.py | 5 ++++- runtimes/mlflow/tests/test_runtime.py | 7 +++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/runtimes/mlflow/tests/conftest.py b/runtimes/mlflow/tests/conftest.py index 4158ada21..fab3070b8 100644 --- a/runtimes/mlflow/tests/conftest.py +++ b/runtimes/mlflow/tests/conftest.py @@ -4,6 +4,7 @@ import numpy as np from sklearn.dummy import DummyClassifier +from mlflow.models.signature import ModelSignature, infer_signature from mlserver.settings import ModelSettings, ModelParameters from mlserver.types import InferenceRequest @@ -22,16 +23,29 @@ def pytest_collection_modifyitems(items): @pytest.fixture -def model_uri(tmp_path) -> str: +def dataset() -> tuple: n = 4 X = np.random.rand(n) y = np.random.rand(n) + return X, y + + +@pytest.fixture +def model_signature(dataset: tuple) -> ModelSignature: + X, y = dataset + return infer_signature(X, y) + + +@pytest.fixture +def model_uri(tmp_path, dataset: tuple, model_signature: ModelSignature) -> str: + X, y = dataset + clf = DummyClassifier(strategy="prior") clf.fit(X, y) model_path = os.path.join(tmp_path, "dummy-model") - mlflow.sklearn.save_model(clf, path=model_path) + mlflow.sklearn.save_model(clf, path=model_path, signature=model_signature) return model_path diff --git a/runtimes/mlflow/tests/test_encoding.py b/runtimes/mlflow/tests/test_encoding.py index 0929cfeea..894fca076 100644 --- a/runtimes/mlflow/tests/test_encoding.py +++ b/runtimes/mlflow/tests/test_encoding.py @@ -1,6 +1,9 @@ import numpy as np import pandas as pd import pytest + +from mlserver.codecs.numpy import to_datatype + from mlserver_mlflow.encoding import ( MLflowPayload, to_outputs, @@ -35,5 +38,5 @@ def test_to_outputs(mlflow_payload: MLflowPayload): assert output.data.__root__ == value.flatten().tolist() else: assert output.data.__root__ == value.tolist() - assert output.datatype == _to_datatype(value.dtype) + assert output.datatype == to_datatype(value.dtype) assert output.shape == list(value.shape) diff --git a/runtimes/mlflow/tests/test_runtime.py b/runtimes/mlflow/tests/test_runtime.py index 2ff3decb1..dde7d2727 100644 --- a/runtimes/mlflow/tests/test_runtime.py +++ b/runtimes/mlflow/tests/test_runtime.py @@ -42,3 +42,10 @@ async def test_predict_pytorch(runtime_pytorch: MLflowRuntime): outputs = response.outputs assert len(outputs) == 1 assert outputs[0].name == DefaultOutputName + + +async def test_metadata(runtime: MLflowRuntime): + metadata = await runtime.metadata() + + breakpoint() + assert metadata is not None From 685460c0af3158446746117104efbdfdd9fcb657 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Fri, 20 Aug 2021 16:30:26 +0200 Subject: [PATCH 03/28] Start to add helpers to convert from mlflow signature to mlserver types --- runtimes/mlflow/mlserver_mlflow/metadata.py | 36 +++++++++++++++++++++ runtimes/mlflow/tests/test_metadata.py | 23 +++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 runtimes/mlflow/mlserver_mlflow/metadata.py create mode 100644 runtimes/mlflow/tests/test_metadata.py diff --git a/runtimes/mlflow/mlserver_mlflow/metadata.py b/runtimes/mlflow/mlserver_mlflow/metadata.py new file mode 100644 index 000000000..497bb02d0 --- /dev/null +++ b/runtimes/mlflow/mlserver_mlflow/metadata.py @@ -0,0 +1,36 @@ +from typing import Union, Tuple + +from mlflow.types.schema import ColSpec, TensorSpec, DataType +from mlserver.types import MetadataTensor, Tags +from mlserver.codecs import NumpyCodec, StringCodec +from mlserver.codecs.numpy import to_datatype + +InputSpec = Union[ColSpec, TensorSpec] + +_MLflowToContentType = { + DataType.boolean: ("BOOL", NumpyCodec.ContentType), + DataType.integer: ("INT32", NumpyCodec.ContentType), + DataType.long: ("INT64", NumpyCodec.ContentType), + DataType.float: ("FP32", NumpyCodec.ContentType), + DataType.double: ("FP64", NumpyCodec.ContentType), + DataType.string: ("BYTES", StringCodec.ContentType), + # TODO: Add Base64 codec + # DataType.binary: ("BYTES", Base64Codec.ContentType), + # TODO: Add DateTimeCodec + # DataType.datetime: ("BYTES", DateTimeCodec.ContentType), +} + + +def to_content_type(input_spec: InputSpec) -> Tuple[str, str]: + if isinstance(input_spec, TensorSpec): + datatype = to_datatype(input_spec.type) + content_type = NumpyCodec.ContentType + return datatype, content_type + + +def to_metadata_tensor(input_spec: InputSpec) -> MetadataTensor: + # TODO: Can input_spec.name be None? + + datatype, tags = to_content_type(input_spec) + + return MetadataTensor(name=input_spec.name, datatype="", shape=[], tags=Tags()) diff --git a/runtimes/mlflow/tests/test_metadata.py b/runtimes/mlflow/tests/test_metadata.py new file mode 100644 index 000000000..340868355 --- /dev/null +++ b/runtimes/mlflow/tests/test_metadata.py @@ -0,0 +1,23 @@ +import pytest +import numpy as np + +from typing import Tuple + +from mlflow.types.schema import ColSpec, TensorSpec, DataType +from mlserver.codecs import NumpyCodec + +from mlserver_mlflow.metadata import InputSpec, to_content_type + + +@pytest.mark.parametrize( + "input_spec, expected", + [ + ( + TensorSpec(type=np.dtype("int32"), shape=(2, 2), name="foo"), + ("INT32", NumpyCodec.ContentType), + ) + ], +) +def test_to_content_type(input_spec: InputSpec, expected: Tuple[str, str]): + datatype, content_type = to_content_type(input_spec) + assert (datatype, content_type) == expected From 34e2e75e84e29fe02932b0c826500359a466d65c Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Fri, 20 Aug 2021 18:11:53 +0200 Subject: [PATCH 04/28] Refactor helper methods into pack / unpack --- mlserver/codecs/string.py | 64 +++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/mlserver/codecs/string.py b/mlserver/codecs/string.py index 49489046a..ab7cac97a 100644 --- a/mlserver/codecs/string.py +++ b/mlserver/codecs/string.py @@ -1,4 +1,4 @@ -from typing import Generator, Union, List +from typing import Generator, Union, List, Tuple from ..types import RequestInput, ResponseOutput @@ -7,6 +7,8 @@ _DefaultStrCodec = "utf-8" +PackedPayload = Union[bytes, str, List[str]] + def _decode_str(encoded: Union[str, bytes], str_codec=_DefaultStrCodec) -> str: if isinstance(encoded, bytes): @@ -40,6 +42,38 @@ def _split_elements( yield encoded +def unpack( + packed: PackedPayload, shape: List[int], str_codec: str = _DefaultStrCodec +) -> Generator[str, None, None]: + for elem in _split_elements(packed, shape): + yield _decode_str(elem, str_codec) + + +def pack( + unpacked: List[str], str_codec: str = _DefaultStrCodec +) -> Tuple[PackedPayload, List[int]]: + packed = b"" + common_length = -1 + for elem in unpacked: + as_bytes = elem.encode(str_codec) + + # TODO: Should we use the length of the UTF8 string or the bytes + # array? + elem_length = len(as_bytes) + if common_length == -1: + common_length = elem_length + + if common_length != elem_length: + # TODO: Raise an error here + # TODO: Should we try to add padding? + pass + + packed += as_bytes + + shape = [len(unpacked), common_length] + return packed, shape + + @register_input_codec class StringCodec(InputCodec): """ @@ -50,28 +84,11 @@ class StringCodec(InputCodec): @classmethod def encode(cls, name: str, payload: List[str]) -> ResponseOutput: - packed = b"" - common_length = None - for elem in payload: - as_bytes = elem.encode(_DefaultStrCodec) - - # TODO: Should we use the length of the UTF8 string or the bytes - # array? - elem_length = len(as_bytes) - if common_length is None: - common_length = elem_length - - if common_length != elem_length: - # TODO: Raise an error here - # TODO: Should we try to add padding? - pass - - packed += as_bytes - + packed, shape = pack(payload) return ResponseOutput( name=name, datatype="BYTES", - shape=[len(payload), common_length], + shape=shape, data=packed, ) @@ -87,3 +104,10 @@ def decode(cls, request_input: RequestInput) -> List[str]: class StringRequestCodec(FirstInputRequestCodec): InputCodec = StringCodec ContentType = StringCodec.ContentType + + @classmethod + def decode(cls, request_input: RequestInput) -> List[str]: + packed = request_input.data.__root__ + shape = request_input.shape + + return list(unpack(packed, shape)) From 780aa694062209e9dafe23f01b09d509b7720708 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Tue, 24 Aug 2021 10:07:41 +0200 Subject: [PATCH 05/28] Move pack code into its own module --- mlserver/codecs/__init__.py | 2 ++ mlserver/codecs/pack.py | 57 +++++++++++++++++++++++++++++++++ mlserver/codecs/string.py | 64 +++++-------------------------------- 3 files changed, 67 insertions(+), 56 deletions(-) create mode 100644 mlserver/codecs/pack.py diff --git a/mlserver/codecs/__init__.py b/mlserver/codecs/__init__.py index edfc19644..428b516e2 100644 --- a/mlserver/codecs/__init__.py +++ b/mlserver/codecs/__init__.py @@ -1,6 +1,7 @@ from .numpy import NumpyCodec from .pandas import PandasCodec from .string import StringCodec +from .base64 import Base64Codec from .base import ( InputCodec, RequestCodec, @@ -19,6 +20,7 @@ __all__ = [ "NumpyCodec", "StringCodec", + "Base64Codec", "PandasCodec", "InputCodec", "RequestCodec", diff --git a/mlserver/codecs/pack.py b/mlserver/codecs/pack.py new file mode 100644 index 000000000..69501dff8 --- /dev/null +++ b/mlserver/codecs/pack.py @@ -0,0 +1,57 @@ +from typing import Any, Callable, Generator, Union, List, Tuple + + +PayloadElement = Union[bytes, str] +PackedPayload = Union[PayloadElement, List[PayloadElement]] +Encoder = Callable[[Any], bytes] +Decoder = Callable[[PayloadElement], Any] + + +def _split_elements( + encoded: PackedPayload, shape: List[int] +) -> Generator[PayloadElement, None, None]: + if isinstance(encoded, list): + # If it's a list, assume list of strings + yield from encoded + elif isinstance(encoded, bytes): + if len(shape) == 0: + # If there is no shape, assume that it's a single element + yield encoded + else: + # Otherwise, assume content is a concatenated list of same-length + # strings and get the common length from the shape + common_length = shape[-1] + for i in range(0, len(encoded), common_length): + yield encoded[i : i + common_length] + elif isinstance(encoded, str): + yield encoded + + +def unpack( + packed: PackedPayload, shape: List[int], decoder: Decoder +) -> Generator[Any, None, None]: + for elem in _split_elements(packed, shape): + yield decoder(elem) + + +def pack(unpacked: List[Any], encoder: Encoder) -> Tuple[PackedPayload, List[int]]: + packed = b"" + common_length = -1 + for elem in unpacked: + as_bytes = encoder(elem) + + # TODO: Should we use the length of the UTF8 string or the bytes + # array? + elem_length = len(as_bytes) + if common_length == -1: + common_length = elem_length + + if common_length != elem_length: + # TODO: Raise an error here + # TODO: Should we try to add padding? + pass + + packed += as_bytes + + shape = [len(unpacked), common_length] + return packed, shape diff --git a/mlserver/codecs/string.py b/mlserver/codecs/string.py index ab7cac97a..59de369c6 100644 --- a/mlserver/codecs/string.py +++ b/mlserver/codecs/string.py @@ -1,13 +1,16 @@ -from typing import Generator, Union, List, Tuple +from typing import Callable, Union, List from ..types import RequestInput, ResponseOutput from .utils import FirstInputRequestCodec from .base import InputCodec, register_input_codec, register_request_codec +from .pack import pack, unpack _DefaultStrCodec = "utf-8" -PackedPayload = Union[bytes, str, List[str]] + +def _encode_str(elem: str) -> bytes: + return elem.encode(_DefaultStrCodec) def _decode_str(encoded: Union[str, bytes], str_codec=_DefaultStrCodec) -> str: @@ -22,58 +25,6 @@ def _decode_str(encoded: Union[str, bytes], str_codec=_DefaultStrCodec) -> str: return "" -def _split_elements( - encoded: Union[bytes, str, List[str]], shape: List[int] -) -> Generator[Union[str, bytes], None, None]: - if isinstance(encoded, list): - # If it's a list, assume list of strings - yield from encoded - elif isinstance(encoded, bytes): - if len(shape) == 0: - # If there is no shape, assume that it's a single element - yield encoded - else: - # Otherwise, assume content is a concatenated list of same-length - # strings and get the common length from the shape - common_length = shape[-1] - for i in range(0, len(encoded), common_length): - yield encoded[i : i + common_length] - elif isinstance(encoded, str): - yield encoded - - -def unpack( - packed: PackedPayload, shape: List[int], str_codec: str = _DefaultStrCodec -) -> Generator[str, None, None]: - for elem in _split_elements(packed, shape): - yield _decode_str(elem, str_codec) - - -def pack( - unpacked: List[str], str_codec: str = _DefaultStrCodec -) -> Tuple[PackedPayload, List[int]]: - packed = b"" - common_length = -1 - for elem in unpacked: - as_bytes = elem.encode(str_codec) - - # TODO: Should we use the length of the UTF8 string or the bytes - # array? - elem_length = len(as_bytes) - if common_length == -1: - common_length = elem_length - - if common_length != elem_length: - # TODO: Raise an error here - # TODO: Should we try to add padding? - pass - - packed += as_bytes - - shape = [len(unpacked), common_length] - return packed, shape - - @register_input_codec class StringCodec(InputCodec): """ @@ -84,7 +35,7 @@ class StringCodec(InputCodec): @classmethod def encode(cls, name: str, payload: List[str]) -> ResponseOutput: - packed, shape = pack(payload) + packed, shape = pack(payload, encoder=_encode_str) return ResponseOutput( name=name, datatype="BYTES", @@ -110,4 +61,5 @@ def decode(cls, request_input: RequestInput) -> List[str]: packed = request_input.data.__root__ shape = request_input.shape - return list(unpack(packed, shape)) + unpacked = unpack(packed, shape, decoder=_decode_str) + return list(unpacked) From 03880cf08bb3ab868661eb0c850dae42654a7dac Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Tue, 24 Aug 2021 11:04:51 +0200 Subject: [PATCH 06/28] Tweak pack / unpack methods --- mlserver/codecs/base64.py | 38 ++++++++++++++++++++++++++++ mlserver/codecs/pack.py | 49 +++++++++++++++---------------------- mlserver/codecs/string.py | 8 +++--- tests/codecs/test_base64.py | 34 +++++++++++++++++++++++++ tests/codecs/test_string.py | 6 ++--- 5 files changed, 99 insertions(+), 36 deletions(-) create mode 100644 mlserver/codecs/base64.py create mode 100644 tests/codecs/test_base64.py diff --git a/mlserver/codecs/base64.py b/mlserver/codecs/base64.py new file mode 100644 index 000000000..c95013205 --- /dev/null +++ b/mlserver/codecs/base64.py @@ -0,0 +1,38 @@ +import base64 + +from typing import List + +from ..types import RequestInput, ResponseOutput +from .base import InputCodec, register_input_codec +from .pack import pack, unpack, PackElement + +_Base64StrCodec = "ascii" + + +def _decode_base64(elem: PackElement) -> bytes: + as_bytes = elem.encode(_Base64StrCodec) if isinstance(elem, str) else elem + return base64.b64decode(as_bytes) + + +@register_input_codec +class Base64Codec(InputCodec): + """ + Encodes binary data as base64 + """ + + ContentType = "base64" + + def encode(self, name: str, payload: List[bytes]) -> ResponseOutput: + packed, shape = pack(map(base64.b64encode, payload)) + return ResponseOutput( + name=name, + datatype="BYTES", + shape=shape, + data=packed, + ) + + def decode(self, request_input: RequestInput) -> List[str]: + packed = request_input.data.__root__ + shape = request_input.shape + + return map(_decode_base64, unpack(packed, shape)) diff --git a/mlserver/codecs/pack.py b/mlserver/codecs/pack.py index 69501dff8..16d425bb6 100644 --- a/mlserver/codecs/pack.py +++ b/mlserver/codecs/pack.py @@ -1,48 +1,38 @@ -from typing import Any, Callable, Generator, Union, List, Tuple +from typing import Generator, Union, List, Tuple -PayloadElement = Union[bytes, str] -PackedPayload = Union[PayloadElement, List[PayloadElement]] -Encoder = Callable[[Any], bytes] -Decoder = Callable[[PayloadElement], Any] +PackElement = Union[bytes, str] +PackedPayload = Union[PackElement, List[PackElement]] -def _split_elements( - encoded: PackedPayload, shape: List[int] -) -> Generator[PayloadElement, None, None]: - if isinstance(encoded, list): +def unpack( + packed: PackedPayload, shape: List[int] +) -> Generator[PackElement, None, None]: + if isinstance(packed, list): # If it's a list, assume list of strings - yield from encoded - elif isinstance(encoded, bytes): + yield from packed + elif isinstance(packed, bytes): if len(shape) == 0: # If there is no shape, assume that it's a single element - yield encoded + yield packed else: # Otherwise, assume content is a concatenated list of same-length # strings and get the common length from the shape common_length = shape[-1] - for i in range(0, len(encoded), common_length): - yield encoded[i : i + common_length] - elif isinstance(encoded, str): - yield encoded - + for i in range(0, len(packed), common_length): + yield packed[i : i + common_length] + elif isinstance(packed, str): + yield packed -def unpack( - packed: PackedPayload, shape: List[int], decoder: Decoder -) -> Generator[Any, None, None]: - for elem in _split_elements(packed, shape): - yield decoder(elem) - -def pack(unpacked: List[Any], encoder: Encoder) -> Tuple[PackedPayload, List[int]]: +def pack(unpacked: List[bytes]) -> Tuple[PackedPayload, List[int]]: packed = b"" common_length = -1 + N = 0 for elem in unpacked: - as_bytes = encoder(elem) - # TODO: Should we use the length of the UTF8 string or the bytes # array? - elem_length = len(as_bytes) + elem_length = len(elem) if common_length == -1: common_length = elem_length @@ -51,7 +41,8 @@ def pack(unpacked: List[Any], encoder: Encoder) -> Tuple[PackedPayload, List[int # TODO: Should we try to add padding? pass - packed += as_bytes + N += 1 + packed += elem - shape = [len(unpacked), common_length] + shape = [N, common_length] return packed, shape diff --git a/mlserver/codecs/string.py b/mlserver/codecs/string.py index 59de369c6..9ada67eb5 100644 --- a/mlserver/codecs/string.py +++ b/mlserver/codecs/string.py @@ -4,7 +4,7 @@ from .utils import FirstInputRequestCodec from .base import InputCodec, register_input_codec, register_request_codec -from .pack import pack, unpack +from .pack import pack, unpack, PackElement _DefaultStrCodec = "utf-8" @@ -13,7 +13,7 @@ def _encode_str(elem: str) -> bytes: return elem.encode(_DefaultStrCodec) -def _decode_str(encoded: Union[str, bytes], str_codec=_DefaultStrCodec) -> str: +def _decode_str(encoded: PackElement, str_codec=_DefaultStrCodec) -> str: if isinstance(encoded, bytes): return encoded.decode(str_codec) @@ -35,7 +35,7 @@ class StringCodec(InputCodec): @classmethod def encode(cls, name: str, payload: List[str]) -> ResponseOutput: - packed, shape = pack(payload, encoder=_encode_str) + packed, shape = pack(map(_encode_str, payload)) return ResponseOutput( name=name, datatype="BYTES", @@ -61,5 +61,5 @@ def decode(cls, request_input: RequestInput) -> List[str]: packed = request_input.data.__root__ shape = request_input.shape - unpacked = unpack(packed, shape, decoder=_decode_str) + unpacked = map(_decode_str, unpack(packed, shape)) return list(unpacked) diff --git a/tests/codecs/test_base64.py b/tests/codecs/test_base64.py new file mode 100644 index 000000000..a4e8a8591 --- /dev/null +++ b/tests/codecs/test_base64.py @@ -0,0 +1,34 @@ +import pytest + +from mlserver.codecs import Base64Codec +from mlserver.types import RequestInput, ResponseOutput + + +@pytest.mark.parametrize( + "decoded, expected", + [ + ( + [b"Python is fun"], + ResponseOutput( + name="foo", + shape=[1, 20], + datatype="BYTES", + data=b"UHl0aG9uIGlzIGZ1bg==", + ), + ), + ( + [b"Python is fun", b"Python is fun"], + ResponseOutput( + name="foo", + shape=[2, 20], + datatype="BYTES", + data=b"UHl0aG9uIGlzIGZ1bg==UHl0aG9uIGlzIGZ1bg==", + ), + ), + ], +) +def test_encode(decoded, expected): + codec = Base64Codec() + response_output = codec.encode(name="foo", payload=decoded) + + assert expected == response_output diff --git a/tests/codecs/test_string.py b/tests/codecs/test_string.py index 44d75418b..eee782f48 100644 --- a/tests/codecs/test_string.py +++ b/tests/codecs/test_string.py @@ -1,7 +1,7 @@ import pytest from mlserver.codecs import StringCodec -from mlserver.types import RequestInput +from mlserver.types import RequestInput, ResponseOutput @pytest.mark.parametrize( @@ -56,13 +56,13 @@ def test_decode(request_input, expected): [ ( ["hello world"], - RequestInput( + ResponseOutput( name="foo", shape=[1, 11], datatype="BYTES", data=b"hello world" ), ), ( ["hey", "abc"], - RequestInput(name="foo", shape=[2, 3], datatype="BYTES", data=b"heyabc"), + ResponseOutput(name="foo", shape=[2, 3], datatype="BYTES", data=b"heyabc"), ), ], ) From e76b6bb1fbf725ff20533527fcc0ffcd5fc5d62a Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Tue, 24 Aug 2021 12:09:27 +0200 Subject: [PATCH 07/28] Add some tests to ensure that payload is packed / unpacked correctly --- mlserver/codecs/base64.py | 18 ++++++++----- mlserver/codecs/pack.py | 4 +-- tests/codecs/test_base64.py | 52 +++++++++++++++++++++++++++++++++++-- 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/mlserver/codecs/base64.py b/mlserver/codecs/base64.py index c95013205..6ce9f3fc8 100644 --- a/mlserver/codecs/base64.py +++ b/mlserver/codecs/base64.py @@ -9,9 +9,12 @@ _Base64StrCodec = "ascii" -def _decode_base64(elem: PackElement) -> bytes: - as_bytes = elem.encode(_Base64StrCodec) if isinstance(elem, str) else elem - return base64.b64decode(as_bytes) +def _to_bytes(elem: PackElement) -> bytes: + if isinstance(elem, str): + return elem.encode(_Base64StrCodec) + + # TODO: Ensure that payload is in base64 + return elem @register_input_codec @@ -23,7 +26,10 @@ class Base64Codec(InputCodec): ContentType = "base64" def encode(self, name: str, payload: List[bytes]) -> ResponseOutput: - packed, shape = pack(map(base64.b64encode, payload)) + # Assume that payload is already in b64, so we only need to + # pack it + # TODO: Ensure that payload is in base64 + packed, shape = pack(payload) return ResponseOutput( name=name, datatype="BYTES", @@ -31,8 +37,8 @@ def encode(self, name: str, payload: List[bytes]) -> ResponseOutput: data=packed, ) - def decode(self, request_input: RequestInput) -> List[str]: + def decode(self, request_input: RequestInput) -> List[bytes]: packed = request_input.data.__root__ shape = request_input.shape - return map(_decode_base64, unpack(packed, shape)) + return list(map(_to_bytes, unpack(packed, shape))) diff --git a/mlserver/codecs/pack.py b/mlserver/codecs/pack.py index 16d425bb6..4133d8bb2 100644 --- a/mlserver/codecs/pack.py +++ b/mlserver/codecs/pack.py @@ -11,7 +11,7 @@ def unpack( if isinstance(packed, list): # If it's a list, assume list of strings yield from packed - elif isinstance(packed, bytes): + else: if len(shape) == 0: # If there is no shape, assume that it's a single element yield packed @@ -21,8 +21,6 @@ def unpack( common_length = shape[-1] for i in range(0, len(packed), common_length): yield packed[i : i + common_length] - elif isinstance(packed, str): - yield packed def pack(unpacked: List[bytes]) -> Tuple[PackedPayload, List[int]]: diff --git a/tests/codecs/test_base64.py b/tests/codecs/test_base64.py index a4e8a8591..aa7def09e 100644 --- a/tests/codecs/test_base64.py +++ b/tests/codecs/test_base64.py @@ -8,7 +8,7 @@ "decoded, expected", [ ( - [b"Python is fun"], + [b"UHl0aG9uIGlzIGZ1bg=="], ResponseOutput( name="foo", shape=[1, 20], @@ -17,7 +17,7 @@ ), ), ( - [b"Python is fun", b"Python is fun"], + [b"UHl0aG9uIGlzIGZ1bg==", b"UHl0aG9uIGlzIGZ1bg=="], ResponseOutput( name="foo", shape=[2, 20], @@ -32,3 +32,51 @@ def test_encode(decoded, expected): response_output = codec.encode(name="foo", payload=decoded) assert expected == response_output + + +@pytest.mark.parametrize( + "encoded, expected", + [ + ( + RequestInput( + name="foo", + shape=[1, 20], + datatype="BYTES", + data=b"UHl0aG9uIGlzIGZ1bg==", + ), + [b"UHl0aG9uIGlzIGZ1bg=="], + ), + ( + RequestInput( + name="foo", + shape=[1, 20], + datatype="BYTES", + data="UHl0aG9uIGlzIGZ1bg==", + ), + [b"UHl0aG9uIGlzIGZ1bg=="], + ), + ( + RequestInput( + name="foo", + shape=[2, 20], + datatype="BYTES", + data=b"UHl0aG9uIGlzIGZ1bg==UHl0aG9uIGlzIGZ1bg==", + ), + [b"UHl0aG9uIGlzIGZ1bg==", b"UHl0aG9uIGlzIGZ1bg=="], + ), + ( + RequestInput( + name="foo", + shape=[2, 20], + datatype="BYTES", + data="UHl0aG9uIGlzIGZ1bg==UHl0aG9uIGlzIGZ1bg==", + ), + [b"UHl0aG9uIGlzIGZ1bg==", b"UHl0aG9uIGlzIGZ1bg=="], + ), + ], +) +def test_decode(encoded, expected): + codec = Base64Codec() + decoded_input = codec.decode(encoded) + + assert expected == decoded_input From 4e020e922f977eb8969408011e8a88f12267ad82 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Tue, 24 Aug 2021 12:19:13 +0200 Subject: [PATCH 08/28] Ensure input is valid base64 --- mlserver/codecs/base64.py | 24 +++++++++++++++++------- tests/codecs/test_base64.py | 9 +++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/mlserver/codecs/base64.py b/mlserver/codecs/base64.py index 6ce9f3fc8..97e28bcaf 100644 --- a/mlserver/codecs/base64.py +++ b/mlserver/codecs/base64.py @@ -1,4 +1,5 @@ import base64 +import binascii from typing import List @@ -9,26 +10,35 @@ _Base64StrCodec = "ascii" -def _to_bytes(elem: PackElement) -> bytes: +def _ensure_bytes(elem: PackElement) -> bytes: if isinstance(elem, str): return elem.encode(_Base64StrCodec) - # TODO: Ensure that payload is in base64 return elem +def _ensure_base64(elem: PackElement) -> bytes: + as_bytes = _ensure_bytes(elem) + + # Check that the input is valid base64. + # Otherwise, convert into base64. + try: + base64.b64decode(as_bytes, validate=True) + return as_bytes + except binascii.Error: + return base64.b64encode(as_bytes) + + @register_input_codec class Base64Codec(InputCodec): """ - Encodes binary data as base64 + Ensures that the input that the model receives is a base64 bytes array. """ ContentType = "base64" def encode(self, name: str, payload: List[bytes]) -> ResponseOutput: - # Assume that payload is already in b64, so we only need to - # pack it - # TODO: Ensure that payload is in base64 + # Assume that payload is already in b64, so we only need to pack it packed, shape = pack(payload) return ResponseOutput( name=name, @@ -41,4 +51,4 @@ def decode(self, request_input: RequestInput) -> List[bytes]: packed = request_input.data.__root__ shape = request_input.shape - return list(map(_to_bytes, unpack(packed, shape))) + return list(map(_ensure_base64, unpack(packed, shape))) diff --git a/tests/codecs/test_base64.py b/tests/codecs/test_base64.py index aa7def09e..2368d461f 100644 --- a/tests/codecs/test_base64.py +++ b/tests/codecs/test_base64.py @@ -55,6 +55,15 @@ def test_encode(decoded, expected): ), [b"UHl0aG9uIGlzIGZ1bg=="], ), + ( + RequestInput( + name="foo", + shape=[1, 13], + datatype="BYTES", + data=b"Python is fun", + ), + [b"UHl0aG9uIGlzIGZ1bg=="], + ), ( RequestInput( name="foo", From a93bca6a941e80d94f7285c9020cee21a091d66c Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Tue, 24 Aug 2021 14:43:09 +0200 Subject: [PATCH 09/28] Ensure b64 gets transformed --- mlserver/codecs/base64.py | 18 +++++++++++------- tests/codecs/test_base64.py | 32 +++++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/mlserver/codecs/base64.py b/mlserver/codecs/base64.py index 97e28bcaf..f506a7520 100644 --- a/mlserver/codecs/base64.py +++ b/mlserver/codecs/base64.py @@ -17,29 +17,33 @@ def _ensure_bytes(elem: PackElement) -> bytes: return elem -def _ensure_base64(elem: PackElement) -> bytes: +def _decode_base64(elem: PackElement) -> bytes: as_bytes = _ensure_bytes(elem) # Check that the input is valid base64. # Otherwise, convert into base64. try: - base64.b64decode(as_bytes, validate=True) - return as_bytes + return base64.b64decode(as_bytes, validate=True) except binascii.Error: - return base64.b64encode(as_bytes) + return as_bytes + + +def _encode_base64(elem: PackElement) -> bytes: + as_bytes = _ensure_bytes(elem) + return base64.b64encode(as_bytes) @register_input_codec class Base64Codec(InputCodec): """ - Ensures that the input that the model receives is a base64 bytes array. + Codec that convers to / from a base64 input. """ ContentType = "base64" def encode(self, name: str, payload: List[bytes]) -> ResponseOutput: # Assume that payload is already in b64, so we only need to pack it - packed, shape = pack(payload) + packed, shape = pack(map(_encode_base64, payload)) return ResponseOutput( name=name, datatype="BYTES", @@ -51,4 +55,4 @@ def decode(self, request_input: RequestInput) -> List[bytes]: packed = request_input.data.__root__ shape = request_input.shape - return list(map(_ensure_base64, unpack(packed, shape))) + return list(map(_decode_base64, unpack(packed, shape))) diff --git a/tests/codecs/test_base64.py b/tests/codecs/test_base64.py index 2368d461f..2010140d2 100644 --- a/tests/codecs/test_base64.py +++ b/tests/codecs/test_base64.py @@ -8,7 +8,7 @@ "decoded, expected", [ ( - [b"UHl0aG9uIGlzIGZ1bg=="], + [b"Python is fun"], ResponseOutput( name="foo", shape=[1, 20], @@ -17,7 +17,16 @@ ), ), ( - [b"UHl0aG9uIGlzIGZ1bg==", b"UHl0aG9uIGlzIGZ1bg=="], + ["Python is fun"], + ResponseOutput( + name="foo", + shape=[1, 20], + datatype="BYTES", + data=b"UHl0aG9uIGlzIGZ1bg==", + ), + ), + ( + [b"Python is fun", b"Python is fun"], ResponseOutput( name="foo", shape=[2, 20], @@ -44,7 +53,7 @@ def test_encode(decoded, expected): datatype="BYTES", data=b"UHl0aG9uIGlzIGZ1bg==", ), - [b"UHl0aG9uIGlzIGZ1bg=="], + [b"Python is fun"], ), ( RequestInput( @@ -53,7 +62,7 @@ def test_encode(decoded, expected): datatype="BYTES", data="UHl0aG9uIGlzIGZ1bg==", ), - [b"UHl0aG9uIGlzIGZ1bg=="], + [b"Python is fun"], ), ( RequestInput( @@ -62,7 +71,16 @@ def test_encode(decoded, expected): datatype="BYTES", data=b"Python is fun", ), - [b"UHl0aG9uIGlzIGZ1bg=="], + [b"Python is fun"], + ), + ( + RequestInput( + name="foo", + shape=[1, 13], + datatype="BYTES", + data="Python is fun", + ), + [b"Python is fun"], ), ( RequestInput( @@ -71,7 +89,7 @@ def test_encode(decoded, expected): datatype="BYTES", data=b"UHl0aG9uIGlzIGZ1bg==UHl0aG9uIGlzIGZ1bg==", ), - [b"UHl0aG9uIGlzIGZ1bg==", b"UHl0aG9uIGlzIGZ1bg=="], + [b"Python is fun", b"Python is fun"], ), ( RequestInput( @@ -80,7 +98,7 @@ def test_encode(decoded, expected): datatype="BYTES", data="UHl0aG9uIGlzIGZ1bg==UHl0aG9uIGlzIGZ1bg==", ), - [b"UHl0aG9uIGlzIGZ1bg==", b"UHl0aG9uIGlzIGZ1bg=="], + [b"Python is fun", b"Python is fun"], ), ], ) From 4d2d0c1acf0d65a6439e97de928560ab4e09d2b5 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Tue, 24 Aug 2021 15:09:23 +0200 Subject: [PATCH 10/28] Add datetime codec --- mlserver/codecs/__init__.py | 2 + mlserver/codecs/base64.py | 10 ++-- mlserver/codecs/datetime.py | 59 +++++++++++++++++++++ tests/codecs/test_datetime.py | 99 +++++++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 5 deletions(-) create mode 100644 mlserver/codecs/datetime.py create mode 100644 tests/codecs/test_datetime.py diff --git a/mlserver/codecs/__init__.py b/mlserver/codecs/__init__.py index 428b516e2..251416cc4 100644 --- a/mlserver/codecs/__init__.py +++ b/mlserver/codecs/__init__.py @@ -2,6 +2,7 @@ from .pandas import PandasCodec from .string import StringCodec from .base64 import Base64Codec +from .datetime import DatetimeCodec from .base import ( InputCodec, RequestCodec, @@ -21,6 +22,7 @@ "NumpyCodec", "StringCodec", "Base64Codec", + "DatetimeCodec", "PandasCodec", "InputCodec", "RequestCodec", diff --git a/mlserver/codecs/base64.py b/mlserver/codecs/base64.py index f506a7520..5290f9245 100644 --- a/mlserver/codecs/base64.py +++ b/mlserver/codecs/base64.py @@ -17,6 +17,11 @@ def _ensure_bytes(elem: PackElement) -> bytes: return elem +def _encode_base64(elem: PackElement) -> bytes: + as_bytes = _ensure_bytes(elem) + return base64.b64encode(as_bytes) + + def _decode_base64(elem: PackElement) -> bytes: as_bytes = _ensure_bytes(elem) @@ -28,11 +33,6 @@ def _decode_base64(elem: PackElement) -> bytes: return as_bytes -def _encode_base64(elem: PackElement) -> bytes: - as_bytes = _ensure_bytes(elem) - return base64.b64encode(as_bytes) - - @register_input_codec class Base64Codec(InputCodec): """ diff --git a/mlserver/codecs/datetime.py b/mlserver/codecs/datetime.py new file mode 100644 index 000000000..7b4cdf6b9 --- /dev/null +++ b/mlserver/codecs/datetime.py @@ -0,0 +1,59 @@ +from typing import Union, List +from datetime import datetime + +from ..types import RequestInput, ResponseOutput +from .base import InputCodec, register_input_codec +from .pack import pack, unpack, PackElement + +_Datetime = Union[str, datetime] +_DatetimeStrCodec = "ascii" + + +def _to_iso(elem: _Datetime) -> str: + if isinstance(elem, str): + # Assume date has already been encoded upstream + return elem + + return elem.isoformat() + + +def _encode_datetime(elem: _Datetime) -> bytes: + iso_date = _to_iso(elem) + return iso_date.encode(_DatetimeStrCodec) + + +def _ensure_str(elem: PackElement) -> str: + if isinstance(elem, str): + return elem + + return elem.decode(_DatetimeStrCodec) + + +def _decode_datetime(elem: PackElement) -> datetime: + iso_format = _ensure_str(elem) + return datetime.fromisoformat(iso_format) + + +@register_input_codec +class DatetimeCodec(InputCodec): + """ + Codec that convers to / from a base64 input. + """ + + ContentType = "datetime" + + def encode(self, name: str, payload: List[_Datetime]) -> ResponseOutput: + # Assume that payload is already in b64, so we only need to pack it + packed, shape = pack(map(_encode_datetime, payload)) + return ResponseOutput( + name=name, + datatype="BYTES", + shape=shape, + data=packed, + ) + + def decode(self, request_input: RequestInput) -> List[datetime]: + packed = request_input.data.__root__ + shape = request_input.shape + + return list(map(_decode_datetime, unpack(packed, shape))) diff --git a/tests/codecs/test_datetime.py b/tests/codecs/test_datetime.py new file mode 100644 index 000000000..dcebdf774 --- /dev/null +++ b/tests/codecs/test_datetime.py @@ -0,0 +1,99 @@ +import pytest + +from datetime import datetime + +from mlserver.codecs import DatetimeCodec +from mlserver.types import RequestInput, ResponseOutput + +TestDatetimeIso = "2021-08-24T15:01:19" +TestDatetimeIsoB = b"2021-08-24T15:01:19" +TestDatetime = datetime.fromisoformat(TestDatetimeIso) + + +@pytest.mark.parametrize( + "decoded, expected", + [ + ( + [TestDatetime], + ResponseOutput( + name="foo", + shape=[1, 19], + datatype="BYTES", + data=TestDatetimeIsoB, + ), + ), + ( + [TestDatetime, TestDatetime], + ResponseOutput( + name="foo", + shape=[2, 19], + datatype="BYTES", + data=TestDatetimeIsoB + TestDatetimeIsoB, + ), + ), + ( + [ + TestDatetimeIso, + ], + ResponseOutput( + name="foo", + shape=[1, 19], + datatype="BYTES", + data=TestDatetimeIsoB, + ), + ), + ], +) +def test_encode(decoded, expected): + codec = DatetimeCodec() + response_output = codec.encode(name="foo", payload=decoded) + + assert expected == response_output + + +@pytest.mark.parametrize( + "encoded, expected", + [ + ( + RequestInput( + name="foo", + shape=[1, 19], + datatype="BYTES", + data=TestDatetimeIsoB, + ), + [TestDatetime], + ), + ( + RequestInput( + name="foo", + shape=[1, 19], + datatype="BYTES", + data=TestDatetimeIso, + ), + [TestDatetime], + ), + ( + RequestInput( + name="foo", + shape=[1, 19], + datatype="BYTES", + data=TestDatetimeIsoB + TestDatetimeIsoB, + ), + [TestDatetime, TestDatetime], + ), + ( + RequestInput( + name="foo", + shape=[1, 19], + datatype="BYTES", + data=TestDatetimeIso + TestDatetimeIso, + ), + [TestDatetime, TestDatetime], + ), + ], +) +def test_decode(encoded, expected): + codec = DatetimeCodec() + decoded_input = codec.decode(encoded) + + assert expected == decoded_input From 90d8d616c33b8e548d009f025cb50fd941f14334 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Tue, 24 Aug 2021 15:35:08 +0200 Subject: [PATCH 11/28] Add tests for metadata --- runtimes/mlflow/mlserver_mlflow/metadata.py | 37 ++++++++++---- runtimes/mlflow/tests/test_metadata.py | 56 ++++++++++++++++++--- 2 files changed, 76 insertions(+), 17 deletions(-) diff --git a/runtimes/mlflow/mlserver_mlflow/metadata.py b/runtimes/mlflow/mlserver_mlflow/metadata.py index 497bb02d0..fc1926b28 100644 --- a/runtimes/mlflow/mlserver_mlflow/metadata.py +++ b/runtimes/mlflow/mlserver_mlflow/metadata.py @@ -1,8 +1,8 @@ -from typing import Union, Tuple +from typing import Union, Tuple, List -from mlflow.types.schema import ColSpec, TensorSpec, DataType +from mlflow.types.schema import Schema, ColSpec, TensorSpec, DataType from mlserver.types import MetadataTensor, Tags -from mlserver.codecs import NumpyCodec, StringCodec +from mlserver.codecs import NumpyCodec, StringCodec, Base64Codec, DatetimeCodec from mlserver.codecs.numpy import to_datatype InputSpec = Union[ColSpec, TensorSpec] @@ -14,23 +14,40 @@ DataType.float: ("FP32", NumpyCodec.ContentType), DataType.double: ("FP64", NumpyCodec.ContentType), DataType.string: ("BYTES", StringCodec.ContentType), - # TODO: Add Base64 codec - # DataType.binary: ("BYTES", Base64Codec.ContentType), - # TODO: Add DateTimeCodec - # DataType.datetime: ("BYTES", DateTimeCodec.ContentType), + DataType.binary: ("BYTES", Base64Codec.ContentType), + DataType.datetime: ("BYTES", DatetimeCodec.ContentType), } -def to_content_type(input_spec: InputSpec) -> Tuple[str, str]: +def _get_content_type(input_spec: InputSpec) -> Tuple[str, str]: if isinstance(input_spec, TensorSpec): datatype = to_datatype(input_spec.type) content_type = NumpyCodec.ContentType return datatype, content_type + # TODO: Check if new type, which may not exist + return _MLflowToContentType[input_spec.type] + + +def _get_shape(input_spec: InputSpec) -> List[int]: + if isinstance(input_spec, TensorSpec): + return list(input_spec.shape) + + return [-1] + def to_metadata_tensor(input_spec: InputSpec) -> MetadataTensor: # TODO: Can input_spec.name be None? + datatype, content_type = _get_content_type(input_spec) + shape = _get_shape(input_spec) + + return MetadataTensor( + name=input_spec.name, + datatype=datatype, + shape=shape, + tags=Tags(content_type=content_type), + ) - datatype, tags = to_content_type(input_spec) - return MetadataTensor(name=input_spec.name, datatype="", shape=[], tags=Tags()) +def to_metadata(schema: Schema) -> List[MetadataTensor]: + return [to_metadata_tensor(schema_input) for schema_input in schema.inputs] diff --git a/runtimes/mlflow/tests/test_metadata.py b/runtimes/mlflow/tests/test_metadata.py index 340868355..1c5eef152 100644 --- a/runtimes/mlflow/tests/test_metadata.py +++ b/runtimes/mlflow/tests/test_metadata.py @@ -1,23 +1,65 @@ import pytest import numpy as np -from typing import Tuple +from typing import Tuple, List from mlflow.types.schema import ColSpec, TensorSpec, DataType -from mlserver.codecs import NumpyCodec +from mlserver.codecs import NumpyCodec, StringCodec, Base64Codec +from mlserver.types import Tags -from mlserver_mlflow.metadata import InputSpec, to_content_type +from mlserver_mlflow.metadata import ( + InputSpec, + _get_content_type, + _get_shape, + to_metadata_tensor, +) @pytest.mark.parametrize( "input_spec, expected", [ ( - TensorSpec(type=np.dtype("int32"), shape=(2, 2), name="foo"), + TensorSpec(name="foo", shape=(2, 2), type=np.dtype("int32")), ("INT32", NumpyCodec.ContentType), - ) + ), + ( + ColSpec(name="foo", type=DataType.string), + ("BYTES", StringCodec.ContentType), + ), + ( + ColSpec(name="foo", type=DataType.binary), + ("BYTES", Base64Codec.ContentType), + ), ], ) -def test_to_content_type(input_spec: InputSpec, expected: Tuple[str, str]): - datatype, content_type = to_content_type(input_spec) +def test_get_content_type(input_spec: InputSpec, expected: Tuple[str, str]): + datatype, content_type = _get_content_type(input_spec) assert (datatype, content_type) == expected + + +@pytest.mark.parametrize( + "input_spec, expected", + [ + ( + TensorSpec(name="foo", shape=(2, 2), type=np.dtype("int32")), + [2, 2], + ), + ( + ColSpec(name="foo", type=DataType.string), + [-1], + ), + ], +) +def test_get_shape(input_spec: InputSpec, expected: List[int]): + shape = _get_shape(input_spec) + assert shape == expected + + +def test_to_metadata_tensor(): + input_spec = TensorSpec(name="foo", shape=(2, 2), type=np.dtype("int32")) + metadata_tensor = to_metadata_tensor(input_spec) + + assert metadata_tensor.name == input_spec.name + assert metadata_tensor.datatype == "INT32" + assert metadata_tensor.shape == list(input_spec.shape) + assert metadata_tensor.tags == Tags(content_type=NumpyCodec.ContentType) From cddb247478a9e82d7d3bc5d6f33f90255e8a0cd8 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Tue, 24 Aug 2021 15:47:55 +0200 Subject: [PATCH 12/28] Ensure name is always added --- runtimes/mlflow/mlserver_mlflow/metadata.py | 28 +++++---- runtimes/mlflow/tests/test_metadata.py | 67 ++++++++++++++++++--- 2 files changed, 73 insertions(+), 22 deletions(-) diff --git a/runtimes/mlflow/mlserver_mlflow/metadata.py b/runtimes/mlflow/mlserver_mlflow/metadata.py index fc1926b28..db0bab097 100644 --- a/runtimes/mlflow/mlserver_mlflow/metadata.py +++ b/runtimes/mlflow/mlserver_mlflow/metadata.py @@ -36,18 +36,22 @@ def _get_shape(input_spec: InputSpec) -> List[int]: return [-1] -def to_metadata_tensor(input_spec: InputSpec) -> MetadataTensor: - # TODO: Can input_spec.name be None? - datatype, content_type = _get_content_type(input_spec) - shape = _get_shape(input_spec) +def to_metadata_tensors(schema: Schema, prefix="input-") -> List[MetadataTensor]: + metadata_tensors = [] - return MetadataTensor( - name=input_spec.name, - datatype=datatype, - shape=shape, - tags=Tags(content_type=content_type), - ) + for idx, input_spec in enumerate(schema.inputs): + datatype, content_type = _get_content_type(input_spec) + shape = _get_shape(input_spec) + name = input_spec.name if input_spec.name else f"{prefix}{idx}" -def to_metadata(schema: Schema) -> List[MetadataTensor]: - return [to_metadata_tensor(schema_input) for schema_input in schema.inputs] + metadata_tensors.append( + MetadataTensor( + name=name, + datatype=datatype, + shape=shape, + tags=Tags(content_type=content_type), + ) + ) + + return metadata_tensors diff --git a/runtimes/mlflow/tests/test_metadata.py b/runtimes/mlflow/tests/test_metadata.py index 1c5eef152..b49f4cb6f 100644 --- a/runtimes/mlflow/tests/test_metadata.py +++ b/runtimes/mlflow/tests/test_metadata.py @@ -3,15 +3,15 @@ from typing import Tuple, List -from mlflow.types.schema import ColSpec, TensorSpec, DataType +from mlflow.types.schema import ColSpec, TensorSpec, DataType, Schema from mlserver.codecs import NumpyCodec, StringCodec, Base64Codec -from mlserver.types import Tags +from mlserver.types import Tags, MetadataTensor from mlserver_mlflow.metadata import ( InputSpec, _get_content_type, _get_shape, - to_metadata_tensor, + to_metadata_tensors, ) @@ -55,11 +55,58 @@ def test_get_shape(input_spec: InputSpec, expected: List[int]): assert shape == expected -def test_to_metadata_tensor(): - input_spec = TensorSpec(name="foo", shape=(2, 2), type=np.dtype("int32")) - metadata_tensor = to_metadata_tensor(input_spec) +@pytest.mark.parametrize( + "schema, expected", + [ + ( + Schema( + inputs=[TensorSpec(name="foo", shape=(2, 2), type=np.dtype("int32"))] + ), + [ + MetadataTensor( + name="foo", + datatype="INT32", + shape=[2, 2], + tags=Tags(content_type=NumpyCodec.ContentType), + ) + ], + ), + ( + Schema(inputs=[TensorSpec(shape=(2, 2), type=np.dtype("int32"))]), + [ + MetadataTensor( + name="input-0", + datatype="INT32", + shape=[2, 2], + tags=Tags(content_type=NumpyCodec.ContentType), + ) + ], + ), + ( + Schema( + inputs=[ + ColSpec(type=DataType.string), + ColSpec(type=DataType.integer), + ] + ), + [ + MetadataTensor( + name="input-0", + datatype="BYTES", + shape=[-1], + tags=Tags(content_type=StringCodec.ContentType), + ), + MetadataTensor( + name="input-1", + datatype="INT32", + shape=[-1], + tags=Tags(content_type=NumpyCodec.ContentType), + ), + ], + ), + ], +) +def test_to_metadata_tensors(schema: Schema, expected: List[MetadataTensor]): + metadata_tensors = to_metadata_tensors(schema) - assert metadata_tensor.name == input_spec.name - assert metadata_tensor.datatype == "INT32" - assert metadata_tensor.shape == list(input_spec.shape) - assert metadata_tensor.tags == Tags(content_type=NumpyCodec.ContentType) + assert metadata_tensors == expected From 63c0142ad697cac556335e6dde98835b45da700a Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Tue, 24 Aug 2021 16:47:20 +0200 Subject: [PATCH 13/28] Fix tests after adding model schema --- runtimes/mlflow/mlserver_mlflow/metadata.py | 28 ++++++++++++++-- runtimes/mlflow/mlserver_mlflow/runtime.py | 9 ++++- runtimes/mlflow/tests/conftest.py | 7 +++- runtimes/mlflow/tests/test_metadata.py | 33 +++++++++++++++++++ runtimes/mlflow/tests/test_runtime.py | 21 ++++++++---- .../tests/testdata/inference-request.json | 4 +-- 6 files changed, 90 insertions(+), 12 deletions(-) diff --git a/runtimes/mlflow/mlserver_mlflow/metadata.py b/runtimes/mlflow/mlserver_mlflow/metadata.py index db0bab097..4b84b5513 100644 --- a/runtimes/mlflow/mlserver_mlflow/metadata.py +++ b/runtimes/mlflow/mlserver_mlflow/metadata.py @@ -1,12 +1,18 @@ from typing import Union, Tuple, List from mlflow.types.schema import Schema, ColSpec, TensorSpec, DataType -from mlserver.types import MetadataTensor, Tags +from mlflow.models.signature import ModelSignature + +from mlserver.settings import ModelSettings +from mlserver.types import MetadataModelResponse, MetadataTensor, Tags from mlserver.codecs import NumpyCodec, StringCodec, Base64Codec, DatetimeCodec from mlserver.codecs.numpy import to_datatype InputSpec = Union[ColSpec, TensorSpec] +InputDefaultPrefix = "input-" +OutputDefaultPrefix = "output-" + _MLflowToContentType = { DataType.boolean: ("BOOL", NumpyCodec.ContentType), DataType.integer: ("INT32", NumpyCodec.ContentType), @@ -36,7 +42,9 @@ def _get_shape(input_spec: InputSpec) -> List[int]: return [-1] -def to_metadata_tensors(schema: Schema, prefix="input-") -> List[MetadataTensor]: +def to_metadata_tensors( + schema: Schema, prefix=InputDefaultPrefix +) -> List[MetadataTensor]: metadata_tensors = [] for idx, input_spec in enumerate(schema.inputs): @@ -55,3 +63,19 @@ def to_metadata_tensors(schema: Schema, prefix="input-") -> List[MetadataTensor] ) return metadata_tensors + + +def to_metadata( + signature: ModelSignature, model_settings: ModelSettings +) -> MetadataModelResponse: + # TODO: Merge lists with existing metadata (if any) [how?] + inputs = to_metadata_tensors(signature.inputs, prefix=InputDefaultPrefix) + outputs = to_metadata_tensors(signature.outputs, prefix=OutputDefaultPrefix) + + return MetadataModelResponse( + name=model_settings.name, + platform=model_settings.platform, + versions=model_settings.versions, + inputs=inputs, + outputs=outputs, + ) diff --git a/runtimes/mlflow/mlserver_mlflow/runtime.py b/runtimes/mlflow/mlserver_mlflow/runtime.py index 93328a96d..d7c04ac35 100644 --- a/runtimes/mlflow/mlserver_mlflow/runtime.py +++ b/runtimes/mlflow/mlserver_mlflow/runtime.py @@ -18,13 +18,14 @@ predictions_to_json, ) -from mlserver.types import InferenceRequest, InferenceResponse +from mlserver.types import InferenceRequest, InferenceResponse, MetadataModelResponse from mlserver.model import MLModel from mlserver.utils import get_model_uri from mlserver.handlers import custom_handler from mlserver.errors import InferenceError from .encoding import to_outputs +from .metadata import to_metadata class MLflowRuntime(MLModel): @@ -90,6 +91,12 @@ async def invocations(self, request: Request) -> Response: predictions_to_json(raw_predictions, result) return Response(content=result.getvalue(), media_type="application/json") + async def metadata(self) -> MetadataModelResponse: + signature = self._model.metadata.signature + + # NOTE: Signature can be None + return to_metadata(signature, self._settings) + async def load(self) -> bool: # TODO: Log info message model_uri = await get_model_uri(self._settings) diff --git a/runtimes/mlflow/tests/conftest.py b/runtimes/mlflow/tests/conftest.py index fab3070b8..6655eb0cf 100644 --- a/runtimes/mlflow/tests/conftest.py +++ b/runtimes/mlflow/tests/conftest.py @@ -34,7 +34,12 @@ def dataset() -> tuple: @pytest.fixture def model_signature(dataset: tuple) -> ModelSignature: X, y = dataset - return infer_signature(X, y) + signature = infer_signature(X, y) + + signature.inputs.inputs[0]._name = "foo" + signature.outputs.inputs[0]._name = "bar" + + return signature @pytest.fixture diff --git a/runtimes/mlflow/tests/test_metadata.py b/runtimes/mlflow/tests/test_metadata.py index b49f4cb6f..e6983405d 100644 --- a/runtimes/mlflow/tests/test_metadata.py +++ b/runtimes/mlflow/tests/test_metadata.py @@ -3,15 +3,20 @@ from typing import Tuple, List +from mlflow.models.signature import ModelSignature from mlflow.types.schema import ColSpec, TensorSpec, DataType, Schema from mlserver.codecs import NumpyCodec, StringCodec, Base64Codec from mlserver.types import Tags, MetadataTensor +from mlserver.settings import ModelSettings from mlserver_mlflow.metadata import ( InputSpec, + InputDefaultPrefix, + OutputDefaultPrefix, _get_content_type, _get_shape, to_metadata_tensors, + to_metadata, ) @@ -110,3 +115,31 @@ def test_to_metadata_tensors(schema: Schema, expected: List[MetadataTensor]): metadata_tensors = to_metadata_tensors(schema) assert metadata_tensors == expected + + +def test_metadata(model_signature: ModelSignature, model_settings: ModelSettings): + metadata = to_metadata(model_signature, model_settings) + + assert metadata.name == model_settings.name + assert metadata.versions == model_settings.versions + assert metadata.platform == model_settings.platform + + assert metadata.inputs is not None + assert len(model_signature.inputs.inputs) == len(metadata.inputs) + for idx, met in enumerate(metadata.inputs): + sig = model_signature.inputs.inputs[idx] + + if sig.name is None: + assert met.name == f"{InputDefaultPrefix}{idx}" + else: + assert met.name == sig.name + + assert metadata.outputs is not None + assert len(model_signature.outputs.inputs) == len(metadata.outputs) + for idx, met in enumerate(metadata.outputs): + sig = model_signature.outputs.inputs[idx] + + if sig.name is None: + assert met.name == f"{OutputDefaultPrefix}{idx}" + else: + assert met.name == sig.name diff --git a/runtimes/mlflow/tests/test_runtime.py b/runtimes/mlflow/tests/test_runtime.py index dde7d2727..83e04e04f 100644 --- a/runtimes/mlflow/tests/test_runtime.py +++ b/runtimes/mlflow/tests/test_runtime.py @@ -1,10 +1,12 @@ import numpy as np -from mlflow.pyfunc import PyFuncModel -from mlserver_mlflow import MLflowRuntime -from mlserver_mlflow.encoding import DefaultOutputName from mlserver.codecs import NumpyCodec from mlserver.types import InferenceRequest, Parameters, RequestInput +from mlflow.pyfunc import PyFuncModel +from mlflow.models.signature import ModelSignature + +from mlserver_mlflow import MLflowRuntime +from mlserver_mlflow.encoding import DefaultOutputName def test_load(runtime: MLflowRuntime): @@ -44,8 +46,15 @@ async def test_predict_pytorch(runtime_pytorch: MLflowRuntime): assert outputs[0].name == DefaultOutputName -async def test_metadata(runtime: MLflowRuntime): +async def test_metadata(runtime: MLflowRuntime, model_signature: ModelSignature): metadata = await runtime.metadata() - breakpoint() - assert metadata is not None + assert metadata.name == runtime.name + assert metadata.versions == runtime._settings.versions + assert metadata.platform == runtime._settings.platform + + assert metadata.inputs is not None + assert len(model_signature.inputs.inputs) == len(metadata.inputs) + + assert metadata.outputs is not None + assert len(model_signature.outputs.inputs) == len(metadata.outputs) diff --git a/runtimes/mlflow/tests/testdata/inference-request.json b/runtimes/mlflow/tests/testdata/inference-request.json index 082279ca2..4d326c2ea 100644 --- a/runtimes/mlflow/tests/testdata/inference-request.json +++ b/runtimes/mlflow/tests/testdata/inference-request.json @@ -1,9 +1,9 @@ { "inputs": [ { - "name": "input-0", + "name": "foo", "shape": [3], - "datatype": "INT32", + "datatype": "FP64", "data": [1, 2, 3], "parameters": { "content_type": "np" From 960cab635734835c0680b4e46e4a3fc609f2cda4 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Tue, 24 Aug 2021 18:12:55 +0200 Subject: [PATCH 14/28] Update metadata indices after changing inputs and outputs --- mlserver/model.py | 39 +++++++++++++++++-- runtimes/mlflow/mlserver_mlflow/metadata.py | 10 ++--- runtimes/mlflow/mlserver_mlflow/runtime.py | 23 +++++++---- runtimes/mlflow/tests/test_metadata.py | 8 ++-- .../tests/testdata/inference-request.json | 5 +-- 5 files changed, 61 insertions(+), 24 deletions(-) diff --git a/mlserver/model.py b/mlserver/model.py index 3d3d21922..54eb55e95 100644 --- a/mlserver/model.py +++ b/mlserver/model.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, List from .types import ( InferenceRequest, @@ -17,6 +17,20 @@ ) +def _generate_metadata_index( + metadata_tensors: Optional[List[MetadataTensor]], +) -> Dict[str, MetadataTensor]: + metadata_index = {} + + if not metadata_tensors: + return metadata_index + + for metadata_tensor in metadata_tensors: + metadata_index[metadata_tensor.name] = metadata_tensor + + return metadata_index + + class MLModel: """ Abstract class which serves as the main interface to interact with ML @@ -27,9 +41,8 @@ def __init__(self, settings: ModelSettings): self._settings = settings self._inputs_index: Dict[str, MetadataTensor] = {} - if self._settings.inputs: - for request_input in self._settings.inputs: - self._inputs_index[request_input.name] = request_input + self._inputs_index = _generate_metadata_index(self._settings.inputs) + self._outputs_index = _generate_metadata_index(self._settings.outputs) self.ready = False @@ -48,6 +61,24 @@ def version(self) -> Optional[str]: def settings(self) -> ModelSettings: return self._settings + @property + def inputs(self) -> Optional[List[MetadataTensor]]: + return self._settings.inputs + + @inputs.setter + def inputs(self, value: List[MetadataTensor]): + self._settings.inputs = value + self._inputs_index = _generate_metadata_index(self._settings.inputs) + + @property + def outputs(self) -> Optional[List[MetadataTensor]]: + return self._settings.inputs + + @outputs.setter + def outputs(self, value: List[MetadataTensor]): + self._settings.outputs = value + self._outputs_index = _generate_metadata_index(self._settings.outputs) + def decode( self, request_input: RequestInput, default_codec: Optional[InputCodec] = None ) -> Any: diff --git a/runtimes/mlflow/mlserver_mlflow/metadata.py b/runtimes/mlflow/mlserver_mlflow/metadata.py index 4b84b5513..b0929de22 100644 --- a/runtimes/mlflow/mlserver_mlflow/metadata.py +++ b/runtimes/mlflow/mlserver_mlflow/metadata.py @@ -10,8 +10,8 @@ InputSpec = Union[ColSpec, TensorSpec] -InputDefaultPrefix = "input-" -OutputDefaultPrefix = "output-" +DefaultInputPrefix = "input-" +DefaultOutputPrefix = "output-" _MLflowToContentType = { DataType.boolean: ("BOOL", NumpyCodec.ContentType), @@ -43,7 +43,7 @@ def _get_shape(input_spec: InputSpec) -> List[int]: def to_metadata_tensors( - schema: Schema, prefix=InputDefaultPrefix + schema: Schema, prefix=DefaultInputPrefix ) -> List[MetadataTensor]: metadata_tensors = [] @@ -69,8 +69,8 @@ def to_metadata( signature: ModelSignature, model_settings: ModelSettings ) -> MetadataModelResponse: # TODO: Merge lists with existing metadata (if any) [how?] - inputs = to_metadata_tensors(signature.inputs, prefix=InputDefaultPrefix) - outputs = to_metadata_tensors(signature.outputs, prefix=OutputDefaultPrefix) + inputs = to_metadata_tensors(signature.inputs, prefix=DefaultInputPrefix) + outputs = to_metadata_tensors(signature.outputs, prefix=DefaultOutputPrefix) return MetadataModelResponse( name=model_settings.name, diff --git a/runtimes/mlflow/mlserver_mlflow/runtime.py b/runtimes/mlflow/mlserver_mlflow/runtime.py index d7c04ac35..cea4837c6 100644 --- a/runtimes/mlflow/mlserver_mlflow/runtime.py +++ b/runtimes/mlflow/mlserver_mlflow/runtime.py @@ -25,7 +25,7 @@ from mlserver.errors import InferenceError from .encoding import to_outputs -from .metadata import to_metadata +from .metadata import to_metadata_tensors, DefaultInputPrefix, DefaultOutputPrefix class MLflowRuntime(MLModel): @@ -91,21 +91,30 @@ async def invocations(self, request: Request) -> Response: predictions_to_json(raw_predictions, result) return Response(content=result.getvalue(), media_type="application/json") - async def metadata(self) -> MetadataModelResponse: - signature = self._model.metadata.signature - - # NOTE: Signature can be None - return to_metadata(signature, self._settings) - async def load(self) -> bool: # TODO: Log info message model_uri = await get_model_uri(self._settings) self._model = mlflow.pyfunc.load_model(model_uri) + self._input_schema = self._model.metadata.get_input_schema() + self._signature = self._model.metadata.signature + self._sync_metadata() self.ready = True return self.ready + def _sync_metadata(self): + # Update metadata from model signature (if present) + if self._signature is None: + return + + self.inputs = to_metadata_tensors( + self._signature.inputs, prefix=DefaultInputPrefix + ) + self.outputs = to_metadata_tensors( + self._signature.outputs, prefix=DefaultOutputPrefix + ) + async def predict(self, payload: InferenceRequest) -> InferenceResponse: decoded_payload = self.decode_request(payload) diff --git a/runtimes/mlflow/tests/test_metadata.py b/runtimes/mlflow/tests/test_metadata.py index e6983405d..f0d3511cc 100644 --- a/runtimes/mlflow/tests/test_metadata.py +++ b/runtimes/mlflow/tests/test_metadata.py @@ -11,8 +11,8 @@ from mlserver_mlflow.metadata import ( InputSpec, - InputDefaultPrefix, - OutputDefaultPrefix, + DefaultInputPrefix, + DefaultOutputPrefix, _get_content_type, _get_shape, to_metadata_tensors, @@ -130,7 +130,7 @@ def test_metadata(model_signature: ModelSignature, model_settings: ModelSettings sig = model_signature.inputs.inputs[idx] if sig.name is None: - assert met.name == f"{InputDefaultPrefix}{idx}" + assert met.name == f"{DefaultInputPrefix}{idx}" else: assert met.name == sig.name @@ -140,6 +140,6 @@ def test_metadata(model_signature: ModelSignature, model_settings: ModelSettings sig = model_signature.outputs.inputs[idx] if sig.name is None: - assert met.name == f"{OutputDefaultPrefix}{idx}" + assert met.name == f"{DefaultOutputPrefix}{idx}" else: assert met.name == sig.name diff --git a/runtimes/mlflow/tests/testdata/inference-request.json b/runtimes/mlflow/tests/testdata/inference-request.json index 4d326c2ea..cdc488bd2 100644 --- a/runtimes/mlflow/tests/testdata/inference-request.json +++ b/runtimes/mlflow/tests/testdata/inference-request.json @@ -4,10 +4,7 @@ "name": "foo", "shape": [3], "datatype": "FP64", - "data": [1, 2, 3], - "parameters": { - "content_type": "np" - } + "data": [1, 2, 3] } ], "parameters": { From 49eff63e5cde693958de0fc32afaf8bebe2db4bf Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Wed, 25 Aug 2021 11:38:49 +0200 Subject: [PATCH 15/28] Remvoe import --- runtimes/mlflow/mlserver_mlflow/runtime.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtimes/mlflow/mlserver_mlflow/runtime.py b/runtimes/mlflow/mlserver_mlflow/runtime.py index cea4837c6..f4b9f3fbf 100644 --- a/runtimes/mlflow/mlserver_mlflow/runtime.py +++ b/runtimes/mlflow/mlserver_mlflow/runtime.py @@ -18,7 +18,7 @@ predictions_to_json, ) -from mlserver.types import InferenceRequest, InferenceResponse, MetadataModelResponse +from mlserver.types import InferenceRequest, InferenceResponse from mlserver.model import MLModel from mlserver.utils import get_model_uri from mlserver.handlers import custom_handler From 9c947aa4d4e2c5794315d80118766e14ab886874 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Wed, 25 Aug 2021 12:07:47 +0200 Subject: [PATCH 16/28] Add tests to ensure content types are compatible with MLflow's datatypes --- runtimes/mlflow/tests/test_metadata.py | 76 +++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/runtimes/mlflow/tests/test_metadata.py b/runtimes/mlflow/tests/test_metadata.py index f0d3511cc..6d2514170 100644 --- a/runtimes/mlflow/tests/test_metadata.py +++ b/runtimes/mlflow/tests/test_metadata.py @@ -5,8 +5,22 @@ from mlflow.models.signature import ModelSignature from mlflow.types.schema import ColSpec, TensorSpec, DataType, Schema -from mlserver.codecs import NumpyCodec, StringCodec, Base64Codec -from mlserver.types import Tags, MetadataTensor +from mlflow.pyfunc import _enforce_schema +from mlserver.codecs import ( + NumpyCodec, + StringCodec, + Base64Codec, + PandasCodec, + DatetimeCodec, + decode_inference_request, +) +from mlserver.types import ( + Tags, + MetadataTensor, + RequestInput, + InferenceRequest, + Parameters, +) from mlserver.settings import ModelSettings from mlserver_mlflow.metadata import ( @@ -117,6 +131,64 @@ def test_to_metadata_tensors(schema: Schema, expected: List[MetadataTensor]): assert metadata_tensors == expected +@pytest.mark.parametrize( + "tensor_spec, request_input", + [ + ( + ColSpec(name="foo", type=DataType.boolean), + RequestInput( + name="foo", + datatype="BOOL", + parameters=Parameters(content_type=NumpyCodec.ContentType), + shape=[2], + data=[True, False], + ), + ), + ( + ColSpec(name="foo", type=DataType.string), + RequestInput( + name="foo", + datatype="BYTES", + parameters=Parameters(content_type=StringCodec.ContentType), + shape=[2, 11], + data=b"hello worldhello world", + ), + ), + ( + ColSpec(name="foo", type=DataType.binary), + RequestInput( + name="foo", + datatype="BYTES", + parameters=Parameters(content_type=Base64Codec.ContentType), + shape=[1, 20], + data=b"UHl0aG9uIGlzIGZ1bg==", + ), + ), + ( + ColSpec(name="foo", type=DataType.datetime), + RequestInput( + name="foo", + datatype="BYTES", + parameters=Parameters(content_type=DatetimeCodec.ContentType), + shape=[1, 19], + data=b"2021-08-24T15:01:19", + ), + ), + ], +) +def test_content_types(tensor_spec: TensorSpec, request_input: RequestInput): + input_schema = Schema(inputs=[tensor_spec]) + + inference_request = InferenceRequest( + parameters=Parameters(content_type=PandasCodec.ContentType), + inputs=[request_input], + ) + data = decode_inference_request(inference_request) + + # _enforce_schema will raise if something fails + _enforce_schema(data, input_schema) + + def test_metadata(model_signature: ModelSignature, model_settings: ModelSettings): metadata = to_metadata(model_signature, model_settings) From a1dbadd987f19c7715039ea884b65c0d486b4b26 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Wed, 25 Aug 2021 12:08:11 +0200 Subject: [PATCH 17/28] Add default values to codec utils --- mlserver/codecs/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlserver/codecs/utils.py b/mlserver/codecs/utils.py index 38493b3fc..1dc9c2a43 100644 --- a/mlserver/codecs/utils.py +++ b/mlserver/codecs/utils.py @@ -42,7 +42,7 @@ def _save_decoded(parametrised_obj: Parametrised, decoded_payload: Any): def decode_request_input( request_input: RequestInput, - metadata_inputs: Dict[str, MetadataTensor], + metadata_inputs: Dict[str, MetadataTensor] = {}, ) -> Optional[Any]: input_metadata = metadata_inputs.get(request_input.name) content_type = _get_content_type(request_input, input_metadata) @@ -59,7 +59,7 @@ def decode_request_input( def decode_inference_request( - inference_request: InferenceRequest, metadata_inputs: Dict[str, MetadataTensor] + inference_request: InferenceRequest, metadata_inputs: Dict[str, MetadataTensor] = {} ) -> Optional[Any]: for request_input in inference_request.inputs: decode_request_input(request_input, metadata_inputs) From 645cb199d69dcb472c4934d1efc570ae821fcc22 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Wed, 25 Aug 2021 12:11:13 +0200 Subject: [PATCH 18/28] Fix linter --- mlserver/codecs/pack.py | 4 ++-- mlserver/codecs/string.py | 2 +- mlserver/model.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mlserver/codecs/pack.py b/mlserver/codecs/pack.py index 4133d8bb2..f18ec80b4 100644 --- a/mlserver/codecs/pack.py +++ b/mlserver/codecs/pack.py @@ -1,4 +1,4 @@ -from typing import Generator, Union, List, Tuple +from typing import Generator, Union, Iterable, List, Tuple PackElement = Union[bytes, str] @@ -23,7 +23,7 @@ def unpack( yield packed[i : i + common_length] -def pack(unpacked: List[bytes]) -> Tuple[PackedPayload, List[int]]: +def pack(unpacked: Iterable[bytes]) -> Tuple[PackedPayload, List[int]]: packed = b"" common_length = -1 N = 0 diff --git a/mlserver/codecs/string.py b/mlserver/codecs/string.py index 9ada67eb5..201fc0ccc 100644 --- a/mlserver/codecs/string.py +++ b/mlserver/codecs/string.py @@ -1,4 +1,4 @@ -from typing import Callable, Union, List +from typing import List from ..types import RequestInput, ResponseOutput diff --git a/mlserver/model.py b/mlserver/model.py index 54eb55e95..60d428688 100644 --- a/mlserver/model.py +++ b/mlserver/model.py @@ -20,7 +20,7 @@ def _generate_metadata_index( metadata_tensors: Optional[List[MetadataTensor]], ) -> Dict[str, MetadataTensor]: - metadata_index = {} + metadata_index: Dict[str, MetadataTensor] = {} if not metadata_tensors: return metadata_index From 0500cd93d5fda2b0370d523c82d4ba06eb8ba02e Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Wed, 25 Aug 2021 12:21:23 +0200 Subject: [PATCH 19/28] Fix linter after rebase --- runtimes/mlflow/tests/test_encoding.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/runtimes/mlflow/tests/test_encoding.py b/runtimes/mlflow/tests/test_encoding.py index 894fca076..23171df52 100644 --- a/runtimes/mlflow/tests/test_encoding.py +++ b/runtimes/mlflow/tests/test_encoding.py @@ -10,8 +10,6 @@ _convert_to_tensor_data_if_raw, ) -from mlserver.codecs.numpy import _to_datatype - @pytest.mark.parametrize( "mlflow_payload", From fcdc09cfd4e52a419bf7287b785ca984ee829597 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Wed, 25 Aug 2021 12:29:56 +0200 Subject: [PATCH 20/28] Fix mlflow tests after adding model signature --- runtimes/mlflow/tests/rest/test_invocations.py | 9 ++++++--- runtimes/mlflow/tests/test_codecs.py | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/runtimes/mlflow/tests/rest/test_invocations.py b/runtimes/mlflow/tests/rest/test_invocations.py index 9077b9b69..e38887d18 100644 --- a/runtimes/mlflow/tests/rest/test_invocations.py +++ b/runtimes/mlflow/tests/rest/test_invocations.py @@ -13,8 +13,11 @@ def test_invocations_invalid_content_type(rest_client, content_type: str): @pytest.mark.parametrize( "content_type, payload", [ - ("application/json", {"columns": ["a"], "data": [1, 2, 3]}), - ("application/json; format=pandas-records", [{"a": 1}, {"a": 2}, {"a": 3}]), + ("application/json", {"columns": ["foo"], "data": [1, 2, 3]}), + ( + "application/json; format=pandas-records", + [{"foo": 1}, {"foo": 2}, {"foo": 3}], + ), ("application/json", {"instances": [1, 2, 3]}), ("application/json", {"inputs": [1, 2, 3]}), ], @@ -28,4 +31,4 @@ def test_invocations(rest_client, content_type: str, payload: Union[list, dict]) y_pred = response.json() assert isinstance(y_pred, list) - assert len(y_pred) == 3 + assert len(y_pred) == 1 diff --git a/runtimes/mlflow/tests/test_codecs.py b/runtimes/mlflow/tests/test_codecs.py index 9ebf5da85..6ed5a0558 100644 --- a/runtimes/mlflow/tests/test_codecs.py +++ b/runtimes/mlflow/tests/test_codecs.py @@ -8,7 +8,7 @@ def test_decode(inference_request: InferenceRequest): codec = TensorDictCodec() tensor_dict = codec.decode(inference_request) - expected_dict = {"input-0": np.array([1, 2, 3], dtype=np.int32)} + expected_dict = {"foo": np.array([1, 2, 3], dtype=np.int32)} assert tensor_dict.keys() == expected_dict.keys() for key, val in tensor_dict.items(): From 400aa5dfaf11f8c692f664b69c5435ea8ef1fcef Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Wed, 25 Aug 2021 12:52:17 +0200 Subject: [PATCH 21/28] Fix linter --- Makefile | 2 +- mlserver/grpc/dataplane_pb2.py | 3311 +++++++++++++++++---------- mlserver/grpc/dataplane_pb2.pyi | 790 ++++--- mlserver/grpc/dataplane_pb2_grpc.py | 371 +-- 4 files changed, 2814 insertions(+), 1660 deletions(-) diff --git a/Makefile b/Makefile index 4d95ec799..b51a7ae0d 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ licenses: fmt: black . \ - --exclude "(mlserver/grpc/dataplane_pb2*)" + --exclude "(\.tox | mlserver/grpc/dataplane_pb2*)" version: @echo ${VERSION} diff --git a/mlserver/grpc/dataplane_pb2.py b/mlserver/grpc/dataplane_pb2.py index 50cfb3f4a..e97e76bae 100644 --- a/mlserver/grpc/dataplane_pb2.py +++ b/mlserver/grpc/dataplane_pb2.py @@ -6,1254 +6,2090 @@ from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database + # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() - - DESCRIPTOR = _descriptor.FileDescriptor( - name='dataplane.proto', - package='inference', - syntax='proto3', - serialized_options=None, - create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x0f\x64\x61taplane.proto\x12\tinference\"\x13\n\x11ServerLiveRequest\"\"\n\x12ServerLiveResponse\x12\x0c\n\x04live\x18\x01 \x01(\x08\"\x14\n\x12ServerReadyRequest\"$\n\x13ServerReadyResponse\x12\r\n\x05ready\x18\x01 \x01(\x08\"2\n\x11ModelReadyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\"#\n\x12ModelReadyResponse\x12\r\n\x05ready\x18\x01 \x01(\x08\"\x17\n\x15ServerMetadataRequest\"K\n\x16ServerMetadataResponse\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\x12\x12\n\nextensions\x18\x03 \x03(\t\"5\n\x14ModelMetadataRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\"\x9f\x03\n\x15ModelMetadataResponse\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08versions\x18\x02 \x03(\t\x12\x10\n\x08platform\x18\x03 \x01(\t\x12?\n\x06inputs\x18\x04 \x03(\x0b\x32/.inference.ModelMetadataResponse.TensorMetadata\x12@\n\x07outputs\x18\x05 \x03(\x0b\x32/.inference.ModelMetadataResponse.TensorMetadata\x1a\xd0\x01\n\x0eTensorMetadata\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08\x64\x61tatype\x18\x02 \x01(\t\x12\r\n\x05shape\x18\x03 \x03(\x03\x12G\n\x04tags\x18\x04 \x03(\x0b\x32\x39.inference.ModelMetadataResponse.TensorMetadata.TagsEntry\x1a\x46\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.inference.InferParameter:\x02\x38\x01\"\xd2\x06\n\x11ModelInferRequest\x12\x12\n\nmodel_name\x18\x01 \x01(\t\x12\x15\n\rmodel_version\x18\x02 \x01(\t\x12\n\n\x02id\x18\x03 \x01(\t\x12@\n\nparameters\x18\x04 \x03(\x0b\x32,.inference.ModelInferRequest.ParametersEntry\x12=\n\x06inputs\x18\x05 \x03(\x0b\x32-.inference.ModelInferRequest.InferInputTensor\x12H\n\x07outputs\x18\x06 \x03(\x0b\x32\x37.inference.ModelInferRequest.InferRequestedOutputTensor\x1a\x94\x02\n\x10InferInputTensor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08\x64\x61tatype\x18\x02 \x01(\t\x12\r\n\x05shape\x18\x03 \x03(\x03\x12Q\n\nparameters\x18\x04 \x03(\x0b\x32=.inference.ModelInferRequest.InferInputTensor.ParametersEntry\x12\x30\n\x08\x63ontents\x18\x05 \x01(\x0b\x32\x1e.inference.InferTensorContents\x1aL\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.inference.InferParameter:\x02\x38\x01\x1a\xd5\x01\n\x1aInferRequestedOutputTensor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12[\n\nparameters\x18\x02 \x03(\x0b\x32G.inference.ModelInferRequest.InferRequestedOutputTensor.ParametersEntry\x1aL\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.inference.InferParameter:\x02\x38\x01\x1aL\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.inference.InferParameter:\x02\x38\x01\"\xb8\x04\n\x12ModelInferResponse\x12\x12\n\nmodel_name\x18\x01 \x01(\t\x12\x15\n\rmodel_version\x18\x02 \x01(\t\x12\n\n\x02id\x18\x03 \x01(\t\x12\x41\n\nparameters\x18\x04 \x03(\x0b\x32-.inference.ModelInferResponse.ParametersEntry\x12@\n\x07outputs\x18\x05 \x03(\x0b\x32/.inference.ModelInferResponse.InferOutputTensor\x1a\x97\x02\n\x11InferOutputTensor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08\x64\x61tatype\x18\x02 \x01(\t\x12\r\n\x05shape\x18\x03 \x03(\x03\x12S\n\nparameters\x18\x04 \x03(\x0b\x32?.inference.ModelInferResponse.InferOutputTensor.ParametersEntry\x12\x30\n\x08\x63ontents\x18\x05 \x01(\x0b\x32\x1e.inference.InferTensorContents\x1aL\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.inference.InferParameter:\x02\x38\x01\x1aL\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.inference.InferParameter:\x02\x38\x01\"i\n\x0eInferParameter\x12\x14\n\nbool_param\x18\x01 \x01(\x08H\x00\x12\x15\n\x0bint64_param\x18\x02 \x01(\x03H\x00\x12\x16\n\x0cstring_param\x18\x03 \x01(\tH\x00\x42\x12\n\x10parameter_choice\"\xd0\x01\n\x13InferTensorContents\x12\x15\n\rbool_contents\x18\x01 \x03(\x08\x12\x14\n\x0cint_contents\x18\x02 \x03(\x05\x12\x16\n\x0eint64_contents\x18\x03 \x03(\x03\x12\x15\n\ruint_contents\x18\x04 \x03(\r\x12\x17\n\x0fuint64_contents\x18\x05 \x03(\x04\x12\x15\n\rfp32_contents\x18\x06 \x03(\x02\x12\x15\n\rfp64_contents\x18\x07 \x03(\x01\x12\x16\n\x0e\x62ytes_contents\x18\x08 \x03(\x0c\x32\xfc\x03\n\x14GRPCInferenceService\x12K\n\nServerLive\x12\x1c.inference.ServerLiveRequest\x1a\x1d.inference.ServerLiveResponse\"\x00\x12N\n\x0bServerReady\x12\x1d.inference.ServerReadyRequest\x1a\x1e.inference.ServerReadyResponse\"\x00\x12K\n\nModelReady\x12\x1c.inference.ModelReadyRequest\x1a\x1d.inference.ModelReadyResponse\"\x00\x12W\n\x0eServerMetadata\x12 .inference.ServerMetadataRequest\x1a!.inference.ServerMetadataResponse\"\x00\x12T\n\rModelMetadata\x12\x1f.inference.ModelMetadataRequest\x1a .inference.ModelMetadataResponse\"\x00\x12K\n\nModelInfer\x12\x1c.inference.ModelInferRequest\x1a\x1d.inference.ModelInferResponse\"\x00\x62\x06proto3' + name="dataplane.proto", + package="inference", + syntax="proto3", + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x0f\x64\x61taplane.proto\x12\tinference"\x13\n\x11ServerLiveRequest""\n\x12ServerLiveResponse\x12\x0c\n\x04live\x18\x01 \x01(\x08"\x14\n\x12ServerReadyRequest"$\n\x13ServerReadyResponse\x12\r\n\x05ready\x18\x01 \x01(\x08"2\n\x11ModelReadyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t"#\n\x12ModelReadyResponse\x12\r\n\x05ready\x18\x01 \x01(\x08"\x17\n\x15ServerMetadataRequest"K\n\x16ServerMetadataResponse\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\x12\x12\n\nextensions\x18\x03 \x03(\t"5\n\x14ModelMetadataRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t"\x9f\x03\n\x15ModelMetadataResponse\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08versions\x18\x02 \x03(\t\x12\x10\n\x08platform\x18\x03 \x01(\t\x12?\n\x06inputs\x18\x04 \x03(\x0b\x32/.inference.ModelMetadataResponse.TensorMetadata\x12@\n\x07outputs\x18\x05 \x03(\x0b\x32/.inference.ModelMetadataResponse.TensorMetadata\x1a\xd0\x01\n\x0eTensorMetadata\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08\x64\x61tatype\x18\x02 \x01(\t\x12\r\n\x05shape\x18\x03 \x03(\x03\x12G\n\x04tags\x18\x04 \x03(\x0b\x32\x39.inference.ModelMetadataResponse.TensorMetadata.TagsEntry\x1a\x46\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.inference.InferParameter:\x02\x38\x01"\xd2\x06\n\x11ModelInferRequest\x12\x12\n\nmodel_name\x18\x01 \x01(\t\x12\x15\n\rmodel_version\x18\x02 \x01(\t\x12\n\n\x02id\x18\x03 \x01(\t\x12@\n\nparameters\x18\x04 \x03(\x0b\x32,.inference.ModelInferRequest.ParametersEntry\x12=\n\x06inputs\x18\x05 \x03(\x0b\x32-.inference.ModelInferRequest.InferInputTensor\x12H\n\x07outputs\x18\x06 \x03(\x0b\x32\x37.inference.ModelInferRequest.InferRequestedOutputTensor\x1a\x94\x02\n\x10InferInputTensor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08\x64\x61tatype\x18\x02 \x01(\t\x12\r\n\x05shape\x18\x03 \x03(\x03\x12Q\n\nparameters\x18\x04 \x03(\x0b\x32=.inference.ModelInferRequest.InferInputTensor.ParametersEntry\x12\x30\n\x08\x63ontents\x18\x05 \x01(\x0b\x32\x1e.inference.InferTensorContents\x1aL\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.inference.InferParameter:\x02\x38\x01\x1a\xd5\x01\n\x1aInferRequestedOutputTensor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12[\n\nparameters\x18\x02 \x03(\x0b\x32G.inference.ModelInferRequest.InferRequestedOutputTensor.ParametersEntry\x1aL\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.inference.InferParameter:\x02\x38\x01\x1aL\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.inference.InferParameter:\x02\x38\x01"\xb8\x04\n\x12ModelInferResponse\x12\x12\n\nmodel_name\x18\x01 \x01(\t\x12\x15\n\rmodel_version\x18\x02 \x01(\t\x12\n\n\x02id\x18\x03 \x01(\t\x12\x41\n\nparameters\x18\x04 \x03(\x0b\x32-.inference.ModelInferResponse.ParametersEntry\x12@\n\x07outputs\x18\x05 \x03(\x0b\x32/.inference.ModelInferResponse.InferOutputTensor\x1a\x97\x02\n\x11InferOutputTensor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08\x64\x61tatype\x18\x02 \x01(\t\x12\r\n\x05shape\x18\x03 \x03(\x03\x12S\n\nparameters\x18\x04 \x03(\x0b\x32?.inference.ModelInferResponse.InferOutputTensor.ParametersEntry\x12\x30\n\x08\x63ontents\x18\x05 \x01(\x0b\x32\x1e.inference.InferTensorContents\x1aL\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.inference.InferParameter:\x02\x38\x01\x1aL\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.inference.InferParameter:\x02\x38\x01"i\n\x0eInferParameter\x12\x14\n\nbool_param\x18\x01 \x01(\x08H\x00\x12\x15\n\x0bint64_param\x18\x02 \x01(\x03H\x00\x12\x16\n\x0cstring_param\x18\x03 \x01(\tH\x00\x42\x12\n\x10parameter_choice"\xd0\x01\n\x13InferTensorContents\x12\x15\n\rbool_contents\x18\x01 \x03(\x08\x12\x14\n\x0cint_contents\x18\x02 \x03(\x05\x12\x16\n\x0eint64_contents\x18\x03 \x03(\x03\x12\x15\n\ruint_contents\x18\x04 \x03(\r\x12\x17\n\x0fuint64_contents\x18\x05 \x03(\x04\x12\x15\n\rfp32_contents\x18\x06 \x03(\x02\x12\x15\n\rfp64_contents\x18\x07 \x03(\x01\x12\x16\n\x0e\x62ytes_contents\x18\x08 \x03(\x0c\x32\xfc\x03\n\x14GRPCInferenceService\x12K\n\nServerLive\x12\x1c.inference.ServerLiveRequest\x1a\x1d.inference.ServerLiveResponse"\x00\x12N\n\x0bServerReady\x12\x1d.inference.ServerReadyRequest\x1a\x1e.inference.ServerReadyResponse"\x00\x12K\n\nModelReady\x12\x1c.inference.ModelReadyRequest\x1a\x1d.inference.ModelReadyResponse"\x00\x12W\n\x0eServerMetadata\x12 .inference.ServerMetadataRequest\x1a!.inference.ServerMetadataResponse"\x00\x12T\n\rModelMetadata\x12\x1f.inference.ModelMetadataRequest\x1a .inference.ModelMetadataResponse"\x00\x12K\n\nModelInfer\x12\x1c.inference.ModelInferRequest\x1a\x1d.inference.ModelInferResponse"\x00\x62\x06proto3', ) - - _SERVERLIVEREQUEST = _descriptor.Descriptor( - name='ServerLiveRequest', - full_name='inference.ServerLiveRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=30, - serialized_end=49, + name="ServerLiveRequest", + full_name="inference.ServerLiveRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=30, + serialized_end=49, ) _SERVERLIVERESPONSE = _descriptor.Descriptor( - name='ServerLiveResponse', - full_name='inference.ServerLiveResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='live', full_name='inference.ServerLiveResponse.live', index=0, - number=1, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=51, - serialized_end=85, + name="ServerLiveResponse", + full_name="inference.ServerLiveResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="live", + full_name="inference.ServerLiveResponse.live", + index=0, + number=1, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=51, + serialized_end=85, ) _SERVERREADYREQUEST = _descriptor.Descriptor( - name='ServerReadyRequest', - full_name='inference.ServerReadyRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=87, - serialized_end=107, + name="ServerReadyRequest", + full_name="inference.ServerReadyRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=87, + serialized_end=107, ) _SERVERREADYRESPONSE = _descriptor.Descriptor( - name='ServerReadyResponse', - full_name='inference.ServerReadyResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='ready', full_name='inference.ServerReadyResponse.ready', index=0, - number=1, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=109, - serialized_end=145, + name="ServerReadyResponse", + full_name="inference.ServerReadyResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="ready", + full_name="inference.ServerReadyResponse.ready", + index=0, + number=1, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=109, + serialized_end=145, ) _MODELREADYREQUEST = _descriptor.Descriptor( - name='ModelReadyRequest', - full_name='inference.ModelReadyRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='name', full_name='inference.ModelReadyRequest.name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='version', full_name='inference.ModelReadyRequest.version', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=147, - serialized_end=197, + name="ModelReadyRequest", + full_name="inference.ModelReadyRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="inference.ModelReadyRequest.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="version", + full_name="inference.ModelReadyRequest.version", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=147, + serialized_end=197, ) _MODELREADYRESPONSE = _descriptor.Descriptor( - name='ModelReadyResponse', - full_name='inference.ModelReadyResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='ready', full_name='inference.ModelReadyResponse.ready', index=0, - number=1, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=199, - serialized_end=234, + name="ModelReadyResponse", + full_name="inference.ModelReadyResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="ready", + full_name="inference.ModelReadyResponse.ready", + index=0, + number=1, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=199, + serialized_end=234, ) _SERVERMETADATAREQUEST = _descriptor.Descriptor( - name='ServerMetadataRequest', - full_name='inference.ServerMetadataRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=236, - serialized_end=259, + name="ServerMetadataRequest", + full_name="inference.ServerMetadataRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=236, + serialized_end=259, ) _SERVERMETADATARESPONSE = _descriptor.Descriptor( - name='ServerMetadataResponse', - full_name='inference.ServerMetadataResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='name', full_name='inference.ServerMetadataResponse.name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='version', full_name='inference.ServerMetadataResponse.version', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='extensions', full_name='inference.ServerMetadataResponse.extensions', index=2, - number=3, type=9, cpp_type=9, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=261, - serialized_end=336, + name="ServerMetadataResponse", + full_name="inference.ServerMetadataResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="inference.ServerMetadataResponse.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="version", + full_name="inference.ServerMetadataResponse.version", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="extensions", + full_name="inference.ServerMetadataResponse.extensions", + index=2, + number=3, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=261, + serialized_end=336, ) _MODELMETADATAREQUEST = _descriptor.Descriptor( - name='ModelMetadataRequest', - full_name='inference.ModelMetadataRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='name', full_name='inference.ModelMetadataRequest.name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='version', full_name='inference.ModelMetadataRequest.version', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=338, - serialized_end=391, + name="ModelMetadataRequest", + full_name="inference.ModelMetadataRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="inference.ModelMetadataRequest.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="version", + full_name="inference.ModelMetadataRequest.version", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=338, + serialized_end=391, ) _MODELMETADATARESPONSE_TENSORMETADATA_TAGSENTRY = _descriptor.Descriptor( - name='TagsEntry', - full_name='inference.ModelMetadataResponse.TensorMetadata.TagsEntry', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='inference.ModelMetadataResponse.TensorMetadata.TagsEntry.key', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='value', full_name='inference.ModelMetadataResponse.TensorMetadata.TagsEntry.value', index=1, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=b'8\001', - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=739, - serialized_end=809, + name="TagsEntry", + full_name="inference.ModelMetadataResponse.TensorMetadata.TagsEntry", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="inference.ModelMetadataResponse.TensorMetadata.TagsEntry.key", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="inference.ModelMetadataResponse.TensorMetadata.TagsEntry.value", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b"8\001", + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=739, + serialized_end=809, ) _MODELMETADATARESPONSE_TENSORMETADATA = _descriptor.Descriptor( - name='TensorMetadata', - full_name='inference.ModelMetadataResponse.TensorMetadata', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='name', full_name='inference.ModelMetadataResponse.TensorMetadata.name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='datatype', full_name='inference.ModelMetadataResponse.TensorMetadata.datatype', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='shape', full_name='inference.ModelMetadataResponse.TensorMetadata.shape', index=2, - number=3, type=3, cpp_type=2, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='tags', full_name='inference.ModelMetadataResponse.TensorMetadata.tags', index=3, - number=4, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[_MODELMETADATARESPONSE_TENSORMETADATA_TAGSENTRY, ], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=601, - serialized_end=809, + name="TensorMetadata", + full_name="inference.ModelMetadataResponse.TensorMetadata", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="inference.ModelMetadataResponse.TensorMetadata.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="datatype", + full_name="inference.ModelMetadataResponse.TensorMetadata.datatype", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="shape", + full_name="inference.ModelMetadataResponse.TensorMetadata.shape", + index=2, + number=3, + type=3, + cpp_type=2, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="tags", + full_name="inference.ModelMetadataResponse.TensorMetadata.tags", + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[ + _MODELMETADATARESPONSE_TENSORMETADATA_TAGSENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=601, + serialized_end=809, ) _MODELMETADATARESPONSE = _descriptor.Descriptor( - name='ModelMetadataResponse', - full_name='inference.ModelMetadataResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='name', full_name='inference.ModelMetadataResponse.name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='versions', full_name='inference.ModelMetadataResponse.versions', index=1, - number=2, type=9, cpp_type=9, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='platform', full_name='inference.ModelMetadataResponse.platform', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='inputs', full_name='inference.ModelMetadataResponse.inputs', index=3, - number=4, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='outputs', full_name='inference.ModelMetadataResponse.outputs', index=4, - number=5, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[_MODELMETADATARESPONSE_TENSORMETADATA, ], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=394, - serialized_end=809, + name="ModelMetadataResponse", + full_name="inference.ModelMetadataResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="inference.ModelMetadataResponse.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="versions", + full_name="inference.ModelMetadataResponse.versions", + index=1, + number=2, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="platform", + full_name="inference.ModelMetadataResponse.platform", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="inputs", + full_name="inference.ModelMetadataResponse.inputs", + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="outputs", + full_name="inference.ModelMetadataResponse.outputs", + index=4, + number=5, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[ + _MODELMETADATARESPONSE_TENSORMETADATA, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=394, + serialized_end=809, ) _MODELINFERREQUEST_INFERINPUTTENSOR_PARAMETERSENTRY = _descriptor.Descriptor( - name='ParametersEntry', - full_name='inference.ModelInferRequest.InferInputTensor.ParametersEntry', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='inference.ModelInferRequest.InferInputTensor.ParametersEntry.key', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='value', full_name='inference.ModelInferRequest.InferInputTensor.ParametersEntry.value', index=1, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=b'8\001', - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1292, - serialized_end=1368, + name="ParametersEntry", + full_name="inference.ModelInferRequest.InferInputTensor.ParametersEntry", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="inference.ModelInferRequest.InferInputTensor.ParametersEntry.key", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="inference.ModelInferRequest.InferInputTensor.ParametersEntry.value", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b"8\001", + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1292, + serialized_end=1368, ) _MODELINFERREQUEST_INFERINPUTTENSOR = _descriptor.Descriptor( - name='InferInputTensor', - full_name='inference.ModelInferRequest.InferInputTensor', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='name', full_name='inference.ModelInferRequest.InferInputTensor.name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='datatype', full_name='inference.ModelInferRequest.InferInputTensor.datatype', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='shape', full_name='inference.ModelInferRequest.InferInputTensor.shape', index=2, - number=3, type=3, cpp_type=2, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='parameters', full_name='inference.ModelInferRequest.InferInputTensor.parameters', index=3, - number=4, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='contents', full_name='inference.ModelInferRequest.InferInputTensor.contents', index=4, - number=5, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[_MODELINFERREQUEST_INFERINPUTTENSOR_PARAMETERSENTRY, ], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1092, - serialized_end=1368, + name="InferInputTensor", + full_name="inference.ModelInferRequest.InferInputTensor", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="inference.ModelInferRequest.InferInputTensor.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="datatype", + full_name="inference.ModelInferRequest.InferInputTensor.datatype", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="shape", + full_name="inference.ModelInferRequest.InferInputTensor.shape", + index=2, + number=3, + type=3, + cpp_type=2, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="parameters", + full_name="inference.ModelInferRequest.InferInputTensor.parameters", + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="contents", + full_name="inference.ModelInferRequest.InferInputTensor.contents", + index=4, + number=5, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[ + _MODELINFERREQUEST_INFERINPUTTENSOR_PARAMETERSENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1092, + serialized_end=1368, ) _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR_PARAMETERSENTRY = _descriptor.Descriptor( - name='ParametersEntry', - full_name='inference.ModelInferRequest.InferRequestedOutputTensor.ParametersEntry', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='inference.ModelInferRequest.InferRequestedOutputTensor.ParametersEntry.key', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='value', full_name='inference.ModelInferRequest.InferRequestedOutputTensor.ParametersEntry.value', index=1, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=b'8\001', - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1292, - serialized_end=1368, + name="ParametersEntry", + full_name="inference.ModelInferRequest.InferRequestedOutputTensor.ParametersEntry", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="inference.ModelInferRequest.InferRequestedOutputTensor.ParametersEntry.key", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="inference.ModelInferRequest.InferRequestedOutputTensor.ParametersEntry.value", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b"8\001", + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1292, + serialized_end=1368, ) _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR = _descriptor.Descriptor( - name='InferRequestedOutputTensor', - full_name='inference.ModelInferRequest.InferRequestedOutputTensor', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='name', full_name='inference.ModelInferRequest.InferRequestedOutputTensor.name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='parameters', full_name='inference.ModelInferRequest.InferRequestedOutputTensor.parameters', index=1, - number=2, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[_MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR_PARAMETERSENTRY, ], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1371, - serialized_end=1584, + name="InferRequestedOutputTensor", + full_name="inference.ModelInferRequest.InferRequestedOutputTensor", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="inference.ModelInferRequest.InferRequestedOutputTensor.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="parameters", + full_name="inference.ModelInferRequest.InferRequestedOutputTensor.parameters", + index=1, + number=2, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[ + _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR_PARAMETERSENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1371, + serialized_end=1584, ) _MODELINFERREQUEST_PARAMETERSENTRY = _descriptor.Descriptor( - name='ParametersEntry', - full_name='inference.ModelInferRequest.ParametersEntry', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='inference.ModelInferRequest.ParametersEntry.key', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='value', full_name='inference.ModelInferRequest.ParametersEntry.value', index=1, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=b'8\001', - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1292, - serialized_end=1368, + name="ParametersEntry", + full_name="inference.ModelInferRequest.ParametersEntry", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="inference.ModelInferRequest.ParametersEntry.key", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="inference.ModelInferRequest.ParametersEntry.value", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b"8\001", + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1292, + serialized_end=1368, ) _MODELINFERREQUEST = _descriptor.Descriptor( - name='ModelInferRequest', - full_name='inference.ModelInferRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='model_name', full_name='inference.ModelInferRequest.model_name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='model_version', full_name='inference.ModelInferRequest.model_version', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='id', full_name='inference.ModelInferRequest.id', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='parameters', full_name='inference.ModelInferRequest.parameters', index=3, - number=4, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='inputs', full_name='inference.ModelInferRequest.inputs', index=4, - number=5, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='outputs', full_name='inference.ModelInferRequest.outputs', index=5, - number=6, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[_MODELINFERREQUEST_INFERINPUTTENSOR, _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR, _MODELINFERREQUEST_PARAMETERSENTRY, ], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=812, - serialized_end=1662, + name="ModelInferRequest", + full_name="inference.ModelInferRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="model_name", + full_name="inference.ModelInferRequest.model_name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="model_version", + full_name="inference.ModelInferRequest.model_version", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="id", + full_name="inference.ModelInferRequest.id", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="parameters", + full_name="inference.ModelInferRequest.parameters", + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="inputs", + full_name="inference.ModelInferRequest.inputs", + index=4, + number=5, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="outputs", + full_name="inference.ModelInferRequest.outputs", + index=5, + number=6, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[ + _MODELINFERREQUEST_INFERINPUTTENSOR, + _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR, + _MODELINFERREQUEST_PARAMETERSENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=812, + serialized_end=1662, ) _MODELINFERRESPONSE_INFEROUTPUTTENSOR_PARAMETERSENTRY = _descriptor.Descriptor( - name='ParametersEntry', - full_name='inference.ModelInferResponse.InferOutputTensor.ParametersEntry', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='inference.ModelInferResponse.InferOutputTensor.ParametersEntry.key', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='value', full_name='inference.ModelInferResponse.InferOutputTensor.ParametersEntry.value', index=1, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=b'8\001', - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1292, - serialized_end=1368, + name="ParametersEntry", + full_name="inference.ModelInferResponse.InferOutputTensor.ParametersEntry", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="inference.ModelInferResponse.InferOutputTensor.ParametersEntry.key", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="inference.ModelInferResponse.InferOutputTensor.ParametersEntry.value", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b"8\001", + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1292, + serialized_end=1368, ) _MODELINFERRESPONSE_INFEROUTPUTTENSOR = _descriptor.Descriptor( - name='InferOutputTensor', - full_name='inference.ModelInferResponse.InferOutputTensor', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='name', full_name='inference.ModelInferResponse.InferOutputTensor.name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='datatype', full_name='inference.ModelInferResponse.InferOutputTensor.datatype', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='shape', full_name='inference.ModelInferResponse.InferOutputTensor.shape', index=2, - number=3, type=3, cpp_type=2, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='parameters', full_name='inference.ModelInferResponse.InferOutputTensor.parameters', index=3, - number=4, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='contents', full_name='inference.ModelInferResponse.InferOutputTensor.contents', index=4, - number=5, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[_MODELINFERRESPONSE_INFEROUTPUTTENSOR_PARAMETERSENTRY, ], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1876, - serialized_end=2155, + name="InferOutputTensor", + full_name="inference.ModelInferResponse.InferOutputTensor", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="inference.ModelInferResponse.InferOutputTensor.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="datatype", + full_name="inference.ModelInferResponse.InferOutputTensor.datatype", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="shape", + full_name="inference.ModelInferResponse.InferOutputTensor.shape", + index=2, + number=3, + type=3, + cpp_type=2, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="parameters", + full_name="inference.ModelInferResponse.InferOutputTensor.parameters", + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="contents", + full_name="inference.ModelInferResponse.InferOutputTensor.contents", + index=4, + number=5, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[ + _MODELINFERRESPONSE_INFEROUTPUTTENSOR_PARAMETERSENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1876, + serialized_end=2155, ) _MODELINFERRESPONSE_PARAMETERSENTRY = _descriptor.Descriptor( - name='ParametersEntry', - full_name='inference.ModelInferResponse.ParametersEntry', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='inference.ModelInferResponse.ParametersEntry.key', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='value', full_name='inference.ModelInferResponse.ParametersEntry.value', index=1, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=b'8\001', - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1292, - serialized_end=1368, + name="ParametersEntry", + full_name="inference.ModelInferResponse.ParametersEntry", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="inference.ModelInferResponse.ParametersEntry.key", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="inference.ModelInferResponse.ParametersEntry.value", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b"8\001", + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1292, + serialized_end=1368, ) _MODELINFERRESPONSE = _descriptor.Descriptor( - name='ModelInferResponse', - full_name='inference.ModelInferResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='model_name', full_name='inference.ModelInferResponse.model_name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='model_version', full_name='inference.ModelInferResponse.model_version', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='id', full_name='inference.ModelInferResponse.id', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='parameters', full_name='inference.ModelInferResponse.parameters', index=3, - number=4, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='outputs', full_name='inference.ModelInferResponse.outputs', index=4, - number=5, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[_MODELINFERRESPONSE_INFEROUTPUTTENSOR, _MODELINFERRESPONSE_PARAMETERSENTRY, ], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1665, - serialized_end=2233, + name="ModelInferResponse", + full_name="inference.ModelInferResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="model_name", + full_name="inference.ModelInferResponse.model_name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="model_version", + full_name="inference.ModelInferResponse.model_version", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="id", + full_name="inference.ModelInferResponse.id", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="parameters", + full_name="inference.ModelInferResponse.parameters", + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="outputs", + full_name="inference.ModelInferResponse.outputs", + index=4, + number=5, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[ + _MODELINFERRESPONSE_INFEROUTPUTTENSOR, + _MODELINFERRESPONSE_PARAMETERSENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1665, + serialized_end=2233, ) _INFERPARAMETER = _descriptor.Descriptor( - name='InferParameter', - full_name='inference.InferParameter', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='bool_param', full_name='inference.InferParameter.bool_param', index=0, - number=1, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='int64_param', full_name='inference.InferParameter.int64_param', index=1, - number=2, type=3, cpp_type=2, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='string_param', full_name='inference.InferParameter.string_param', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name='parameter_choice', full_name='inference.InferParameter.parameter_choice', - index=0, containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[]), - ], - serialized_start=2235, - serialized_end=2340, + name="InferParameter", + full_name="inference.InferParameter", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="bool_param", + full_name="inference.InferParameter.bool_param", + index=0, + number=1, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="int64_param", + full_name="inference.InferParameter.int64_param", + index=1, + number=2, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="string_param", + full_name="inference.InferParameter.string_param", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name="parameter_choice", + full_name="inference.InferParameter.parameter_choice", + index=0, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[], + ), + ], + serialized_start=2235, + serialized_end=2340, ) _INFERTENSORCONTENTS = _descriptor.Descriptor( - name='InferTensorContents', - full_name='inference.InferTensorContents', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='bool_contents', full_name='inference.InferTensorContents.bool_contents', index=0, - number=1, type=8, cpp_type=7, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='int_contents', full_name='inference.InferTensorContents.int_contents', index=1, - number=2, type=5, cpp_type=1, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='int64_contents', full_name='inference.InferTensorContents.int64_contents', index=2, - number=3, type=3, cpp_type=2, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='uint_contents', full_name='inference.InferTensorContents.uint_contents', index=3, - number=4, type=13, cpp_type=3, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='uint64_contents', full_name='inference.InferTensorContents.uint64_contents', index=4, - number=5, type=4, cpp_type=4, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='fp32_contents', full_name='inference.InferTensorContents.fp32_contents', index=5, - number=6, type=2, cpp_type=6, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='fp64_contents', full_name='inference.InferTensorContents.fp64_contents', index=6, - number=7, type=1, cpp_type=5, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='bytes_contents', full_name='inference.InferTensorContents.bytes_contents', index=7, - number=8, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2343, - serialized_end=2551, + name="InferTensorContents", + full_name="inference.InferTensorContents", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="bool_contents", + full_name="inference.InferTensorContents.bool_contents", + index=0, + number=1, + type=8, + cpp_type=7, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="int_contents", + full_name="inference.InferTensorContents.int_contents", + index=1, + number=2, + type=5, + cpp_type=1, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="int64_contents", + full_name="inference.InferTensorContents.int64_contents", + index=2, + number=3, + type=3, + cpp_type=2, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="uint_contents", + full_name="inference.InferTensorContents.uint_contents", + index=3, + number=4, + type=13, + cpp_type=3, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="uint64_contents", + full_name="inference.InferTensorContents.uint64_contents", + index=4, + number=5, + type=4, + cpp_type=4, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="fp32_contents", + full_name="inference.InferTensorContents.fp32_contents", + index=5, + number=6, + type=2, + cpp_type=6, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="fp64_contents", + full_name="inference.InferTensorContents.fp64_contents", + index=6, + number=7, + type=1, + cpp_type=5, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="bytes_contents", + full_name="inference.InferTensorContents.bytes_contents", + index=7, + number=8, + type=12, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=2343, + serialized_end=2551, ) -_MODELMETADATARESPONSE_TENSORMETADATA_TAGSENTRY.fields_by_name['value'].message_type = _INFERPARAMETER -_MODELMETADATARESPONSE_TENSORMETADATA_TAGSENTRY.containing_type = _MODELMETADATARESPONSE_TENSORMETADATA -_MODELMETADATARESPONSE_TENSORMETADATA.fields_by_name['tags'].message_type = _MODELMETADATARESPONSE_TENSORMETADATA_TAGSENTRY +_MODELMETADATARESPONSE_TENSORMETADATA_TAGSENTRY.fields_by_name[ + "value" +].message_type = _INFERPARAMETER +_MODELMETADATARESPONSE_TENSORMETADATA_TAGSENTRY.containing_type = ( + _MODELMETADATARESPONSE_TENSORMETADATA +) +_MODELMETADATARESPONSE_TENSORMETADATA.fields_by_name[ + "tags" +].message_type = _MODELMETADATARESPONSE_TENSORMETADATA_TAGSENTRY _MODELMETADATARESPONSE_TENSORMETADATA.containing_type = _MODELMETADATARESPONSE -_MODELMETADATARESPONSE.fields_by_name['inputs'].message_type = _MODELMETADATARESPONSE_TENSORMETADATA -_MODELMETADATARESPONSE.fields_by_name['outputs'].message_type = _MODELMETADATARESPONSE_TENSORMETADATA -_MODELINFERREQUEST_INFERINPUTTENSOR_PARAMETERSENTRY.fields_by_name['value'].message_type = _INFERPARAMETER -_MODELINFERREQUEST_INFERINPUTTENSOR_PARAMETERSENTRY.containing_type = _MODELINFERREQUEST_INFERINPUTTENSOR -_MODELINFERREQUEST_INFERINPUTTENSOR.fields_by_name['parameters'].message_type = _MODELINFERREQUEST_INFERINPUTTENSOR_PARAMETERSENTRY -_MODELINFERREQUEST_INFERINPUTTENSOR.fields_by_name['contents'].message_type = _INFERTENSORCONTENTS +_MODELMETADATARESPONSE.fields_by_name[ + "inputs" +].message_type = _MODELMETADATARESPONSE_TENSORMETADATA +_MODELMETADATARESPONSE.fields_by_name[ + "outputs" +].message_type = _MODELMETADATARESPONSE_TENSORMETADATA +_MODELINFERREQUEST_INFERINPUTTENSOR_PARAMETERSENTRY.fields_by_name[ + "value" +].message_type = _INFERPARAMETER +_MODELINFERREQUEST_INFERINPUTTENSOR_PARAMETERSENTRY.containing_type = ( + _MODELINFERREQUEST_INFERINPUTTENSOR +) +_MODELINFERREQUEST_INFERINPUTTENSOR.fields_by_name[ + "parameters" +].message_type = _MODELINFERREQUEST_INFERINPUTTENSOR_PARAMETERSENTRY +_MODELINFERREQUEST_INFERINPUTTENSOR.fields_by_name[ + "contents" +].message_type = _INFERTENSORCONTENTS _MODELINFERREQUEST_INFERINPUTTENSOR.containing_type = _MODELINFERREQUEST -_MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR_PARAMETERSENTRY.fields_by_name['value'].message_type = _INFERPARAMETER -_MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR_PARAMETERSENTRY.containing_type = _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR -_MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR.fields_by_name['parameters'].message_type = _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR_PARAMETERSENTRY +_MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR_PARAMETERSENTRY.fields_by_name[ + "value" +].message_type = _INFERPARAMETER +_MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR_PARAMETERSENTRY.containing_type = ( + _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR +) +_MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR.fields_by_name[ + "parameters" +].message_type = _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR_PARAMETERSENTRY _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR.containing_type = _MODELINFERREQUEST -_MODELINFERREQUEST_PARAMETERSENTRY.fields_by_name['value'].message_type = _INFERPARAMETER +_MODELINFERREQUEST_PARAMETERSENTRY.fields_by_name[ + "value" +].message_type = _INFERPARAMETER _MODELINFERREQUEST_PARAMETERSENTRY.containing_type = _MODELINFERREQUEST -_MODELINFERREQUEST.fields_by_name['parameters'].message_type = _MODELINFERREQUEST_PARAMETERSENTRY -_MODELINFERREQUEST.fields_by_name['inputs'].message_type = _MODELINFERREQUEST_INFERINPUTTENSOR -_MODELINFERREQUEST.fields_by_name['outputs'].message_type = _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR -_MODELINFERRESPONSE_INFEROUTPUTTENSOR_PARAMETERSENTRY.fields_by_name['value'].message_type = _INFERPARAMETER -_MODELINFERRESPONSE_INFEROUTPUTTENSOR_PARAMETERSENTRY.containing_type = _MODELINFERRESPONSE_INFEROUTPUTTENSOR -_MODELINFERRESPONSE_INFEROUTPUTTENSOR.fields_by_name['parameters'].message_type = _MODELINFERRESPONSE_INFEROUTPUTTENSOR_PARAMETERSENTRY -_MODELINFERRESPONSE_INFEROUTPUTTENSOR.fields_by_name['contents'].message_type = _INFERTENSORCONTENTS +_MODELINFERREQUEST.fields_by_name[ + "parameters" +].message_type = _MODELINFERREQUEST_PARAMETERSENTRY +_MODELINFERREQUEST.fields_by_name[ + "inputs" +].message_type = _MODELINFERREQUEST_INFERINPUTTENSOR +_MODELINFERREQUEST.fields_by_name[ + "outputs" +].message_type = _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR +_MODELINFERRESPONSE_INFEROUTPUTTENSOR_PARAMETERSENTRY.fields_by_name[ + "value" +].message_type = _INFERPARAMETER +_MODELINFERRESPONSE_INFEROUTPUTTENSOR_PARAMETERSENTRY.containing_type = ( + _MODELINFERRESPONSE_INFEROUTPUTTENSOR +) +_MODELINFERRESPONSE_INFEROUTPUTTENSOR.fields_by_name[ + "parameters" +].message_type = _MODELINFERRESPONSE_INFEROUTPUTTENSOR_PARAMETERSENTRY +_MODELINFERRESPONSE_INFEROUTPUTTENSOR.fields_by_name[ + "contents" +].message_type = _INFERTENSORCONTENTS _MODELINFERRESPONSE_INFEROUTPUTTENSOR.containing_type = _MODELINFERRESPONSE -_MODELINFERRESPONSE_PARAMETERSENTRY.fields_by_name['value'].message_type = _INFERPARAMETER +_MODELINFERRESPONSE_PARAMETERSENTRY.fields_by_name[ + "value" +].message_type = _INFERPARAMETER _MODELINFERRESPONSE_PARAMETERSENTRY.containing_type = _MODELINFERRESPONSE -_MODELINFERRESPONSE.fields_by_name['parameters'].message_type = _MODELINFERRESPONSE_PARAMETERSENTRY -_MODELINFERRESPONSE.fields_by_name['outputs'].message_type = _MODELINFERRESPONSE_INFEROUTPUTTENSOR -_INFERPARAMETER.oneofs_by_name['parameter_choice'].fields.append( - _INFERPARAMETER.fields_by_name['bool_param']) -_INFERPARAMETER.fields_by_name['bool_param'].containing_oneof = _INFERPARAMETER.oneofs_by_name['parameter_choice'] -_INFERPARAMETER.oneofs_by_name['parameter_choice'].fields.append( - _INFERPARAMETER.fields_by_name['int64_param']) -_INFERPARAMETER.fields_by_name['int64_param'].containing_oneof = _INFERPARAMETER.oneofs_by_name['parameter_choice'] -_INFERPARAMETER.oneofs_by_name['parameter_choice'].fields.append( - _INFERPARAMETER.fields_by_name['string_param']) -_INFERPARAMETER.fields_by_name['string_param'].containing_oneof = _INFERPARAMETER.oneofs_by_name['parameter_choice'] -DESCRIPTOR.message_types_by_name['ServerLiveRequest'] = _SERVERLIVEREQUEST -DESCRIPTOR.message_types_by_name['ServerLiveResponse'] = _SERVERLIVERESPONSE -DESCRIPTOR.message_types_by_name['ServerReadyRequest'] = _SERVERREADYREQUEST -DESCRIPTOR.message_types_by_name['ServerReadyResponse'] = _SERVERREADYRESPONSE -DESCRIPTOR.message_types_by_name['ModelReadyRequest'] = _MODELREADYREQUEST -DESCRIPTOR.message_types_by_name['ModelReadyResponse'] = _MODELREADYRESPONSE -DESCRIPTOR.message_types_by_name['ServerMetadataRequest'] = _SERVERMETADATAREQUEST -DESCRIPTOR.message_types_by_name['ServerMetadataResponse'] = _SERVERMETADATARESPONSE -DESCRIPTOR.message_types_by_name['ModelMetadataRequest'] = _MODELMETADATAREQUEST -DESCRIPTOR.message_types_by_name['ModelMetadataResponse'] = _MODELMETADATARESPONSE -DESCRIPTOR.message_types_by_name['ModelInferRequest'] = _MODELINFERREQUEST -DESCRIPTOR.message_types_by_name['ModelInferResponse'] = _MODELINFERRESPONSE -DESCRIPTOR.message_types_by_name['InferParameter'] = _INFERPARAMETER -DESCRIPTOR.message_types_by_name['InferTensorContents'] = _INFERTENSORCONTENTS +_MODELINFERRESPONSE.fields_by_name[ + "parameters" +].message_type = _MODELINFERRESPONSE_PARAMETERSENTRY +_MODELINFERRESPONSE.fields_by_name[ + "outputs" +].message_type = _MODELINFERRESPONSE_INFEROUTPUTTENSOR +_INFERPARAMETER.oneofs_by_name["parameter_choice"].fields.append( + _INFERPARAMETER.fields_by_name["bool_param"] +) +_INFERPARAMETER.fields_by_name[ + "bool_param" +].containing_oneof = _INFERPARAMETER.oneofs_by_name["parameter_choice"] +_INFERPARAMETER.oneofs_by_name["parameter_choice"].fields.append( + _INFERPARAMETER.fields_by_name["int64_param"] +) +_INFERPARAMETER.fields_by_name[ + "int64_param" +].containing_oneof = _INFERPARAMETER.oneofs_by_name["parameter_choice"] +_INFERPARAMETER.oneofs_by_name["parameter_choice"].fields.append( + _INFERPARAMETER.fields_by_name["string_param"] +) +_INFERPARAMETER.fields_by_name[ + "string_param" +].containing_oneof = _INFERPARAMETER.oneofs_by_name["parameter_choice"] +DESCRIPTOR.message_types_by_name["ServerLiveRequest"] = _SERVERLIVEREQUEST +DESCRIPTOR.message_types_by_name["ServerLiveResponse"] = _SERVERLIVERESPONSE +DESCRIPTOR.message_types_by_name["ServerReadyRequest"] = _SERVERREADYREQUEST +DESCRIPTOR.message_types_by_name["ServerReadyResponse"] = _SERVERREADYRESPONSE +DESCRIPTOR.message_types_by_name["ModelReadyRequest"] = _MODELREADYREQUEST +DESCRIPTOR.message_types_by_name["ModelReadyResponse"] = _MODELREADYRESPONSE +DESCRIPTOR.message_types_by_name["ServerMetadataRequest"] = _SERVERMETADATAREQUEST +DESCRIPTOR.message_types_by_name["ServerMetadataResponse"] = _SERVERMETADATARESPONSE +DESCRIPTOR.message_types_by_name["ModelMetadataRequest"] = _MODELMETADATAREQUEST +DESCRIPTOR.message_types_by_name["ModelMetadataResponse"] = _MODELMETADATARESPONSE +DESCRIPTOR.message_types_by_name["ModelInferRequest"] = _MODELINFERREQUEST +DESCRIPTOR.message_types_by_name["ModelInferResponse"] = _MODELINFERRESPONSE +DESCRIPTOR.message_types_by_name["InferParameter"] = _INFERPARAMETER +DESCRIPTOR.message_types_by_name["InferTensorContents"] = _INFERTENSORCONTENTS _sym_db.RegisterFileDescriptor(DESCRIPTOR) -ServerLiveRequest = _reflection.GeneratedProtocolMessageType('ServerLiveRequest', (_message.Message,), { - 'DESCRIPTOR' : _SERVERLIVEREQUEST, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ServerLiveRequest) - }) +ServerLiveRequest = _reflection.GeneratedProtocolMessageType( + "ServerLiveRequest", + (_message.Message,), + { + "DESCRIPTOR": _SERVERLIVEREQUEST, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ServerLiveRequest) + }, +) _sym_db.RegisterMessage(ServerLiveRequest) -ServerLiveResponse = _reflection.GeneratedProtocolMessageType('ServerLiveResponse', (_message.Message,), { - 'DESCRIPTOR' : _SERVERLIVERESPONSE, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ServerLiveResponse) - }) +ServerLiveResponse = _reflection.GeneratedProtocolMessageType( + "ServerLiveResponse", + (_message.Message,), + { + "DESCRIPTOR": _SERVERLIVERESPONSE, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ServerLiveResponse) + }, +) _sym_db.RegisterMessage(ServerLiveResponse) -ServerReadyRequest = _reflection.GeneratedProtocolMessageType('ServerReadyRequest', (_message.Message,), { - 'DESCRIPTOR' : _SERVERREADYREQUEST, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ServerReadyRequest) - }) +ServerReadyRequest = _reflection.GeneratedProtocolMessageType( + "ServerReadyRequest", + (_message.Message,), + { + "DESCRIPTOR": _SERVERREADYREQUEST, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ServerReadyRequest) + }, +) _sym_db.RegisterMessage(ServerReadyRequest) -ServerReadyResponse = _reflection.GeneratedProtocolMessageType('ServerReadyResponse', (_message.Message,), { - 'DESCRIPTOR' : _SERVERREADYRESPONSE, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ServerReadyResponse) - }) +ServerReadyResponse = _reflection.GeneratedProtocolMessageType( + "ServerReadyResponse", + (_message.Message,), + { + "DESCRIPTOR": _SERVERREADYRESPONSE, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ServerReadyResponse) + }, +) _sym_db.RegisterMessage(ServerReadyResponse) -ModelReadyRequest = _reflection.GeneratedProtocolMessageType('ModelReadyRequest', (_message.Message,), { - 'DESCRIPTOR' : _MODELREADYREQUEST, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelReadyRequest) - }) +ModelReadyRequest = _reflection.GeneratedProtocolMessageType( + "ModelReadyRequest", + (_message.Message,), + { + "DESCRIPTOR": _MODELREADYREQUEST, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelReadyRequest) + }, +) _sym_db.RegisterMessage(ModelReadyRequest) -ModelReadyResponse = _reflection.GeneratedProtocolMessageType('ModelReadyResponse', (_message.Message,), { - 'DESCRIPTOR' : _MODELREADYRESPONSE, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelReadyResponse) - }) +ModelReadyResponse = _reflection.GeneratedProtocolMessageType( + "ModelReadyResponse", + (_message.Message,), + { + "DESCRIPTOR": _MODELREADYRESPONSE, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelReadyResponse) + }, +) _sym_db.RegisterMessage(ModelReadyResponse) -ServerMetadataRequest = _reflection.GeneratedProtocolMessageType('ServerMetadataRequest', (_message.Message,), { - 'DESCRIPTOR' : _SERVERMETADATAREQUEST, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ServerMetadataRequest) - }) +ServerMetadataRequest = _reflection.GeneratedProtocolMessageType( + "ServerMetadataRequest", + (_message.Message,), + { + "DESCRIPTOR": _SERVERMETADATAREQUEST, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ServerMetadataRequest) + }, +) _sym_db.RegisterMessage(ServerMetadataRequest) -ServerMetadataResponse = _reflection.GeneratedProtocolMessageType('ServerMetadataResponse', (_message.Message,), { - 'DESCRIPTOR' : _SERVERMETADATARESPONSE, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ServerMetadataResponse) - }) +ServerMetadataResponse = _reflection.GeneratedProtocolMessageType( + "ServerMetadataResponse", + (_message.Message,), + { + "DESCRIPTOR": _SERVERMETADATARESPONSE, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ServerMetadataResponse) + }, +) _sym_db.RegisterMessage(ServerMetadataResponse) -ModelMetadataRequest = _reflection.GeneratedProtocolMessageType('ModelMetadataRequest', (_message.Message,), { - 'DESCRIPTOR' : _MODELMETADATAREQUEST, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelMetadataRequest) - }) +ModelMetadataRequest = _reflection.GeneratedProtocolMessageType( + "ModelMetadataRequest", + (_message.Message,), + { + "DESCRIPTOR": _MODELMETADATAREQUEST, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelMetadataRequest) + }, +) _sym_db.RegisterMessage(ModelMetadataRequest) -ModelMetadataResponse = _reflection.GeneratedProtocolMessageType('ModelMetadataResponse', (_message.Message,), { - - 'TensorMetadata' : _reflection.GeneratedProtocolMessageType('TensorMetadata', (_message.Message,), { - - 'TagsEntry' : _reflection.GeneratedProtocolMessageType('TagsEntry', (_message.Message,), { - 'DESCRIPTOR' : _MODELMETADATARESPONSE_TENSORMETADATA_TAGSENTRY, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelMetadataResponse.TensorMetadata.TagsEntry) - }) - , - 'DESCRIPTOR' : _MODELMETADATARESPONSE_TENSORMETADATA, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelMetadataResponse.TensorMetadata) - }) - , - 'DESCRIPTOR' : _MODELMETADATARESPONSE, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelMetadataResponse) - }) +ModelMetadataResponse = _reflection.GeneratedProtocolMessageType( + "ModelMetadataResponse", + (_message.Message,), + { + "TensorMetadata": _reflection.GeneratedProtocolMessageType( + "TensorMetadata", + (_message.Message,), + { + "TagsEntry": _reflection.GeneratedProtocolMessageType( + "TagsEntry", + (_message.Message,), + { + "DESCRIPTOR": _MODELMETADATARESPONSE_TENSORMETADATA_TAGSENTRY, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelMetadataResponse.TensorMetadata.TagsEntry) + }, + ), + "DESCRIPTOR": _MODELMETADATARESPONSE_TENSORMETADATA, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelMetadataResponse.TensorMetadata) + }, + ), + "DESCRIPTOR": _MODELMETADATARESPONSE, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelMetadataResponse) + }, +) _sym_db.RegisterMessage(ModelMetadataResponse) _sym_db.RegisterMessage(ModelMetadataResponse.TensorMetadata) _sym_db.RegisterMessage(ModelMetadataResponse.TensorMetadata.TagsEntry) -ModelInferRequest = _reflection.GeneratedProtocolMessageType('ModelInferRequest', (_message.Message,), { - - 'InferInputTensor' : _reflection.GeneratedProtocolMessageType('InferInputTensor', (_message.Message,), { - - 'ParametersEntry' : _reflection.GeneratedProtocolMessageType('ParametersEntry', (_message.Message,), { - 'DESCRIPTOR' : _MODELINFERREQUEST_INFERINPUTTENSOR_PARAMETERSENTRY, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelInferRequest.InferInputTensor.ParametersEntry) - }) - , - 'DESCRIPTOR' : _MODELINFERREQUEST_INFERINPUTTENSOR, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelInferRequest.InferInputTensor) - }) - , - - 'InferRequestedOutputTensor' : _reflection.GeneratedProtocolMessageType('InferRequestedOutputTensor', (_message.Message,), { - - 'ParametersEntry' : _reflection.GeneratedProtocolMessageType('ParametersEntry', (_message.Message,), { - 'DESCRIPTOR' : _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR_PARAMETERSENTRY, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelInferRequest.InferRequestedOutputTensor.ParametersEntry) - }) - , - 'DESCRIPTOR' : _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelInferRequest.InferRequestedOutputTensor) - }) - , - - 'ParametersEntry' : _reflection.GeneratedProtocolMessageType('ParametersEntry', (_message.Message,), { - 'DESCRIPTOR' : _MODELINFERREQUEST_PARAMETERSENTRY, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelInferRequest.ParametersEntry) - }) - , - 'DESCRIPTOR' : _MODELINFERREQUEST, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelInferRequest) - }) +ModelInferRequest = _reflection.GeneratedProtocolMessageType( + "ModelInferRequest", + (_message.Message,), + { + "InferInputTensor": _reflection.GeneratedProtocolMessageType( + "InferInputTensor", + (_message.Message,), + { + "ParametersEntry": _reflection.GeneratedProtocolMessageType( + "ParametersEntry", + (_message.Message,), + { + "DESCRIPTOR": _MODELINFERREQUEST_INFERINPUTTENSOR_PARAMETERSENTRY, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelInferRequest.InferInputTensor.ParametersEntry) + }, + ), + "DESCRIPTOR": _MODELINFERREQUEST_INFERINPUTTENSOR, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelInferRequest.InferInputTensor) + }, + ), + "InferRequestedOutputTensor": _reflection.GeneratedProtocolMessageType( + "InferRequestedOutputTensor", + (_message.Message,), + { + "ParametersEntry": _reflection.GeneratedProtocolMessageType( + "ParametersEntry", + (_message.Message,), + { + "DESCRIPTOR": _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR_PARAMETERSENTRY, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelInferRequest.InferRequestedOutputTensor.ParametersEntry) + }, + ), + "DESCRIPTOR": _MODELINFERREQUEST_INFERREQUESTEDOUTPUTTENSOR, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelInferRequest.InferRequestedOutputTensor) + }, + ), + "ParametersEntry": _reflection.GeneratedProtocolMessageType( + "ParametersEntry", + (_message.Message,), + { + "DESCRIPTOR": _MODELINFERREQUEST_PARAMETERSENTRY, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelInferRequest.ParametersEntry) + }, + ), + "DESCRIPTOR": _MODELINFERREQUEST, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelInferRequest) + }, +) _sym_db.RegisterMessage(ModelInferRequest) _sym_db.RegisterMessage(ModelInferRequest.InferInputTensor) _sym_db.RegisterMessage(ModelInferRequest.InferInputTensor.ParametersEntry) @@ -1261,49 +2097,67 @@ _sym_db.RegisterMessage(ModelInferRequest.InferRequestedOutputTensor.ParametersEntry) _sym_db.RegisterMessage(ModelInferRequest.ParametersEntry) -ModelInferResponse = _reflection.GeneratedProtocolMessageType('ModelInferResponse', (_message.Message,), { - - 'InferOutputTensor' : _reflection.GeneratedProtocolMessageType('InferOutputTensor', (_message.Message,), { - - 'ParametersEntry' : _reflection.GeneratedProtocolMessageType('ParametersEntry', (_message.Message,), { - 'DESCRIPTOR' : _MODELINFERRESPONSE_INFEROUTPUTTENSOR_PARAMETERSENTRY, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelInferResponse.InferOutputTensor.ParametersEntry) - }) - , - 'DESCRIPTOR' : _MODELINFERRESPONSE_INFEROUTPUTTENSOR, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelInferResponse.InferOutputTensor) - }) - , - - 'ParametersEntry' : _reflection.GeneratedProtocolMessageType('ParametersEntry', (_message.Message,), { - 'DESCRIPTOR' : _MODELINFERRESPONSE_PARAMETERSENTRY, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelInferResponse.ParametersEntry) - }) - , - 'DESCRIPTOR' : _MODELINFERRESPONSE, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.ModelInferResponse) - }) +ModelInferResponse = _reflection.GeneratedProtocolMessageType( + "ModelInferResponse", + (_message.Message,), + { + "InferOutputTensor": _reflection.GeneratedProtocolMessageType( + "InferOutputTensor", + (_message.Message,), + { + "ParametersEntry": _reflection.GeneratedProtocolMessageType( + "ParametersEntry", + (_message.Message,), + { + "DESCRIPTOR": _MODELINFERRESPONSE_INFEROUTPUTTENSOR_PARAMETERSENTRY, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelInferResponse.InferOutputTensor.ParametersEntry) + }, + ), + "DESCRIPTOR": _MODELINFERRESPONSE_INFEROUTPUTTENSOR, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelInferResponse.InferOutputTensor) + }, + ), + "ParametersEntry": _reflection.GeneratedProtocolMessageType( + "ParametersEntry", + (_message.Message,), + { + "DESCRIPTOR": _MODELINFERRESPONSE_PARAMETERSENTRY, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelInferResponse.ParametersEntry) + }, + ), + "DESCRIPTOR": _MODELINFERRESPONSE, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.ModelInferResponse) + }, +) _sym_db.RegisterMessage(ModelInferResponse) _sym_db.RegisterMessage(ModelInferResponse.InferOutputTensor) _sym_db.RegisterMessage(ModelInferResponse.InferOutputTensor.ParametersEntry) _sym_db.RegisterMessage(ModelInferResponse.ParametersEntry) -InferParameter = _reflection.GeneratedProtocolMessageType('InferParameter', (_message.Message,), { - 'DESCRIPTOR' : _INFERPARAMETER, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.InferParameter) - }) +InferParameter = _reflection.GeneratedProtocolMessageType( + "InferParameter", + (_message.Message,), + { + "DESCRIPTOR": _INFERPARAMETER, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.InferParameter) + }, +) _sym_db.RegisterMessage(InferParameter) -InferTensorContents = _reflection.GeneratedProtocolMessageType('InferTensorContents', (_message.Message,), { - 'DESCRIPTOR' : _INFERTENSORCONTENTS, - '__module__' : 'dataplane_pb2' - # @@protoc_insertion_point(class_scope:inference.InferTensorContents) - }) +InferTensorContents = _reflection.GeneratedProtocolMessageType( + "InferTensorContents", + (_message.Message,), + { + "DESCRIPTOR": _INFERTENSORCONTENTS, + "__module__": "dataplane_pb2" + # @@protoc_insertion_point(class_scope:inference.InferTensorContents) + }, +) _sym_db.RegisterMessage(InferTensorContents) @@ -1315,78 +2169,79 @@ _MODELINFERRESPONSE_PARAMETERSENTRY._options = None _GRPCINFERENCESERVICE = _descriptor.ServiceDescriptor( - name='GRPCInferenceService', - full_name='inference.GRPCInferenceService', - file=DESCRIPTOR, - index=0, - serialized_options=None, - create_key=_descriptor._internal_create_key, - serialized_start=2554, - serialized_end=3062, - methods=[ - _descriptor.MethodDescriptor( - name='ServerLive', - full_name='inference.GRPCInferenceService.ServerLive', + name="GRPCInferenceService", + full_name="inference.GRPCInferenceService", + file=DESCRIPTOR, index=0, - containing_service=None, - input_type=_SERVERLIVEREQUEST, - output_type=_SERVERLIVERESPONSE, serialized_options=None, create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name='ServerReady', - full_name='inference.GRPCInferenceService.ServerReady', - index=1, - containing_service=None, - input_type=_SERVERREADYREQUEST, - output_type=_SERVERREADYRESPONSE, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name='ModelReady', - full_name='inference.GRPCInferenceService.ModelReady', - index=2, - containing_service=None, - input_type=_MODELREADYREQUEST, - output_type=_MODELREADYRESPONSE, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name='ServerMetadata', - full_name='inference.GRPCInferenceService.ServerMetadata', - index=3, - containing_service=None, - input_type=_SERVERMETADATAREQUEST, - output_type=_SERVERMETADATARESPONSE, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name='ModelMetadata', - full_name='inference.GRPCInferenceService.ModelMetadata', - index=4, - containing_service=None, - input_type=_MODELMETADATAREQUEST, - output_type=_MODELMETADATARESPONSE, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name='ModelInfer', - full_name='inference.GRPCInferenceService.ModelInfer', - index=5, - containing_service=None, - input_type=_MODELINFERREQUEST, - output_type=_MODELINFERRESPONSE, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), -]) + serialized_start=2554, + serialized_end=3062, + methods=[ + _descriptor.MethodDescriptor( + name="ServerLive", + full_name="inference.GRPCInferenceService.ServerLive", + index=0, + containing_service=None, + input_type=_SERVERLIVEREQUEST, + output_type=_SERVERLIVERESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name="ServerReady", + full_name="inference.GRPCInferenceService.ServerReady", + index=1, + containing_service=None, + input_type=_SERVERREADYREQUEST, + output_type=_SERVERREADYRESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name="ModelReady", + full_name="inference.GRPCInferenceService.ModelReady", + index=2, + containing_service=None, + input_type=_MODELREADYREQUEST, + output_type=_MODELREADYRESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name="ServerMetadata", + full_name="inference.GRPCInferenceService.ServerMetadata", + index=3, + containing_service=None, + input_type=_SERVERMETADATAREQUEST, + output_type=_SERVERMETADATARESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name="ModelMetadata", + full_name="inference.GRPCInferenceService.ModelMetadata", + index=4, + containing_service=None, + input_type=_MODELMETADATAREQUEST, + output_type=_MODELMETADATARESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name="ModelInfer", + full_name="inference.GRPCInferenceService.ModelInfer", + index=5, + containing_service=None, + input_type=_MODELINFERREQUEST, + output_type=_MODELINFERRESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + ], +) _sym_db.RegisterServiceDescriptor(_GRPCINFERENCESERVICE) -DESCRIPTOR.services_by_name['GRPCInferenceService'] = _GRPCINFERENCESERVICE +DESCRIPTOR.services_by_name["GRPCInferenceService"] = _GRPCINFERENCESERVICE # @@protoc_insertion_point(module_scope) diff --git a/mlserver/grpc/dataplane_pb2.pyi b/mlserver/grpc/dataplane_pb2.pyi index 6aa1dc2d1..eed0bbe16 100644 --- a/mlserver/grpc/dataplane_pb2.pyi +++ b/mlserver/grpc/dataplane_pb2.pyi @@ -11,83 +11,92 @@ import typing_extensions DESCRIPTOR: google.protobuf.descriptor.FileDescriptor = ... -# -# ServerLive messages. class ServerLiveRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... - def __init__(self, - ) -> None: ... + def __init__( + self, + ) -> None: ... + global___ServerLiveRequest = ServerLiveRequest class ServerLiveResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... LIVE_FIELD_NUMBER: builtins.int - # True if the inference server is live, false if not live. live: builtins.bool = ... - def __init__(self, + def __init__( + self, *, - live : builtins.bool = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal[u"live",b"live"]) -> None: ... + live: builtins.bool = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["live", b"live"] + ) -> None: ... + global___ServerLiveResponse = ServerLiveResponse -# -# ServerReady messages. class ServerReadyRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... - def __init__(self, - ) -> None: ... + def __init__( + self, + ) -> None: ... + global___ServerReadyRequest = ServerReadyRequest class ServerReadyResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... READY_FIELD_NUMBER: builtins.int - # True if the inference server is ready, false if not ready. ready: builtins.bool = ... - def __init__(self, + def __init__( + self, *, - ready : builtins.bool = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal[u"ready",b"ready"]) -> None: ... + ready: builtins.bool = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["ready", b"ready"] + ) -> None: ... + global___ServerReadyResponse = ServerReadyResponse -# -# ModelReady messages. class ModelReadyRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... NAME_FIELD_NUMBER: builtins.int VERSION_FIELD_NUMBER: builtins.int - # The name of the model to check for readiness. name: typing.Text = ... - # The version of the model to check for readiness. If not given the - # server will choose a version based on the model and internal policy. version: typing.Text = ... - def __init__(self, + def __init__( + self, *, - name : typing.Text = ..., - version : typing.Text = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal[u"name",b"name",u"version",b"version"]) -> None: ... + name: typing.Text = ..., + version: typing.Text = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal["name", b"name", "version", b"version"], + ) -> None: ... + global___ModelReadyRequest = ModelReadyRequest class ModelReadyResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... READY_FIELD_NUMBER: builtins.int - # True if the model is ready, false if not ready. ready: builtins.bool = ... - def __init__(self, + def __init__( + self, *, - ready : builtins.bool = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal[u"ready",b"ready"]) -> None: ... + ready: builtins.bool = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["ready", b"ready"] + ) -> None: ... + global___ModelReadyResponse = ModelReadyResponse -# -# ServerMetadata messages. class ServerMetadataRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... - def __init__(self, - ) -> None: ... + def __init__( + self, + ) -> None: ... + global___ServerMetadataRequest = ServerMetadataRequest class ServerMetadataResponse(google.protobuf.message.Message): @@ -95,44 +104,51 @@ class ServerMetadataResponse(google.protobuf.message.Message): NAME_FIELD_NUMBER: builtins.int VERSION_FIELD_NUMBER: builtins.int EXTENSIONS_FIELD_NUMBER: builtins.int - # The server name. name: typing.Text = ... - # The server version. version: typing.Text = ... - # The extensions supported by the server. @property - def extensions(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: ... - def __init__(self, + def extensions( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + typing.Text + ]: ... + def __init__( + self, *, - name : typing.Text = ..., - version : typing.Text = ..., - extensions : typing.Optional[typing.Iterable[typing.Text]] = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal[u"extensions",b"extensions",u"name",b"name",u"version",b"version"]) -> None: ... + name: typing.Text = ..., + version: typing.Text = ..., + extensions: typing.Optional[typing.Iterable[typing.Text]] = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "extensions", b"extensions", "name", b"name", "version", b"version" + ], + ) -> None: ... + global___ServerMetadataResponse = ServerMetadataResponse -# -# ModelMetadata messages. class ModelMetadataRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... NAME_FIELD_NUMBER: builtins.int VERSION_FIELD_NUMBER: builtins.int - # The name of the model. name: typing.Text = ... - # The version of the model to check for readiness. If not given the - # server will choose a version based on the model and internal policy. version: typing.Text = ... - def __init__(self, + def __init__( + self, *, - name : typing.Text = ..., - version : typing.Text = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal[u"name",b"name",u"version",b"version"]) -> None: ... + name: typing.Text = ..., + version: typing.Text = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal["name", b"name", "version", b"version"], + ) -> None: ... + global___ModelMetadataRequest = ModelMetadataRequest class ModelMetadataResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... - # Metadata for a tensor. class TensorMetadata(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... class TagsEntry(google.protobuf.message.Message): @@ -142,73 +158,118 @@ class ModelMetadataResponse(google.protobuf.message.Message): key: typing.Text = ... @property def value(self) -> global___InferParameter: ... - def __init__(self, + def __init__( + self, *, - key : typing.Text = ..., - value : typing.Optional[global___InferParameter] = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal[u"value",b"value"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal[u"key",b"key",u"value",b"value"]) -> None: ... - + key: typing.Text = ..., + value: typing.Optional[global___InferParameter] = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... NAME_FIELD_NUMBER: builtins.int DATATYPE_FIELD_NUMBER: builtins.int SHAPE_FIELD_NUMBER: builtins.int TAGS_FIELD_NUMBER: builtins.int - # The tensor name. name: typing.Text = ... - # The tensor data type. datatype: typing.Text = ... - # The tensor shape. A variable-size dimension is represented - # by a -1 value. @property - def shape(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... - # Optional tags about the input. - # NOTE: This is an extension to the standard + def shape( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.int + ]: ... @property - def tags(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, global___InferParameter]: ... - def __init__(self, + def tags( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + typing.Text, global___InferParameter + ]: ... + def __init__( + self, *, - name : typing.Text = ..., - datatype : typing.Text = ..., - shape : typing.Optional[typing.Iterable[builtins.int]] = ..., - tags : typing.Optional[typing.Mapping[typing.Text, global___InferParameter]] = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal[u"datatype",b"datatype",u"name",b"name",u"shape",b"shape",u"tags",b"tags"]) -> None: ... - + name: typing.Text = ..., + datatype: typing.Text = ..., + shape: typing.Optional[typing.Iterable[builtins.int]] = ..., + tags: typing.Optional[ + typing.Mapping[typing.Text, global___InferParameter] + ] = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "datatype", + b"datatype", + "name", + b"name", + "shape", + b"shape", + "tags", + b"tags", + ], + ) -> None: ... NAME_FIELD_NUMBER: builtins.int VERSIONS_FIELD_NUMBER: builtins.int PLATFORM_FIELD_NUMBER: builtins.int INPUTS_FIELD_NUMBER: builtins.int OUTPUTS_FIELD_NUMBER: builtins.int - # The model name. name: typing.Text = ... - # The versions of the model available on the server. @property - def versions(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: ... - # The model's platform. See Platforms. + def versions( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + typing.Text + ]: ... platform: typing.Text = ... - # The model's inputs. @property - def inputs(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___ModelMetadataResponse.TensorMetadata]: ... - # The model's outputs. + def inputs( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___ModelMetadataResponse.TensorMetadata + ]: ... @property - def outputs(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___ModelMetadataResponse.TensorMetadata]: ... - def __init__(self, + def outputs( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___ModelMetadataResponse.TensorMetadata + ]: ... + def __init__( + self, *, - name : typing.Text = ..., - versions : typing.Optional[typing.Iterable[typing.Text]] = ..., - platform : typing.Text = ..., - inputs : typing.Optional[typing.Iterable[global___ModelMetadataResponse.TensorMetadata]] = ..., - outputs : typing.Optional[typing.Iterable[global___ModelMetadataResponse.TensorMetadata]] = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal[u"inputs",b"inputs",u"name",b"name",u"outputs",b"outputs",u"platform",b"platform",u"versions",b"versions"]) -> None: ... + name: typing.Text = ..., + versions: typing.Optional[typing.Iterable[typing.Text]] = ..., + platform: typing.Text = ..., + inputs: typing.Optional[ + typing.Iterable[global___ModelMetadataResponse.TensorMetadata] + ] = ..., + outputs: typing.Optional[ + typing.Iterable[global___ModelMetadataResponse.TensorMetadata] + ] = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "inputs", + b"inputs", + "name", + b"name", + "outputs", + b"outputs", + "platform", + b"platform", + "versions", + b"versions", + ], + ) -> None: ... + global___ModelMetadataResponse = ModelMetadataResponse -# -# ModelInfer messages. class ModelInferRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... - # An input tensor for an inference request. class InferInputTensor(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... class ParametersEntry(google.protobuf.message.Message): @@ -218,44 +279,69 @@ class ModelInferRequest(google.protobuf.message.Message): key: typing.Text = ... @property def value(self) -> global___InferParameter: ... - def __init__(self, + def __init__( + self, *, - key : typing.Text = ..., - value : typing.Optional[global___InferParameter] = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal[u"value",b"value"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal[u"key",b"key",u"value",b"value"]) -> None: ... - + key: typing.Text = ..., + value: typing.Optional[global___InferParameter] = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... NAME_FIELD_NUMBER: builtins.int DATATYPE_FIELD_NUMBER: builtins.int SHAPE_FIELD_NUMBER: builtins.int PARAMETERS_FIELD_NUMBER: builtins.int CONTENTS_FIELD_NUMBER: builtins.int - # The tensor name. name: typing.Text = ... - # The tensor data type. datatype: typing.Text = ... - # The tensor shape. @property - def shape(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... - # Optional inference input tensor parameters. + def shape( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.int + ]: ... @property - def parameters(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, global___InferParameter]: ... - # The input tensor data. + def parameters( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + typing.Text, global___InferParameter + ]: ... @property def contents(self) -> global___InferTensorContents: ... - def __init__(self, + def __init__( + self, *, - name : typing.Text = ..., - datatype : typing.Text = ..., - shape : typing.Optional[typing.Iterable[builtins.int]] = ..., - parameters : typing.Optional[typing.Mapping[typing.Text, global___InferParameter]] = ..., - contents : typing.Optional[global___InferTensorContents] = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal[u"contents",b"contents"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal[u"contents",b"contents",u"datatype",b"datatype",u"name",b"name",u"parameters",b"parameters",u"shape",b"shape"]) -> None: ... - - # An output tensor requested for an inference request. + name: typing.Text = ..., + datatype: typing.Text = ..., + shape: typing.Optional[typing.Iterable[builtins.int]] = ..., + parameters: typing.Optional[ + typing.Mapping[typing.Text, global___InferParameter] + ] = ..., + contents: typing.Optional[global___InferTensorContents] = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["contents", b"contents"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "contents", + b"contents", + "datatype", + b"datatype", + "name", + b"name", + "parameters", + b"parameters", + "shape", + b"shape", + ], + ) -> None: ... class InferRequestedOutputTensor(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... class ParametersEntry(google.protobuf.message.Message): @@ -265,28 +351,42 @@ class ModelInferRequest(google.protobuf.message.Message): key: typing.Text = ... @property def value(self) -> global___InferParameter: ... - def __init__(self, + def __init__( + self, *, - key : typing.Text = ..., - value : typing.Optional[global___InferParameter] = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal[u"value",b"value"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal[u"key",b"key",u"value",b"value"]) -> None: ... - + key: typing.Text = ..., + value: typing.Optional[global___InferParameter] = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... NAME_FIELD_NUMBER: builtins.int PARAMETERS_FIELD_NUMBER: builtins.int - # The tensor name. name: typing.Text = ... - # Optional requested output tensor parameters. @property - def parameters(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, global___InferParameter]: ... - def __init__(self, + def parameters( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + typing.Text, global___InferParameter + ]: ... + def __init__( + self, *, - name : typing.Text = ..., - parameters : typing.Optional[typing.Mapping[typing.Text, global___InferParameter]] = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal[u"name",b"name",u"parameters",b"parameters"]) -> None: ... - + name: typing.Text = ..., + parameters: typing.Optional[ + typing.Mapping[typing.Text, global___InferParameter] + ] = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "name", b"name", "parameters", b"parameters" + ], + ) -> None: ... class ParametersEntry(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... KEY_FIELD_NUMBER: builtins.int @@ -294,53 +394,84 @@ class ModelInferRequest(google.protobuf.message.Message): key: typing.Text = ... @property def value(self) -> global___InferParameter: ... - def __init__(self, + def __init__( + self, *, - key : typing.Text = ..., - value : typing.Optional[global___InferParameter] = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal[u"value",b"value"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal[u"key",b"key",u"value",b"value"]) -> None: ... - + key: typing.Text = ..., + value: typing.Optional[global___InferParameter] = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... MODEL_NAME_FIELD_NUMBER: builtins.int MODEL_VERSION_FIELD_NUMBER: builtins.int ID_FIELD_NUMBER: builtins.int PARAMETERS_FIELD_NUMBER: builtins.int INPUTS_FIELD_NUMBER: builtins.int OUTPUTS_FIELD_NUMBER: builtins.int - # The name of the model to use for inferencing. model_name: typing.Text = ... - # The version of the model to use for inference. If not given the - # server will choose a version based on the model and internal policy. model_version: typing.Text = ... - # Optional identifier for the request. If specified will be - # returned in the response. id: typing.Text = ... - # Optional inference parameters. @property - def parameters(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, global___InferParameter]: ... - # The input tensors for the inference. + def parameters( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + typing.Text, global___InferParameter + ]: ... @property - def inputs(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___ModelInferRequest.InferInputTensor]: ... - # The requested output tensors for the inference. Optional, if not - # specified all outputs produced by the model will be returned. + def inputs( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___ModelInferRequest.InferInputTensor + ]: ... @property - def outputs(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___ModelInferRequest.InferRequestedOutputTensor]: ... - def __init__(self, + def outputs( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___ModelInferRequest.InferRequestedOutputTensor + ]: ... + def __init__( + self, *, - model_name : typing.Text = ..., - model_version : typing.Text = ..., - id : typing.Text = ..., - parameters : typing.Optional[typing.Mapping[typing.Text, global___InferParameter]] = ..., - inputs : typing.Optional[typing.Iterable[global___ModelInferRequest.InferInputTensor]] = ..., - outputs : typing.Optional[typing.Iterable[global___ModelInferRequest.InferRequestedOutputTensor]] = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal[u"id",b"id",u"inputs",b"inputs",u"model_name",b"model_name",u"model_version",b"model_version",u"outputs",b"outputs",u"parameters",b"parameters"]) -> None: ... + model_name: typing.Text = ..., + model_version: typing.Text = ..., + id: typing.Text = ..., + parameters: typing.Optional[ + typing.Mapping[typing.Text, global___InferParameter] + ] = ..., + inputs: typing.Optional[ + typing.Iterable[global___ModelInferRequest.InferInputTensor] + ] = ..., + outputs: typing.Optional[ + typing.Iterable[global___ModelInferRequest.InferRequestedOutputTensor] + ] = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "id", + b"id", + "inputs", + b"inputs", + "model_name", + b"model_name", + "model_version", + b"model_version", + "outputs", + b"outputs", + "parameters", + b"parameters", + ], + ) -> None: ... + global___ModelInferRequest = ModelInferRequest class ModelInferResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... - # An output tensor returned for an inference request. class InferOutputTensor(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... class ParametersEntry(google.protobuf.message.Message): @@ -350,43 +481,69 @@ class ModelInferResponse(google.protobuf.message.Message): key: typing.Text = ... @property def value(self) -> global___InferParameter: ... - def __init__(self, + def __init__( + self, *, - key : typing.Text = ..., - value : typing.Optional[global___InferParameter] = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal[u"value",b"value"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal[u"key",b"key",u"value",b"value"]) -> None: ... - + key: typing.Text = ..., + value: typing.Optional[global___InferParameter] = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... NAME_FIELD_NUMBER: builtins.int DATATYPE_FIELD_NUMBER: builtins.int SHAPE_FIELD_NUMBER: builtins.int PARAMETERS_FIELD_NUMBER: builtins.int CONTENTS_FIELD_NUMBER: builtins.int - # The tensor name. name: typing.Text = ... - # The tensor data type. datatype: typing.Text = ... - # The tensor shape. @property - def shape(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... - # Optional output tensor parameters. + def shape( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.int + ]: ... @property - def parameters(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, global___InferParameter]: ... - # The output tensor data. + def parameters( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + typing.Text, global___InferParameter + ]: ... @property def contents(self) -> global___InferTensorContents: ... - def __init__(self, + def __init__( + self, *, - name : typing.Text = ..., - datatype : typing.Text = ..., - shape : typing.Optional[typing.Iterable[builtins.int]] = ..., - parameters : typing.Optional[typing.Mapping[typing.Text, global___InferParameter]] = ..., - contents : typing.Optional[global___InferTensorContents] = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal[u"contents",b"contents"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal[u"contents",b"contents",u"datatype",b"datatype",u"name",b"name",u"parameters",b"parameters",u"shape",b"shape"]) -> None: ... - + name: typing.Text = ..., + datatype: typing.Text = ..., + shape: typing.Optional[typing.Iterable[builtins.int]] = ..., + parameters: typing.Optional[ + typing.Mapping[typing.Text, global___InferParameter] + ] = ..., + contents: typing.Optional[global___InferTensorContents] = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["contents", b"contents"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "contents", + b"contents", + "datatype", + b"datatype", + "name", + b"name", + "parameters", + b"parameters", + "shape", + b"shape", + ], + ) -> None: ... class ParametersEntry(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... KEY_FIELD_NUMBER: builtins.int @@ -394,71 +551,118 @@ class ModelInferResponse(google.protobuf.message.Message): key: typing.Text = ... @property def value(self) -> global___InferParameter: ... - def __init__(self, + def __init__( + self, *, - key : typing.Text = ..., - value : typing.Optional[global___InferParameter] = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal[u"value",b"value"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal[u"key",b"key",u"value",b"value"]) -> None: ... - + key: typing.Text = ..., + value: typing.Optional[global___InferParameter] = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... MODEL_NAME_FIELD_NUMBER: builtins.int MODEL_VERSION_FIELD_NUMBER: builtins.int ID_FIELD_NUMBER: builtins.int PARAMETERS_FIELD_NUMBER: builtins.int OUTPUTS_FIELD_NUMBER: builtins.int - # The name of the model used for inference. model_name: typing.Text = ... - # The version of the model used for inference. model_version: typing.Text = ... - # The id of the inference request if one was specified. id: typing.Text = ... - # Optional inference response parameters. @property - def parameters(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, global___InferParameter]: ... - # The output tensors holding inference results. + def parameters( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + typing.Text, global___InferParameter + ]: ... @property - def outputs(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___ModelInferResponse.InferOutputTensor]: ... - def __init__(self, + def outputs( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___ModelInferResponse.InferOutputTensor + ]: ... + def __init__( + self, *, - model_name : typing.Text = ..., - model_version : typing.Text = ..., - id : typing.Text = ..., - parameters : typing.Optional[typing.Mapping[typing.Text, global___InferParameter]] = ..., - outputs : typing.Optional[typing.Iterable[global___ModelInferResponse.InferOutputTensor]] = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal[u"id",b"id",u"model_name",b"model_name",u"model_version",b"model_version",u"outputs",b"outputs",u"parameters",b"parameters"]) -> None: ... + model_name: typing.Text = ..., + model_version: typing.Text = ..., + id: typing.Text = ..., + parameters: typing.Optional[ + typing.Mapping[typing.Text, global___InferParameter] + ] = ..., + outputs: typing.Optional[ + typing.Iterable[global___ModelInferResponse.InferOutputTensor] + ] = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "id", + b"id", + "model_name", + b"model_name", + "model_version", + b"model_version", + "outputs", + b"outputs", + "parameters", + b"parameters", + ], + ) -> None: ... + global___ModelInferResponse = ModelInferResponse -# -# An inference parameter value. class InferParameter(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... BOOL_PARAM_FIELD_NUMBER: builtins.int INT64_PARAM_FIELD_NUMBER: builtins.int STRING_PARAM_FIELD_NUMBER: builtins.int - # A boolean parameter value. bool_param: builtins.bool = ... - # An int64 parameter value. int64_param: builtins.int = ... - # A string parameter value. string_param: typing.Text = ... - def __init__(self, + def __init__( + self, *, - bool_param : builtins.bool = ..., - int64_param : builtins.int = ..., - string_param : typing.Text = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal[u"bool_param",b"bool_param",u"int64_param",b"int64_param",u"parameter_choice",b"parameter_choice",u"string_param",b"string_param"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal[u"bool_param",b"bool_param",u"int64_param",b"int64_param",u"parameter_choice",b"parameter_choice",u"string_param",b"string_param"]) -> None: ... - def WhichOneof(self, oneof_group: typing_extensions.Literal[u"parameter_choice",b"parameter_choice"]) -> typing.Optional[typing_extensions.Literal["bool_param","int64_param","string_param"]]: ... + bool_param: builtins.bool = ..., + int64_param: builtins.int = ..., + string_param: typing.Text = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "bool_param", + b"bool_param", + "int64_param", + b"int64_param", + "parameter_choice", + b"parameter_choice", + "string_param", + b"string_param", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "bool_param", + b"bool_param", + "int64_param", + b"int64_param", + "parameter_choice", + b"parameter_choice", + "string_param", + b"string_param", + ], + ) -> None: ... + def WhichOneof( + self, + oneof_group: typing_extensions.Literal["parameter_choice", b"parameter_choice"], + ) -> typing_extensions.Literal["bool_param", "int64_param", "string_param"]: ... + global___InferParameter = InferParameter -# -# The data contained in a tensor. For a given data type the -# tensor contents can be represented in "raw" bytes form or in -# the repeated type that matches the tensor's data type. Protobuf -# oneof is not used because oneofs cannot contain repeated fields. class InferTensorContents(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... BOOL_CONTENTS_FIELD_NUMBER: builtins.int @@ -469,58 +673,86 @@ class InferTensorContents(google.protobuf.message.Message): FP32_CONTENTS_FIELD_NUMBER: builtins.int FP64_CONTENTS_FIELD_NUMBER: builtins.int BYTES_CONTENTS_FIELD_NUMBER: builtins.int - # Representation for BOOL data type. The size must match what is - # expected by the tensor's shape. The contents must be the flattened, - # one-dimensional, row-major order of the tensor elements. @property - def bool_contents(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.bool]: ... - # Representation for INT8, INT16, and INT32 data types. The size - # must match what is expected by the tensor's shape. The contents - # must be the flattened, one-dimensional, row-major order of the - # tensor elements. + def bool_contents( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.bool + ]: ... @property - def int_contents(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... - # Representation for INT64 data types. The size must match what - # is expected by the tensor's shape. The contents must be the - # flattened, one-dimensional, row-major order of the tensor elements. + def int_contents( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.int + ]: ... @property - def int64_contents(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... - # Representation for UINT8, UINT16, and UINT32 data types. The size - # must match what is expected by the tensor's shape. The contents - # must be the flattened, one-dimensional, row-major order of the - # tensor elements. + def int64_contents( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.int + ]: ... @property - def uint_contents(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... - # Representation for UINT64 data types. The size must match what - # is expected by the tensor's shape. The contents must be the - # flattened, one-dimensional, row-major order of the tensor elements. + def uint_contents( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.int + ]: ... @property - def uint64_contents(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... - # Representation for FP32 data type. The size must match what is - # expected by the tensor's shape. The contents must be the flattened, - # one-dimensional, row-major order of the tensor elements. + def uint64_contents( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.int + ]: ... @property - def fp32_contents(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: ... - # Representation for FP64 data type. The size must match what is - # expected by the tensor's shape. The contents must be the flattened, - # one-dimensional, row-major order of the tensor elements. + def fp32_contents( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.float + ]: ... @property - def fp64_contents(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: ... - # Representation for BYTES data type. The size must match what is - # expected by the tensor's shape. The contents must be the flattened, - # one-dimensional, row-major order of the tensor elements. + def fp64_contents( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.float + ]: ... @property - def bytes_contents(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.bytes]: ... - def __init__(self, + def bytes_contents( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.bytes + ]: ... + def __init__( + self, *, - bool_contents : typing.Optional[typing.Iterable[builtins.bool]] = ..., - int_contents : typing.Optional[typing.Iterable[builtins.int]] = ..., - int64_contents : typing.Optional[typing.Iterable[builtins.int]] = ..., - uint_contents : typing.Optional[typing.Iterable[builtins.int]] = ..., - uint64_contents : typing.Optional[typing.Iterable[builtins.int]] = ..., - fp32_contents : typing.Optional[typing.Iterable[builtins.float]] = ..., - fp64_contents : typing.Optional[typing.Iterable[builtins.float]] = ..., - bytes_contents : typing.Optional[typing.Iterable[builtins.bytes]] = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal[u"bool_contents",b"bool_contents",u"bytes_contents",b"bytes_contents",u"fp32_contents",b"fp32_contents",u"fp64_contents",b"fp64_contents",u"int64_contents",b"int64_contents",u"int_contents",b"int_contents",u"uint64_contents",b"uint64_contents",u"uint_contents",b"uint_contents"]) -> None: ... + bool_contents: typing.Optional[typing.Iterable[builtins.bool]] = ..., + int_contents: typing.Optional[typing.Iterable[builtins.int]] = ..., + int64_contents: typing.Optional[typing.Iterable[builtins.int]] = ..., + uint_contents: typing.Optional[typing.Iterable[builtins.int]] = ..., + uint64_contents: typing.Optional[typing.Iterable[builtins.int]] = ..., + fp32_contents: typing.Optional[typing.Iterable[builtins.float]] = ..., + fp64_contents: typing.Optional[typing.Iterable[builtins.float]] = ..., + bytes_contents: typing.Optional[typing.Iterable[builtins.bytes]] = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "bool_contents", + b"bool_contents", + "bytes_contents", + b"bytes_contents", + "fp32_contents", + b"fp32_contents", + "fp64_contents", + b"fp64_contents", + "int64_contents", + b"int64_contents", + "int_contents", + b"int_contents", + "uint64_contents", + b"uint64_contents", + "uint_contents", + b"uint_contents", + ], + ) -> None: ... + global___InferTensorContents = InferTensorContents diff --git a/mlserver/grpc/dataplane_pb2_grpc.py b/mlserver/grpc/dataplane_pb2_grpc.py index b6a118947..85e8979f6 100644 --- a/mlserver/grpc/dataplane_pb2_grpc.py +++ b/mlserver/grpc/dataplane_pb2_grpc.py @@ -18,35 +18,35 @@ def __init__(self, channel): channel: A grpc.Channel. """ self.ServerLive = channel.unary_unary( - '/inference.GRPCInferenceService/ServerLive', - request_serializer=dataplane__pb2.ServerLiveRequest.SerializeToString, - response_deserializer=dataplane__pb2.ServerLiveResponse.FromString, - ) + "/inference.GRPCInferenceService/ServerLive", + request_serializer=dataplane__pb2.ServerLiveRequest.SerializeToString, + response_deserializer=dataplane__pb2.ServerLiveResponse.FromString, + ) self.ServerReady = channel.unary_unary( - '/inference.GRPCInferenceService/ServerReady', - request_serializer=dataplane__pb2.ServerReadyRequest.SerializeToString, - response_deserializer=dataplane__pb2.ServerReadyResponse.FromString, - ) + "/inference.GRPCInferenceService/ServerReady", + request_serializer=dataplane__pb2.ServerReadyRequest.SerializeToString, + response_deserializer=dataplane__pb2.ServerReadyResponse.FromString, + ) self.ModelReady = channel.unary_unary( - '/inference.GRPCInferenceService/ModelReady', - request_serializer=dataplane__pb2.ModelReadyRequest.SerializeToString, - response_deserializer=dataplane__pb2.ModelReadyResponse.FromString, - ) + "/inference.GRPCInferenceService/ModelReady", + request_serializer=dataplane__pb2.ModelReadyRequest.SerializeToString, + response_deserializer=dataplane__pb2.ModelReadyResponse.FromString, + ) self.ServerMetadata = channel.unary_unary( - '/inference.GRPCInferenceService/ServerMetadata', - request_serializer=dataplane__pb2.ServerMetadataRequest.SerializeToString, - response_deserializer=dataplane__pb2.ServerMetadataResponse.FromString, - ) + "/inference.GRPCInferenceService/ServerMetadata", + request_serializer=dataplane__pb2.ServerMetadataRequest.SerializeToString, + response_deserializer=dataplane__pb2.ServerMetadataResponse.FromString, + ) self.ModelMetadata = channel.unary_unary( - '/inference.GRPCInferenceService/ModelMetadata', - request_serializer=dataplane__pb2.ModelMetadataRequest.SerializeToString, - response_deserializer=dataplane__pb2.ModelMetadataResponse.FromString, - ) + "/inference.GRPCInferenceService/ModelMetadata", + request_serializer=dataplane__pb2.ModelMetadataRequest.SerializeToString, + response_deserializer=dataplane__pb2.ModelMetadataResponse.FromString, + ) self.ModelInfer = channel.unary_unary( - '/inference.GRPCInferenceService/ModelInfer', - request_serializer=dataplane__pb2.ModelInferRequest.SerializeToString, - response_deserializer=dataplane__pb2.ModelInferResponse.FromString, - ) + "/inference.GRPCInferenceService/ModelInfer", + request_serializer=dataplane__pb2.ModelInferRequest.SerializeToString, + response_deserializer=dataplane__pb2.ModelInferResponse.FromString, + ) class GRPCInferenceServiceServicer(object): @@ -56,87 +56,82 @@ class GRPCInferenceServiceServicer(object): """ def ServerLive(self, request, context): - """Check liveness of the inference server. - """ + """Check liveness of the inference server.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") def ServerReady(self, request, context): - """Check readiness of the inference server. - """ + """Check readiness of the inference server.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") def ModelReady(self, request, context): - """Check readiness of a model in the inference server. - """ + """Check readiness of a model in the inference server.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") def ServerMetadata(self, request, context): - """Get server metadata. - """ + """Get server metadata.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") def ModelMetadata(self, request, context): - """Get model metadata. - """ + """Get model metadata.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") def ModelInfer(self, request, context): - """Perform inference using a specific model. - """ + """Perform inference using a specific model.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") def add_GRPCInferenceServiceServicer_to_server(servicer, server): rpc_method_handlers = { - 'ServerLive': grpc.unary_unary_rpc_method_handler( - servicer.ServerLive, - request_deserializer=dataplane__pb2.ServerLiveRequest.FromString, - response_serializer=dataplane__pb2.ServerLiveResponse.SerializeToString, - ), - 'ServerReady': grpc.unary_unary_rpc_method_handler( - servicer.ServerReady, - request_deserializer=dataplane__pb2.ServerReadyRequest.FromString, - response_serializer=dataplane__pb2.ServerReadyResponse.SerializeToString, - ), - 'ModelReady': grpc.unary_unary_rpc_method_handler( - servicer.ModelReady, - request_deserializer=dataplane__pb2.ModelReadyRequest.FromString, - response_serializer=dataplane__pb2.ModelReadyResponse.SerializeToString, - ), - 'ServerMetadata': grpc.unary_unary_rpc_method_handler( - servicer.ServerMetadata, - request_deserializer=dataplane__pb2.ServerMetadataRequest.FromString, - response_serializer=dataplane__pb2.ServerMetadataResponse.SerializeToString, - ), - 'ModelMetadata': grpc.unary_unary_rpc_method_handler( - servicer.ModelMetadata, - request_deserializer=dataplane__pb2.ModelMetadataRequest.FromString, - response_serializer=dataplane__pb2.ModelMetadataResponse.SerializeToString, - ), - 'ModelInfer': grpc.unary_unary_rpc_method_handler( - servicer.ModelInfer, - request_deserializer=dataplane__pb2.ModelInferRequest.FromString, - response_serializer=dataplane__pb2.ModelInferResponse.SerializeToString, - ), + "ServerLive": grpc.unary_unary_rpc_method_handler( + servicer.ServerLive, + request_deserializer=dataplane__pb2.ServerLiveRequest.FromString, + response_serializer=dataplane__pb2.ServerLiveResponse.SerializeToString, + ), + "ServerReady": grpc.unary_unary_rpc_method_handler( + servicer.ServerReady, + request_deserializer=dataplane__pb2.ServerReadyRequest.FromString, + response_serializer=dataplane__pb2.ServerReadyResponse.SerializeToString, + ), + "ModelReady": grpc.unary_unary_rpc_method_handler( + servicer.ModelReady, + request_deserializer=dataplane__pb2.ModelReadyRequest.FromString, + response_serializer=dataplane__pb2.ModelReadyResponse.SerializeToString, + ), + "ServerMetadata": grpc.unary_unary_rpc_method_handler( + servicer.ServerMetadata, + request_deserializer=dataplane__pb2.ServerMetadataRequest.FromString, + response_serializer=dataplane__pb2.ServerMetadataResponse.SerializeToString, + ), + "ModelMetadata": grpc.unary_unary_rpc_method_handler( + servicer.ModelMetadata, + request_deserializer=dataplane__pb2.ModelMetadataRequest.FromString, + response_serializer=dataplane__pb2.ModelMetadataResponse.SerializeToString, + ), + "ModelInfer": grpc.unary_unary_rpc_method_handler( + servicer.ModelInfer, + request_deserializer=dataplane__pb2.ModelInferRequest.FromString, + response_serializer=dataplane__pb2.ModelInferResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( - 'inference.GRPCInferenceService', rpc_method_handlers) + "inference.GRPCInferenceService", rpc_method_handlers + ) server.add_generic_rpc_handlers((generic_handler,)) - # This class is part of an EXPERIMENTAL API. +# This class is part of an EXPERIMENTAL API. class GRPCInferenceService(object): """ Inference Server GRPC endpoints. @@ -144,103 +139,175 @@ class GRPCInferenceService(object): """ @staticmethod - def ServerLive(request, + def ServerLive( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/inference.GRPCInferenceService/ServerLive', + "/inference.GRPCInferenceService/ServerLive", dataplane__pb2.ServerLiveRequest.SerializeToString, dataplane__pb2.ServerLiveResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) @staticmethod - def ServerReady(request, + def ServerReady( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/inference.GRPCInferenceService/ServerReady', + "/inference.GRPCInferenceService/ServerReady", dataplane__pb2.ServerReadyRequest.SerializeToString, dataplane__pb2.ServerReadyResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) @staticmethod - def ModelReady(request, + def ModelReady( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/inference.GRPCInferenceService/ModelReady', + "/inference.GRPCInferenceService/ModelReady", dataplane__pb2.ModelReadyRequest.SerializeToString, dataplane__pb2.ModelReadyResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) @staticmethod - def ServerMetadata(request, + def ServerMetadata( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/inference.GRPCInferenceService/ServerMetadata', + "/inference.GRPCInferenceService/ServerMetadata", dataplane__pb2.ServerMetadataRequest.SerializeToString, dataplane__pb2.ServerMetadataResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) @staticmethod - def ModelMetadata(request, + def ModelMetadata( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/inference.GRPCInferenceService/ModelMetadata', + "/inference.GRPCInferenceService/ModelMetadata", dataplane__pb2.ModelMetadataRequest.SerializeToString, dataplane__pb2.ModelMetadataResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) @staticmethod - def ModelInfer(request, + def ModelInfer( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/inference.GRPCInferenceService/ModelInfer', + "/inference.GRPCInferenceService/ModelInfer", dataplane__pb2.ModelInferRequest.SerializeToString, dataplane__pb2.ModelInferResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) From 9904fd6cccd65209dc6a26be6c8d3c1db2bab3cc Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Tue, 31 Aug 2021 10:43:57 +0100 Subject: [PATCH 22/28] Fix merge --- mlserver/codecs/base64.py | 6 ++++-- mlserver/codecs/datetime.py | 6 ++++-- mlserver/codecs/numpy.py | 2 +- mlserver/codecs/string.py | 5 +++-- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/mlserver/codecs/base64.py b/mlserver/codecs/base64.py index 5290f9245..f264e3d7c 100644 --- a/mlserver/codecs/base64.py +++ b/mlserver/codecs/base64.py @@ -41,7 +41,8 @@ class Base64Codec(InputCodec): ContentType = "base64" - def encode(self, name: str, payload: List[bytes]) -> ResponseOutput: + @classmethod + def encode(cls, name: str, payload: List[bytes]) -> ResponseOutput: # Assume that payload is already in b64, so we only need to pack it packed, shape = pack(map(_encode_base64, payload)) return ResponseOutput( @@ -51,7 +52,8 @@ def encode(self, name: str, payload: List[bytes]) -> ResponseOutput: data=packed, ) - def decode(self, request_input: RequestInput) -> List[bytes]: + @classmethod + def decode(cls, request_input: RequestInput) -> List[bytes]: packed = request_input.data.__root__ shape = request_input.shape diff --git a/mlserver/codecs/datetime.py b/mlserver/codecs/datetime.py index 7b4cdf6b9..81a62e0f1 100644 --- a/mlserver/codecs/datetime.py +++ b/mlserver/codecs/datetime.py @@ -42,7 +42,8 @@ class DatetimeCodec(InputCodec): ContentType = "datetime" - def encode(self, name: str, payload: List[_Datetime]) -> ResponseOutput: + @classmethod + def encode(cls, name: str, payload: List[_Datetime]) -> ResponseOutput: # Assume that payload is already in b64, so we only need to pack it packed, shape = pack(map(_encode_datetime, payload)) return ResponseOutput( @@ -52,7 +53,8 @@ def encode(self, name: str, payload: List[_Datetime]) -> ResponseOutput: data=packed, ) - def decode(self, request_input: RequestInput) -> List[datetime]: + @classmethod + def decode(cls, request_input: RequestInput) -> List[datetime]: packed = request_input.data.__root__ shape = request_input.shape diff --git a/mlserver/codecs/numpy.py b/mlserver/codecs/numpy.py index 403343d22..a5cec21be 100644 --- a/mlserver/codecs/numpy.py +++ b/mlserver/codecs/numpy.py @@ -83,7 +83,7 @@ class NumpyCodec(InputCodec): @classmethod def encode(cls, name: str, payload: np.ndarray) -> ResponseOutput: - datatype = _to_datatype(payload.dtype) + datatype = to_datatype(payload.dtype) return ResponseOutput( name=name, diff --git a/mlserver/codecs/string.py b/mlserver/codecs/string.py index 201fc0ccc..b2e26a9f8 100644 --- a/mlserver/codecs/string.py +++ b/mlserver/codecs/string.py @@ -45,10 +45,11 @@ def encode(cls, name: str, payload: List[str]) -> ResponseOutput: @classmethod def decode(cls, request_input: RequestInput) -> List[str]: - encoded = request_input.data.__root__ + packed = request_input.data.__root__ shape = request_input.shape - return [_decode_str(elem) for elem in _split_elements(encoded, shape)] + unpacked = map(_decode_str, unpack(packed, shape)) + return list(unpacked) @register_request_codec From c79626e431b6289c70ec8bd0a60cdd11da8a2e94 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Tue, 31 Aug 2021 10:45:10 +0100 Subject: [PATCH 23/28] Fix linter --- mlserver/codecs/string.py | 8 --- mlserver/grpc/dataplane_pb2.pyi | 105 +++++++++++++++++++++++++++++++- 2 files changed, 104 insertions(+), 9 deletions(-) diff --git a/mlserver/codecs/string.py b/mlserver/codecs/string.py index b2e26a9f8..5a4fce0df 100644 --- a/mlserver/codecs/string.py +++ b/mlserver/codecs/string.py @@ -56,11 +56,3 @@ def decode(cls, request_input: RequestInput) -> List[str]: class StringRequestCodec(FirstInputRequestCodec): InputCodec = StringCodec ContentType = StringCodec.ContentType - - @classmethod - def decode(cls, request_input: RequestInput) -> List[str]: - packed = request_input.data.__root__ - shape = request_input.shape - - unpacked = map(_decode_str, unpack(packed, shape)) - return list(unpacked) diff --git a/mlserver/grpc/dataplane_pb2.pyi b/mlserver/grpc/dataplane_pb2.pyi index eed0bbe16..a399e897d 100644 --- a/mlserver/grpc/dataplane_pb2.pyi +++ b/mlserver/grpc/dataplane_pb2.pyi @@ -11,6 +11,8 @@ import typing_extensions DESCRIPTOR: google.protobuf.descriptor.FileDescriptor = ... +# +# ServerLive messages. class ServerLiveRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... def __init__( @@ -22,6 +24,7 @@ global___ServerLiveRequest = ServerLiveRequest class ServerLiveResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... LIVE_FIELD_NUMBER: builtins.int + # True if the inference server is live, false if not live. live: builtins.bool = ... def __init__( self, @@ -34,6 +37,8 @@ class ServerLiveResponse(google.protobuf.message.Message): global___ServerLiveResponse = ServerLiveResponse +# +# ServerReady messages. class ServerReadyRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... def __init__( @@ -45,6 +50,7 @@ global___ServerReadyRequest = ServerReadyRequest class ServerReadyResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... READY_FIELD_NUMBER: builtins.int + # True if the inference server is ready, false if not ready. ready: builtins.bool = ... def __init__( self, @@ -57,11 +63,16 @@ class ServerReadyResponse(google.protobuf.message.Message): global___ServerReadyResponse = ServerReadyResponse +# +# ModelReady messages. class ModelReadyRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... NAME_FIELD_NUMBER: builtins.int VERSION_FIELD_NUMBER: builtins.int + # The name of the model to check for readiness. name: typing.Text = ... + # The version of the model to check for readiness. If not given the + # server will choose a version based on the model and internal policy. version: typing.Text = ... def __init__( self, @@ -79,6 +90,7 @@ global___ModelReadyRequest = ModelReadyRequest class ModelReadyResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... READY_FIELD_NUMBER: builtins.int + # True if the model is ready, false if not ready. ready: builtins.bool = ... def __init__( self, @@ -91,6 +103,8 @@ class ModelReadyResponse(google.protobuf.message.Message): global___ModelReadyResponse = ModelReadyResponse +# +# ServerMetadata messages. class ServerMetadataRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... def __init__( @@ -104,8 +118,11 @@ class ServerMetadataResponse(google.protobuf.message.Message): NAME_FIELD_NUMBER: builtins.int VERSION_FIELD_NUMBER: builtins.int EXTENSIONS_FIELD_NUMBER: builtins.int + # The server name. name: typing.Text = ... + # The server version. version: typing.Text = ... + # The extensions supported by the server. @property def extensions( self, @@ -128,11 +145,16 @@ class ServerMetadataResponse(google.protobuf.message.Message): global___ServerMetadataResponse = ServerMetadataResponse +# +# ModelMetadata messages. class ModelMetadataRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... NAME_FIELD_NUMBER: builtins.int VERSION_FIELD_NUMBER: builtins.int + # The name of the model. name: typing.Text = ... + # The version of the model to check for readiness. If not given the + # server will choose a version based on the model and internal policy. version: typing.Text = ... def __init__( self, @@ -149,6 +171,7 @@ global___ModelMetadataRequest = ModelMetadataRequest class ModelMetadataResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... + # Metadata for a tensor. class TensorMetadata(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... class TagsEntry(google.protobuf.message.Message): @@ -175,14 +198,20 @@ class ModelMetadataResponse(google.protobuf.message.Message): DATATYPE_FIELD_NUMBER: builtins.int SHAPE_FIELD_NUMBER: builtins.int TAGS_FIELD_NUMBER: builtins.int + # The tensor name. name: typing.Text = ... + # The tensor data type. datatype: typing.Text = ... + # The tensor shape. A variable-size dimension is represented + # by a -1 value. @property def shape( self, ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ builtins.int ]: ... + # Optional tags about the input. + # NOTE: This is an extension to the standard @property def tags( self, @@ -217,20 +246,25 @@ class ModelMetadataResponse(google.protobuf.message.Message): PLATFORM_FIELD_NUMBER: builtins.int INPUTS_FIELD_NUMBER: builtins.int OUTPUTS_FIELD_NUMBER: builtins.int + # The model name. name: typing.Text = ... + # The versions of the model available on the server. @property def versions( self, ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ typing.Text ]: ... + # The model's platform. See Platforms. platform: typing.Text = ... + # The model's inputs. @property def inputs( self, ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ global___ModelMetadataResponse.TensorMetadata ]: ... + # The model's outputs. @property def outputs( self, @@ -268,8 +302,11 @@ class ModelMetadataResponse(google.protobuf.message.Message): global___ModelMetadataResponse = ModelMetadataResponse +# +# ModelInfer messages. class ModelInferRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... + # An input tensor for an inference request. class InferInputTensor(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... class ParametersEntry(google.protobuf.message.Message): @@ -297,20 +334,25 @@ class ModelInferRequest(google.protobuf.message.Message): SHAPE_FIELD_NUMBER: builtins.int PARAMETERS_FIELD_NUMBER: builtins.int CONTENTS_FIELD_NUMBER: builtins.int + # The tensor name. name: typing.Text = ... + # The tensor data type. datatype: typing.Text = ... + # The tensor shape. @property def shape( self, ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ builtins.int ]: ... + # Optional inference input tensor parameters. @property def parameters( self, ) -> google.protobuf.internal.containers.MessageMap[ typing.Text, global___InferParameter ]: ... + # The input tensor data. @property def contents(self) -> global___InferTensorContents: ... def __init__( @@ -342,6 +384,7 @@ class ModelInferRequest(google.protobuf.message.Message): b"shape", ], ) -> None: ... + # An output tensor requested for an inference request. class InferRequestedOutputTensor(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... class ParametersEntry(google.protobuf.message.Message): @@ -366,7 +409,9 @@ class ModelInferRequest(google.protobuf.message.Message): ) -> None: ... NAME_FIELD_NUMBER: builtins.int PARAMETERS_FIELD_NUMBER: builtins.int + # The tensor name. name: typing.Text = ... + # Optional requested output tensor parameters. @property def parameters( self, @@ -413,21 +458,30 @@ class ModelInferRequest(google.protobuf.message.Message): PARAMETERS_FIELD_NUMBER: builtins.int INPUTS_FIELD_NUMBER: builtins.int OUTPUTS_FIELD_NUMBER: builtins.int + # The name of the model to use for inferencing. model_name: typing.Text = ... + # The version of the model to use for inference. If not given the + # server will choose a version based on the model and internal policy. model_version: typing.Text = ... + # Optional identifier for the request. If specified will be + # returned in the response. id: typing.Text = ... + # Optional inference parameters. @property def parameters( self, ) -> google.protobuf.internal.containers.MessageMap[ typing.Text, global___InferParameter ]: ... + # The input tensors for the inference. @property def inputs( self, ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ global___ModelInferRequest.InferInputTensor ]: ... + # The requested output tensors for the inference. Optional, if not + # specified all outputs produced by the model will be returned. @property def outputs( self, @@ -472,6 +526,7 @@ global___ModelInferRequest = ModelInferRequest class ModelInferResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... + # An output tensor returned for an inference request. class InferOutputTensor(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... class ParametersEntry(google.protobuf.message.Message): @@ -499,20 +554,25 @@ class ModelInferResponse(google.protobuf.message.Message): SHAPE_FIELD_NUMBER: builtins.int PARAMETERS_FIELD_NUMBER: builtins.int CONTENTS_FIELD_NUMBER: builtins.int + # The tensor name. name: typing.Text = ... + # The tensor data type. datatype: typing.Text = ... + # The tensor shape. @property def shape( self, ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ builtins.int ]: ... + # Optional output tensor parameters. @property def parameters( self, ) -> google.protobuf.internal.containers.MessageMap[ typing.Text, global___InferParameter ]: ... + # The output tensor data. @property def contents(self) -> global___InferTensorContents: ... def __init__( @@ -569,15 +629,20 @@ class ModelInferResponse(google.protobuf.message.Message): ID_FIELD_NUMBER: builtins.int PARAMETERS_FIELD_NUMBER: builtins.int OUTPUTS_FIELD_NUMBER: builtins.int + # The name of the model used for inference. model_name: typing.Text = ... + # The version of the model used for inference. model_version: typing.Text = ... + # The id of the inference request if one was specified. id: typing.Text = ... + # Optional inference response parameters. @property def parameters( self, ) -> google.protobuf.internal.containers.MessageMap[ typing.Text, global___InferParameter ]: ... + # The output tensors holding inference results. @property def outputs( self, @@ -615,13 +680,18 @@ class ModelInferResponse(google.protobuf.message.Message): global___ModelInferResponse = ModelInferResponse +# +# An inference parameter value. class InferParameter(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... BOOL_PARAM_FIELD_NUMBER: builtins.int INT64_PARAM_FIELD_NUMBER: builtins.int STRING_PARAM_FIELD_NUMBER: builtins.int + # A boolean parameter value. bool_param: builtins.bool = ... + # An int64 parameter value. int64_param: builtins.int = ... + # A string parameter value. string_param: typing.Text = ... def __init__( self, @@ -659,10 +729,17 @@ class InferParameter(google.protobuf.message.Message): def WhichOneof( self, oneof_group: typing_extensions.Literal["parameter_choice", b"parameter_choice"], - ) -> typing_extensions.Literal["bool_param", "int64_param", "string_param"]: ... + ) -> typing.Optional[ + typing_extensions.Literal["bool_param", "int64_param", "string_param"] + ]: ... global___InferParameter = InferParameter +# +# The data contained in a tensor. For a given data type the +# tensor contents can be represented in "raw" bytes form or in +# the repeated type that matches the tensor's data type. Protobuf +# oneof is not used because oneofs cannot contain repeated fields. class InferTensorContents(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor = ... BOOL_CONTENTS_FIELD_NUMBER: builtins.int @@ -673,48 +750,74 @@ class InferTensorContents(google.protobuf.message.Message): FP32_CONTENTS_FIELD_NUMBER: builtins.int FP64_CONTENTS_FIELD_NUMBER: builtins.int BYTES_CONTENTS_FIELD_NUMBER: builtins.int + # Representation for BOOL data type. The size must match what is + # expected by the tensor's shape. The contents must be the flattened, + # one-dimensional, row-major order of the tensor elements. @property def bool_contents( self, ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ builtins.bool ]: ... + # Representation for INT8, INT16, and INT32 data types. The size + # must match what is expected by the tensor's shape. The contents + # must be the flattened, one-dimensional, row-major order of the + # tensor elements. @property def int_contents( self, ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ builtins.int ]: ... + # Representation for INT64 data types. The size must match what + # is expected by the tensor's shape. The contents must be the + # flattened, one-dimensional, row-major order of the tensor elements. @property def int64_contents( self, ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ builtins.int ]: ... + # Representation for UINT8, UINT16, and UINT32 data types. The size + # must match what is expected by the tensor's shape. The contents + # must be the flattened, one-dimensional, row-major order of the + # tensor elements. @property def uint_contents( self, ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ builtins.int ]: ... + # Representation for UINT64 data types. The size must match what + # is expected by the tensor's shape. The contents must be the + # flattened, one-dimensional, row-major order of the tensor elements. @property def uint64_contents( self, ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ builtins.int ]: ... + # Representation for FP32 data type. The size must match what is + # expected by the tensor's shape. The contents must be the flattened, + # one-dimensional, row-major order of the tensor elements. @property def fp32_contents( self, ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ builtins.float ]: ... + # Representation for FP64 data type. The size must match what is + # expected by the tensor's shape. The contents must be the flattened, + # one-dimensional, row-major order of the tensor elements. @property def fp64_contents( self, ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ builtins.float ]: ... + # Representation for BYTES data type. The size must match what is + # expected by the tensor's shape. The contents must be the flattened, + # one-dimensional, row-major order of the tensor elements. @property def bytes_contents( self, From c4b8a0d1cdb79aa331746fa332f4632d5a553b17 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Thu, 2 Sep 2021 12:11:33 +0100 Subject: [PATCH 24/28] Add section on metadata to MLflow example --- docs/examples/alibi-detect/README.md | 347 +++++++++++++++++++++++ docs/examples/mlflow/README.ipynb | 238 +++++++++++++--- docs/examples/mlflow/README.md | 68 ++++- docs/examples/mlflow/model-settings.json | 2 +- docs/examples/mlflow/src/train.py | 9 +- 5 files changed, 618 insertions(+), 46 deletions(-) create mode 100644 docs/examples/alibi-detect/README.md diff --git a/docs/examples/alibi-detect/README.md b/docs/examples/alibi-detect/README.md new file mode 100644 index 000000000..3aff8a64e --- /dev/null +++ b/docs/examples/alibi-detect/README.md @@ -0,0 +1,347 @@ +# Serving Alibi-Detect models + +Out of the box, `mlserver` supports the deployment and serving of `alibi-detect` models. In this example, we will cover how we can create a detector configuration to then serve it using `mlserver`. + +## Reference Data and Configuration + +The first step will be to fetch a reference data for an `alibi-detect` model. For that, we will use the [income Classifier example from the `alibi-detect` documentation](https://docs.seldon.io/projects/alibi-detect/en/latest/examples/cd_chi2ks_adult.html) + +Install Alibi dependencies for dataset and detector creation + + +```python +!pip install alibi alibi_detect +``` + + +```python +import alibi +import matplotlib.pyplot as plt +import numpy as np +``` + + +```python +adult = alibi.datasets.fetch_adult() +X, y = adult.data, adult.target +feature_names = adult.feature_names +category_map = adult.category_map +X.shape, y.shape +``` + + +```python +n_ref = 10000 +n_test = 10000 + +X_ref, X_t0, X_t1 = X[:n_ref], X[n_ref:n_ref + n_test], X[n_ref + n_test:n_ref + 2 * n_test] +X_ref.shape, X_t0.shape, X_t1.shape +``` + + +```python +categories_per_feature = {f: None for f in list(category_map.keys())} +``` + +### Saving our reference data + + +```python +detector_data={"x_ref":X_ref,"categories_per_feature":categories_per_feature} +``` + + +```python +import pickle +filepath = 'alibi-detector-artifacts/detector_data.pkl' +pickle.dump(detector_data, open(filepath,"wb")) +``` + +## Serving + +Now that we have the reference data and other configuration parameters, the next step will be to serve it using `mlserver`. +For that, we will need to create 2 configuration files: + +- `settings.json`: holds the configuration of our server (e.g. ports, log level, etc.). +- `model-settings.json`: holds the configuration of our model (e.g. input type, runtime to use, etc.). + +### `settings.json` + + +```python +%%writefile settings.json +{ + "debug": "true" +} +``` + +### `model-settings.json` + + +```python +%%writefile model-settings.json +{ + "name": "income-classifier-cd", + "implementation": "mlserver_alibi_detect.AlibiDriftDetectRuntime", + "parameters": { + "uri": "./alibi-detector-artifacts/detector_data.pkl", + "version": "v0.1.0", + "extra":{ + "detector_type":"alibi_detect.cd.TabularDrift", + "protocol": "kfserving.http", + "init_detector": true, + "init_parameters": { + "p_val": 0.05 + }, + "predict_parameters": { + "drift_type": "feature" + } + } + } +} +``` + +### Start serving our model + +Now that we have our config in-place, we can start the server by running `mlserver start .`. This needs to either be ran from the same directory where our config files are or pointing to the folder where they are. + +```shell +mlserver start . +``` + +Since this command will start the server and block the terminal, waiting for requests, this will need to be ran in the background on a separate terminal. + +### Send test inference request + +We now have our model being served by `mlserver`. +To make sure that everything is working as expected, let's send a request from our test set. + +For that, we can use the Python types that `mlserver` provides out of box, or we can build our request manually. + +# TabularDrift + +### Detecting Drift locally + + +```python +from alibi_detect.cd import TabularDrift +cd = TabularDrift(X_ref, p_val=.05, categories_per_feature=categories_per_feature) +cd.predict(X_t0,drift_type="feature") +``` + +### Detecting Drift via MLServer + + +```python +import requests + +inference_request = { + "inputs": [ + { + "name": "predict", + "shape": X_t0.shape, + "datatype": "FP32", + "data": X_t0.tolist(), + } + ], +} + +endpoint = "http://localhost:8080/v2/models/income-classifier-cd/versions/v0.1.0/infer" +response = requests.post(endpoint, json=inference_request) +``` + + +```python +import json +response_dict = json.loads(response.text) +print(response_dict,"\n") + +labels = ['No!', 'Yes!'] +for f in range(cd.n_features): + stat = 'Chi2' if f in list(categories_per_feature.keys()) else 'K-S' + fname = feature_names[f] + is_drift = response_dict['outputs'][0]['data'][f] + print(f'{fname} -- Drift? {labels[is_drift]}') +``` + +### Detecting Drift via custom endpoint for v2 protocol + + +```python +import requests + +inference_request = { + "inputs": [ + { + "name": "predict", + "shape": X_t0.shape, + "datatype": "FP32", + "data": X_t0.tolist(), + } + ], +} + +endpoint = "http://localhost:8080/" +response = requests.post(endpoint, json=inference_request) +``` + + +```python +import json +response_dict = json.loads(response.text) +print(response_dict,"\n") + +labels = ['No!', 'Yes!'] +for f in range(cd.n_features): + stat = 'Chi2' if f in list(categories_per_feature.keys()) else 'K-S' + fname = feature_names[f] + is_drift = response_dict['data']['is_drift'][f] + stat_val, p_val = response_dict['data']['distance'][f], response_dict['data']['p_val'][f] + print(f'{fname} -- Drift? {labels[is_drift]} -- {stat} {stat_val:.3f} -- p-value {p_val:.3f}') +``` + +### Detecting Drift via custom endpoint for Tensorflow protocol + + +```python +%%writefile model-settings.json +{ + "name": "income-classifier-cd", + "implementation": "mlserver_alibi_detect.AlibiDriftDetectRuntime", + "parameters": { + "uri": "./alibi-detector-artifacts/detector_data.pkl", + "version": "v0.1.0", + "extra":{ + "detector_type":"alibi_detect.cd.TabularDrift", + "init_detector":true, + "protocol": "tensorflow.http", + "init_parameters": { + "p_val": 0.05 + }, + "predict_parameters": { + "drift_type": "feature" + } + } + } +} +``` + +Restart the mlserver after changing the settings file. + + +```python +import requests + +inference_request = { + "instances": X_t1.tolist() +} + +endpoint = "http://localhost:8080/" +response = requests.post(endpoint, json=inference_request) +``` + + +```python +import json +response_dict = json.loads(response.text) +print(response_dict,"\n") + +labels = ['No!', 'Yes!'] +for f in range(cd.n_features): + stat = 'Chi2' if f in list(categories_per_feature.keys()) else 'K-S' + fname = feature_names[f] + is_drift = response_dict['data']['is_drift'][f] + stat_val, p_val = response_dict['data']['distance'][f], response_dict['data']['p_val'][f] + print(f'{fname} -- Drift? {labels[is_drift]} -- {stat} {stat_val:.3f} -- p-value {p_val:.3f}') +``` + +# ChiSquareDrift + +### Detecting Drift locally + + +```python +cols = list(category_map.keys()) +cat_names = [feature_names[_] for _ in list(category_map.keys())] +X_ref_cat, X_t0_cat = X_ref[:, cols], X_t0[:, cols] +X_ref_cat.shape, X_t0_cat.shape +``` + + +```python +from alibi_detect.cd import ChiSquareDrift +cd = ChiSquareDrift(X_ref_cat, p_val=.05) +preds = cd.predict(X_t0_cat,drift_type="feature") +``` + + +```python +labels = ['No!', 'Yes!'] +print(f"Threshold {preds['data']['threshold']}") +for f in range(cd.n_features): + fname = cat_names[f] + is_drift = (preds['data']['p_val'][f] < preds['data']['threshold']).astype(int) + stat_val, p_val = preds['data']['distance'][f], preds['data']['p_val'][f] + print(f'{fname} -- Drift? {labels[is_drift]} -- Chi2 {stat_val:.3f} -- p-value {p_val:.3f}') +``` + +### Detecting Drift via custom endpoint for Seldon protocol + + +```python +from alibi_detect.utils.saving import save_detector +filepath = "alibi-detector-artifacts/detector_data_cat" +save_detector(cd, filepath) +``` + + +```python +%%writefile model-settings.json +{ + "name": "income-classifier-cd", + "implementation": "mlserver_alibi_detect.AlibiDriftDetectRuntime", + "parameters": { + "uri": "./alibi-detector-artifacts/detector_data_cat", + "version": "v0.1.0", + "extra":{ + "detector_type":"alibi_detect.cd.ChiSquareDrift", + "init_detector": false, + "protocol": "seldon.http", + "predict_parameters": { + "drift_type": "feature" + } + } + } +} +``` + +Restart the mlserver after changing the settings file. + + +```python +import requests + +inference_request = { + "data":{ + "ndarray": X_t0_cat.tolist() + } +} + +endpoint = "http://localhost:8080/" +response = requests.post(endpoint, json=inference_request) +``` + + +```python +import json +response_dict = json.loads(response.text) +print(response_dict,"\n") + +labels = ['No!', 'Yes!'] +for f in range(cd.n_features): + stat = 'Chi2' if f in list(categories_per_feature.keys()) else 'K-S' + fname = cat_names[f] + is_drift = response_dict['data']['is_drift'][f] + stat_val, p_val = response_dict['data']['distance'][f], response_dict['data']['p_val'][f] + print(f'{fname} -- Drift? {labels[is_drift]} -- {stat} {stat_val:.3f} -- p-value {p_val:.3f}') +``` diff --git a/docs/examples/mlflow/README.ipynb b/docs/examples/mlflow/README.ipynb index 8aef08210..1ddac2ce8 100644 --- a/docs/examples/mlflow/README.ipynb +++ b/docs/examples/mlflow/README.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "cooked-value", + "id": "vocal-tamil", "metadata": {}, "source": [ "# Serving MLflow models\n", @@ -17,8 +17,8 @@ }, { "cell_type": "code", - "execution_count": 38, - "id": "duplicate-arnold", + "execution_count": 12, + "id": "second-america", "metadata": {}, "outputs": [], "source": [ @@ -32,7 +32,7 @@ }, { "cell_type": "markdown", - "id": "structured-arabic", + "id": "based-turning", "metadata": {}, "source": [ "## Training\n", @@ -43,12 +43,9 @@ }, { "cell_type": "code", - "execution_count": 2, - "id": "accepted-sharing", + "execution_count": 3, + "id": "small-dressing", "metadata": { - "jupyter": { - "source_hidden": true - }, "tags": [] }, "outputs": [], @@ -57,11 +54,12 @@ "# Original source code and more details can be found in:\n", "# https://www.mlflow.org/docs/latest/tutorials-and-examples/tutorial.html\n", "\n", - "# The data set used in this example is from http://archive.ics.uci.edu/ml/datasets/Wine+Quality\n", + "# The data set used in this example is from\n", + "# http://archive.ics.uci.edu/ml/datasets/Wine+Quality\n", "# P. Cortez, A. Cerdeira, F. Almeida, T. Matos and J. Reis.\n", - "# Modeling wine preferences by data mining from physicochemical properties. In Decision Support Systems, Elsevier, 47(4):547-553, 2009.\n", + "# Modeling wine preferences by data mining from physicochemical properties.\n", + "# In Decision Support Systems, Elsevier, 47(4):547-553, 2009.\n", "\n", - "import os\n", "import warnings\n", "import sys\n", "\n", @@ -73,6 +71,7 @@ "from urllib.parse import urlparse\n", "import mlflow\n", "import mlflow.sklearn\n", + "from mlflow.models.signature import infer_signature\n", "\n", "import logging\n", "\n", @@ -92,12 +91,16 @@ " np.random.seed(40)\n", "\n", " # Read the wine-quality csv file from the URL\n", - " csv_url = \"http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv\"\n", + " csv_url = (\n", + " \"http://archive.ics.uci.edu/ml\"\n", + " \"/machine-learning-databases/wine-quality/winequality-red.csv\"\n", + " )\n", " try:\n", " data = pd.read_csv(csv_url, sep=\";\")\n", " except Exception as e:\n", " logger.exception(\n", - " \"Unable to download training & test CSV, check your internet connection. Error: %s\",\n", + " \"Unable to download training & test CSV, \"\n", + " \"check your internet connection. Error: %s\",\n", " e,\n", " )\n", "\n", @@ -133,25 +136,30 @@ " mlflow.log_metric(\"mae\", mae)\n", "\n", " tracking_url_type_store = urlparse(mlflow.get_tracking_uri()).scheme\n", + " model_signature = infer_signature(train_x, train_y)\n", "\n", " # Model registry does not work with file store\n", " if tracking_url_type_store != \"file\":\n", "\n", " # Register the model\n", - " # There are other ways to use the Model Registry, which depends on the use case,\n", + " # There are other ways to use the Model Registry,\n", + " # which depends on the use case,\n", " # please refer to the doc for more information:\n", " # https://mlflow.org/docs/latest/model-registry.html#api-workflow\n", " mlflow.sklearn.log_model(\n", - " lr, \"model\", registered_model_name=\"ElasticnetWineModel\"\n", + " lr,\n", + " \"model\",\n", + " registered_model_name=\"ElasticnetWineModel\",\n", + " signature=model_signature,\n", " )\n", " else:\n", - " mlflow.sklearn.log_model(lr, \"model\")\n" + " mlflow.sklearn.log_model(lr, \"model\", signature=model_signature)\n" ] }, { "cell_type": "code", - "execution_count": 3, - "id": "distinct-senator", + "execution_count": 8, + "id": "intensive-interstate", "metadata": {}, "outputs": [ { @@ -171,7 +179,7 @@ }, { "cell_type": "markdown", - "id": "black-retreat", + "id": "republican-accent", "metadata": {}, "source": [ "The training script will also serialise our trained model, leveraging the [MLflow Model format](https://www.mlflow.org/docs/latest/models.html).\n", @@ -180,15 +188,15 @@ }, { "cell_type": "code", - "execution_count": 19, - "id": "honey-necessity", + "execution_count": 9, + "id": "dramatic-physiology", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "./mlruns/0/7bb8825ef42d4ae992ab17dc419b9c0a/artifacts/model\n" + "./mlruns/0/3dbfe3a610214e09b6fd01e72d3b9597/artifacts/model\n" ] } ], @@ -200,8 +208,8 @@ }, { "cell_type": "code", - "execution_count": 20, - "id": "retained-sweet", + "execution_count": 10, + "id": "saving-cattle", "metadata": {}, "outputs": [ { @@ -218,7 +226,7 @@ }, { "cell_type": "markdown", - "id": "bizarre-parameter", + "id": "inner-perception", "metadata": {}, "source": [ "## Serving\n", @@ -229,8 +237,8 @@ }, { "cell_type": "code", - "execution_count": 43, - "id": "yellow-newsletter", + "execution_count": 13, + "id": "romantic-dispatch", "metadata": {}, "outputs": [], "source": [ @@ -246,7 +254,7 @@ }, { "cell_type": "markdown", - "id": "direct-romantic", + "id": "chinese-table", "metadata": {}, "source": [ "Now that we have our config in-place, we can start the server by running `mlserver start .`. This needs to either be ran from the same directory where our config files are or pointing to the folder where they are.\n", @@ -260,7 +268,7 @@ }, { "cell_type": "markdown", - "id": "formed-there", + "id": "endangered-creature", "metadata": {}, "source": [ "### Send test inference request\n", @@ -281,7 +289,7 @@ { "cell_type": "code", "execution_count": 57, - "id": "concrete-setting", + "id": "potential-complement", "metadata": {}, "outputs": [ { @@ -421,7 +429,7 @@ }, { "cell_type": "markdown", - "id": "paperback-penny", + "id": "reflected-david", "metadata": {}, "source": [ "As we can see in the output above, the predicted quality score for our input wine was `5.57`." @@ -429,7 +437,7 @@ }, { "cell_type": "markdown", - "id": "eight-premises", + "id": "frank-pottery", "metadata": {}, "source": [ "### MLflow Scoring Protocol\n", @@ -444,7 +452,7 @@ { "cell_type": "code", "execution_count": 9, - "id": "portuguese-likelihood", + "id": "lesbian-mitchell", "metadata": {}, "outputs": [ { @@ -486,11 +494,171 @@ }, { "cell_type": "markdown", - "id": "applied-tunisia", + "id": "macro-vocabulary", "metadata": {}, "source": [ "As we can see above, the predicted quality for our input is `5.57`, matching the prediction we obtained above." ] + }, + { + "cell_type": "markdown", + "id": "weekly-colorado", + "metadata": {}, + "source": [ + "### MLflow Model Signature\n", + "\n", + "MLflow lets users define a [_model signature_](https://www.mlflow.org/docs/latest/models.html#model-signature-and-input-example), where they can specify what types of inputs does the model accept, and what types of outputs it returns. \n", + "Similarly, the [V2 inference protocol](https://github.com/kubeflow/kfserving/tree/master/docs/predict-api/v2) employed by MLServer defines a [_metadata endpoint_](https://github.com/kubeflow/kfserving/blob/master/docs/predict-api/v2/required_api.md#model-metadata) which can be used to query what inputs and outputs does the model accept.\n", + "However, even though they serve similar functions, the data schemas used by each one of them are not compatible between them.\n", + "\n", + "To solve this, if your model defines a MLflow model signature, MLServer will convert _on-the-fly_ this signature to a metadata schema compatible with the V2 Inference Protocol.\n", + "This will also include specifying any extra [content type](../content-type/README.md) that is required to correctly decode / encode your data.\n", + "\n", + "As an example, we can first have a look at the model signature saved for our MLflow model.\n", + "This can be seen directly on the `MLModel` file saved by our model.\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "driving-continent", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "artifact_path: model\n", + "flavors:\n", + " python_function:\n", + " env: conda.yaml\n", + " loader_module: mlflow.sklearn\n", + " model_path: model.pkl\n", + " python_version: 3.7.8\n", + " sklearn:\n", + " pickled_model: model.pkl\n", + " serialization_format: cloudpickle\n", + " sklearn_version: 0.24.1\n", + "run_id: 3dbfe3a610214e09b6fd01e72d3b9597\n", + "signature:\n", + " inputs: '[{\"name\": \"fixed acidity\", \"type\": \"double\"}, {\"name\": \"volatile acidity\",\n", + " \"type\": \"double\"}, {\"name\": \"citric acid\", \"type\": \"double\"}, {\"name\": \"residual\n", + " sugar\", \"type\": \"double\"}, {\"name\": \"chlorides\", \"type\": \"double\"}, {\"name\": \"free\n", + " sulfur dioxide\", \"type\": \"double\"}, {\"name\": \"total sulfur dioxide\", \"type\": \"double\"},\n", + " {\"name\": \"density\", \"type\": \"double\"}, {\"name\": \"pH\", \"type\": \"double\"}, {\"name\":\n", + " \"sulphates\", \"type\": \"double\"}, {\"name\": \"alcohol\", \"type\": \"double\"}]'\n", + " outputs: '[{\"name\": \"quality\", \"type\": \"long\"}]'\n", + "utc_time_created: '2021-09-02 11:06:20.928245'\n" + ] + } + ], + "source": [ + "!cat {model_path}/MLmodel" + ] + }, + { + "cell_type": "markdown", + "id": "successful-gross", + "metadata": {}, + "source": [ + "We can then query the metadata endpoint, to see the model metadata inferred by MLServer from our test model's signature.\n", + "For this, we will use the `/v2/models/wine-classifier/` endpoint." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "clinical-exploration", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'name': 'wine-classifier',\n", + " 'versions': [],\n", + " 'platform': '',\n", + " 'inputs': [{'name': 'fixed acidity',\n", + " 'datatype': 'FP64',\n", + " 'shape': [-1],\n", + " 'tags': {'content_type': 'np'}},\n", + " {'name': 'volatile acidity',\n", + " 'datatype': 'FP64',\n", + " 'shape': [-1],\n", + " 'tags': {'content_type': 'np'}},\n", + " {'name': 'citric acid',\n", + " 'datatype': 'FP64',\n", + " 'shape': [-1],\n", + " 'tags': {'content_type': 'np'}},\n", + " {'name': 'residual sugar',\n", + " 'datatype': 'FP64',\n", + " 'shape': [-1],\n", + " 'tags': {'content_type': 'np'}},\n", + " {'name': 'chlorides',\n", + " 'datatype': 'FP64',\n", + " 'shape': [-1],\n", + " 'tags': {'content_type': 'np'}},\n", + " {'name': 'free sulfur dioxide',\n", + " 'datatype': 'FP64',\n", + " 'shape': [-1],\n", + " 'tags': {'content_type': 'np'}},\n", + " {'name': 'total sulfur dioxide',\n", + " 'datatype': 'FP64',\n", + " 'shape': [-1],\n", + " 'tags': {'content_type': 'np'}},\n", + " {'name': 'density',\n", + " 'datatype': 'FP64',\n", + " 'shape': [-1],\n", + " 'tags': {'content_type': 'np'}},\n", + " {'name': 'pH',\n", + " 'datatype': 'FP64',\n", + " 'shape': [-1],\n", + " 'tags': {'content_type': 'np'}},\n", + " {'name': 'sulphates',\n", + " 'datatype': 'FP64',\n", + " 'shape': [-1],\n", + " 'tags': {'content_type': 'np'}},\n", + " {'name': 'alcohol',\n", + " 'datatype': 'FP64',\n", + " 'shape': [-1],\n", + " 'tags': {'content_type': 'np'}}],\n", + " 'outputs': [{'name': 'quality',\n", + " 'datatype': 'INT64',\n", + " 'shape': [-1],\n", + " 'tags': {'content_type': 'np'}}]}" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import requests\n", + "\n", + "\n", + "endpoint = \"http://localhost:8080/v2/models/wine-classifier/\"\n", + "response = requests.get(endpoint)\n", + "\n", + "response.json()" + ] + }, + { + "cell_type": "markdown", + "id": "spanish-treat", + "metadata": {}, + "source": [ + "As we should be able to see, the model metadata now matches the information contained in our model signature, including any extra content types necessary to decode our data correctly." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "saved-group", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/docs/examples/mlflow/README.md b/docs/examples/mlflow/README.md index 006bd4d20..a7f0b4d64 100644 --- a/docs/examples/mlflow/README.md +++ b/docs/examples/mlflow/README.md @@ -28,11 +28,12 @@ For that, we will use the [linear regression examle from the MLflow docs](https: # Original source code and more details can be found in: # https://www.mlflow.org/docs/latest/tutorials-and-examples/tutorial.html -# The data set used in this example is from http://archive.ics.uci.edu/ml/datasets/Wine+Quality +# The data set used in this example is from +# http://archive.ics.uci.edu/ml/datasets/Wine+Quality # P. Cortez, A. Cerdeira, F. Almeida, T. Matos and J. Reis. -# Modeling wine preferences by data mining from physicochemical properties. In Decision Support Systems, Elsevier, 47(4):547-553, 2009. +# Modeling wine preferences by data mining from physicochemical properties. +# In Decision Support Systems, Elsevier, 47(4):547-553, 2009. -import os import warnings import sys @@ -44,6 +45,7 @@ from sklearn.linear_model import ElasticNet from urllib.parse import urlparse import mlflow import mlflow.sklearn +from mlflow.models.signature import infer_signature import logging @@ -63,12 +65,16 @@ if __name__ == "__main__": np.random.seed(40) # Read the wine-quality csv file from the URL - csv_url = "http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv" + csv_url = ( + "http://archive.ics.uci.edu/ml" + "/machine-learning-databases/wine-quality/winequality-red.csv" + ) try: data = pd.read_csv(csv_url, sep=";") except Exception as e: logger.exception( - "Unable to download training & test CSV, check your internet connection. Error: %s", + "Unable to download training & test CSV, " + "check your internet connection. Error: %s", e, ) @@ -104,19 +110,24 @@ if __name__ == "__main__": mlflow.log_metric("mae", mae) tracking_url_type_store = urlparse(mlflow.get_tracking_uri()).scheme + model_signature = infer_signature(train_x, train_y) # Model registry does not work with file store if tracking_url_type_store != "file": # Register the model - # There are other ways to use the Model Registry, which depends on the use case, + # There are other ways to use the Model Registry, + # which depends on the use case, # please refer to the doc for more information: # https://mlflow.org/docs/latest/model-registry.html#api-workflow mlflow.sklearn.log_model( - lr, "model", registered_model_name="ElasticnetWineModel" + lr, + "model", + registered_model_name="ElasticnetWineModel", + signature=model_signature, ) else: - mlflow.sklearn.log_model(lr, "model") + mlflow.sklearn.log_model(lr, "model", signature=model_signature) ``` @@ -334,3 +345,44 @@ response.json() ``` As we can see above, the predicted quality for our input is `5.57`, matching the prediction we obtained above. + +### MLflow Model Signature + +MLflow lets users define a [_model signature_](https://www.mlflow.org/docs/latest/models.html#model-signature-and-input-example), where they can specify what types of inputs does the model accept, and what types of outputs it returns. +Similarly, the [V2 inference protocol](https://github.com/kubeflow/kfserving/tree/master/docs/predict-api/v2) employed by MLServer defines a [_metadata endpoint_](https://github.com/kubeflow/kfserving/blob/master/docs/predict-api/v2/required_api.md#model-metadata) which can be used to query what inputs and outputs does the model accept. +However, even though they serve similar functions, the data schemas used by each one of them are not compatible between them. + +To solve this, if your model defines a MLflow model signature, MLServer will convert _on-the-fly_ this signature to a metadata schema compatible with the V2 Inference Protocol. +This will also include specifying any extra [content type](../content-type/README.md) that is required to correctly decode / encode your data. + +As an example, we can first have a look at the model signature saved for our MLflow model. +This can be seen directly on the `MLModel` file saved by our model. + + + + + +```python +!cat {model_path}/MLmodel +``` + +We can then query the metadata endpoint, to see the model metadata inferred by MLServer from our test model's signature. +For this, we will use the `/v2/models/wine-classifier/` endpoint. + + +```python +import requests + + +endpoint = "http://localhost:8080/v2/models/wine-classifier/" +response = requests.get(endpoint) + +response.json() +``` + +As we should be able to see, the model metadata now matches the information contained in our model signature, including any extra content types necessary to decode our data correctly. + + +```python + +``` diff --git a/docs/examples/mlflow/model-settings.json b/docs/examples/mlflow/model-settings.json index 8b0512136..89e5cd0e5 100644 --- a/docs/examples/mlflow/model-settings.json +++ b/docs/examples/mlflow/model-settings.json @@ -2,6 +2,6 @@ "name": "wine-classifier", "implementation": "mlserver_mlflow.MLflowRuntime", "parameters": { - "uri": "./mlruns/0/7bb8825ef42d4ae992ab17dc419b9c0a/artifacts/model" + "uri": "./mlruns/0/3dbfe3a610214e09b6fd01e72d3b9597/artifacts/model" } } diff --git a/docs/examples/mlflow/src/train.py b/docs/examples/mlflow/src/train.py index 1e9704edb..c19fd5aa3 100644 --- a/docs/examples/mlflow/src/train.py +++ b/docs/examples/mlflow/src/train.py @@ -18,6 +18,7 @@ from urllib.parse import urlparse import mlflow import mlflow.sklearn +from mlflow.models.signature import infer_signature import logging @@ -82,6 +83,7 @@ def eval_metrics(actual, pred): mlflow.log_metric("mae", mae) tracking_url_type_store = urlparse(mlflow.get_tracking_uri()).scheme + model_signature = infer_signature(train_x, train_y) # Model registry does not work with file store if tracking_url_type_store != "file": @@ -92,7 +94,10 @@ def eval_metrics(actual, pred): # please refer to the doc for more information: # https://mlflow.org/docs/latest/model-registry.html#api-workflow mlflow.sklearn.log_model( - lr, "model", registered_model_name="ElasticnetWineModel" + lr, + "model", + registered_model_name="ElasticnetWineModel", + signature=model_signature, ) else: - mlflow.sklearn.log_model(lr, "model") + mlflow.sklearn.log_model(lr, "model", signature=model_signature) From 0f24cc44cf3623a5e278004b3fdfe8832a9ba700 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Fri, 10 Sep 2021 10:41:50 +0100 Subject: [PATCH 25/28] Remove unused to_metadata method --- runtimes/mlflow/mlserver_mlflow/metadata.py | 20 +------------ runtimes/mlflow/tests/test_metadata.py | 33 --------------------- 2 files changed, 1 insertion(+), 52 deletions(-) diff --git a/runtimes/mlflow/mlserver_mlflow/metadata.py b/runtimes/mlflow/mlserver_mlflow/metadata.py index b0929de22..6a5688947 100644 --- a/runtimes/mlflow/mlserver_mlflow/metadata.py +++ b/runtimes/mlflow/mlserver_mlflow/metadata.py @@ -1,10 +1,8 @@ from typing import Union, Tuple, List from mlflow.types.schema import Schema, ColSpec, TensorSpec, DataType -from mlflow.models.signature import ModelSignature -from mlserver.settings import ModelSettings -from mlserver.types import MetadataModelResponse, MetadataTensor, Tags +from mlserver.types import MetadataTensor, Tags from mlserver.codecs import NumpyCodec, StringCodec, Base64Codec, DatetimeCodec from mlserver.codecs.numpy import to_datatype @@ -63,19 +61,3 @@ def to_metadata_tensors( ) return metadata_tensors - - -def to_metadata( - signature: ModelSignature, model_settings: ModelSettings -) -> MetadataModelResponse: - # TODO: Merge lists with existing metadata (if any) [how?] - inputs = to_metadata_tensors(signature.inputs, prefix=DefaultInputPrefix) - outputs = to_metadata_tensors(signature.outputs, prefix=DefaultOutputPrefix) - - return MetadataModelResponse( - name=model_settings.name, - platform=model_settings.platform, - versions=model_settings.versions, - inputs=inputs, - outputs=outputs, - ) diff --git a/runtimes/mlflow/tests/test_metadata.py b/runtimes/mlflow/tests/test_metadata.py index 6d2514170..2c3daa08e 100644 --- a/runtimes/mlflow/tests/test_metadata.py +++ b/runtimes/mlflow/tests/test_metadata.py @@ -3,7 +3,6 @@ from typing import Tuple, List -from mlflow.models.signature import ModelSignature from mlflow.types.schema import ColSpec, TensorSpec, DataType, Schema from mlflow.pyfunc import _enforce_schema from mlserver.codecs import ( @@ -21,16 +20,12 @@ InferenceRequest, Parameters, ) -from mlserver.settings import ModelSettings from mlserver_mlflow.metadata import ( InputSpec, - DefaultInputPrefix, - DefaultOutputPrefix, _get_content_type, _get_shape, to_metadata_tensors, - to_metadata, ) @@ -187,31 +182,3 @@ def test_content_types(tensor_spec: TensorSpec, request_input: RequestInput): # _enforce_schema will raise if something fails _enforce_schema(data, input_schema) - - -def test_metadata(model_signature: ModelSignature, model_settings: ModelSettings): - metadata = to_metadata(model_signature, model_settings) - - assert metadata.name == model_settings.name - assert metadata.versions == model_settings.versions - assert metadata.platform == model_settings.platform - - assert metadata.inputs is not None - assert len(model_signature.inputs.inputs) == len(metadata.inputs) - for idx, met in enumerate(metadata.inputs): - sig = model_signature.inputs.inputs[idx] - - if sig.name is None: - assert met.name == f"{DefaultInputPrefix}{idx}" - else: - assert met.name == sig.name - - assert metadata.outputs is not None - assert len(model_signature.outputs.inputs) == len(metadata.outputs) - for idx, met in enumerate(metadata.outputs): - sig = model_signature.outputs.inputs[idx] - - if sig.name is None: - assert met.name == f"{DefaultOutputPrefix}{idx}" - else: - assert met.name == sig.name From 81bc2461859ef3c2368ddb571c80c51be9232780 Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Fri, 10 Sep 2021 10:45:44 +0100 Subject: [PATCH 26/28] Add test for multiple TensorSpec --- runtimes/mlflow/tests/test_metadata.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/runtimes/mlflow/tests/test_metadata.py b/runtimes/mlflow/tests/test_metadata.py index 2c3daa08e..360b25d91 100644 --- a/runtimes/mlflow/tests/test_metadata.py +++ b/runtimes/mlflow/tests/test_metadata.py @@ -96,6 +96,28 @@ def test_get_shape(input_spec: InputSpec, expected: List[int]): ) ], ), + ( + Schema( + inputs=[ + TensorSpec(name="foo", shape=(-1, 2), type=np.dtype("int32")), + TensorSpec(name="bar", shape=(-1, 10), type=np.dtype("float32")), + ] + ), + [ + MetadataTensor( + name="foo", + datatype="INT32", + shape=[-1, 2], + tags=Tags(content_type=NumpyCodec.ContentType), + ), + MetadataTensor( + name="bar", + datatype="FP32", + shape=[-1, 10], + tags=Tags(content_type=NumpyCodec.ContentType), + ), + ], + ), ( Schema( inputs=[ From 1b02bb3ba36be9654ac30b331667cf50ffc2bc1f Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Fri, 10 Sep 2021 10:54:02 +0100 Subject: [PATCH 27/28] Add tests for timezone-aware datetimes --- tests/codecs/test_datetime.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/tests/codecs/test_datetime.py b/tests/codecs/test_datetime.py index dcebdf774..207eb04c3 100644 --- a/tests/codecs/test_datetime.py +++ b/tests/codecs/test_datetime.py @@ -9,6 +9,10 @@ TestDatetimeIsoB = b"2021-08-24T15:01:19" TestDatetime = datetime.fromisoformat(TestDatetimeIso) +TestTzDatetimeIso = "2021-08-24T15:01:19-04:00" +TestTzDatetimeIsoB = b"2021-08-24T15:01:19-04:00" +TestTzDatetime = datetime.fromisoformat(TestTzDatetimeIso) + @pytest.mark.parametrize( "decoded, expected", @@ -32,9 +36,7 @@ ), ), ( - [ - TestDatetimeIso, - ], + [TestDatetimeIso], ResponseOutput( name="foo", shape=[1, 19], @@ -42,6 +44,15 @@ data=TestDatetimeIsoB, ), ), + ( + [TestTzDatetime], + ResponseOutput( + name="foo", + shape=[1, 25], + datatype="BYTES", + data=TestTzDatetimeIsoB, + ), + ), ], ) def test_encode(decoded, expected): @@ -90,6 +101,15 @@ def test_encode(decoded, expected): ), [TestDatetime, TestDatetime], ), + ( + RequestInput( + name="foo", + shape=[1, 25], + datatype="BYTES", + data=TestTzDatetimeIso, + ), + [TestTzDatetime], + ), ], ) def test_decode(encoded, expected): From 64978c9c42758faac0f602efd3846c48bfa53f2b Mon Sep 17 00:00:00 2001 From: Adrian Gonzalez-Martin Date: Tue, 21 Sep 2021 16:20:00 +0100 Subject: [PATCH 28/28] Add comments to differentiate between test cases --- runtimes/mlflow/mlserver_mlflow/runtime.py | 2 +- tests/codecs/test_base64.py | 25 ++++++---------------- tests/codecs/test_datetime.py | 9 ++++++++ 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/runtimes/mlflow/mlserver_mlflow/runtime.py b/runtimes/mlflow/mlserver_mlflow/runtime.py index f4b9f3fbf..54bec18bf 100644 --- a/runtimes/mlflow/mlserver_mlflow/runtime.py +++ b/runtimes/mlflow/mlserver_mlflow/runtime.py @@ -103,7 +103,7 @@ async def load(self) -> bool: self.ready = True return self.ready - def _sync_metadata(self): + def _sync_metadata(self) -> None: # Update metadata from model signature (if present) if self._signature is None: return diff --git a/tests/codecs/test_base64.py b/tests/codecs/test_base64.py index 2010140d2..487c196c5 100644 --- a/tests/codecs/test_base64.py +++ b/tests/codecs/test_base64.py @@ -8,6 +8,7 @@ "decoded, expected", [ ( + # List with a single binary string [b"Python is fun"], ResponseOutput( name="foo", @@ -17,6 +18,7 @@ ), ), ( + # List with a single (non-binary) string ["Python is fun"], ResponseOutput( name="foo", @@ -26,6 +28,7 @@ ), ), ( + # List with two binary strings [b"Python is fun", b"Python is fun"], ResponseOutput( name="foo", @@ -47,15 +50,7 @@ def test_encode(decoded, expected): "encoded, expected", [ ( - RequestInput( - name="foo", - shape=[1, 20], - datatype="BYTES", - data=b"UHl0aG9uIGlzIGZ1bg==", - ), - [b"Python is fun"], - ), - ( + # Single base64-encoded binary string RequestInput( name="foo", shape=[1, 20], @@ -65,6 +60,7 @@ def test_encode(decoded, expected): [b"Python is fun"], ), ( + # Single (non-base64-encoded) binary string RequestInput( name="foo", shape=[1, 13], @@ -74,6 +70,7 @@ def test_encode(decoded, expected): [b"Python is fun"], ), ( + # Single (non-base64-encoded) (non-binary) string RequestInput( name="foo", shape=[1, 13], @@ -83,6 +80,7 @@ def test_encode(decoded, expected): [b"Python is fun"], ), ( + # Multiple base64-encoded binary strings RequestInput( name="foo", shape=[2, 20], @@ -91,15 +89,6 @@ def test_encode(decoded, expected): ), [b"Python is fun", b"Python is fun"], ), - ( - RequestInput( - name="foo", - shape=[2, 20], - datatype="BYTES", - data="UHl0aG9uIGlzIGZ1bg==UHl0aG9uIGlzIGZ1bg==", - ), - [b"Python is fun", b"Python is fun"], - ), ], ) def test_decode(encoded, expected): diff --git a/tests/codecs/test_datetime.py b/tests/codecs/test_datetime.py index 207eb04c3..ad42911cf 100644 --- a/tests/codecs/test_datetime.py +++ b/tests/codecs/test_datetime.py @@ -18,6 +18,7 @@ "decoded, expected", [ ( + # Single Python datetime object [TestDatetime], ResponseOutput( name="foo", @@ -27,6 +28,7 @@ ), ), ( + # Multiple Python datetime objects [TestDatetime, TestDatetime], ResponseOutput( name="foo", @@ -36,6 +38,7 @@ ), ), ( + # Single ISO-encoded string [TestDatetimeIso], ResponseOutput( name="foo", @@ -45,6 +48,7 @@ ), ), ( + # Single Python datetime object with timezone [TestTzDatetime], ResponseOutput( name="foo", @@ -66,6 +70,7 @@ def test_encode(decoded, expected): "encoded, expected", [ ( + # Single binary ISO-encoded datetime RequestInput( name="foo", shape=[1, 19], @@ -75,6 +80,7 @@ def test_encode(decoded, expected): [TestDatetime], ), ( + # Single (non-binary) ISO-encoded datetime RequestInput( name="foo", shape=[1, 19], @@ -84,6 +90,7 @@ def test_encode(decoded, expected): [TestDatetime], ), ( + # Multiple binary ISO-encoded datetime RequestInput( name="foo", shape=[1, 19], @@ -93,6 +100,7 @@ def test_encode(decoded, expected): [TestDatetime, TestDatetime], ), ( + # Multiple (non-binary) ISO-encoded datetime RequestInput( name="foo", shape=[1, 19], @@ -102,6 +110,7 @@ def test_encode(decoded, expected): [TestDatetime, TestDatetime], ), ( + # Single (non-binary) ISO-encoded datetime with timezone RequestInput( name="foo", shape=[1, 25],