clarifai 11.2.3rc1__py3-none-any.whl → 11.2.3rc2__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 (248) 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/cli/base.py +81 -228
  15. clarifai/cli/compute_cluster.py +17 -25
  16. clarifai/cli/deployment.py +41 -67
  17. clarifai/cli/model.py +39 -26
  18. clarifai/cli/nodepool.py +40 -59
  19. clarifai/client/__pycache__/__init__.cpython-310.pyc +0 -0
  20. clarifai/client/__pycache__/__init__.cpython-39.pyc +0 -0
  21. clarifai/client/__pycache__/app.cpython-310.pyc +0 -0
  22. clarifai/client/__pycache__/app.cpython-39.pyc +0 -0
  23. clarifai/client/__pycache__/base.cpython-310.pyc +0 -0
  24. clarifai/client/__pycache__/compute_cluster.cpython-310.pyc +0 -0
  25. clarifai/client/__pycache__/dataset.cpython-310.pyc +0 -0
  26. clarifai/client/__pycache__/deployment.cpython-310.pyc +0 -0
  27. clarifai/client/__pycache__/input.cpython-310.pyc +0 -0
  28. clarifai/client/__pycache__/lister.cpython-310.pyc +0 -0
  29. clarifai/client/__pycache__/model.cpython-310.pyc +0 -0
  30. clarifai/client/__pycache__/module.cpython-310.pyc +0 -0
  31. clarifai/client/__pycache__/nodepool.cpython-310.pyc +0 -0
  32. clarifai/client/__pycache__/search.cpython-310.pyc +0 -0
  33. clarifai/client/__pycache__/user.cpython-310.pyc +0 -0
  34. clarifai/client/__pycache__/workflow.cpython-310.pyc +0 -0
  35. clarifai/client/app.py +1 -1
  36. clarifai/client/auth/__pycache__/__init__.cpython-310.pyc +0 -0
  37. clarifai/client/auth/__pycache__/helper.cpython-310.pyc +0 -0
  38. clarifai/client/auth/__pycache__/register.cpython-310.pyc +0 -0
  39. clarifai/client/auth/__pycache__/stub.cpython-310.pyc +0 -0
  40. clarifai/client/cli/__init__.py +0 -0
  41. clarifai/client/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  42. clarifai/client/cli/__pycache__/base_cli.cpython-310.pyc +0 -0
  43. clarifai/client/cli/__pycache__/model_cli.cpython-310.pyc +0 -0
  44. clarifai/client/cli/base_cli.py +88 -0
  45. clarifai/client/cli/model_cli.py +29 -0
  46. clarifai/client/model.py +159 -393
  47. clarifai/client/model_client.py +502 -0
  48. clarifai/constants/__pycache__/base.cpython-310.pyc +0 -0
  49. clarifai/constants/__pycache__/dataset.cpython-310.pyc +0 -0
  50. clarifai/constants/__pycache__/input.cpython-310.pyc +0 -0
  51. clarifai/constants/__pycache__/{model.cpython-312.pyc → model.cpython-310.pyc} +0 -0
  52. clarifai/constants/__pycache__/rag.cpython-310.pyc +0 -0
  53. clarifai/constants/__pycache__/search.cpython-310.pyc +0 -0
  54. clarifai/constants/__pycache__/workflow.cpython-310.pyc +0 -0
  55. clarifai/datasets/__pycache__/__init__.cpython-310.pyc +0 -0
  56. clarifai/datasets/__pycache__/__init__.cpython-39.pyc +0 -0
  57. clarifai/datasets/export/__pycache__/__init__.cpython-310.pyc +0 -0
  58. clarifai/datasets/export/__pycache__/__init__.cpython-39.pyc +0 -0
  59. clarifai/datasets/export/__pycache__/inputs_annotations.cpython-310.pyc +0 -0
  60. clarifai/datasets/upload/__pycache__/__init__.cpython-310.pyc +0 -0
  61. clarifai/datasets/upload/__pycache__/__init__.cpython-39.pyc +0 -0
  62. clarifai/datasets/upload/__pycache__/base.cpython-310.pyc +0 -0
  63. clarifai/datasets/upload/__pycache__/features.cpython-310.pyc +0 -0
  64. clarifai/datasets/upload/__pycache__/image.cpython-310.pyc +0 -0
  65. clarifai/datasets/upload/__pycache__/multimodal.cpython-310.pyc +0 -0
  66. clarifai/datasets/upload/__pycache__/text.cpython-310.pyc +0 -0
  67. clarifai/datasets/upload/__pycache__/utils.cpython-310.pyc +0 -0
  68. clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-39.pyc +0 -0
  69. clarifai/models/__pycache__/__init__.cpython-39.pyc +0 -0
  70. clarifai/modules/__pycache__/__init__.cpython-39.pyc +0 -0
  71. clarifai/rag/__pycache__/__init__.cpython-310.pyc +0 -0
  72. clarifai/rag/__pycache__/__init__.cpython-39.pyc +0 -0
  73. clarifai/rag/__pycache__/rag.cpython-310.pyc +0 -0
  74. clarifai/rag/__pycache__/rag.cpython-39.pyc +0 -0
  75. clarifai/rag/__pycache__/utils.cpython-310.pyc +0 -0
  76. clarifai/runners/__init__.py +2 -7
  77. clarifai/runners/__pycache__/__init__.cpython-310.pyc +0 -0
  78. clarifai/runners/__pycache__/__init__.cpython-39.pyc +0 -0
  79. clarifai/runners/dockerfile_template/Dockerfile.cpu.template +31 -0
  80. clarifai/runners/dockerfile_template/Dockerfile.cuda.template +42 -0
  81. clarifai/runners/dockerfile_template/Dockerfile.nim +71 -0
  82. clarifai/runners/models/__pycache__/__init__.cpython-310.pyc +0 -0
  83. clarifai/runners/models/__pycache__/__init__.cpython-39.pyc +0 -0
  84. clarifai/runners/models/__pycache__/base_typed_model.cpython-310.pyc +0 -0
  85. clarifai/runners/models/__pycache__/base_typed_model.cpython-39.pyc +0 -0
  86. clarifai/runners/models/__pycache__/model_class.cpython-310.pyc +0 -0
  87. clarifai/runners/models/__pycache__/model_run_locally.cpython-310-pytest-7.1.2.pyc +0 -0
  88. clarifai/runners/models/__pycache__/model_run_locally.cpython-310.pyc +0 -0
  89. clarifai/runners/models/__pycache__/model_runner.cpython-310.pyc +0 -0
  90. clarifai/runners/models/__pycache__/model_upload.cpython-310.pyc +0 -0
  91. clarifai/runners/models/model_builder.py +138 -51
  92. clarifai/runners/models/model_class.py +441 -28
  93. clarifai/runners/models/model_class_refract.py +80 -0
  94. clarifai/runners/models/model_run_locally.py +25 -89
  95. clarifai/runners/models/model_runner.py +8 -0
  96. clarifai/runners/models/model_servicer.py +11 -2
  97. clarifai/runners/models/model_upload.py +607 -0
  98. clarifai/runners/models/temp.py +25 -0
  99. clarifai/runners/utils/__pycache__/__init__.cpython-310.pyc +0 -0
  100. clarifai/runners/utils/__pycache__/__init__.cpython-38.pyc +0 -0
  101. clarifai/runners/utils/__pycache__/__init__.cpython-39.pyc +0 -0
  102. clarifai/runners/utils/__pycache__/buffered_stream.cpython-310.pyc +0 -0
  103. clarifai/runners/utils/__pycache__/buffered_stream.cpython-38.pyc +0 -0
  104. clarifai/runners/utils/__pycache__/buffered_stream.cpython-39.pyc +0 -0
  105. clarifai/runners/utils/__pycache__/const.cpython-310.pyc +0 -0
  106. clarifai/runners/utils/__pycache__/constants.cpython-310.pyc +0 -0
  107. clarifai/runners/utils/__pycache__/constants.cpython-38.pyc +0 -0
  108. clarifai/runners/utils/__pycache__/constants.cpython-39.pyc +0 -0
  109. clarifai/runners/utils/__pycache__/data_handler.cpython-310.pyc +0 -0
  110. clarifai/runners/utils/__pycache__/data_handler.cpython-38.pyc +0 -0
  111. clarifai/runners/utils/__pycache__/data_handler.cpython-39.pyc +0 -0
  112. clarifai/runners/utils/__pycache__/data_utils.cpython-310.pyc +0 -0
  113. clarifai/runners/utils/__pycache__/data_utils.cpython-38.pyc +0 -0
  114. clarifai/runners/utils/__pycache__/data_utils.cpython-39.pyc +0 -0
  115. clarifai/runners/utils/__pycache__/grpc_server.cpython-310.pyc +0 -0
  116. clarifai/runners/utils/__pycache__/grpc_server.cpython-38.pyc +0 -0
  117. clarifai/runners/utils/__pycache__/grpc_server.cpython-39.pyc +0 -0
  118. clarifai/runners/utils/__pycache__/health.cpython-310.pyc +0 -0
  119. clarifai/runners/utils/__pycache__/health.cpython-38.pyc +0 -0
  120. clarifai/runners/utils/__pycache__/health.cpython-39.pyc +0 -0
  121. clarifai/runners/utils/__pycache__/loader.cpython-310.pyc +0 -0
  122. clarifai/runners/utils/__pycache__/logging.cpython-310.pyc +0 -0
  123. clarifai/runners/utils/__pycache__/logging.cpython-38.pyc +0 -0
  124. clarifai/runners/utils/__pycache__/logging.cpython-39.pyc +0 -0
  125. clarifai/runners/utils/__pycache__/stream_source.cpython-310.pyc +0 -0
  126. clarifai/runners/utils/__pycache__/stream_source.cpython-39.pyc +0 -0
  127. clarifai/runners/utils/__pycache__/url_fetcher.cpython-310.pyc +0 -0
  128. clarifai/runners/utils/__pycache__/url_fetcher.cpython-38.pyc +0 -0
  129. clarifai/runners/utils/__pycache__/url_fetcher.cpython-39.pyc +0 -0
  130. clarifai/runners/utils/code_script.py +217 -0
  131. clarifai/runners/utils/const.py +8 -9
  132. clarifai/runners/utils/data_handler.py +271 -210
  133. clarifai/runners/utils/data_handler_refract.py +213 -0
  134. clarifai/runners/utils/data_types.py +473 -0
  135. clarifai/runners/utils/data_utils.py +165 -0
  136. clarifai/runners/utils/loader.py +6 -36
  137. clarifai/runners/utils/logger.py +0 -0
  138. clarifai/runners/utils/method_signatures.py +518 -0
  139. clarifai/runners/utils/serializers.py +222 -0
  140. clarifai/schema/__pycache__/search.cpython-310.pyc +0 -0
  141. clarifai/urls/__pycache__/helper.cpython-310.pyc +0 -0
  142. clarifai/utils/__pycache__/__init__.cpython-310.pyc +0 -0
  143. clarifai/utils/__pycache__/__init__.cpython-39.pyc +0 -0
  144. clarifai/utils/__pycache__/cli.cpython-310.pyc +0 -0
  145. clarifai/utils/__pycache__/constants.cpython-310.pyc +0 -0
  146. clarifai/utils/__pycache__/logging.cpython-310.pyc +0 -0
  147. clarifai/utils/__pycache__/misc.cpython-310.pyc +0 -0
  148. clarifai/utils/__pycache__/model_train.cpython-310.pyc +0 -0
  149. clarifai/utils/cli.py +33 -132
  150. clarifai/utils/constants.py +0 -4
  151. clarifai/utils/evaluation/__pycache__/__init__.cpython-39.pyc +0 -0
  152. clarifai/utils/evaluation/__pycache__/main.cpython-39.pyc +0 -0
  153. clarifai/utils/misc.py +0 -2
  154. clarifai/workflows/__pycache__/__init__.cpython-310.pyc +0 -0
  155. clarifai/workflows/__pycache__/__init__.cpython-39.pyc +0 -0
  156. clarifai/workflows/__pycache__/export.cpython-310.pyc +0 -0
  157. clarifai/workflows/__pycache__/utils.cpython-310.pyc +0 -0
  158. clarifai/workflows/__pycache__/validate.cpython-310.pyc +0 -0
  159. {clarifai-11.2.3rc1.dist-info → clarifai-11.2.3rc2.dist-info}/METADATA +14 -3
  160. clarifai-11.2.3rc2.dist-info/RECORD +238 -0
  161. {clarifai-11.2.3rc1.dist-info → clarifai-11.2.3rc2.dist-info}/WHEEL +1 -1
  162. clarifai/__pycache__/__init__.cpython-312.pyc +0 -0
  163. clarifai/__pycache__/errors.cpython-312.pyc +0 -0
  164. clarifai/__pycache__/versions.cpython-312.pyc +0 -0
  165. clarifai/cli/__pycache__/__init__.cpython-312.pyc +0 -0
  166. clarifai/cli/__pycache__/base.cpython-312.pyc +0 -0
  167. clarifai/cli/__pycache__/compute_cluster.cpython-312.pyc +0 -0
  168. clarifai/cli/__pycache__/deployment.cpython-312.pyc +0 -0
  169. clarifai/cli/__pycache__/model.cpython-312.pyc +0 -0
  170. clarifai/cli/__pycache__/nodepool.cpython-312.pyc +0 -0
  171. clarifai/client/__pycache__/__init__.cpython-312.pyc +0 -0
  172. clarifai/client/__pycache__/app.cpython-312.pyc +0 -0
  173. clarifai/client/__pycache__/base.cpython-312.pyc +0 -0
  174. clarifai/client/__pycache__/compute_cluster.cpython-312.pyc +0 -0
  175. clarifai/client/__pycache__/dataset.cpython-312.pyc +0 -0
  176. clarifai/client/__pycache__/deployment.cpython-312.pyc +0 -0
  177. clarifai/client/__pycache__/input.cpython-312.pyc +0 -0
  178. clarifai/client/__pycache__/lister.cpython-312.pyc +0 -0
  179. clarifai/client/__pycache__/model.cpython-312.pyc +0 -0
  180. clarifai/client/__pycache__/model_client.cpython-312.pyc +0 -0
  181. clarifai/client/__pycache__/module.cpython-312.pyc +0 -0
  182. clarifai/client/__pycache__/nodepool.cpython-312.pyc +0 -0
  183. clarifai/client/__pycache__/search.cpython-312.pyc +0 -0
  184. clarifai/client/__pycache__/user.cpython-312.pyc +0 -0
  185. clarifai/client/__pycache__/workflow.cpython-312.pyc +0 -0
  186. clarifai/client/auth/__pycache__/__init__.cpython-312.pyc +0 -0
  187. clarifai/client/auth/__pycache__/helper.cpython-312.pyc +0 -0
  188. clarifai/client/auth/__pycache__/register.cpython-312.pyc +0 -0
  189. clarifai/client/auth/__pycache__/stub.cpython-312.pyc +0 -0
  190. clarifai/constants/__pycache__/base.cpython-312.pyc +0 -0
  191. clarifai/constants/__pycache__/dataset.cpython-312.pyc +0 -0
  192. clarifai/constants/__pycache__/input.cpython-312.pyc +0 -0
  193. clarifai/constants/__pycache__/search.cpython-312.pyc +0 -0
  194. clarifai/constants/__pycache__/workflow.cpython-312.pyc +0 -0
  195. clarifai/datasets/__pycache__/__init__.cpython-312.pyc +0 -0
  196. clarifai/datasets/export/__pycache__/__init__.cpython-312.pyc +0 -0
  197. clarifai/datasets/export/__pycache__/inputs_annotations.cpython-312.pyc +0 -0
  198. clarifai/datasets/upload/__pycache__/__init__.cpython-312.pyc +0 -0
  199. clarifai/datasets/upload/__pycache__/base.cpython-312.pyc +0 -0
  200. clarifai/datasets/upload/__pycache__/features.cpython-312.pyc +0 -0
  201. clarifai/datasets/upload/__pycache__/image.cpython-312.pyc +0 -0
  202. clarifai/datasets/upload/__pycache__/multimodal.cpython-312.pyc +0 -0
  203. clarifai/datasets/upload/__pycache__/text.cpython-312.pyc +0 -0
  204. clarifai/datasets/upload/__pycache__/utils.cpython-312.pyc +0 -0
  205. clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-312.pyc +0 -0
  206. clarifai/datasets/upload/loaders/__pycache__/coco_detection.cpython-312.pyc +0 -0
  207. clarifai/modules/__pycache__/__init__.cpython-312.pyc +0 -0
  208. clarifai/modules/__pycache__/css.cpython-312.pyc +0 -0
  209. clarifai/runners/__pycache__/__init__.cpython-312.pyc +0 -0
  210. clarifai/runners/__pycache__/server.cpython-312.pyc +0 -0
  211. clarifai/runners/models/__pycache__/__init__.cpython-312.pyc +0 -0
  212. clarifai/runners/models/__pycache__/base_typed_model.cpython-312.pyc +0 -0
  213. clarifai/runners/models/__pycache__/model_builder.cpython-312.pyc +0 -0
  214. clarifai/runners/models/__pycache__/model_class.cpython-312.pyc +0 -0
  215. clarifai/runners/models/__pycache__/model_run_locally.cpython-312.pyc +0 -0
  216. clarifai/runners/models/__pycache__/model_runner.cpython-312.pyc +0 -0
  217. clarifai/runners/models/__pycache__/model_servicer.cpython-312.pyc +0 -0
  218. clarifai/runners/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  219. clarifai/runners/utils/__pycache__/const.cpython-312.pyc +0 -0
  220. clarifai/runners/utils/__pycache__/data_handler.cpython-312.pyc +0 -0
  221. clarifai/runners/utils/__pycache__/data_types.cpython-312.pyc +0 -0
  222. clarifai/runners/utils/__pycache__/data_utils.cpython-312.pyc +0 -0
  223. clarifai/runners/utils/__pycache__/loader.cpython-312.pyc +0 -0
  224. clarifai/runners/utils/__pycache__/method_signatures.cpython-312.pyc +0 -0
  225. clarifai/runners/utils/__pycache__/serializers.cpython-312.pyc +0 -0
  226. clarifai/runners/utils/__pycache__/url_fetcher.cpython-312.pyc +0 -0
  227. clarifai/schema/__pycache__/search.cpython-312.pyc +0 -0
  228. clarifai/urls/__pycache__/helper.cpython-312.pyc +0 -0
  229. clarifai/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  230. clarifai/utils/__pycache__/cli.cpython-312.pyc +0 -0
  231. clarifai/utils/__pycache__/config.cpython-312.pyc +0 -0
  232. clarifai/utils/__pycache__/constants.cpython-312.pyc +0 -0
  233. clarifai/utils/__pycache__/logging.cpython-312.pyc +0 -0
  234. clarifai/utils/__pycache__/misc.cpython-312.pyc +0 -0
  235. clarifai/utils/__pycache__/model_train.cpython-312.pyc +0 -0
  236. clarifai/utils/config.py +0 -105
  237. clarifai/utils/config.py~ +0 -145
  238. clarifai/utils/evaluation/__pycache__/__init__.cpython-312.pyc +0 -0
  239. clarifai/utils/evaluation/__pycache__/helpers.cpython-312.pyc +0 -0
  240. clarifai/utils/evaluation/__pycache__/main.cpython-312.pyc +0 -0
  241. clarifai/workflows/__pycache__/__init__.cpython-312.pyc +0 -0
  242. clarifai/workflows/__pycache__/export.cpython-312.pyc +0 -0
  243. clarifai/workflows/__pycache__/utils.cpython-312.pyc +0 -0
  244. clarifai/workflows/__pycache__/validate.cpython-312.pyc +0 -0
  245. clarifai-11.2.3rc1.dist-info/RECORD +0 -185
  246. {clarifai-11.2.3rc1.dist-info → clarifai-11.2.3rc2.dist-info}/LICENSE +0 -0
  247. {clarifai-11.2.3rc1.dist-info → clarifai-11.2.3rc2.dist-info}/entry_points.txt +0 -0
  248. {clarifai-11.2.3rc1.dist-info → clarifai-11.2.3rc2.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
+ '''
@@ -0,0 +1,473 @@
1
+ import io
2
+ import json
3
+ from typing import Iterable, List, get_args, get_origin
4
+
5
+ import numpy as np
6
+ from clarifai_grpc.grpc.api.resources_pb2 import Audio as AudioProto
7
+ from clarifai_grpc.grpc.api.resources_pb2 import Concept as ConceptProto
8
+ from clarifai_grpc.grpc.api.resources_pb2 import Frame as FrameProto
9
+ from clarifai_grpc.grpc.api.resources_pb2 import Image as ImageProto
10
+ from clarifai_grpc.grpc.api.resources_pb2 import Region as RegionProto
11
+ from clarifai_grpc.grpc.api.resources_pb2 import Text as TextProto
12
+ from clarifai_grpc.grpc.api.resources_pb2 import Video as VideoProto
13
+ from PIL import Image as PILImage
14
+
15
+
16
+ class MessageData:
17
+
18
+ def to_proto(self):
19
+ raise NotImplementedError
20
+
21
+ @classmethod
22
+ def from_proto(cls, proto):
23
+ raise NotImplementedError
24
+
25
+ @classmethod
26
+ def from_value(cls, value):
27
+ if isinstance(value, cls):
28
+ return value
29
+ return cls(value)
30
+
31
+ def cast(self, python_type):
32
+ if python_type == self.__class__:
33
+ return self
34
+ raise TypeError(f'Incompatible type for {self.__class__.__name__}: {python_type}')
35
+
36
+
37
+ class NamedFieldsMeta(type):
38
+ """Metaclass to create NamedFields subclasses with __annotations__ when fields are specified."""
39
+
40
+ def __call__(cls, *args, **kwargs):
41
+ # Check if keyword arguments are types (used in type annotations)
42
+ if kwargs and all(isinstance(v, type) for v in kwargs.values()):
43
+ # Dynamically create a subclass with __annotations__
44
+ name = f"NamedFields({', '.join(f'{k}:{v.__name__}' for k, v in kwargs.items())})"
45
+ return type(name, (cls,), {'__annotations__': kwargs})
46
+ else:
47
+ # Create a normal instance for runtime data
48
+ return super().__call__(*args, **kwargs)
49
+
50
+
51
+ class NamedFields(metaclass=NamedFieldsMeta):
52
+ """A class that can be used to store named fields with values."""
53
+
54
+ def __init__(self, **kwargs):
55
+ for key, value in kwargs.items():
56
+ setattr(self, key, value)
57
+
58
+ def items(self):
59
+ return self.__dict__.items()
60
+
61
+ def keys(self):
62
+ return self.__dict__.keys()
63
+
64
+ def values(self):
65
+ return self.__dict__.values()
66
+
67
+ def __contains__(self, key):
68
+ return key in self.__dict__
69
+
70
+ def __getitem__(self, key):
71
+ return getattr(self, key)
72
+
73
+ def __setitem__(self, key, value):
74
+ setattr(self, key, value)
75
+
76
+ def __repr__(self):
77
+ return f"{self.__class__.__name__}({', '.join(f'{key}={value!r}' for key, value in self.__dict__.items())})"
78
+
79
+ def __origin__(self):
80
+ return self
81
+
82
+ def __args__(self):
83
+ return list(self.keys())
84
+
85
+
86
+ class Stream(Iterable):
87
+ pass
88
+
89
+
90
+ class JSON:
91
+
92
+ def __init__(self, value):
93
+ self.value = value
94
+
95
+ def __eq__(self, other):
96
+ return self.value == other
97
+
98
+ def __bool__(self):
99
+ return bool(self.value)
100
+
101
+ def __repr__(self):
102
+ return f"JSON({self.value})"
103
+
104
+ def to_json(self):
105
+ return json.dumps(self.value)
106
+
107
+ @classmethod
108
+ def from_json(cls, json_str):
109
+ return cls(json.loads(json_str))
110
+
111
+ @classmethod
112
+ def from_value(cls, value):
113
+ return cls(value)
114
+
115
+ def cast(self, python_type):
116
+ if not isinstance(self.value, python_type):
117
+ raise TypeError(f'Incompatible type {type(self.value)} for {python_type}')
118
+ return self.value
119
+
120
+
121
+ class Text(MessageData):
122
+
123
+ def __init__(self, text: str, url: str = None):
124
+ self.text = text
125
+ self.url = url
126
+
127
+ def __eq__(self, other):
128
+ if isinstance(other, Text):
129
+ return self.text == other.text and self.url == other.url
130
+ if isinstance(other, str):
131
+ return self.text == other
132
+ return False
133
+
134
+ def __bool__(self):
135
+ return bool(self.text) or bool(self.url)
136
+
137
+ def __repr__(self) -> str:
138
+ return f"Text(text={self.text!r}, url={self.url!r})"
139
+
140
+ def to_proto(self) -> TextProto:
141
+ return TextProto(raw=self.text or '', url=self.url or '')
142
+
143
+ @classmethod
144
+ def from_proto(cls, proto: TextProto) -> "Text":
145
+ return cls(proto.raw, proto.url or None)
146
+
147
+ @classmethod
148
+ def from_value(cls, value):
149
+ if isinstance(value, str):
150
+ return cls(value)
151
+ if isinstance(value, Text):
152
+ return value
153
+ if isinstance(value, dict):
154
+ return cls(value.get('text'), value.get('url'))
155
+ raise TypeError(f'Incompatible type for Text: {type(value)}')
156
+
157
+ def cast(self, python_type):
158
+ if python_type == str:
159
+ return self.text
160
+ if python_type == Text:
161
+ return self
162
+ raise TypeError(f'Incompatible type for Text: {python_type}')
163
+
164
+
165
+ class Concept(MessageData):
166
+
167
+ def __init__(self, id: str, name: str, value: float = 1):
168
+ self.id = id
169
+ self.name = name
170
+ self.value = value
171
+
172
+ def __repr__(self) -> str:
173
+ return f"Concept(id={self.id!r}, name={self.name!r}, value={self.value})"
174
+
175
+ def to_proto(self):
176
+ return ConceptProto(id=self.id, name=self.name, value=self.value)
177
+
178
+ @classmethod
179
+ def from_proto(cls, proto: ConceptProto) -> "Concept":
180
+ return cls(proto.id, proto.name, proto.value)
181
+
182
+
183
+ class Region(MessageData):
184
+
185
+ def __init__(self,
186
+ proto_region: RegionProto = None,
187
+ box: List[float] = None,
188
+ concepts: List[Concept] = None):
189
+ if proto_region is None:
190
+ proto_region = RegionProto()
191
+ self.proto = proto_region
192
+ # use setters for init vals
193
+ if box and isinstance(
194
+ box, list) and len(box) == 4 and all(isinstance(val, (int, float)) for val in box):
195
+ self.box = box
196
+ if concepts and isinstance(concepts,
197
+ list) and all(isinstance(concept, Concept) for concept in concepts):
198
+ self.concepts = concepts
199
+
200
+ @property
201
+ def box(self) -> List[float]:
202
+ bbox = self.proto.region_info.bounding_box
203
+ return [bbox.left_col, bbox.top_row, bbox.right_col, bbox.bottom_row] # x1, y1, x2, y2
204
+
205
+ @box.setter
206
+ def box(self, value: List[float]):
207
+ bbox = self.proto.region_info.bounding_box
208
+ bbox.left_col, bbox.top_row, bbox.right_col, bbox.bottom_row = value
209
+
210
+ @property
211
+ def concepts(self) -> List[Concept]:
212
+ return [Concept.from_proto(proto) for proto in self.proto.data.concepts]
213
+
214
+ @concepts.setter
215
+ def concepts(self, value: List[Concept]):
216
+ self.proto.data.concepts.extend([concept.to_proto() for concept in value])
217
+
218
+ def __repr__(self) -> str:
219
+ return f"Region(box={self.box}, concepts={self.concepts})"
220
+
221
+ def to_proto(self) -> RegionProto:
222
+ return self.proto
223
+
224
+ @classmethod
225
+ def from_proto(cls, proto: RegionProto) -> "Region":
226
+ return cls(proto)
227
+
228
+
229
+ class Image(MessageData):
230
+
231
+ def __init__(self, proto_image: ImageProto = None, url: str = None, bytes: bytes = None):
232
+ if proto_image is None:
233
+ proto_image = ImageProto()
234
+ self.proto = proto_image
235
+ # use setters for init vals
236
+ if url:
237
+ self.url = url
238
+ if bytes:
239
+ self.bytes = bytes
240
+
241
+ @property
242
+ def url(self) -> str:
243
+ return self.proto.url
244
+
245
+ @url.setter
246
+ def url(self, value: str):
247
+ self.proto.url = value
248
+
249
+ @property
250
+ def bytes(self) -> bytes:
251
+ return self.proto.base64
252
+
253
+ @bytes.setter
254
+ def bytes(self, value: bytes):
255
+ self.proto.base64 = value
256
+
257
+ def __repr__(self) -> str:
258
+ attrs = []
259
+ if self.url:
260
+ attrs.append(f"url={self.url!r}")
261
+ if self.bytes:
262
+ attrs.append(f"bytes=<{len(self.bytes)} bytes>")
263
+ return f"Image({', '.join(attrs)})"
264
+
265
+ @classmethod
266
+ def from_url(cls, url: str) -> "Image":
267
+ proto_image = ImageProto(url=url)
268
+ return cls(proto_image)
269
+
270
+ @classmethod
271
+ def from_pil(cls, pil_image: PILImage.Image) -> "Image":
272
+ with io.BytesIO() as output:
273
+ pil_image.save(output, format="PNG")
274
+ image_bytes = output.getvalue()
275
+ proto_image = ImageProto(base64=image_bytes)
276
+ return cls(proto_image)
277
+
278
+ def to_pil(self) -> PILImage.Image:
279
+ if not self.proto.base64:
280
+ raise ValueError("Image has no bytes")
281
+ return PILImage.open(io.BytesIO(self.proto.base64))
282
+
283
+ def to_numpy(self) -> np.ndarray:
284
+ return np.asarray(self.to_pil())
285
+
286
+ def to_proto(self) -> ImageProto:
287
+ return self.proto
288
+
289
+ @classmethod
290
+ def from_proto(cls, proto: ImageProto) -> "Image":
291
+ return cls(proto)
292
+
293
+ @classmethod
294
+ def from_value(cls, value):
295
+ if isinstance(value, PILImage.Image):
296
+ return cls.from_pil(value)
297
+ if isinstance(value, Image):
298
+ return value
299
+ raise TypeError(f'Incompatible type for Image: {type(value)}')
300
+
301
+ def cast(self, python_type):
302
+ if python_type == Image:
303
+ return self
304
+ if python_type in (PILImage.Image, PILImage):
305
+ return self.to_pil()
306
+ if python_type == np.ndarray or get_origin(python_type) == np.ndarray:
307
+ return self.to_numpy()
308
+ raise TypeError(f'Incompatible type for Image: {python_type}')
309
+
310
+
311
+ class Audio(MessageData):
312
+
313
+ def __init__(self, proto_audio: AudioProto = None, url: str = None, bytes: bytes = None):
314
+ if proto_audio is None:
315
+ proto_audio = AudioProto()
316
+ self.proto = proto_audio
317
+
318
+ if url:
319
+ self.url = url
320
+ if bytes:
321
+ self.bytes = bytes
322
+
323
+ @property
324
+ def url(self) -> str:
325
+ return self.proto.url
326
+
327
+ @url.setter
328
+ def url(self, value: str):
329
+ self.proto.url = value
330
+
331
+ @property
332
+ def bytes(self) -> bytes:
333
+ return self.proto.base64
334
+
335
+ @bytes.setter
336
+ def bytes(self, value: bytes):
337
+ self.proto.base64 = value
338
+
339
+ @classmethod
340
+ def from_url(cls, url: str) -> "Audio":
341
+ proto_audio = AudioProto(url=url)
342
+ return cls(proto_audio)
343
+
344
+ def __repr__(self) -> str:
345
+ attrs = []
346
+ if self.url:
347
+ attrs.append(f"url={self.url!r}")
348
+ if self.bytes:
349
+ attrs.append(f"bytes=<{len(self.bytes)} bytes>")
350
+ return f"Audio({', '.join(attrs)})"
351
+
352
+ def to_proto(self) -> AudioProto:
353
+ return self.proto
354
+
355
+ @classmethod
356
+ def from_proto(cls, proto: AudioProto) -> "Audio":
357
+ return cls(proto)
358
+
359
+
360
+ class Frame(MessageData):
361
+
362
+ def __init__(self,
363
+ proto_frame: FrameProto = None,
364
+ image: Image = None,
365
+ regions: List[Region] = None,
366
+ time: float = None):
367
+ if proto_frame is None:
368
+ proto_frame = FrameProto()
369
+ self.proto = proto_frame
370
+ # use setters for init vals
371
+ if image:
372
+ self.image = image
373
+ if regions:
374
+ self.regions = regions
375
+ if time:
376
+ self.time = time
377
+
378
+ @property
379
+ def time(self) -> float:
380
+ # TODO: time is a uint32, so this will overflow at 49.7 days
381
+ # we should be using double or uint64 in the proto instead
382
+ return self.proto.frame_info.time / 1000.0
383
+
384
+ @time.setter
385
+ def time(self, value: float):
386
+ self.proto.frame_info.time = int(value * 1000)
387
+
388
+ @property
389
+ def image(self) -> Image:
390
+ return Image.from_proto(self.proto.data.image)
391
+
392
+ @image.setter
393
+ def image(self, value: Image):
394
+ self.proto.data.image.CopyFrom(value.to_proto())
395
+
396
+ @property
397
+ def regions(self) -> List[Region]:
398
+ return [Region(region) for region in self.proto.data.regions]
399
+
400
+ @regions.setter
401
+ def regions(self, value: List[Region]):
402
+ self.proto.data.regions.extend([region.proto for region in value])
403
+
404
+ def to_proto(self) -> FrameProto:
405
+ return self.proto
406
+
407
+ @classmethod
408
+ def from_proto(cls, proto: FrameProto) -> "Frame":
409
+ return cls(proto)
410
+
411
+
412
+ class Video(MessageData):
413
+
414
+ def __init__(self, proto_video: VideoProto = None, url: str = None, bytes: bytes = None):
415
+ if proto_video is None:
416
+ proto_video = VideoProto()
417
+ self.proto = proto_video
418
+
419
+ if url:
420
+ self.url = url
421
+ if bytes:
422
+ self.bytes = bytes
423
+
424
+ @property
425
+ def url(self) -> str:
426
+ return self.proto.url
427
+
428
+ @url.setter
429
+ def url(self, value: str):
430
+ self.proto.url = value
431
+
432
+ @property
433
+ def bytes(self) -> bytes:
434
+ return self.proto.base64
435
+
436
+ @bytes.setter
437
+ def bytes(self, value: bytes):
438
+ self.proto.base64 = value
439
+
440
+ @classmethod
441
+ def from_url(cls, url: str) -> "Video":
442
+ proto_video = VideoProto(url=url)
443
+ return cls(proto_video)
444
+
445
+ def __repr__(self) -> str:
446
+ attrs = []
447
+ if self.url:
448
+ attrs.append(f"url={self.url!r}")
449
+ if self.bytes:
450
+ attrs.append(f"bytes=<{len(self.bytes)} bytes>")
451
+ return f"Video({', '.join(attrs)})"
452
+
453
+ def to_proto(self) -> VideoProto:
454
+ return self.proto
455
+
456
+ @classmethod
457
+ def from_proto(cls, proto: VideoProto) -> "Video":
458
+ return cls(proto)
459
+
460
+
461
+ def cast(value, python_type):
462
+ list_type = (get_origin(python_type) == list)
463
+ if isinstance(value, MessageData):
464
+ return value.cast(python_type)
465
+ if list_type and isinstance(value, np.ndarray):
466
+ return value.tolist()
467
+ if list_type and isinstance(value, list):
468
+ if get_args(python_type):
469
+ inner_type = get_args(python_type)[0]
470
+ return [cast(item, inner_type) for item in value]
471
+ if not isinstance(value, Iterable):
472
+ raise TypeError(f'Expected list, got {type(value)}')
473
+ return value