clarifai 11.1.7rc1__py3-none-any.whl → 11.1.7rc2__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.
Files changed (183) hide show
  1. clarifai/__init__.py +1 -1
  2. clarifai/__pycache__/__init__.cpython-310.pyc +0 -0
  3. clarifai/__pycache__/__init__.cpython-39.pyc +0 -0
  4. clarifai/__pycache__/errors.cpython-310.pyc +0 -0
  5. clarifai/__pycache__/versions.cpython-310.pyc +0 -0
  6. clarifai/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  7. clarifai/cli/__pycache__/base.cpython-310.pyc +0 -0
  8. clarifai/cli/__pycache__/base_cli.cpython-310.pyc +0 -0
  9. clarifai/cli/__pycache__/compute_cluster.cpython-310.pyc +0 -0
  10. clarifai/cli/__pycache__/deployment.cpython-310.pyc +0 -0
  11. clarifai/cli/__pycache__/model.cpython-310.pyc +0 -0
  12. clarifai/cli/__pycache__/model_cli.cpython-310.pyc +0 -0
  13. clarifai/cli/__pycache__/nodepool.cpython-310.pyc +0 -0
  14. clarifai/client/__pycache__/__init__.cpython-310.pyc +0 -0
  15. clarifai/client/__pycache__/__init__.cpython-39.pyc +0 -0
  16. clarifai/client/__pycache__/app.cpython-310.pyc +0 -0
  17. clarifai/client/__pycache__/app.cpython-39.pyc +0 -0
  18. clarifai/client/__pycache__/base.cpython-310.pyc +0 -0
  19. clarifai/client/__pycache__/compute_cluster.cpython-310.pyc +0 -0
  20. clarifai/client/__pycache__/dataset.cpython-310.pyc +0 -0
  21. clarifai/client/__pycache__/deployment.cpython-310.pyc +0 -0
  22. clarifai/client/__pycache__/input.cpython-310.pyc +0 -0
  23. clarifai/client/__pycache__/lister.cpython-310.pyc +0 -0
  24. clarifai/client/__pycache__/model.cpython-310.pyc +0 -0
  25. clarifai/client/__pycache__/module.cpython-310.pyc +0 -0
  26. clarifai/client/__pycache__/nodepool.cpython-310.pyc +0 -0
  27. clarifai/client/__pycache__/search.cpython-310.pyc +0 -0
  28. clarifai/client/__pycache__/user.cpython-310.pyc +0 -0
  29. clarifai/client/__pycache__/workflow.cpython-310.pyc +0 -0
  30. clarifai/client/auth/__pycache__/__init__.cpython-310.pyc +0 -0
  31. clarifai/client/auth/__pycache__/helper.cpython-310.pyc +0 -0
  32. clarifai/client/auth/__pycache__/register.cpython-310.pyc +0 -0
  33. clarifai/client/auth/__pycache__/stub.cpython-310.pyc +0 -0
  34. clarifai/client/cli/__init__.py +0 -0
  35. clarifai/client/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  36. clarifai/client/cli/__pycache__/base_cli.cpython-310.pyc +0 -0
  37. clarifai/client/cli/__pycache__/model_cli.cpython-310.pyc +0 -0
  38. clarifai/client/cli/base_cli.py +88 -0
  39. clarifai/client/cli/model_cli.py +29 -0
  40. clarifai/client/model.py +0 -1
  41. clarifai/client/model_client.py +22 -24
  42. clarifai/constants/__pycache__/base.cpython-310.pyc +0 -0
  43. clarifai/constants/__pycache__/dataset.cpython-310.pyc +0 -0
  44. clarifai/constants/__pycache__/input.cpython-310.pyc +0 -0
  45. clarifai/constants/__pycache__/model.cpython-310.pyc +0 -0
  46. clarifai/constants/__pycache__/rag.cpython-310.pyc +0 -0
  47. clarifai/constants/__pycache__/search.cpython-310.pyc +0 -0
  48. clarifai/constants/__pycache__/workflow.cpython-310.pyc +0 -0
  49. clarifai/datasets/__pycache__/__init__.cpython-310.pyc +0 -0
  50. clarifai/datasets/__pycache__/__init__.cpython-39.pyc +0 -0
  51. clarifai/datasets/export/__pycache__/__init__.cpython-310.pyc +0 -0
  52. clarifai/datasets/export/__pycache__/__init__.cpython-39.pyc +0 -0
  53. clarifai/datasets/export/__pycache__/inputs_annotations.cpython-310.pyc +0 -0
  54. clarifai/datasets/upload/__pycache__/__init__.cpython-310.pyc +0 -0
  55. clarifai/datasets/upload/__pycache__/__init__.cpython-39.pyc +0 -0
  56. clarifai/datasets/upload/__pycache__/base.cpython-310.pyc +0 -0
  57. clarifai/datasets/upload/__pycache__/features.cpython-310.pyc +0 -0
  58. clarifai/datasets/upload/__pycache__/image.cpython-310.pyc +0 -0
  59. clarifai/datasets/upload/__pycache__/multimodal.cpython-310.pyc +0 -0
  60. clarifai/datasets/upload/__pycache__/text.cpython-310.pyc +0 -0
  61. clarifai/datasets/upload/__pycache__/utils.cpython-310.pyc +0 -0
  62. clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-39.pyc +0 -0
  63. clarifai/models/__pycache__/__init__.cpython-39.pyc +0 -0
  64. clarifai/modules/__pycache__/__init__.cpython-39.pyc +0 -0
  65. clarifai/rag/__pycache__/__init__.cpython-310.pyc +0 -0
  66. clarifai/rag/__pycache__/__init__.cpython-39.pyc +0 -0
  67. clarifai/rag/__pycache__/rag.cpython-310.pyc +0 -0
  68. clarifai/rag/__pycache__/rag.cpython-39.pyc +0 -0
  69. clarifai/rag/__pycache__/utils.cpython-310.pyc +0 -0
  70. clarifai/runners/__pycache__/__init__.cpython-310.pyc +0 -0
  71. clarifai/runners/__pycache__/__init__.cpython-39.pyc +0 -0
  72. clarifai/runners/dockerfile_template/Dockerfile.cpu.template +31 -0
  73. clarifai/runners/dockerfile_template/Dockerfile.cuda.template +42 -0
  74. clarifai/runners/dockerfile_template/Dockerfile.nim +71 -0
  75. clarifai/runners/models/__pycache__/__init__.cpython-310.pyc +0 -0
  76. clarifai/runners/models/__pycache__/__init__.cpython-39.pyc +0 -0
  77. clarifai/runners/models/__pycache__/base_typed_model.cpython-310.pyc +0 -0
  78. clarifai/runners/models/__pycache__/base_typed_model.cpython-39.pyc +0 -0
  79. clarifai/runners/models/__pycache__/model_class.cpython-310.pyc +0 -0
  80. clarifai/runners/models/__pycache__/model_run_locally.cpython-310-pytest-7.1.2.pyc +0 -0
  81. clarifai/runners/models/__pycache__/model_run_locally.cpython-310.pyc +0 -0
  82. clarifai/runners/models/__pycache__/model_runner.cpython-310.pyc +0 -0
  83. clarifai/runners/models/__pycache__/model_upload.cpython-310.pyc +0 -0
  84. clarifai/runners/models/model_builder.py +12 -1
  85. clarifai/runners/models/model_class.py +18 -12
  86. clarifai/runners/models/model_class_refract.py +80 -0
  87. clarifai/runners/models/model_upload.py +607 -0
  88. clarifai/runners/models/temp.py +25 -0
  89. clarifai/runners/utils/__pycache__/__init__.cpython-310.pyc +0 -0
  90. clarifai/runners/utils/__pycache__/__init__.cpython-38.pyc +0 -0
  91. clarifai/runners/utils/__pycache__/__init__.cpython-39.pyc +0 -0
  92. clarifai/runners/utils/__pycache__/buffered_stream.cpython-310.pyc +0 -0
  93. clarifai/runners/utils/__pycache__/buffered_stream.cpython-38.pyc +0 -0
  94. clarifai/runners/utils/__pycache__/buffered_stream.cpython-39.pyc +0 -0
  95. clarifai/runners/utils/__pycache__/const.cpython-310.pyc +0 -0
  96. clarifai/runners/utils/__pycache__/constants.cpython-310.pyc +0 -0
  97. clarifai/runners/utils/__pycache__/constants.cpython-38.pyc +0 -0
  98. clarifai/runners/utils/__pycache__/constants.cpython-39.pyc +0 -0
  99. clarifai/runners/utils/__pycache__/data_handler.cpython-310.pyc +0 -0
  100. clarifai/runners/utils/__pycache__/data_handler.cpython-38.pyc +0 -0
  101. clarifai/runners/utils/__pycache__/data_handler.cpython-39.pyc +0 -0
  102. clarifai/runners/utils/__pycache__/data_utils.cpython-310.pyc +0 -0
  103. clarifai/runners/utils/__pycache__/data_utils.cpython-38.pyc +0 -0
  104. clarifai/runners/utils/__pycache__/data_utils.cpython-39.pyc +0 -0
  105. clarifai/runners/utils/__pycache__/grpc_server.cpython-310.pyc +0 -0
  106. clarifai/runners/utils/__pycache__/grpc_server.cpython-38.pyc +0 -0
  107. clarifai/runners/utils/__pycache__/grpc_server.cpython-39.pyc +0 -0
  108. clarifai/runners/utils/__pycache__/health.cpython-310.pyc +0 -0
  109. clarifai/runners/utils/__pycache__/health.cpython-38.pyc +0 -0
  110. clarifai/runners/utils/__pycache__/health.cpython-39.pyc +0 -0
  111. clarifai/runners/utils/__pycache__/loader.cpython-310.pyc +0 -0
  112. clarifai/runners/utils/__pycache__/logging.cpython-310.pyc +0 -0
  113. clarifai/runners/utils/__pycache__/logging.cpython-38.pyc +0 -0
  114. clarifai/runners/utils/__pycache__/logging.cpython-39.pyc +0 -0
  115. clarifai/runners/utils/__pycache__/stream_source.cpython-310.pyc +0 -0
  116. clarifai/runners/utils/__pycache__/stream_source.cpython-39.pyc +0 -0
  117. clarifai/runners/utils/__pycache__/url_fetcher.cpython-310.pyc +0 -0
  118. clarifai/runners/utils/__pycache__/url_fetcher.cpython-38.pyc +0 -0
  119. clarifai/runners/utils/__pycache__/url_fetcher.cpython-39.pyc +0 -0
  120. clarifai/runners/utils/data_handler.py +271 -210
  121. clarifai/runners/utils/data_handler_refract.py +213 -0
  122. clarifai/runners/utils/logger.py +0 -0
  123. clarifai/runners/utils/method_signatures.py +100 -128
  124. clarifai/schema/__pycache__/search.cpython-310.pyc +0 -0
  125. clarifai/urls/__pycache__/helper.cpython-310.pyc +0 -0
  126. clarifai/utils/__pycache__/__init__.cpython-310.pyc +0 -0
  127. clarifai/utils/__pycache__/__init__.cpython-39.pyc +0 -0
  128. clarifai/utils/__pycache__/cli.cpython-310.pyc +0 -0
  129. clarifai/utils/__pycache__/constants.cpython-310.pyc +0 -0
  130. clarifai/utils/__pycache__/logging.cpython-310.pyc +0 -0
  131. clarifai/utils/__pycache__/misc.cpython-310.pyc +0 -0
  132. clarifai/utils/__pycache__/model_train.cpython-310.pyc +0 -0
  133. clarifai/utils/evaluation/__pycache__/__init__.cpython-39.pyc +0 -0
  134. clarifai/utils/evaluation/__pycache__/main.cpython-39.pyc +0 -0
  135. clarifai/workflows/__pycache__/__init__.cpython-310.pyc +0 -0
  136. clarifai/workflows/__pycache__/__init__.cpython-39.pyc +0 -0
  137. clarifai/workflows/__pycache__/export.cpython-310.pyc +0 -0
  138. clarifai/workflows/__pycache__/utils.cpython-310.pyc +0 -0
  139. clarifai/workflows/__pycache__/validate.cpython-310.pyc +0 -0
  140. {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc2.dist-info}/METADATA +15 -15
  141. clarifai-11.1.7rc2.dist-info/RECORD +237 -0
  142. {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc2.dist-info}/WHEEL +1 -1
  143. clarifai/cli/__main__.py~ +0 -4
  144. clarifai/cli/__pycache__/__main__.cpython-310.pyc +0 -0
  145. clarifai/client/#model_client.py# +0 -430
  146. clarifai/client/__pycache__/runner.cpython-310.pyc +0 -0
  147. clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-310.pyc +0 -0
  148. clarifai/datasets/upload/loaders/__pycache__/coco_detection.cpython-310.pyc +0 -0
  149. clarifai/models/__pycache__/__init__.cpython-310.pyc +0 -0
  150. clarifai/models/model_serving/__pycache__/__init__.cpython-310.pyc +0 -0
  151. clarifai/models/model_serving/__pycache__/constants.cpython-310.pyc +0 -0
  152. clarifai/models/model_serving/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  153. clarifai/models/model_serving/cli/__pycache__/_utils.cpython-310.pyc +0 -0
  154. clarifai/models/model_serving/cli/__pycache__/base.cpython-310.pyc +0 -0
  155. clarifai/models/model_serving/cli/__pycache__/build.cpython-310.pyc +0 -0
  156. clarifai/models/model_serving/cli/__pycache__/create.cpython-310.pyc +0 -0
  157. clarifai/models/model_serving/model_config/__pycache__/__init__.cpython-310.pyc +0 -0
  158. clarifai/models/model_serving/model_config/__pycache__/base.cpython-310.pyc +0 -0
  159. clarifai/models/model_serving/model_config/__pycache__/config.cpython-310.pyc +0 -0
  160. clarifai/models/model_serving/model_config/__pycache__/inference_parameter.cpython-310.pyc +0 -0
  161. clarifai/models/model_serving/model_config/__pycache__/output.cpython-310.pyc +0 -0
  162. clarifai/models/model_serving/model_config/triton/__pycache__/__init__.cpython-310.pyc +0 -0
  163. clarifai/models/model_serving/model_config/triton/__pycache__/serializer.cpython-310.pyc +0 -0
  164. clarifai/models/model_serving/model_config/triton/__pycache__/triton_config.cpython-310.pyc +0 -0
  165. clarifai/models/model_serving/model_config/triton/__pycache__/wrappers.cpython-310.pyc +0 -0
  166. clarifai/models/model_serving/repo_build/__pycache__/__init__.cpython-310.pyc +0 -0
  167. clarifai/models/model_serving/repo_build/__pycache__/build.cpython-310.pyc +0 -0
  168. clarifai/models/model_serving/repo_build/static_files/__pycache__/base_test.cpython-310-pytest-7.2.0.pyc +0 -0
  169. clarifai/runners/__pycache__/server.cpython-310.pyc +0 -0
  170. clarifai/runners/dockerfile_template/Dockerfile.debug +0 -11
  171. clarifai/runners/dockerfile_template/Dockerfile.debug~ +0 -9
  172. clarifai/runners/models/__pycache__/model_builder.cpython-310.pyc +0 -0
  173. clarifai/runners/models/__pycache__/model_servicer.cpython-310.pyc +0 -0
  174. clarifai/runners/utils/__pycache__/data_types.cpython-310.pyc +0 -0
  175. clarifai/runners/utils/__pycache__/method_signatures.cpython-310.pyc +0 -0
  176. clarifai/runners/utils/__pycache__/serializers.cpython-310.pyc +0 -0
  177. clarifai/utils/evaluation/__pycache__/__init__.cpython-310.pyc +0 -0
  178. clarifai/utils/evaluation/__pycache__/helpers.cpython-310.pyc +0 -0
  179. clarifai/utils/evaluation/__pycache__/main.cpython-310.pyc +0 -0
  180. clarifai-11.1.7rc1.dist-info/RECORD +0 -205
  181. {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc2.dist-info}/LICENSE +0 -0
  182. {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc2.dist-info}/entry_points.txt +0 -0
  183. {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc2.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
- build_variable_signature(p.name, p.annotation, p.default) for p in sig.parameters.values()
37
- ]
38
- input_sigs, input_types, input_streaming = zip(*input_sigs)
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 = 'predict'
50
+ method_type = 'UNARY_UNARY'
49
51
  elif not input_streaming and output_streaming:
50
- method_type = 'generate'
52
+ method_type = 'UNARY_STREAMING'
51
53
  elif input_streaming and output_streaming:
52
- method_type = 'stream'
54
+ method_type = 'STREAMING_STREAMING'
53
55
  else:
54
56
  raise TypeError('stream methods with streaming inputs must have streaming outputs')
55
57
 
56
- #method_signature = resources_pb2.MethodSignature() # TODO
57
- method_signature = _SignatureDict() #for now
58
+ method_signature = resources_pb2.MethodSignature()
58
59
 
59
60
  method_signature.name = func.__name__
60
- #method_signature.method_type = getattr(resources_pb2.RunnerMethodType, method_type)
61
- assert method_type in ('predict', 'generate', 'stream')
62
- method_signature.method_type = method_type
63
- method_signature.docstring = func.__doc__
64
- method_signature.annotations_json = json.dumps(_get_annotations_source(func))
65
-
66
- #method_signature.inputs.extend(input_vars)
67
- #method_signature.outputs.extend(output_vars)
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
- """Extracts raw annotation strings from the function source."""
75
- source = inspect.getsource(func) # Get function source code
76
- source = textwrap.dedent(source) # Dedent source code
77
- tree = ast.parse(source) # Parse into AST
78
- func_node = next(node for node in tree.body
79
- if isinstance(node, ast.FunctionDef)) # Get function node
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
- annotations = {}
82
- for arg in func_node.args.args: # Process arguments
83
- if arg.annotation:
84
- annotations[arg.arg] = ast.unparse(arg.annotation) # Get raw annotation string
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
- if func_node.returns: # Process return type
87
- annotations["return"] = ast.unparse(func_node.returns)
85
+ # if func_node.returns: # Process return type
86
+ # annotations["return"] = ast.unparse(func_node.returns)
88
87
 
89
- return annotations
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
- #var = resources_pb2.VariableSignature() # TODO
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 = _VariableSignature()
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
- # inner_sig = sig.type_args.add()
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
- if get_origin(tp) == tuple:
149
- sig.type = DataType.TUPLE
150
- for inner_type in get_args(tp):
151
- #inner_sig = sig.type_args.add()
152
- sig.type_args.append(inner_sig := _VariableSignature())
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
- if get_origin(tp) == list:
157
- sig.type = DataType.LIST
158
- inner_type = get_args(tp)[0]
159
- #inner_sig = sig.type_args.add()
160
- sig.type_args.append(inner_sig := _VariableSignature())
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
- #signatures = {name: MessageToDict(sig) for name, sig in signatures.items()}
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
- d = json.loads(json_str, object_pairs_hook=_SignatureDict)
194
- return d
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):
@@ -288,7 +294,7 @@ def get_stream_from_signature(signatures):
288
294
  Get the stream signature from the given signatures.
289
295
  '''
290
296
  for sig in signatures:
291
- if sig.streaming:
297
+ if sig.iterator:
292
298
  return sig
293
299
  return None
294
300
 
@@ -357,9 +363,7 @@ def _normalize_data_type(tp):
357
363
  return data_types.Image
358
364
 
359
365
  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
- )
366
+ raise TypeError('Use PIL.Image.Image instead of PIL.Image module')
363
367
 
364
368
  # check for known data types
365
369
  try:
@@ -379,90 +383,58 @@ def _is_jsonable(tp):
379
383
  return False
380
384
 
381
385
 
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
386
  # type: name of the data type
402
387
  # data_field: name of the field in the data proto
403
388
  # serializer: serializer for the data type
404
389
  _DataType = namedtuple('_DataType', ('type', 'serializer'))
405
390
 
406
-
407
- # this will come from the proto module, but for now, define it here
408
- class DataType:
409
- NOT_SET = 'NOT_SET'
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}
391
+ _NON_INLINABLE_TYPES = {
392
+ resources_pb2.ModelTypeField.DataType.NAMED_FIELDS,
393
+ resources_pb2.ModelTypeField.DataType.TUPLE, resources_pb2.ModelTypeField.DataType.LIST
394
+ }
433
395
  _ZERO_VALUE_IDS = {id(None), id(''), id(b''), id(0), id(0.0), id(False)}
434
396
 
435
397
  # simple, non-container types that correspond directly to a data field
436
398
  _DATA_TYPES = {
437
399
  str:
438
- _DataType(DataType.STR, AtomicFieldSerializer('string_value')),
400
+ _DataType(resources_pb2.ModelTypeField.DataType.STR,
401
+ AtomicFieldSerializer('string_value')),
439
402
  bytes:
440
- _DataType(DataType.BYTES, AtomicFieldSerializer('bytes_value')),
403
+ _DataType(resources_pb2.ModelTypeField.DataType.BYTES,
404
+ AtomicFieldSerializer('bytes_value')),
441
405
  int:
442
- _DataType(DataType.INT, AtomicFieldSerializer('int_value')),
406
+ _DataType(resources_pb2.ModelTypeField.DataType.INT, AtomicFieldSerializer('int_value')),
443
407
  float:
444
- _DataType(DataType.FLOAT, AtomicFieldSerializer('float_value')),
408
+ _DataType(resources_pb2.ModelTypeField.DataType.FLOAT,
409
+ AtomicFieldSerializer('float_value')),
445
410
  bool:
446
- _DataType(DataType.BOOL, AtomicFieldSerializer('bool_value')),
411
+ _DataType(resources_pb2.ModelTypeField.DataType.BOOL, AtomicFieldSerializer('bool_value')),
447
412
  np.ndarray:
448
- _DataType(DataType.NDARRAY, NDArraySerializer('ndarray')),
413
+ _DataType(resources_pb2.ModelTypeField.DataType.NDARRAY, NDArraySerializer('ndarray')),
449
414
  data_types.JSON:
450
- _DataType(DataType.JSON, JSONSerializer('string_value')
415
+ _DataType(resources_pb2.ModelTypeField.DataType.JSON_DATA, JSONSerializer('string_value')
451
416
  ), # TODO change to json_value when new proto is ready
452
417
  data_types.Text:
453
- _DataType(DataType.TEXT, MessageSerializer('text', data_types.Text)),
418
+ _DataType(resources_pb2.ModelTypeField.DataType.TEXT,
419
+ MessageSerializer('text', data_types.Text)),
454
420
  data_types.Image:
455
- _DataType(DataType.IMAGE, MessageSerializer('image', data_types.Image)),
421
+ _DataType(resources_pb2.ModelTypeField.DataType.IMAGE,
422
+ MessageSerializer('image', data_types.Image)),
456
423
  data_types.Concept:
457
- _DataType(DataType.CONCEPT, MessageSerializer('concepts', data_types.Concept)),
424
+ _DataType(resources_pb2.ModelTypeField.DataType.CONCEPT,
425
+ MessageSerializer('concepts', data_types.Concept)),
458
426
  data_types.Region:
459
- _DataType(DataType.REGION, MessageSerializer('regions', data_types.Region)),
427
+ _DataType(resources_pb2.ModelTypeField.DataType.REGION,
428
+ MessageSerializer('regions', data_types.Region)),
460
429
  data_types.Frame:
461
- _DataType(DataType.FRAME, MessageSerializer('frames', data_types.Frame)),
430
+ _DataType(resources_pb2.ModelTypeField.DataType.FRAME,
431
+ MessageSerializer('frames', data_types.Frame)),
462
432
  data_types.Audio:
463
- _DataType(DataType.AUDIO, MessageSerializer('audio', data_types.Audio)),
433
+ _DataType(resources_pb2.ModelTypeField.DataType.AUDIO,
434
+ MessageSerializer('audio', data_types.Audio)),
464
435
  data_types.Video:
465
- _DataType(DataType.VIDEO, MessageSerializer('video', data_types.Video)),
436
+ _DataType(resources_pb2.ModelTypeField.DataType.VIDEO,
437
+ MessageSerializer('video', data_types.Video)),
466
438
  }
467
439
 
468
440
  _SERIALIZERS_BY_TYPE_ENUM = {dt.type: dt.serializer for dt in _DATA_TYPES.values()}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: clarifai
3
- Version: 11.1.7rc1
3
+ Version: 11.1.7rc2
4
4
  Summary: Clarifai Python SDK
5
5
  Home-page: https://github.com/Clarifai/clarifai-python
6
6
  Author: Clarifai
@@ -20,21 +20,21 @@ Classifier: Operating System :: OS Independent
20
20
  Requires-Python: >=3.8
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: clarifai-grpc >=11.1.3
24
- Requires-Dist: clarifai-protocol >=0.0.16
25
- Requires-Dist: numpy >=1.22.0
26
- Requires-Dist: tqdm >=4.65.0
27
- Requires-Dist: rich >=13.4.2
28
- Requires-Dist: PyYAML >=6.0.1
29
- Requires-Dist: schema ==0.7.5
30
- Requires-Dist: Pillow >=9.5.0
31
- Requires-Dist: tabulate >=0.9.0
32
- Requires-Dist: fsspec >=2024.6.1
33
- Requires-Dist: click >=8.1.7
34
- Requires-Dist: requests >=2.32.3
35
- Requires-Dist: aiohttp >=3.8.1
23
+ Requires-Dist: clarifai-grpc>=11.1.3
24
+ Requires-Dist: clarifai-protocol>=0.0.16
25
+ Requires-Dist: numpy>=1.22.0
26
+ Requires-Dist: tqdm>=4.65.0
27
+ Requires-Dist: rich>=13.4.2
28
+ Requires-Dist: PyYAML>=6.0.1
29
+ Requires-Dist: schema==0.7.5
30
+ Requires-Dist: Pillow>=9.5.0
31
+ Requires-Dist: tabulate>=0.9.0
32
+ Requires-Dist: fsspec>=2024.6.1
33
+ Requires-Dist: click>=8.1.7
34
+ Requires-Dist: requests>=2.32.3
35
+ Requires-Dist: aiohttp>=3.8.1
36
36
  Provides-Extra: all
37
- Requires-Dist: pycocotools ==2.0.6 ; extra == 'all'
37
+ Requires-Dist: pycocotools==2.0.6; extra == "all"
38
38
 
39
39
  <h1 align="center">
40
40
  <a href="https://www.clarifai.com/"><img alt="Clarifai" title="Clarifai" src="https://github.com/user-attachments/assets/623b883b-7fe5-4b95-bbfa-8691f5779af4"></a>