clarifai 11.1.7rc1__py3-none-any.whl → 11.1.7rc3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- clarifai/__init__.py +1 -1
- clarifai/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/__pycache__/errors.cpython-310.pyc +0 -0
- clarifai/__pycache__/versions.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/base_cli.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/compute_cluster.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/deployment.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/model.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/model_cli.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/nodepool.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/client/__pycache__/app.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/app.cpython-39.pyc +0 -0
- clarifai/client/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/compute_cluster.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/dataset.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/deployment.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/input.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/lister.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/model.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/module.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/nodepool.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/search.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/user.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/workflow.cpython-310.pyc +0 -0
- clarifai/client/auth/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/client/auth/__pycache__/helper.cpython-310.pyc +0 -0
- clarifai/client/auth/__pycache__/register.cpython-310.pyc +0 -0
- clarifai/client/auth/__pycache__/stub.cpython-310.pyc +0 -0
- clarifai/client/cli/__init__.py +0 -0
- clarifai/client/cli/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/client/cli/__pycache__/base_cli.cpython-310.pyc +0 -0
- clarifai/client/cli/__pycache__/model_cli.cpython-310.pyc +0 -0
- clarifai/client/cli/base_cli.py +88 -0
- clarifai/client/cli/model_cli.py +29 -0
- clarifai/client/model.py +0 -1
- clarifai/client/model_client.py +23 -24
- clarifai/constants/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/dataset.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/input.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/model.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/rag.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/search.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/workflow.cpython-310.pyc +0 -0
- clarifai/datasets/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/datasets/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/datasets/export/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/datasets/export/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/datasets/export/__pycache__/inputs_annotations.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/datasets/upload/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/features.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/image.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/multimodal.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/text.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/utils.cpython-310.pyc +0 -0
- clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/models/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/modules/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/rag/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/rag/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/rag/__pycache__/rag.cpython-310.pyc +0 -0
- clarifai/rag/__pycache__/rag.cpython-39.pyc +0 -0
- clarifai/rag/__pycache__/utils.cpython-310.pyc +0 -0
- clarifai/runners/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/runners/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/runners/dockerfile_template/Dockerfile.cpu.template +31 -0
- clarifai/runners/dockerfile_template/Dockerfile.cuda.template +42 -0
- clarifai/runners/dockerfile_template/Dockerfile.nim +71 -0
- clarifai/runners/dockerfile_template/Dockerfile.template +0 -3
- clarifai/runners/models/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/runners/models/__pycache__/base_typed_model.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/base_typed_model.cpython-39.pyc +0 -0
- clarifai/runners/models/__pycache__/model_class.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_run_locally.cpython-310-pytest-7.1.2.pyc +0 -0
- clarifai/runners/models/__pycache__/model_run_locally.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_runner.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_upload.cpython-310.pyc +0 -0
- clarifai/runners/models/model_builder.py +56 -4
- clarifai/runners/models/model_class.py +40 -17
- clarifai/runners/models/model_class_refract.py +80 -0
- clarifai/runners/models/model_upload.py +607 -0
- clarifai/runners/models/temp.py +25 -0
- clarifai/runners/utils/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/__init__.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/buffered_stream.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/buffered_stream.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/buffered_stream.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/const.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/constants.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/constants.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/constants.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_handler.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_handler.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_handler.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_utils.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_utils.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_utils.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/grpc_server.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/grpc_server.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/grpc_server.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/health.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/health.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/health.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/loader.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/logging.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/logging.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/logging.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/stream_source.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/stream_source.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/url_fetcher.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/url_fetcher.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/url_fetcher.cpython-39.pyc +0 -0
- clarifai/runners/utils/data_handler.py +271 -210
- clarifai/runners/utils/data_handler_refract.py +213 -0
- clarifai/runners/utils/logger.py +0 -0
- clarifai/runners/utils/method_signatures.py +108 -131
- clarifai/schema/__pycache__/search.cpython-310.pyc +0 -0
- clarifai/urls/__pycache__/helper.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/utils/__pycache__/cli.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/constants.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/logging.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/misc.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/model_train.cpython-310.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/main.cpython-39.pyc +0 -0
- clarifai/workflows/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/workflows/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/workflows/__pycache__/export.cpython-310.pyc +0 -0
- clarifai/workflows/__pycache__/utils.cpython-310.pyc +0 -0
- clarifai/workflows/__pycache__/validate.cpython-310.pyc +0 -0
- {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/METADATA +15 -15
- clarifai-11.1.7rc3.dist-info/RECORD +237 -0
- {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/WHEEL +1 -1
- clarifai/cli/__main__.py~ +0 -4
- clarifai/cli/__pycache__/__main__.cpython-310.pyc +0 -0
- clarifai/client/#model_client.py# +0 -430
- clarifai/client/__pycache__/runner.cpython-310.pyc +0 -0
- clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/datasets/upload/loaders/__pycache__/coco_detection.cpython-310.pyc +0 -0
- clarifai/models/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/__pycache__/constants.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/_utils.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/build.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/create.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/config.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/inference_parameter.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/output.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/triton/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/triton/__pycache__/serializer.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/triton/__pycache__/triton_config.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/triton/__pycache__/wrappers.cpython-310.pyc +0 -0
- clarifai/models/model_serving/repo_build/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/repo_build/__pycache__/build.cpython-310.pyc +0 -0
- clarifai/models/model_serving/repo_build/static_files/__pycache__/base_test.cpython-310-pytest-7.2.0.pyc +0 -0
- clarifai/runners/__pycache__/server.cpython-310.pyc +0 -0
- clarifai/runners/dockerfile_template/Dockerfile.debug +0 -11
- clarifai/runners/dockerfile_template/Dockerfile.debug~ +0 -9
- clarifai/runners/models/__pycache__/model_builder.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_servicer.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_types.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/method_signatures.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/serializers.cpython-310.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/helpers.cpython-310.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/main.cpython-310.pyc +0 -0
- clarifai-11.1.7rc1.dist-info/RECORD +0 -205
- {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/LICENSE +0 -0
- {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/entry_points.txt +0 -0
- {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,213 @@
|
|
1
|
+
import io
|
2
|
+
from typing import Any, Callable, Dict, Type
|
3
|
+
|
4
|
+
import numpy as np
|
5
|
+
from clarifai_grpc.grpc.api import resources_pb2
|
6
|
+
from clarifai_grpc.grpc.api.resources_pb2 import Audio as AudioProto
|
7
|
+
from clarifai_grpc.grpc.api.resources_pb2 import Image as ImageProto
|
8
|
+
from clarifai_grpc.grpc.api.resources_pb2 import NDArray
|
9
|
+
from clarifai_grpc.grpc.api.resources_pb2 import Text as TextProto
|
10
|
+
from clarifai_grpc.grpc.api.resources_pb2 import Video as VideoProto
|
11
|
+
from google.protobuf.json_format import MessageToDict, ParseDict
|
12
|
+
from google.protobuf.struct_pb2 import Struct
|
13
|
+
from PIL import Image as PILImage
|
14
|
+
|
15
|
+
# Type registry for conversion between Python types and protobuf
|
16
|
+
_TYPE_HANDLERS: Dict[Type, Callable] = {
|
17
|
+
# Python type: (to_proto, from_proto)
|
18
|
+
TextProto: (
|
19
|
+
lambda value: value.to_proto(),
|
20
|
+
lambda proto: Text.from_proto(proto)
|
21
|
+
),
|
22
|
+
ImageProto: (
|
23
|
+
lambda value: value.to_proto(),
|
24
|
+
lambda proto: Image(proto)
|
25
|
+
),
|
26
|
+
AudioProto: (
|
27
|
+
lambda value: value.to_proto(),
|
28
|
+
lambda proto: Audio(proto)
|
29
|
+
),
|
30
|
+
VideoProto: (
|
31
|
+
lambda value: value.to_proto(),
|
32
|
+
lambda proto: Video(proto)
|
33
|
+
),
|
34
|
+
str: (
|
35
|
+
lambda value: TextProto(raw=value),
|
36
|
+
lambda proto: proto.raw
|
37
|
+
),
|
38
|
+
bytes: (
|
39
|
+
lambda value: resources_pb2.Data(base64=value),
|
40
|
+
lambda proto: proto.base64
|
41
|
+
),
|
42
|
+
int: (
|
43
|
+
lambda value: resources_pb2.Data(int_value=value),
|
44
|
+
lambda proto: proto.int_value
|
45
|
+
),
|
46
|
+
float: (
|
47
|
+
lambda value: resources_pb2.Data(float_value=value),
|
48
|
+
lambda proto: proto.float_value
|
49
|
+
),
|
50
|
+
bool: (
|
51
|
+
lambda value: resources_pb2.Data(boolean=value),
|
52
|
+
lambda proto: proto.boolean
|
53
|
+
),
|
54
|
+
np.ndarray: (
|
55
|
+
lambda value: NDArray(buffer=value.tobytes(), shape=value.shape, dtype=str(value.dtype)),
|
56
|
+
lambda proto: np.frombuffer(proto.buffer, dtype=np.dtype(proto.dtype)).reshape(proto.shape)
|
57
|
+
),
|
58
|
+
PILImage.Image: (
|
59
|
+
lambda value: Image.from_pil(value).to_proto(),
|
60
|
+
lambda proto: Image(proto).to_pil()
|
61
|
+
),
|
62
|
+
dict: (
|
63
|
+
lambda value: _dict_to_metadata(value),
|
64
|
+
lambda proto: MessageToDict(proto.metadata)
|
65
|
+
)
|
66
|
+
}
|
67
|
+
|
68
|
+
|
69
|
+
def _dict_to_metadata(metadata: dict) -> Struct:
|
70
|
+
struct = Struct()
|
71
|
+
ParseDict(metadata, struct)
|
72
|
+
return struct
|
73
|
+
|
74
|
+
|
75
|
+
def _value_to_proto(value: Any) -> resources_pb2.Data:
|
76
|
+
"""Convert a Python value to a protobuf Data message."""
|
77
|
+
data = resources_pb2.Data()
|
78
|
+
for py_type, (to_proto, _) in _TYPE_HANDLERS.items():
|
79
|
+
if isinstance(value, py_type):
|
80
|
+
handler = to_proto
|
81
|
+
break
|
82
|
+
else:
|
83
|
+
if isinstance(value, (Text, Image, Audio, Video)):
|
84
|
+
data_part = getattr(data, type(value).__name__.lower())
|
85
|
+
data_part.CopyFrom(value.to_proto())
|
86
|
+
return data
|
87
|
+
raise TypeError(f"Unsupported type: {type(value)}")
|
88
|
+
|
89
|
+
result = handler(value)
|
90
|
+
if isinstance(result, resources_pb2.Data):
|
91
|
+
data.CopyFrom(result)
|
92
|
+
else:
|
93
|
+
field_name = type(result).DESCRIPTOR.name.lower()
|
94
|
+
getattr(data, field_name).CopyFrom(result)
|
95
|
+
return data
|
96
|
+
|
97
|
+
|
98
|
+
def _proto_to_value(proto: resources_pb2.Data) -> Any:
|
99
|
+
"""Convert a protobuf Data message to a Python value."""
|
100
|
+
for field in proto.DESCRIPTOR.fields:
|
101
|
+
if proto.HasField(field.name):
|
102
|
+
_, from_proto = _TYPE_HANDLERS.get(field.type, (None, None))
|
103
|
+
if from_proto:
|
104
|
+
return from_proto(getattr(proto, field.name))
|
105
|
+
if proto.parts:
|
106
|
+
return [_proto_to_value(part.data) for part in proto.parts]
|
107
|
+
return None
|
108
|
+
|
109
|
+
|
110
|
+
def kwargs_to_proto(**kwargs) -> resources_pb2.Data:
|
111
|
+
"""Convert keyword arguments to a Data proto."""
|
112
|
+
data_proto = resources_pb2.Data()
|
113
|
+
for part_name, part_value in kwargs.items():
|
114
|
+
part = data_proto.parts.add()
|
115
|
+
part.id = part_name
|
116
|
+
|
117
|
+
if isinstance(part_value, list):
|
118
|
+
for item in part_value:
|
119
|
+
item_proto = _value_to_proto(item)
|
120
|
+
part_part = part.data.parts.add()
|
121
|
+
part_part.data.CopyFrom(item_proto)
|
122
|
+
else:
|
123
|
+
part_proto = _value_to_proto(part_value)
|
124
|
+
part.data.CopyFrom(part_proto)
|
125
|
+
return data_proto
|
126
|
+
|
127
|
+
|
128
|
+
def proto_to_kwargs(data: resources_pb2.Data) -> dict:
|
129
|
+
"""Convert a Data proto to keyword arguments."""
|
130
|
+
kwargs = {}
|
131
|
+
for part in data.parts:
|
132
|
+
part_name = part.id
|
133
|
+
if part.data.parts:
|
134
|
+
kwargs[part_name] = [_proto_to_value(part.data) for _ in part.data.parts]
|
135
|
+
else:
|
136
|
+
kwargs[part_name] = _proto_to_value(part.data)
|
137
|
+
return kwargs
|
138
|
+
|
139
|
+
|
140
|
+
class Output:
|
141
|
+
|
142
|
+
def __init__(self, **kwargs: Any):
|
143
|
+
if not kwargs:
|
144
|
+
raise ValueError("Output must have at least one key-value pair")
|
145
|
+
self.parts = kwargs
|
146
|
+
|
147
|
+
def to_proto(self) -> resources_pb2.Output:
|
148
|
+
data_proto = kwargs_to_proto(**self.parts)
|
149
|
+
return resources_pb2.Output(data=data_proto)
|
150
|
+
|
151
|
+
|
152
|
+
class Text:
|
153
|
+
|
154
|
+
def __init__(self, text: str):
|
155
|
+
self.text = text
|
156
|
+
|
157
|
+
def to_proto(self) -> TextProto:
|
158
|
+
return TextProto(raw=self.text)
|
159
|
+
|
160
|
+
@classmethod
|
161
|
+
def from_proto(cls, proto: TextProto) -> "Text":
|
162
|
+
return cls(proto.raw)
|
163
|
+
|
164
|
+
|
165
|
+
class Image:
|
166
|
+
|
167
|
+
def __init__(self, proto_image: ImageProto):
|
168
|
+
self.proto = proto_image
|
169
|
+
|
170
|
+
@classmethod
|
171
|
+
def from_url(cls, url: str) -> "Image":
|
172
|
+
return cls(ImageProto(url=url))
|
173
|
+
|
174
|
+
@classmethod
|
175
|
+
def from_pil(cls, pil_image: PILImage.Image) -> "Image":
|
176
|
+
with io.BytesIO() as output:
|
177
|
+
pil_image.save(output, format="PNG")
|
178
|
+
return cls(ImageProto(base64=output.getvalue()))
|
179
|
+
|
180
|
+
def to_pil(self) -> PILImage.Image:
|
181
|
+
return PILImage.open(io.BytesIO(self.proto.base64))
|
182
|
+
|
183
|
+
def to_proto(self) -> ImageProto:
|
184
|
+
return self.proto
|
185
|
+
|
186
|
+
|
187
|
+
class Audio:
|
188
|
+
|
189
|
+
def __init__(self, proto_audio: AudioProto):
|
190
|
+
self.proto = proto_audio
|
191
|
+
|
192
|
+
def to_proto(self) -> AudioProto:
|
193
|
+
return self.proto
|
194
|
+
|
195
|
+
|
196
|
+
class Video:
|
197
|
+
|
198
|
+
def __init__(self, proto_video: VideoProto):
|
199
|
+
self.proto = proto_video
|
200
|
+
|
201
|
+
def to_proto(self) -> VideoProto:
|
202
|
+
return self.proto
|
203
|
+
|
204
|
+
|
205
|
+
'''
|
206
|
+
Type Handling Registry: Centralized conversion logic reduces duplication and enhances extensibility.
|
207
|
+
Simplified Conversion Functions: _value_to_proto and _proto_to_value handle all type conversions using the registry.
|
208
|
+
Streamlined Wrapper Methods: Common processing logic extracted into _process_request, reducing code duplication.
|
209
|
+
Improved Batch Processing: Uses ThreadPoolExecutor.map for cleaner batch prediction.
|
210
|
+
Error Handling: Clearer error messages and validation of required parameters.
|
211
|
+
Removed Redundant Checks: Simplified Output class initialization.
|
212
|
+
|
213
|
+
'''
|
File without changes
|
@@ -1,7 +1,5 @@
|
|
1
|
-
import ast
|
2
1
|
import inspect
|
3
2
|
import json
|
4
|
-
import textwrap
|
5
3
|
from collections import namedtuple
|
6
4
|
from typing import List, Tuple, get_args, get_origin
|
7
5
|
|
@@ -9,6 +7,7 @@ import numpy as np
|
|
9
7
|
import PIL.Image
|
10
8
|
import yaml
|
11
9
|
from clarifai_grpc.grpc.api import resources_pb2
|
10
|
+
from google.protobuf.json_format import MessageToDict, ParseDict
|
12
11
|
from google.protobuf.message import Message as MessageProto
|
13
12
|
|
14
13
|
from clarifai.runners.utils import data_types
|
@@ -32,10 +31,13 @@ def build_function_signature(func):
|
|
32
31
|
if return_annotation == inspect.Parameter.empty:
|
33
32
|
raise TypeError('Function must have a return annotation')
|
34
33
|
|
35
|
-
input_sigs = [
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
input_sigs = []
|
35
|
+
input_streaming = []
|
36
|
+
for p in sig.parameters.values():
|
37
|
+
model_type_field, _, streaming = build_variable_signature(p.name, p.annotation, p.default)
|
38
|
+
input_sigs.append(model_type_field)
|
39
|
+
input_streaming.append(streaming)
|
40
|
+
|
39
41
|
output_sig, output_type, output_streaming = build_variable_signature(
|
40
42
|
'return', return_annotation, is_output=True)
|
41
43
|
# TODO: flatten out "return" layer if not needed
|
@@ -45,48 +47,45 @@ def build_function_signature(func):
|
|
45
47
|
raise TypeError('streaming methods must have at most one streaming input')
|
46
48
|
input_streaming = any(input_streaming)
|
47
49
|
if not (input_streaming or output_streaming):
|
48
|
-
method_type = '
|
50
|
+
method_type = 'UNARY_UNARY'
|
49
51
|
elif not input_streaming and output_streaming:
|
50
|
-
method_type = '
|
52
|
+
method_type = 'UNARY_STREAMING'
|
51
53
|
elif input_streaming and output_streaming:
|
52
|
-
method_type = '
|
54
|
+
method_type = 'STREAMING_STREAMING'
|
53
55
|
else:
|
54
56
|
raise TypeError('stream methods with streaming inputs must have streaming outputs')
|
55
57
|
|
56
|
-
|
57
|
-
method_signature = _SignatureDict() #for now
|
58
|
+
method_signature = resources_pb2.MethodSignature()
|
58
59
|
|
59
60
|
method_signature.name = func.__name__
|
60
|
-
|
61
|
-
assert method_type in ('
|
62
|
-
method_signature.method_type = method_type
|
63
|
-
method_signature.
|
64
|
-
method_signature.annotations_json = json.dumps(_get_annotations_source(func))
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
method_signature.inputs = input_sigs
|
69
|
-
method_signature.outputs = [output_sig]
|
61
|
+
method_signature.method_type = getattr(resources_pb2.RunnerMethodType, method_type)
|
62
|
+
assert method_type in ('UNARY_UNARY', 'UNARY_STREAMING', 'STREAMING_STREAMING')
|
63
|
+
# method_signature.method_type = method_type
|
64
|
+
method_signature.description = inspect.cleandoc(func.__doc__ or '')
|
65
|
+
# method_signature.annotations_json = json.dumps(_get_annotations_source(func))
|
66
|
+
|
67
|
+
method_signature.input_fields.extend(input_sigs)
|
68
|
+
method_signature.output_fields.append(output_sig)
|
70
69
|
return method_signature
|
71
70
|
|
72
71
|
|
73
|
-
def _get_annotations_source(func):
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
72
|
+
# def _get_annotations_source(func):
|
73
|
+
# """Extracts raw annotation strings from the function source."""
|
74
|
+
# source = inspect.getsource(func) # Get function source code
|
75
|
+
# source = textwrap.dedent(source) # Dedent source code
|
76
|
+
# tree = ast.parse(source) # Parse into AST
|
77
|
+
# func_node = next(node for node in tree.body
|
78
|
+
# if isinstance(node, ast.FunctionDef)) # Get function node
|
80
79
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
80
|
+
# annotations = {}
|
81
|
+
# for arg in func_node.args.args: # Process arguments
|
82
|
+
# if arg.annotation:
|
83
|
+
# annotations[arg.arg] = ast.unparse(arg.annotation) # Get raw annotation string
|
85
84
|
|
86
|
-
|
87
|
-
|
85
|
+
# if func_node.returns: # Process return type
|
86
|
+
# annotations["return"] = ast.unparse(func_node.returns)
|
88
87
|
|
89
|
-
|
88
|
+
# return annotations
|
90
89
|
|
91
90
|
|
92
91
|
def build_variable_signature(name, annotation, default=inspect.Parameter.empty, is_output=False):
|
@@ -101,19 +100,17 @@ def build_variable_signature(name, annotation, default=inspect.Parameter.empty,
|
|
101
100
|
# get fields for each variable based on type
|
102
101
|
tp, streaming = _normalize_type(annotation)
|
103
102
|
|
104
|
-
|
105
|
-
sig = _VariableSignature() #for now
|
103
|
+
sig = resources_pb2.ModelTypeField()
|
106
104
|
sig.name = name
|
107
|
-
|
108
|
-
_fill_signature_type(sig, tp)
|
109
|
-
|
110
|
-
sig.streaming = streaming
|
105
|
+
sig.iterator = streaming
|
111
106
|
|
112
107
|
if not is_output:
|
113
108
|
sig.required = (default is inspect.Parameter.empty)
|
114
109
|
if not sig.required:
|
115
110
|
sig.default = str(default)
|
116
111
|
|
112
|
+
_fill_signature_type(sig, tp)
|
113
|
+
|
117
114
|
return sig, type, streaming
|
118
115
|
|
119
116
|
|
@@ -125,40 +122,42 @@ def _fill_signature_type(sig, tp):
|
|
125
122
|
except TypeError:
|
126
123
|
pass # not hashable type
|
127
124
|
|
125
|
+
# Handle NamedFields with annotations
|
128
126
|
# Check for dynamically generated NamedFields subclasses (from type annotations)
|
129
127
|
if inspect.isclass(tp) and issubclass(tp, data_types.NamedFields) and hasattr(
|
130
128
|
tp, '__annotations__'):
|
131
|
-
sig.type = DataType.NAMED_FIELDS
|
129
|
+
sig.type = resources_pb2.ModelTypeField.DataType.NAMED_FIELDS
|
132
130
|
for name, inner_type in tp.__annotations__.items():
|
133
|
-
inner_sig =
|
131
|
+
inner_sig = sig.type_args.add()
|
134
132
|
inner_sig.name = name
|
135
133
|
_fill_signature_type(inner_sig, inner_type)
|
136
|
-
sig.type_args.append(inner_sig)
|
137
134
|
return
|
138
135
|
|
136
|
+
# Handle NamedFields instances (dict-like)
|
139
137
|
if isinstance(tp, data_types.NamedFields):
|
140
|
-
sig.type = DataType.NAMED_FIELDS
|
138
|
+
sig.type = resources_pb2.ModelTypeField.DataType.NAMED_FIELDS
|
141
139
|
for name, inner_type in tp.items():
|
142
|
-
|
143
|
-
sig.type_args.append(inner_sig := _VariableSignature())
|
140
|
+
inner_sig = sig.type_args.add()
|
144
141
|
inner_sig.name = name
|
145
142
|
_fill_signature_type(inner_sig, inner_type)
|
146
143
|
return
|
147
144
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
145
|
+
origin = get_origin(tp)
|
146
|
+
args = get_args(tp)
|
147
|
+
|
148
|
+
# Handle Tuple type
|
149
|
+
if origin == tuple:
|
150
|
+
sig.type = resources_pb2.ModelTypeField.DataType.TUPLE
|
151
|
+
for inner_type in args:
|
152
|
+
inner_sig = sig.type_args.add()
|
153
153
|
_fill_signature_type(inner_sig, inner_type)
|
154
154
|
return
|
155
155
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
_fill_signature_type(inner_sig, inner_type)
|
156
|
+
# Handle List type
|
157
|
+
if origin == list:
|
158
|
+
sig.type = resources_pb2.ModelTypeField.DataType.LIST
|
159
|
+
inner_sig = sig.type_args.add()
|
160
|
+
_fill_signature_type(inner_sig, args[0])
|
162
161
|
return
|
163
162
|
|
164
163
|
raise TypeError(f'Unsupported type: {tp}')
|
@@ -170,11 +169,11 @@ def serializer_from_signature(signature):
|
|
170
169
|
'''
|
171
170
|
if signature.type in _SERIALIZERS_BY_TYPE_ENUM:
|
172
171
|
return _SERIALIZERS_BY_TYPE_ENUM[signature.type]
|
173
|
-
if signature.type == DataType.LIST:
|
172
|
+
if signature.type == resources_pb2.ModelTypeField.DataType.LIST:
|
174
173
|
return ListSerializer(serializer_from_signature(signature.type_args[0]))
|
175
|
-
if signature.type == DataType.TUPLE:
|
174
|
+
if signature.type == resources_pb2.ModelTypeField.DataType.TUPLE:
|
176
175
|
return TupleSerializer([serializer_from_signature(sig) for sig in signature.type_args])
|
177
|
-
if signature.type == DataType.NAMED_FIELDS:
|
176
|
+
if signature.type == resources_pb2.ModelTypeField.DataType.NAMED_FIELDS:
|
178
177
|
return NamedFieldsSerializer(
|
179
178
|
{sig.name: serializer_from_signature(sig)
|
180
179
|
for sig in signature.type_args})
|
@@ -185,13 +184,20 @@ def signatures_to_json(signatures):
|
|
185
184
|
assert isinstance(
|
186
185
|
signatures, dict), 'Expected dict of signatures {name: signature}, got %s' % type(signatures)
|
187
186
|
# TODO change to proto when ready
|
188
|
-
|
187
|
+
signatures = {name: MessageToDict(sig) for name, sig in signatures.items()}
|
189
188
|
return json.dumps(signatures)
|
190
189
|
|
191
190
|
|
192
191
|
def signatures_from_json(json_str):
|
193
|
-
|
194
|
-
|
192
|
+
signatures_dict = json.loads(json_str)
|
193
|
+
assert isinstance(signatures_dict, dict), "Expected JSON to decode into a dictionary"
|
194
|
+
|
195
|
+
return {
|
196
|
+
name: ParseDict(sig_dict, resources_pb2.MethodSignature())
|
197
|
+
for name, sig_dict in signatures_dict.items()
|
198
|
+
}
|
199
|
+
# d = json.loads(json_str, object_pairs_hook=_SignatureDict)
|
200
|
+
# return d
|
195
201
|
|
196
202
|
|
197
203
|
def signatures_to_yaml(signatures):
|
@@ -254,7 +260,7 @@ def serialize(kwargs, signatures, proto=None, is_output=False):
|
|
254
260
|
return proto
|
255
261
|
|
256
262
|
|
257
|
-
def deserialize(proto, signatures, is_output=False):
|
263
|
+
def deserialize(proto, signatures, inference_params={}, is_output=False):
|
258
264
|
'''
|
259
265
|
Deserialize the given proto into kwargs using the given signatures.
|
260
266
|
'''
|
@@ -265,7 +271,12 @@ def deserialize(proto, signatures, is_output=False):
|
|
265
271
|
for sig_i, sig in enumerate(signatures):
|
266
272
|
serializer = serializer_from_signature(sig)
|
267
273
|
part = parts_by_name.get(sig.name)
|
268
|
-
|
274
|
+
inference_params_value = inference_params.get(sig.name)
|
275
|
+
if part is not None:
|
276
|
+
kwargs[sig.name] = serializer.deserialize(part.data)
|
277
|
+
elif inference_params_value is not None:
|
278
|
+
kwargs[sig.name] = inference_params_value
|
279
|
+
else:
|
269
280
|
if sig_i == 0:
|
270
281
|
# possible inlined first value
|
271
282
|
value = serializer.deserialize(proto)
|
@@ -274,10 +285,10 @@ def deserialize(proto, signatures, is_output=False):
|
|
274
285
|
# an actual zero value passed in must be set in an explicit part
|
275
286
|
kwargs[sig.name] = value
|
276
287
|
continue
|
288
|
+
|
277
289
|
if sig.required or is_output: # TODO allow optional outputs?
|
278
290
|
raise ValueError(f'Missing required field: {sig.name}')
|
279
291
|
continue
|
280
|
-
kwargs[sig.name] = serializer.deserialize(part.data)
|
281
292
|
if len(kwargs) == 1 and 'return' in kwargs:
|
282
293
|
return kwargs['return']
|
283
294
|
return kwargs
|
@@ -288,7 +299,7 @@ def get_stream_from_signature(signatures):
|
|
288
299
|
Get the stream signature from the given signatures.
|
289
300
|
'''
|
290
301
|
for sig in signatures:
|
291
|
-
if sig.
|
302
|
+
if sig.iterator:
|
292
303
|
return sig
|
293
304
|
return None
|
294
305
|
|
@@ -357,9 +368,7 @@ def _normalize_data_type(tp):
|
|
357
368
|
return data_types.Image
|
358
369
|
|
359
370
|
if tp == PIL.Image:
|
360
|
-
raise TypeError(
|
361
|
-
'Use the Image class from the PIL.Image module i.e. `PIL.Image.Image`, not the module itself'
|
362
|
-
)
|
371
|
+
raise TypeError('Use PIL.Image.Image instead of PIL.Image module')
|
363
372
|
|
364
373
|
# check for known data types
|
365
374
|
try:
|
@@ -379,90 +388,58 @@ def _is_jsonable(tp):
|
|
379
388
|
return False
|
380
389
|
|
381
390
|
|
382
|
-
# TODO --- tmp classes to stand-in for protos until they are defined and built into this package
|
383
|
-
class _SignatureDict(dict):
|
384
|
-
__getattr__ = dict.__getitem__
|
385
|
-
__setattr__ = dict.__setitem__
|
386
|
-
|
387
|
-
|
388
|
-
class _VariableSignature(_SignatureDict):
|
389
|
-
|
390
|
-
def __init__(self):
|
391
|
-
super().__init__()
|
392
|
-
self.name = ''
|
393
|
-
self.type = ''
|
394
|
-
self.type_args = []
|
395
|
-
self.streaming = False
|
396
|
-
self.required = False
|
397
|
-
self.default = ''
|
398
|
-
self.description = ''
|
399
|
-
|
400
|
-
|
401
391
|
# type: name of the data type
|
402
392
|
# data_field: name of the field in the data proto
|
403
393
|
# serializer: serializer for the data type
|
404
394
|
_DataType = namedtuple('_DataType', ('type', 'serializer'))
|
405
395
|
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
STR = 'STR'
|
412
|
-
BYTES = 'BYTES'
|
413
|
-
INT = 'INT'
|
414
|
-
FLOAT = 'FLOAT'
|
415
|
-
BOOL = 'BOOL'
|
416
|
-
NDARRAY = 'NDARRAY'
|
417
|
-
JSON = 'JSON'
|
418
|
-
|
419
|
-
TEXT = 'TEXT'
|
420
|
-
IMAGE = 'IMAGE'
|
421
|
-
CONCEPT = 'CONCEPT'
|
422
|
-
REGION = 'REGION'
|
423
|
-
FRAME = 'FRAME'
|
424
|
-
AUDIO = 'AUDIO'
|
425
|
-
VIDEO = 'VIDEO'
|
426
|
-
|
427
|
-
NAMED_FIELDS = 'NAMED_FIELDS'
|
428
|
-
TUPLE = 'TUPLE'
|
429
|
-
LIST = 'LIST'
|
430
|
-
|
431
|
-
|
432
|
-
_NON_INLINABLE_TYPES = {DataType.NAMED_FIELDS, DataType.TUPLE, DataType.LIST}
|
396
|
+
_NON_INLINABLE_TYPES = {
|
397
|
+
resources_pb2.ModelTypeField.DataType.NAMED_FIELDS,
|
398
|
+
resources_pb2.ModelTypeField.DataType.TUPLE, resources_pb2.ModelTypeField.DataType.LIST
|
399
|
+
}
|
433
400
|
_ZERO_VALUE_IDS = {id(None), id(''), id(b''), id(0), id(0.0), id(False)}
|
434
401
|
|
435
402
|
# simple, non-container types that correspond directly to a data field
|
436
403
|
_DATA_TYPES = {
|
437
404
|
str:
|
438
|
-
_DataType(DataType.STR,
|
405
|
+
_DataType(resources_pb2.ModelTypeField.DataType.STR,
|
406
|
+
AtomicFieldSerializer('string_value')),
|
439
407
|
bytes:
|
440
|
-
_DataType(DataType.BYTES,
|
408
|
+
_DataType(resources_pb2.ModelTypeField.DataType.BYTES,
|
409
|
+
AtomicFieldSerializer('bytes_value')),
|
441
410
|
int:
|
442
|
-
_DataType(DataType.INT, AtomicFieldSerializer('int_value')),
|
411
|
+
_DataType(resources_pb2.ModelTypeField.DataType.INT, AtomicFieldSerializer('int_value')),
|
443
412
|
float:
|
444
|
-
_DataType(DataType.FLOAT,
|
413
|
+
_DataType(resources_pb2.ModelTypeField.DataType.FLOAT,
|
414
|
+
AtomicFieldSerializer('float_value')),
|
445
415
|
bool:
|
446
|
-
_DataType(DataType.BOOL, AtomicFieldSerializer('bool_value')),
|
416
|
+
_DataType(resources_pb2.ModelTypeField.DataType.BOOL, AtomicFieldSerializer('bool_value')),
|
447
417
|
np.ndarray:
|
448
|
-
_DataType(DataType.NDARRAY, NDArraySerializer('ndarray')),
|
418
|
+
_DataType(resources_pb2.ModelTypeField.DataType.NDARRAY, NDArraySerializer('ndarray')),
|
449
419
|
data_types.JSON:
|
450
|
-
_DataType(DataType.
|
420
|
+
_DataType(resources_pb2.ModelTypeField.DataType.JSON_DATA, JSONSerializer('string_value')
|
451
421
|
), # TODO change to json_value when new proto is ready
|
452
422
|
data_types.Text:
|
453
|
-
_DataType(DataType.TEXT,
|
423
|
+
_DataType(resources_pb2.ModelTypeField.DataType.TEXT,
|
424
|
+
MessageSerializer('text', data_types.Text)),
|
454
425
|
data_types.Image:
|
455
|
-
_DataType(DataType.IMAGE,
|
426
|
+
_DataType(resources_pb2.ModelTypeField.DataType.IMAGE,
|
427
|
+
MessageSerializer('image', data_types.Image)),
|
456
428
|
data_types.Concept:
|
457
|
-
_DataType(DataType.CONCEPT,
|
429
|
+
_DataType(resources_pb2.ModelTypeField.DataType.CONCEPT,
|
430
|
+
MessageSerializer('concepts', data_types.Concept)),
|
458
431
|
data_types.Region:
|
459
|
-
_DataType(DataType.REGION,
|
432
|
+
_DataType(resources_pb2.ModelTypeField.DataType.REGION,
|
433
|
+
MessageSerializer('regions', data_types.Region)),
|
460
434
|
data_types.Frame:
|
461
|
-
_DataType(DataType.FRAME,
|
435
|
+
_DataType(resources_pb2.ModelTypeField.DataType.FRAME,
|
436
|
+
MessageSerializer('frames', data_types.Frame)),
|
462
437
|
data_types.Audio:
|
463
|
-
_DataType(DataType.AUDIO,
|
438
|
+
_DataType(resources_pb2.ModelTypeField.DataType.AUDIO,
|
439
|
+
MessageSerializer('audio', data_types.Audio)),
|
464
440
|
data_types.Video:
|
465
|
-
_DataType(DataType.VIDEO,
|
441
|
+
_DataType(resources_pb2.ModelTypeField.DataType.VIDEO,
|
442
|
+
MessageSerializer('video', data_types.Video)),
|
466
443
|
}
|
467
444
|
|
468
445
|
_SERIALIZERS_BY_TYPE_ENUM = {dt.type: dt.serializer for dt in _DATA_TYPES.values()}
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|