clarifai 11.3.0rc2__py3-none-any.whl → 11.4.0__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 (300) hide show
  1. clarifai/__init__.py +1 -1
  2. clarifai/cli/__main__.py +1 -1
  3. clarifai/cli/base.py +144 -136
  4. clarifai/cli/compute_cluster.py +45 -31
  5. clarifai/cli/deployment.py +93 -76
  6. clarifai/cli/model.py +578 -180
  7. clarifai/cli/nodepool.py +100 -82
  8. clarifai/client/__init__.py +12 -2
  9. clarifai/client/app.py +973 -911
  10. clarifai/client/auth/helper.py +345 -342
  11. clarifai/client/auth/register.py +7 -7
  12. clarifai/client/auth/stub.py +107 -106
  13. clarifai/client/base.py +185 -178
  14. clarifai/client/compute_cluster.py +214 -180
  15. clarifai/client/dataset.py +793 -698
  16. clarifai/client/deployment.py +55 -50
  17. clarifai/client/input.py +1223 -1088
  18. clarifai/client/lister.py +47 -45
  19. clarifai/client/model.py +1939 -1717
  20. clarifai/client/model_client.py +525 -502
  21. clarifai/client/module.py +82 -73
  22. clarifai/client/nodepool.py +358 -213
  23. clarifai/client/runner.py +58 -0
  24. clarifai/client/search.py +342 -309
  25. clarifai/client/user.py +419 -414
  26. clarifai/client/workflow.py +294 -274
  27. clarifai/constants/dataset.py +11 -17
  28. clarifai/constants/model.py +8 -2
  29. clarifai/datasets/export/inputs_annotations.py +233 -217
  30. clarifai/datasets/upload/base.py +63 -51
  31. clarifai/datasets/upload/features.py +43 -38
  32. clarifai/datasets/upload/image.py +237 -207
  33. clarifai/datasets/upload/loaders/coco_captions.py +34 -32
  34. clarifai/datasets/upload/loaders/coco_detection.py +72 -65
  35. clarifai/datasets/upload/loaders/imagenet_classification.py +57 -53
  36. clarifai/datasets/upload/loaders/xview_detection.py +274 -132
  37. clarifai/datasets/upload/multimodal.py +55 -46
  38. clarifai/datasets/upload/text.py +55 -47
  39. clarifai/datasets/upload/utils.py +250 -234
  40. clarifai/errors.py +51 -50
  41. clarifai/models/api.py +260 -238
  42. clarifai/modules/css.py +50 -50
  43. clarifai/modules/pages.py +33 -33
  44. clarifai/rag/rag.py +312 -288
  45. clarifai/rag/utils.py +91 -84
  46. clarifai/runners/models/model_builder.py +906 -802
  47. clarifai/runners/models/model_class.py +370 -331
  48. clarifai/runners/models/model_run_locally.py +459 -419
  49. clarifai/runners/models/model_runner.py +170 -162
  50. clarifai/runners/models/model_servicer.py +78 -70
  51. clarifai/runners/server.py +111 -101
  52. clarifai/runners/utils/code_script.py +225 -187
  53. clarifai/runners/utils/const.py +4 -1
  54. clarifai/runners/utils/data_types/__init__.py +12 -0
  55. clarifai/runners/utils/data_types/data_types.py +598 -0
  56. clarifai/runners/utils/data_utils.py +387 -440
  57. clarifai/runners/utils/loader.py +247 -227
  58. clarifai/runners/utils/method_signatures.py +411 -386
  59. clarifai/runners/utils/openai_convertor.py +108 -109
  60. clarifai/runners/utils/serializers.py +175 -179
  61. clarifai/runners/utils/url_fetcher.py +35 -35
  62. clarifai/schema/search.py +56 -63
  63. clarifai/urls/helper.py +125 -102
  64. clarifai/utils/cli.py +129 -123
  65. clarifai/utils/config.py +127 -87
  66. clarifai/utils/constants.py +49 -0
  67. clarifai/utils/evaluation/helpers.py +503 -466
  68. clarifai/utils/evaluation/main.py +431 -393
  69. clarifai/utils/evaluation/testset_annotation_parser.py +154 -144
  70. clarifai/utils/logging.py +324 -306
  71. clarifai/utils/misc.py +60 -56
  72. clarifai/utils/model_train.py +165 -146
  73. clarifai/utils/protobuf.py +126 -103
  74. clarifai/versions.py +3 -1
  75. clarifai/workflows/export.py +48 -50
  76. clarifai/workflows/utils.py +39 -36
  77. clarifai/workflows/validate.py +55 -43
  78. {clarifai-11.3.0rc2.dist-info → clarifai-11.4.0.dist-info}/METADATA +16 -6
  79. clarifai-11.4.0.dist-info/RECORD +109 -0
  80. {clarifai-11.3.0rc2.dist-info → clarifai-11.4.0.dist-info}/WHEEL +1 -1
  81. clarifai/__pycache__/__init__.cpython-310.pyc +0 -0
  82. clarifai/__pycache__/__init__.cpython-311.pyc +0 -0
  83. clarifai/__pycache__/__init__.cpython-39.pyc +0 -0
  84. clarifai/__pycache__/errors.cpython-310.pyc +0 -0
  85. clarifai/__pycache__/errors.cpython-311.pyc +0 -0
  86. clarifai/__pycache__/versions.cpython-310.pyc +0 -0
  87. clarifai/__pycache__/versions.cpython-311.pyc +0 -0
  88. clarifai/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  89. clarifai/cli/__pycache__/__init__.cpython-311.pyc +0 -0
  90. clarifai/cli/__pycache__/base.cpython-310.pyc +0 -0
  91. clarifai/cli/__pycache__/base.cpython-311.pyc +0 -0
  92. clarifai/cli/__pycache__/base_cli.cpython-310.pyc +0 -0
  93. clarifai/cli/__pycache__/compute_cluster.cpython-310.pyc +0 -0
  94. clarifai/cli/__pycache__/compute_cluster.cpython-311.pyc +0 -0
  95. clarifai/cli/__pycache__/deployment.cpython-310.pyc +0 -0
  96. clarifai/cli/__pycache__/deployment.cpython-311.pyc +0 -0
  97. clarifai/cli/__pycache__/model.cpython-310.pyc +0 -0
  98. clarifai/cli/__pycache__/model.cpython-311.pyc +0 -0
  99. clarifai/cli/__pycache__/model_cli.cpython-310.pyc +0 -0
  100. clarifai/cli/__pycache__/nodepool.cpython-310.pyc +0 -0
  101. clarifai/cli/__pycache__/nodepool.cpython-311.pyc +0 -0
  102. clarifai/client/__pycache__/__init__.cpython-310.pyc +0 -0
  103. clarifai/client/__pycache__/__init__.cpython-311.pyc +0 -0
  104. clarifai/client/__pycache__/__init__.cpython-39.pyc +0 -0
  105. clarifai/client/__pycache__/app.cpython-310.pyc +0 -0
  106. clarifai/client/__pycache__/app.cpython-311.pyc +0 -0
  107. clarifai/client/__pycache__/app.cpython-39.pyc +0 -0
  108. clarifai/client/__pycache__/base.cpython-310.pyc +0 -0
  109. clarifai/client/__pycache__/base.cpython-311.pyc +0 -0
  110. clarifai/client/__pycache__/compute_cluster.cpython-310.pyc +0 -0
  111. clarifai/client/__pycache__/compute_cluster.cpython-311.pyc +0 -0
  112. clarifai/client/__pycache__/dataset.cpython-310.pyc +0 -0
  113. clarifai/client/__pycache__/dataset.cpython-311.pyc +0 -0
  114. clarifai/client/__pycache__/deployment.cpython-310.pyc +0 -0
  115. clarifai/client/__pycache__/deployment.cpython-311.pyc +0 -0
  116. clarifai/client/__pycache__/input.cpython-310.pyc +0 -0
  117. clarifai/client/__pycache__/input.cpython-311.pyc +0 -0
  118. clarifai/client/__pycache__/lister.cpython-310.pyc +0 -0
  119. clarifai/client/__pycache__/lister.cpython-311.pyc +0 -0
  120. clarifai/client/__pycache__/model.cpython-310.pyc +0 -0
  121. clarifai/client/__pycache__/model.cpython-311.pyc +0 -0
  122. clarifai/client/__pycache__/module.cpython-310.pyc +0 -0
  123. clarifai/client/__pycache__/module.cpython-311.pyc +0 -0
  124. clarifai/client/__pycache__/nodepool.cpython-310.pyc +0 -0
  125. clarifai/client/__pycache__/nodepool.cpython-311.pyc +0 -0
  126. clarifai/client/__pycache__/search.cpython-310.pyc +0 -0
  127. clarifai/client/__pycache__/search.cpython-311.pyc +0 -0
  128. clarifai/client/__pycache__/user.cpython-310.pyc +0 -0
  129. clarifai/client/__pycache__/user.cpython-311.pyc +0 -0
  130. clarifai/client/__pycache__/workflow.cpython-310.pyc +0 -0
  131. clarifai/client/__pycache__/workflow.cpython-311.pyc +0 -0
  132. clarifai/client/auth/__pycache__/__init__.cpython-310.pyc +0 -0
  133. clarifai/client/auth/__pycache__/__init__.cpython-311.pyc +0 -0
  134. clarifai/client/auth/__pycache__/helper.cpython-310.pyc +0 -0
  135. clarifai/client/auth/__pycache__/helper.cpython-311.pyc +0 -0
  136. clarifai/client/auth/__pycache__/register.cpython-310.pyc +0 -0
  137. clarifai/client/auth/__pycache__/register.cpython-311.pyc +0 -0
  138. clarifai/client/auth/__pycache__/stub.cpython-310.pyc +0 -0
  139. clarifai/client/auth/__pycache__/stub.cpython-311.pyc +0 -0
  140. clarifai/client/cli/__init__.py +0 -0
  141. clarifai/client/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  142. clarifai/client/cli/__pycache__/base_cli.cpython-310.pyc +0 -0
  143. clarifai/client/cli/__pycache__/model_cli.cpython-310.pyc +0 -0
  144. clarifai/client/cli/base_cli.py +0 -88
  145. clarifai/client/cli/model_cli.py +0 -29
  146. clarifai/constants/__pycache__/base.cpython-310.pyc +0 -0
  147. clarifai/constants/__pycache__/base.cpython-311.pyc +0 -0
  148. clarifai/constants/__pycache__/dataset.cpython-310.pyc +0 -0
  149. clarifai/constants/__pycache__/dataset.cpython-311.pyc +0 -0
  150. clarifai/constants/__pycache__/input.cpython-310.pyc +0 -0
  151. clarifai/constants/__pycache__/input.cpython-311.pyc +0 -0
  152. clarifai/constants/__pycache__/model.cpython-310.pyc +0 -0
  153. clarifai/constants/__pycache__/model.cpython-311.pyc +0 -0
  154. clarifai/constants/__pycache__/rag.cpython-310.pyc +0 -0
  155. clarifai/constants/__pycache__/rag.cpython-311.pyc +0 -0
  156. clarifai/constants/__pycache__/search.cpython-310.pyc +0 -0
  157. clarifai/constants/__pycache__/search.cpython-311.pyc +0 -0
  158. clarifai/constants/__pycache__/workflow.cpython-310.pyc +0 -0
  159. clarifai/constants/__pycache__/workflow.cpython-311.pyc +0 -0
  160. clarifai/datasets/__pycache__/__init__.cpython-310.pyc +0 -0
  161. clarifai/datasets/__pycache__/__init__.cpython-311.pyc +0 -0
  162. clarifai/datasets/__pycache__/__init__.cpython-39.pyc +0 -0
  163. clarifai/datasets/export/__pycache__/__init__.cpython-310.pyc +0 -0
  164. clarifai/datasets/export/__pycache__/__init__.cpython-311.pyc +0 -0
  165. clarifai/datasets/export/__pycache__/__init__.cpython-39.pyc +0 -0
  166. clarifai/datasets/export/__pycache__/inputs_annotations.cpython-310.pyc +0 -0
  167. clarifai/datasets/export/__pycache__/inputs_annotations.cpython-311.pyc +0 -0
  168. clarifai/datasets/upload/__pycache__/__init__.cpython-310.pyc +0 -0
  169. clarifai/datasets/upload/__pycache__/__init__.cpython-311.pyc +0 -0
  170. clarifai/datasets/upload/__pycache__/__init__.cpython-39.pyc +0 -0
  171. clarifai/datasets/upload/__pycache__/base.cpython-310.pyc +0 -0
  172. clarifai/datasets/upload/__pycache__/base.cpython-311.pyc +0 -0
  173. clarifai/datasets/upload/__pycache__/features.cpython-310.pyc +0 -0
  174. clarifai/datasets/upload/__pycache__/features.cpython-311.pyc +0 -0
  175. clarifai/datasets/upload/__pycache__/image.cpython-310.pyc +0 -0
  176. clarifai/datasets/upload/__pycache__/image.cpython-311.pyc +0 -0
  177. clarifai/datasets/upload/__pycache__/multimodal.cpython-310.pyc +0 -0
  178. clarifai/datasets/upload/__pycache__/multimodal.cpython-311.pyc +0 -0
  179. clarifai/datasets/upload/__pycache__/text.cpython-310.pyc +0 -0
  180. clarifai/datasets/upload/__pycache__/text.cpython-311.pyc +0 -0
  181. clarifai/datasets/upload/__pycache__/utils.cpython-310.pyc +0 -0
  182. clarifai/datasets/upload/__pycache__/utils.cpython-311.pyc +0 -0
  183. clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-311.pyc +0 -0
  184. clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-39.pyc +0 -0
  185. clarifai/datasets/upload/loaders/__pycache__/coco_detection.cpython-311.pyc +0 -0
  186. clarifai/datasets/upload/loaders/__pycache__/imagenet_classification.cpython-311.pyc +0 -0
  187. clarifai/models/__pycache__/__init__.cpython-39.pyc +0 -0
  188. clarifai/modules/__pycache__/__init__.cpython-39.pyc +0 -0
  189. clarifai/rag/__pycache__/__init__.cpython-310.pyc +0 -0
  190. clarifai/rag/__pycache__/__init__.cpython-311.pyc +0 -0
  191. clarifai/rag/__pycache__/__init__.cpython-39.pyc +0 -0
  192. clarifai/rag/__pycache__/rag.cpython-310.pyc +0 -0
  193. clarifai/rag/__pycache__/rag.cpython-311.pyc +0 -0
  194. clarifai/rag/__pycache__/rag.cpython-39.pyc +0 -0
  195. clarifai/rag/__pycache__/utils.cpython-310.pyc +0 -0
  196. clarifai/rag/__pycache__/utils.cpython-311.pyc +0 -0
  197. clarifai/runners/__pycache__/__init__.cpython-310.pyc +0 -0
  198. clarifai/runners/__pycache__/__init__.cpython-311.pyc +0 -0
  199. clarifai/runners/__pycache__/__init__.cpython-39.pyc +0 -0
  200. clarifai/runners/dockerfile_template/Dockerfile.cpu.template +0 -31
  201. clarifai/runners/dockerfile_template/Dockerfile.cuda.template +0 -42
  202. clarifai/runners/dockerfile_template/Dockerfile.nim +0 -71
  203. clarifai/runners/models/__pycache__/__init__.cpython-310.pyc +0 -0
  204. clarifai/runners/models/__pycache__/__init__.cpython-311.pyc +0 -0
  205. clarifai/runners/models/__pycache__/__init__.cpython-39.pyc +0 -0
  206. clarifai/runners/models/__pycache__/base_typed_model.cpython-310.pyc +0 -0
  207. clarifai/runners/models/__pycache__/base_typed_model.cpython-311.pyc +0 -0
  208. clarifai/runners/models/__pycache__/base_typed_model.cpython-39.pyc +0 -0
  209. clarifai/runners/models/__pycache__/model_builder.cpython-311.pyc +0 -0
  210. clarifai/runners/models/__pycache__/model_class.cpython-310.pyc +0 -0
  211. clarifai/runners/models/__pycache__/model_class.cpython-311.pyc +0 -0
  212. clarifai/runners/models/__pycache__/model_run_locally.cpython-310-pytest-7.1.2.pyc +0 -0
  213. clarifai/runners/models/__pycache__/model_run_locally.cpython-310.pyc +0 -0
  214. clarifai/runners/models/__pycache__/model_run_locally.cpython-311.pyc +0 -0
  215. clarifai/runners/models/__pycache__/model_runner.cpython-310.pyc +0 -0
  216. clarifai/runners/models/__pycache__/model_runner.cpython-311.pyc +0 -0
  217. clarifai/runners/models/__pycache__/model_upload.cpython-310.pyc +0 -0
  218. clarifai/runners/models/base_typed_model.py +0 -238
  219. clarifai/runners/models/model_class_refract.py +0 -80
  220. clarifai/runners/models/model_upload.py +0 -607
  221. clarifai/runners/models/temp.py +0 -25
  222. clarifai/runners/utils/__pycache__/__init__.cpython-310.pyc +0 -0
  223. clarifai/runners/utils/__pycache__/__init__.cpython-311.pyc +0 -0
  224. clarifai/runners/utils/__pycache__/__init__.cpython-38.pyc +0 -0
  225. clarifai/runners/utils/__pycache__/__init__.cpython-39.pyc +0 -0
  226. clarifai/runners/utils/__pycache__/buffered_stream.cpython-310.pyc +0 -0
  227. clarifai/runners/utils/__pycache__/buffered_stream.cpython-38.pyc +0 -0
  228. clarifai/runners/utils/__pycache__/buffered_stream.cpython-39.pyc +0 -0
  229. clarifai/runners/utils/__pycache__/const.cpython-310.pyc +0 -0
  230. clarifai/runners/utils/__pycache__/const.cpython-311.pyc +0 -0
  231. clarifai/runners/utils/__pycache__/constants.cpython-310.pyc +0 -0
  232. clarifai/runners/utils/__pycache__/constants.cpython-38.pyc +0 -0
  233. clarifai/runners/utils/__pycache__/constants.cpython-39.pyc +0 -0
  234. clarifai/runners/utils/__pycache__/data_handler.cpython-310.pyc +0 -0
  235. clarifai/runners/utils/__pycache__/data_handler.cpython-311.pyc +0 -0
  236. clarifai/runners/utils/__pycache__/data_handler.cpython-38.pyc +0 -0
  237. clarifai/runners/utils/__pycache__/data_handler.cpython-39.pyc +0 -0
  238. clarifai/runners/utils/__pycache__/data_utils.cpython-310.pyc +0 -0
  239. clarifai/runners/utils/__pycache__/data_utils.cpython-311.pyc +0 -0
  240. clarifai/runners/utils/__pycache__/data_utils.cpython-38.pyc +0 -0
  241. clarifai/runners/utils/__pycache__/data_utils.cpython-39.pyc +0 -0
  242. clarifai/runners/utils/__pycache__/grpc_server.cpython-310.pyc +0 -0
  243. clarifai/runners/utils/__pycache__/grpc_server.cpython-38.pyc +0 -0
  244. clarifai/runners/utils/__pycache__/grpc_server.cpython-39.pyc +0 -0
  245. clarifai/runners/utils/__pycache__/health.cpython-310.pyc +0 -0
  246. clarifai/runners/utils/__pycache__/health.cpython-38.pyc +0 -0
  247. clarifai/runners/utils/__pycache__/health.cpython-39.pyc +0 -0
  248. clarifai/runners/utils/__pycache__/loader.cpython-310.pyc +0 -0
  249. clarifai/runners/utils/__pycache__/loader.cpython-311.pyc +0 -0
  250. clarifai/runners/utils/__pycache__/logging.cpython-310.pyc +0 -0
  251. clarifai/runners/utils/__pycache__/logging.cpython-38.pyc +0 -0
  252. clarifai/runners/utils/__pycache__/logging.cpython-39.pyc +0 -0
  253. clarifai/runners/utils/__pycache__/stream_source.cpython-310.pyc +0 -0
  254. clarifai/runners/utils/__pycache__/stream_source.cpython-39.pyc +0 -0
  255. clarifai/runners/utils/__pycache__/url_fetcher.cpython-310.pyc +0 -0
  256. clarifai/runners/utils/__pycache__/url_fetcher.cpython-311.pyc +0 -0
  257. clarifai/runners/utils/__pycache__/url_fetcher.cpython-38.pyc +0 -0
  258. clarifai/runners/utils/__pycache__/url_fetcher.cpython-39.pyc +0 -0
  259. clarifai/runners/utils/data_handler.py +0 -231
  260. clarifai/runners/utils/data_handler_refract.py +0 -213
  261. clarifai/runners/utils/data_types.py +0 -469
  262. clarifai/runners/utils/logger.py +0 -0
  263. clarifai/runners/utils/openai_format.py +0 -87
  264. clarifai/schema/__pycache__/search.cpython-310.pyc +0 -0
  265. clarifai/schema/__pycache__/search.cpython-311.pyc +0 -0
  266. clarifai/urls/__pycache__/helper.cpython-310.pyc +0 -0
  267. clarifai/urls/__pycache__/helper.cpython-311.pyc +0 -0
  268. clarifai/utils/__pycache__/__init__.cpython-310.pyc +0 -0
  269. clarifai/utils/__pycache__/__init__.cpython-311.pyc +0 -0
  270. clarifai/utils/__pycache__/__init__.cpython-39.pyc +0 -0
  271. clarifai/utils/__pycache__/cli.cpython-310.pyc +0 -0
  272. clarifai/utils/__pycache__/cli.cpython-311.pyc +0 -0
  273. clarifai/utils/__pycache__/config.cpython-311.pyc +0 -0
  274. clarifai/utils/__pycache__/constants.cpython-310.pyc +0 -0
  275. clarifai/utils/__pycache__/constants.cpython-311.pyc +0 -0
  276. clarifai/utils/__pycache__/logging.cpython-310.pyc +0 -0
  277. clarifai/utils/__pycache__/logging.cpython-311.pyc +0 -0
  278. clarifai/utils/__pycache__/misc.cpython-310.pyc +0 -0
  279. clarifai/utils/__pycache__/misc.cpython-311.pyc +0 -0
  280. clarifai/utils/__pycache__/model_train.cpython-310.pyc +0 -0
  281. clarifai/utils/__pycache__/model_train.cpython-311.pyc +0 -0
  282. clarifai/utils/__pycache__/protobuf.cpython-311.pyc +0 -0
  283. clarifai/utils/evaluation/__pycache__/__init__.cpython-311.pyc +0 -0
  284. clarifai/utils/evaluation/__pycache__/__init__.cpython-39.pyc +0 -0
  285. clarifai/utils/evaluation/__pycache__/helpers.cpython-311.pyc +0 -0
  286. clarifai/utils/evaluation/__pycache__/main.cpython-311.pyc +0 -0
  287. clarifai/utils/evaluation/__pycache__/main.cpython-39.pyc +0 -0
  288. clarifai/workflows/__pycache__/__init__.cpython-310.pyc +0 -0
  289. clarifai/workflows/__pycache__/__init__.cpython-311.pyc +0 -0
  290. clarifai/workflows/__pycache__/__init__.cpython-39.pyc +0 -0
  291. clarifai/workflows/__pycache__/export.cpython-310.pyc +0 -0
  292. clarifai/workflows/__pycache__/export.cpython-311.pyc +0 -0
  293. clarifai/workflows/__pycache__/utils.cpython-310.pyc +0 -0
  294. clarifai/workflows/__pycache__/utils.cpython-311.pyc +0 -0
  295. clarifai/workflows/__pycache__/validate.cpython-310.pyc +0 -0
  296. clarifai/workflows/__pycache__/validate.cpython-311.pyc +0 -0
  297. clarifai-11.3.0rc2.dist-info/RECORD +0 -322
  298. {clarifai-11.3.0rc2.dist-info → clarifai-11.4.0.dist-info}/entry_points.txt +0 -0
  299. {clarifai-11.3.0rc2.dist-info → clarifai-11.4.0.dist-info/licenses}/LICENSE +0 -0
  300. {clarifai-11.3.0rc2.dist-info → clarifai-11.4.0.dist-info}/top_level.txt +0 -0
@@ -19,125 +19,148 @@ WRAPPER_TYPES = {
19
19
 
20
20
 
21
21
  def dict_to_protobuf(pb_obj: Message, data: dict) -> None:
22
- """Recursively convert a nested dictionary to a Protobuf message object.
22
+ """Recursively convert a nested dictionary to a Protobuf message object.
23
23
 
24
24
  Args:
25
25
  pb_obj: The target Protobuf message instance to populate.
26
26
  data: Source dictionary containing the data to convert.
27
27
  """
28
- for field, value in data.items():
29
- if field not in pb_obj.DESCRIPTOR.fields_by_name:
30
- logger.warning(f"Ignoring unknown field '{field}' in message '{pb_obj.DESCRIPTOR.name}'")
31
- continue
32
28
 
33
- field_descriptor = pb_obj.DESCRIPTOR.fields_by_name[field]
34
-
35
- try:
36
- # Handle repeated fields (lists)
37
- if field_descriptor.label == FieldDescriptor.LABEL_REPEATED:
38
- _handle_repeated_field(pb_obj, field_descriptor, field, value)
39
-
40
- # Handle message fields (nested messages)
41
- elif field_descriptor.type == FieldDescriptor.TYPE_MESSAGE:
42
- _handle_message_field(pb_obj, field_descriptor, field, value)
43
-
44
- # Handle scalar fields
45
- else:
46
- if value:
47
- setattr(pb_obj, field, value)
48
-
49
- except Exception as e:
50
- logger.error(f"Error processing field '{field}': {str(e)}")
51
- raise
52
-
53
-
54
- def _handle_repeated_field(pb_obj: Message, field_descriptor: FieldDescriptor, field: str,
55
- value: list) -> None:
56
- """Process repeated fields (both scalar and message types)."""
57
- if not isinstance(value, list):
58
- logger.warning(f"Expected list for repeated field '{field}', got {type(value).__name__}")
59
- return
60
-
61
- repeated_field = getattr(pb_obj, field)
62
-
63
- # Handle repeated message fields
64
- if field_descriptor.type == FieldDescriptor.TYPE_MESSAGE:
65
- for item in value:
66
- if isinstance(item, dict):
67
- item_msg = repeated_field.add()
68
- dict_to_protobuf(item_msg, item)
69
- elif isinstance(item, Message):
70
- repeated_field.add().CopyFrom(item)
71
- else:
72
- logger.warning(f"Invalid type {type(item).__name__} in repeated message field '{field}'")
73
- else:
74
- # Handle repeated scalar fields
75
- try:
76
- repeated_field.extend(value)
77
- except TypeError as e:
78
- logger.error(f"Type mismatch in repeated scalar field '{field}': {str(e)}")
79
- raise
80
-
81
-
82
- def _handle_message_field(pb_obj: Message, field_descriptor: FieldDescriptor, field: str,
83
- value: object) -> None:
84
- """Process message-type fields including special types."""
85
- msg_class = db.GetSymbol(field_descriptor.message_type.full_name)
86
- target_field = getattr(pb_obj, field)
87
-
88
- # Handle special message types
89
- if msg_class is Timestamp:
90
- _set_timestamp_value(target_field, value)
91
- elif msg_class is struct_pb2.Struct:
92
- _set_struct_value(target_field, value)
93
- elif msg_class in WRAPPER_TYPES:
94
- _set_wrapper_value(target_field, msg_class, value)
95
- else:
29
+ for field, value in data.items():
30
+ if field not in pb_obj.DESCRIPTOR.fields_by_name:
31
+ logger.warning(
32
+ f"Ignoring unknown field '{field}' in message '{pb_obj.DESCRIPTOR.name}'"
33
+ )
34
+ continue
35
+
36
+ field_descriptor = pb_obj.DESCRIPTOR.fields_by_name[field]
37
+
38
+ try:
39
+ # Handle repeated fields (lists)
40
+ if field_descriptor.label == FieldDescriptor.LABEL_REPEATED:
41
+ _handle_repeated_field(pb_obj, field_descriptor, field, value)
42
+
43
+ # Handle message fields (nested messages)
44
+ elif field_descriptor.type == FieldDescriptor.TYPE_MESSAGE:
45
+ _handle_message_field(pb_obj, field_descriptor, field, value)
46
+
47
+ # Handle enums as string or int.
48
+ # Alternative is to use MessageToDict with use_integers_for_enums=True everywhere
49
+ # we end up calling dict_to_protobuf afterwards.
50
+ elif field_descriptor.type == FieldDescriptor.TYPE_ENUM:
51
+ if isinstance(value, str):
52
+ enum_value = field_descriptor.enum_type.values_by_name.get(value)
53
+ if enum_value is not None:
54
+ setattr(pb_obj, field, enum_value.number)
55
+ elif isinstance(value, int):
56
+ enum_value = field_descriptor.enum_type.values_by_number.get(value)
57
+ if enum_value is not None:
58
+ setattr(pb_obj, field, enum_value.number)
59
+
60
+ # Handle scalar fields
61
+ elif value:
62
+ setattr(pb_obj, field, value)
63
+
64
+ except Exception as e:
65
+ logger.error(f"Error processing field '{field}': {str(e)}")
66
+ raise
67
+
68
+
69
+ def _handle_repeated_field(
70
+ pb_obj: Message, field_descriptor: FieldDescriptor, field: str, value: list
71
+ ) -> None:
72
+ """Process repeated fields (both scalar and message types)."""
73
+ if not isinstance(value, list):
74
+ logger.warning(f"Expected list for repeated field '{field}', got {type(value).__name__}")
75
+ return
76
+
77
+ repeated_field = getattr(pb_obj, field)
78
+
79
+ # Handle repeated message fields
80
+ if field_descriptor.type == FieldDescriptor.TYPE_MESSAGE:
81
+ for item in value:
82
+ if isinstance(item, dict):
83
+ item_msg = repeated_field.add()
84
+ dict_to_protobuf(item_msg, item)
85
+ elif isinstance(item, Message):
86
+ repeated_field.add().CopyFrom(item)
87
+ else:
88
+ logger.warning(
89
+ f"Invalid type {type(item).__name__} in repeated message field '{field}'"
90
+ )
91
+ else:
92
+ # Handle repeated scalar fields
93
+ try:
94
+ repeated_field.extend(value)
95
+ except TypeError as e:
96
+ logger.error(f"Type mismatch in repeated scalar field '{field}': {str(e)}")
97
+ raise
98
+
99
+
100
+ def _handle_message_field(
101
+ pb_obj: Message, field_descriptor: FieldDescriptor, field: str, value: object
102
+ ) -> None:
103
+ """Process message-type fields including special types."""
104
+ msg_class = db.GetSymbol(field_descriptor.message_type.full_name)
105
+ target_field = getattr(pb_obj, field)
106
+
107
+ # Handle special message types
108
+ if msg_class is Timestamp:
109
+ _set_timestamp_value(target_field, value)
110
+ elif msg_class is struct_pb2.Struct:
111
+ _set_struct_value(target_field, value)
112
+ elif msg_class in WRAPPER_TYPES:
113
+ _set_wrapper_value(target_field, msg_class, value)
96
114
  # Handle nested messages
97
- if isinstance(value, dict):
98
- nested_pb = msg_class()
99
- dict_to_protobuf(nested_pb, value)
100
- target_field.CopyFrom(nested_pb)
115
+ elif isinstance(value, dict):
116
+ nested_pb = msg_class()
117
+ dict_to_protobuf(nested_pb, value)
118
+ target_field.CopyFrom(nested_pb)
101
119
  elif isinstance(value, Message):
102
- target_field.CopyFrom(value)
120
+ target_field.CopyFrom(value)
103
121
  else:
104
- logger.warning(f"Invalid type {type(value).__name__} for message field '{field}'")
122
+ logger.warning(f"Invalid type {type(value).__name__} for message field '{field}'")
105
123
 
106
124
 
107
125
  def _set_timestamp_value(target_field: Message, value: object) -> None:
108
- """Set timestamp value from dict or numeric timestamp."""
109
- ts = Timestamp()
110
- if isinstance(value, dict):
111
- ts.seconds = value.get('seconds', 0)
112
- ts.nanos = value.get('nanos', 0)
113
- elif isinstance(value, (int, float)):
114
- ts.seconds = int(value)
115
- ts.nanos = int((value - ts.seconds) * 1e9)
116
- else:
117
- logger.warning(f"Unsupported timestamp format: {type(value).__name__}")
118
- target_field.CopyFrom(ts)
126
+ """Set timestamp value from dict or numeric timestamp."""
127
+ ts = Timestamp()
128
+ if isinstance(value, dict):
129
+ ts.seconds = value.get('seconds', 0)
130
+ ts.nanos = value.get('nanos', 0)
131
+ elif isinstance(value, (int, float)):
132
+ ts.seconds = int(value)
133
+ ts.nanos = int((value - ts.seconds) * 1e9)
134
+ elif isinstance(value, Timestamp):
135
+ ts = value
136
+ else:
137
+ logger.warning(f"Unsupported timestamp format: {type(value).__name__}")
138
+ target_field.CopyFrom(ts)
119
139
 
120
140
 
121
141
  def _set_struct_value(target_field: Message, value: object) -> None:
122
- """Convert dictionary to Protobuf Struct."""
123
- if not isinstance(value, dict):
124
- logger.warning(f"Expected dict for Struct field, got {type(value).__name__}")
125
- return
142
+ """Convert dictionary to Protobuf Struct."""
143
+ if isinstance(value, struct_pb2.Struct):
144
+ struct = value
145
+ else:
146
+ if not isinstance(value, dict):
147
+ logger.warning(f"Expected dict for Struct field, got {type(value).__name__}")
148
+ return
126
149
 
127
- struct = struct_pb2.Struct()
128
- try:
129
- struct.update(value)
130
- except ValueError as e:
131
- logger.error(f"Invalid value in Struct: {str(e)}")
132
- raise
133
- target_field.CopyFrom(struct)
150
+ struct = struct_pb2.Struct()
151
+ try:
152
+ struct.update(value)
153
+ except ValueError as e:
154
+ logger.error(f"Invalid value in Struct: {str(e)}")
155
+ raise
156
+ target_field.CopyFrom(struct)
134
157
 
135
158
 
136
159
  def _set_wrapper_value(target_field: Message, wrapper_type: type, value: object) -> None:
137
- """Set value for wrapper types (e.g., Int32Value)."""
138
- try:
139
- wrapper = wrapper_type(value=value)
140
- except TypeError as e:
141
- logger.error(f"Invalid value for {wrapper_type.__name__}: {str(e)}")
142
- raise
143
- target_field.CopyFrom(wrapper)
160
+ """Set value for wrapper types (e.g., Int32Value)."""
161
+ try:
162
+ wrapper = wrapper_type(value=value)
163
+ except TypeError as e:
164
+ logger.error(f"Invalid value for {wrapper_type.__name__}: {str(e)}")
165
+ raise
166
+ target_field.CopyFrom(wrapper)
clarifai/versions.py CHANGED
@@ -1,7 +1,9 @@
1
1
  import os
2
+
2
3
  from clarifai import __version__
3
4
 
4
5
  CLIENT_VERSION = __version__
5
6
  OS_VER = os.sys.platform
6
7
  PYTHON_VERSION = '.'.join(
7
- map(str, [os.sys.version_info.major, os.sys.version_info.minor, os.sys.version_info.micro]))
8
+ map(str, [os.sys.version_info.major, os.sys.version_info.minor, os.sys.version_info.micro])
9
+ )
@@ -7,62 +7,60 @@ VALID_YAML_KEYS = ["workflow", "id", "nodes", "node_inputs", "node_id", "model"]
7
7
 
8
8
 
9
9
  def clean_up_unused_keys(wf: dict):
10
- """Removes unused keys from dict before exporting to yaml. Supports nested dicts."""
11
- new_wf = dict()
12
- for key, val in wf.items():
13
- if key not in VALID_YAML_KEYS:
14
- continue
15
- if key == "model":
16
- new_wf["model"] = {
17
- "model_id": wf["model"]["id"],
18
- "model_version_id": wf["model"]["model_version"]["id"]
19
- }
20
- # If the model is not from clarifai main, add the app_id and user_id to the model dict.
21
- if wf["model"]["user_id"] != "clarifai" and wf["model"]["app_id"] != "main":
22
- new_wf["model"].update({
23
- "app_id": wf["model"]["app_id"],
24
- "user_id": wf["model"]["user_id"]
25
- })
26
- elif isinstance(val, dict):
27
- new_wf[key] = clean_up_unused_keys(val)
28
- elif isinstance(val, list):
29
- new_list = []
30
- for i in val:
31
- new_list.append(clean_up_unused_keys(i))
32
- new_wf[key] = new_list
33
- else:
34
- new_wf[key] = val
35
- return new_wf
10
+ """Removes unused keys from dict before exporting to yaml. Supports nested dicts."""
11
+ new_wf = dict()
12
+ for key, val in wf.items():
13
+ if key not in VALID_YAML_KEYS:
14
+ continue
15
+ if key == "model":
16
+ new_wf["model"] = {
17
+ "model_id": wf["model"]["id"],
18
+ "model_version_id": wf["model"]["model_version"]["id"],
19
+ }
20
+ # If the model is not from clarifai main, add the app_id and user_id to the model dict.
21
+ if wf["model"]["user_id"] != "clarifai" and wf["model"]["app_id"] != "main":
22
+ new_wf["model"].update(
23
+ {"app_id": wf["model"]["app_id"], "user_id": wf["model"]["user_id"]}
24
+ )
25
+ elif isinstance(val, dict):
26
+ new_wf[key] = clean_up_unused_keys(val)
27
+ elif isinstance(val, list):
28
+ new_list = []
29
+ for i in val:
30
+ new_list.append(clean_up_unused_keys(i))
31
+ new_wf[key] = new_list
32
+ else:
33
+ new_wf[key] = val
34
+ return new_wf
36
35
 
37
36
 
38
37
  class Exporter:
38
+ def __init__(self, workflow):
39
+ self.wf = workflow
39
40
 
40
- def __init__(self, workflow):
41
- self.wf = workflow
41
+ def __enter__(self):
42
+ return self
42
43
 
43
- def __enter__(self):
44
- return self
44
+ def parse(self) -> Dict[str, Any]:
45
+ """Reads a resources_pb2.Workflow object (e.g. from a GetWorkflow response)
45
46
 
46
- def parse(self) -> Dict[str, Any]:
47
- """Reads a resources_pb2.Workflow object (e.g. from a GetWorkflow response)
47
+ Returns:
48
+ dict: A dict representation of the workflow.
49
+ """
50
+ if isinstance(self.wf, list):
51
+ self.wf = self.wf[0]
52
+ wf = {"workflow": MessageToDict(self.wf, preserving_proto_field_name=True)}
53
+ clean_wf = clean_up_unused_keys(wf)
54
+ self.wf_dict = clean_wf
55
+ return clean_wf
48
56
 
49
- Returns:
50
- dict: A dict representation of the workflow.
51
- """
52
- if isinstance(self.wf, list):
53
- self.wf = self.wf[0]
54
- wf = {"workflow": MessageToDict(self.wf, preserving_proto_field_name=True)}
55
- clean_wf = clean_up_unused_keys(wf)
56
- self.wf_dict = clean_wf
57
- return clean_wf
57
+ def export(self, out_path):
58
+ with open(out_path, 'w') as out_file:
59
+ yaml.dump(self.wf_dict["workflow"], out_file, default_flow_style=False)
58
60
 
59
- def export(self, out_path):
60
- with open(out_path, 'w') as out_file:
61
- yaml.dump(self.wf_dict["workflow"], out_file, default_flow_style=False)
61
+ def __exit__(self, *args):
62
+ self.close()
62
63
 
63
- def __exit__(self, *args):
64
- self.close()
65
-
66
- def close(self):
67
- del self.wf
68
- del self.wf_dict
64
+ def close(self):
65
+ del self.wf
66
+ del self.wf_dict
@@ -6,54 +6,57 @@ from google.protobuf.json_format import MessageToDict
6
6
 
7
7
 
8
8
  def get_yaml_output_info_proto(yaml_model_output_info: Dict) -> Optional[resources_pb2.OutputInfo]:
9
- """Converts a yaml model output info to an api model output info."""
10
- if not yaml_model_output_info:
11
- return None
9
+ """Converts a yaml model output info to an api model output info."""
10
+ if not yaml_model_output_info:
11
+ return None
12
12
 
13
- return resources_pb2.OutputInfo(
14
- params=convert_yaml_params_to_api_params(yaml_model_output_info.get('params')))
13
+ return resources_pb2.OutputInfo(
14
+ params=convert_yaml_params_to_api_params(yaml_model_output_info.get('params'))
15
+ )
15
16
 
16
17
 
17
18
  def convert_yaml_params_to_api_params(yaml_params: Dict) -> Optional[struct_pb2.Struct]:
18
- """Converts a yaml model output info params to an api model output info params."""
19
- if not yaml_params:
20
- return None
19
+ """Converts a yaml model output info params to an api model output info params."""
20
+ if not yaml_params:
21
+ return None
21
22
 
22
- s = struct_pb2.Struct()
23
- s.update(yaml_params)
23
+ s = struct_pb2.Struct()
24
+ s.update(yaml_params)
24
25
 
25
- return s
26
+ return s
26
27
 
27
28
 
28
29
  def is_same_yaml_model(api_model: resources_pb2.Model, yaml_model: Dict) -> bool:
29
- """Compares a model from the API with a model from a yaml file."""
30
- api_model = MessageToDict(api_model, preserving_proto_field_name=True)
30
+ """Compares a model from the API with a model from a yaml file."""
31
+ api_model = MessageToDict(api_model, preserving_proto_field_name=True)
31
32
 
32
- yaml_model_from_api = dict()
33
- for k, _ in yaml_model.items():
34
- if k == "output_info" and api_model["model_version"].get("output_info", "") != "":
35
- yaml_model_from_api[k] = dict(params=api_model["model_version"]["output_info"].get("params"))
36
- else:
37
- yaml_model_from_api[k] = api_model.get(k)
38
- yaml_model_from_api.update({"model_id": api_model.get("id")})
33
+ yaml_model_from_api = dict()
34
+ for k, _ in yaml_model.items():
35
+ if k == "output_info" and api_model["model_version"].get("output_info", "") != "":
36
+ yaml_model_from_api[k] = dict(
37
+ params=api_model["model_version"]["output_info"].get("params")
38
+ )
39
+ else:
40
+ yaml_model_from_api[k] = api_model.get(k)
41
+ yaml_model_from_api.update({"model_id": api_model.get("id")})
39
42
 
40
- ignore_keys = {}
43
+ ignore_keys = {}
41
44
 
42
- return is_dict_in_dict(yaml_model, yaml_model_from_api, ignore_keys)
45
+ return is_dict_in_dict(yaml_model, yaml_model_from_api, ignore_keys)
43
46
 
44
47
 
45
48
  def is_dict_in_dict(d1: Dict, d2: Dict, ignore_keys: Set = None) -> bool:
46
- """Compares two dicts recursively."""
47
- for k, v in d1.items():
48
- if ignore_keys and k in ignore_keys:
49
- continue
50
- if k not in d2:
51
- return False
52
- if isinstance(v, dict):
53
- if not isinstance(d2[k], dict):
54
- return False
55
- return is_dict_in_dict(d1[k], d2[k], None)
56
- elif v != d2[k]:
57
- return False
58
-
59
- return True
49
+ """Compares two dicts recursively."""
50
+ for k, v in d1.items():
51
+ if ignore_keys and k in ignore_keys:
52
+ continue
53
+ if k not in d2:
54
+ return False
55
+ if isinstance(v, dict):
56
+ if not isinstance(d2[k], dict):
57
+ return False
58
+ return is_dict_in_dict(d1[k], d2[k], None)
59
+ elif v != d2[k]:
60
+ return False
61
+
62
+ return True
@@ -8,60 +8,72 @@ _hex_id_validator = And(str, Use(str.lower), Regex(r'^[0-9a-f]{32}'))
8
8
 
9
9
 
10
10
  def _model_does_not_have_model_version_id_and_other_fields(m):
11
- """ Validate that model does not have model_version_id and other model fields."""
12
- if ('model_version_id' in m) and _model_has_other_fields(m):
13
- raise SchemaError(f"model should not set model_version_id and other model fields: {m};"
14
- f" please remove model_version_id or other model fields.")
15
- return True
11
+ """Validate that model does not have model_version_id and other model fields."""
12
+ if ('model_version_id' in m) and _model_has_other_fields(m):
13
+ raise SchemaError(
14
+ f"model should not set model_version_id and other model fields: {m};"
15
+ f" please remove model_version_id or other model fields."
16
+ )
17
+ return True
16
18
 
17
19
 
18
20
  def _model_has_other_fields(m):
19
- return any(k not in ['model_id', 'model_version_id', 'user_id', 'app_id'] for k in m.keys())
21
+ return any(k not in ['model_id', 'model_version_id', 'user_id', 'app_id'] for k in m.keys())
20
22
 
21
23
 
22
24
  def _workflow_nodes_have_valid_dependencies(nodes):
23
- """Validate that all inputs to a node are declared before it."""
24
- node_ids = set()
25
- for node in nodes:
26
- for node_input in node.get("node_inputs", []):
27
- if node_input["node_id"] not in node_ids:
28
- raise SchemaError(f"missing input '{node_input['node_id']}' for node '{node['id']}'")
29
- node_ids.add(node["id"])
25
+ """Validate that all inputs to a node are declared before it."""
26
+ node_ids = set()
27
+ for node in nodes:
28
+ for node_input in node.get("node_inputs", []):
29
+ if node_input["node_id"] not in node_ids:
30
+ raise SchemaError(
31
+ f"missing input '{node_input['node_id']}' for node '{node['id']}'"
32
+ )
33
+ node_ids.add(node["id"])
30
34
 
31
- return True
35
+ return True
32
36
 
33
37
 
34
- _data_schema = Schema({
35
- "workflow": {
36
- "id":
37
- _id_validator,
38
- "nodes":
39
- And(
38
+ _data_schema = Schema(
39
+ {
40
+ "workflow": {
41
+ "id": _id_validator,
42
+ "nodes": And(
40
43
  len,
41
- [{
42
- "id":
43
- And(str, len), # Node IDs are not validated as IDs by the API.
44
- "model":
45
- And({
46
- "model_id": _id_validator,
47
- Optional("app_id"): _id_validator,
48
- Optional("user_id"): _id_validator,
49
- Optional("model_version_id"): _hex_id_validator,
50
- Optional("model_type_id"): _id_validator,
51
- Optional("description"): str,
52
- Optional("output_info"): {
53
- Optional("params"): dict,
44
+ [
45
+ {
46
+ "id": And(str, len), # Node IDs are not validated as IDs by the API.
47
+ "model": And(
48
+ {
49
+ "model_id": _id_validator,
50
+ Optional("app_id"): _id_validator,
51
+ Optional("user_id"): _id_validator,
52
+ Optional("model_version_id"): _hex_id_validator,
53
+ Optional("model_type_id"): _id_validator,
54
+ Optional("description"): str,
55
+ Optional("output_info"): {
56
+ Optional("params"): dict,
57
+ },
54
58
  },
55
- }, _model_does_not_have_model_version_id_and_other_fields),
56
- Optional("node_inputs"):
57
- And(len, [{
58
- "node_id": And(str, len),
59
- }]),
60
- }],
61
- _workflow_nodes_have_valid_dependencies),
62
- },
63
- })
59
+ _model_does_not_have_model_version_id_and_other_fields,
60
+ ),
61
+ Optional("node_inputs"): And(
62
+ len,
63
+ [
64
+ {
65
+ "node_id": And(str, len),
66
+ }
67
+ ],
68
+ ),
69
+ }
70
+ ],
71
+ _workflow_nodes_have_valid_dependencies,
72
+ ),
73
+ },
74
+ }
75
+ )
64
76
 
65
77
 
66
78
  def validate(data):
67
- return _data_schema.validate(data)
79
+ return _data_schema.validate(data)
@@ -1,7 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: clarifai
3
- Version: 11.3.0rc2
4
- Summary: Clarifai Python SDK
3
+ Version: 11.4.0
5
4
  Home-page: https://github.com/Clarifai/clarifai-python
6
5
  Author: Clarifai
7
6
  Author-email: support@clarifai.com
@@ -20,8 +19,8 @@ Classifier: Operating System :: OS Independent
20
19
  Requires-Python: >=3.8
21
20
  Description-Content-Type: text/markdown
22
21
  License-File: LICENSE
23
- Requires-Dist: clarifai-grpc>=11.3.3
24
- Requires-Dist: clarifai-protocol>=0.0.22
22
+ Requires-Dist: clarifai-grpc>=11.3.4
23
+ Requires-Dist: clarifai-protocol>=0.0.23
25
24
  Requires-Dist: numpy>=1.22.0
26
25
  Requires-Dist: tqdm>=4.65.0
27
26
  Requires-Dist: rich>=13.4.2
@@ -34,7 +33,18 @@ Requires-Dist: click>=8.1.7
34
33
  Requires-Dist: requests>=2.32.3
35
34
  Requires-Dist: aiohttp>=3.10.0
36
35
  Provides-Extra: all
37
- Requires-Dist: pycocotools==2.0.6; extra == "all"
36
+ Requires-Dist: pycocotools>=2.0.7; extra == "all"
37
+ Dynamic: author
38
+ Dynamic: author-email
39
+ Dynamic: classifier
40
+ Dynamic: description
41
+ Dynamic: description-content-type
42
+ Dynamic: home-page
43
+ Dynamic: license
44
+ Dynamic: license-file
45
+ Dynamic: provides-extra
46
+ Dynamic: requires-dist
47
+ Dynamic: requires-python
38
48
 
39
49
  <h1 align="center">
40
50
  <a href="https://www.clarifai.com/"><img alt="Clarifai" title="Clarifai" src="https://github.com/user-attachments/assets/623b883b-7fe5-4b95-bbfa-8691f5779af4"></a>