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
clarifai/client/app.py CHANGED
@@ -26,915 +26,977 @@ from clarifai.workflows.validate import validate
26
26
 
27
27
 
28
28
  class App(Lister, BaseClient):
29
- """App is a class that provides access to Clarifai API endpoints related to App information."""
30
-
31
- def __init__(self,
32
- url: str = None,
33
- app_id: str = None,
34
- user_id: str = None,
35
- base_url: str = "https://api.clarifai.com",
36
- pat: str = None,
37
- token: str = None,
38
- root_certificates_path: str = None,
39
- **kwargs):
40
- """Initializes an App object.
41
-
42
- Args:
43
- url (str): The URL to initialize the app object.
44
- app_id (str): The App ID for the App to interact with.
45
- base_url (str): Base API url. Default "https://api.clarifai.com"
46
- pat (str): A personal access token for authentication. Can be set as env var CLARIFAI_PAT
47
- token (str): A session token for authentication. Accepts either a session token or a pat. Can be set as env var CLARIFAI_SESSION_TOKEN
48
- root_certificates_path (str): Path to the SSL root certificates file, used to establish secure gRPC connections.
49
- **kwargs: Additional keyword arguments to be passed to the App.
50
- - name (str): The name of the app.
51
- - description (str): The description of the app.
52
- """
53
- if url and app_id:
54
- raise UserError("You can only specify one of url or app_id.")
55
- if url:
56
- user_id, app_id = ClarifaiUrlHelper.split_clarifai_app_url(url)
57
- kwargs = {'user_id': user_id}
58
- if user_id:
59
- kwargs = {'user_id': user_id}
60
-
61
- self.kwargs = {**kwargs, 'id': app_id}
62
- self.app_info = resources_pb2.App(**self.kwargs)
63
- self.logger = logger
64
- BaseClient.__init__(
29
+ """App is a class that provides access to Clarifai API endpoints related to App information."""
30
+
31
+ def __init__(
32
+ self,
33
+ url: str = None,
34
+ app_id: str = None,
35
+ user_id: str = None,
36
+ base_url: str = "https://api.clarifai.com",
37
+ pat: str = None,
38
+ token: str = None,
39
+ root_certificates_path: str = None,
40
+ **kwargs,
41
+ ):
42
+ """Initializes an App object.
43
+
44
+ Args:
45
+ url (str): The URL to initialize the app object.
46
+ app_id (str): The App ID for the App to interact with.
47
+ base_url (str): Base API url. Default "https://api.clarifai.com"
48
+ pat (str): A personal access token for authentication. Can be set as env var CLARIFAI_PAT
49
+ token (str): A session token for authentication. Accepts either a session token or a pat. Can be set as env var CLARIFAI_SESSION_TOKEN
50
+ root_certificates_path (str): Path to the SSL root certificates file, used to establish secure gRPC connections.
51
+ **kwargs: Additional keyword arguments to be passed to the App.
52
+ - name (str): The name of the app.
53
+ - description (str): The description of the app.
54
+ """
55
+ if url and app_id:
56
+ raise UserError("You can only specify one of url or app_id.")
57
+ if url:
58
+ user_id, app_id = ClarifaiUrlHelper.split_clarifai_app_url(url)
59
+ kwargs = {'user_id': user_id}
60
+ if user_id:
61
+ kwargs = {'user_id': user_id}
62
+
63
+ self.kwargs = {**kwargs, 'id': app_id}
64
+ self.app_info = resources_pb2.App(**self.kwargs)
65
+ self.logger = logger
66
+ BaseClient.__init__(
67
+ self,
68
+ user_id=self.user_id,
69
+ app_id=self.id,
70
+ base=base_url,
71
+ pat=pat,
72
+ token=token,
73
+ root_certificates_path=root_certificates_path,
74
+ )
75
+ Lister.__init__(self)
76
+
77
+ def list_datasets(
78
+ self, page_no: int = None, per_page: int = None
79
+ ) -> Generator[Dataset, None, None]:
80
+ """Lists all the datasets for the app.
81
+
82
+ Args:
83
+ page_no (int): The page number to list.
84
+ per_page (int): The number of items per page.
85
+
86
+ Yields:
87
+ Dataset: Dataset objects for the datasets in the app.
88
+
89
+ Example:
90
+ >>> from clarifai.client.app import App
91
+ >>> app = App(app_id="app_id", user_id="user_id")
92
+ >>> all_datasets = list(app.list_datasets())
93
+
94
+ Note:
95
+ Defaults to 16 per page if page_no is specified and per_page is not specified.
96
+ If both page_no and per_page are None, then lists all the resources.
97
+ """
98
+ request_data = dict(
99
+ user_app_id=self.user_app_id,
100
+ )
101
+ all_datasets_info = self.list_pages_generator(
102
+ self.STUB.ListDatasets,
103
+ service_pb2.ListDatasetsRequest,
104
+ request_data,
105
+ per_page=per_page,
106
+ page_no=page_no,
107
+ )
108
+ for dataset_info in all_datasets_info:
109
+ if 'version' in dataset_info:
110
+ dataset_info['version'].pop('metrics', None)
111
+ dataset_info['version'].pop('export_info', None)
112
+ yield Dataset.from_auth_helper(auth=self.auth_helper, **dataset_info)
113
+
114
+ def list_models(
115
+ self,
116
+ filter_by: Dict[str, Any] = {},
117
+ only_in_app: bool = True,
118
+ page_no: int = None,
119
+ per_page: int = None,
120
+ ) -> Generator[Model, None, None]:
121
+ """Lists all the available models for the user.
122
+
123
+ Args:
124
+ filter_by (dict): A dictionary of filters to apply to the list of models.
125
+ only_in_app (bool): If True, only return models that are in the app.
126
+ page_no (int): The page number to list.
127
+ per_page (int): The number of items per page.
128
+
129
+ Yields:
130
+ Model: Model objects for the models in the app.
131
+
132
+ Example:
133
+ >>> from clarifai.client.user import User
134
+ >>> app = User(user_id="user_id").app(app_id="app_id")
135
+ >>> all_models = list(app.list_models())
136
+
137
+ Note:
138
+ Defaults to 16 per page if page_no is specified and per_page is not specified.
139
+ If both page_no and per_page are None, then lists all the resources.
140
+ """
141
+ request_data = dict(user_app_id=self.user_app_id, **filter_by)
142
+ all_models_info = self.list_pages_generator(
143
+ self.STUB.ListModels,
144
+ service_pb2.ListModelsRequest,
145
+ request_data,
146
+ per_page=per_page,
147
+ page_no=page_no,
148
+ )
149
+
150
+ for model_info in all_models_info:
151
+ if 'model_version' not in list(model_info.keys()):
152
+ continue
153
+ if only_in_app:
154
+ if model_info['app_id'] != self.id:
155
+ continue
156
+ yield Model.from_auth_helper(auth=self.auth_helper, **model_info)
157
+
158
+ def list_workflows(
159
+ self,
160
+ filter_by: Dict[str, Any] = {},
161
+ only_in_app: bool = True,
162
+ page_no: int = None,
163
+ per_page: int = None,
164
+ ) -> Generator[Workflow, None, None]:
165
+ """Lists all the available workflows for the user.
166
+
167
+ Args:
168
+ filter_by (dict): A dictionary of filters to apply to the list of workflows.
169
+ only_in_app (bool): If True, only return workflows that are in the app.
170
+ page_no (int): The page number to list.
171
+ per_page (int): The number of items per page.
172
+
173
+ Yields:
174
+ Workflow: Workflow objects for the workflows in the app.
175
+
176
+ Example:
177
+ >>> from clarifai.client.app import App
178
+ >>> app = App(app_id="app_id", user_id="user_id")
179
+ >>> all_workflows = list(app.list_workflows())
180
+
181
+ Note:
182
+ Defaults to 16 per page if page_no is specified and per_page is not specified.
183
+ If both page_no and per_page are None, then lists all the resources.
184
+ """
185
+ request_data = dict(user_app_id=self.user_app_id, **filter_by)
186
+ all_workflows_info = self.list_pages_generator(
187
+ self.STUB.ListWorkflows,
188
+ service_pb2.ListWorkflowsRequest,
189
+ request_data,
190
+ per_page=per_page,
191
+ page_no=page_no,
192
+ )
193
+
194
+ for workflow_info in all_workflows_info:
195
+ if only_in_app:
196
+ if workflow_info['app_id'] != self.id:
197
+ continue
198
+ yield Workflow.from_auth_helper(auth=self.auth_helper, **workflow_info)
199
+
200
+ def list_modules(
201
+ self,
202
+ filter_by: Dict[str, Any] = {},
203
+ only_in_app: bool = True,
204
+ page_no: int = None,
205
+ per_page: int = None,
206
+ ) -> Generator[Module, None, None]:
207
+ """Lists all the available modules for the user.
208
+
209
+ Args:
210
+ filter_by (dict): A dictionary of filters to apply to the list of modules.
211
+ only_in_app (bool): If True, only return modules that are in the app.
212
+ page_no (int): The page number to list.
213
+ per_page (int): The number of items per page.
214
+
215
+ Yields:
216
+ Module: Module objects for the modules in the app.
217
+
218
+ Example:
219
+ >>> from clarifai.client.app import App
220
+ >>> app = App(app_id="app_id", user_id="user_id")
221
+ >>> all_modules = list(app.list_modules())
222
+
223
+ Note:
224
+ Defaults to 16 per page if page_no is specified and per_page is not specified.
225
+ If both page_no and per_page are None, then lists all the resources.
226
+ """
227
+ request_data = dict(user_app_id=self.user_app_id, **filter_by)
228
+ all_modules_info = self.list_pages_generator(
229
+ self.STUB.ListModules,
230
+ service_pb2.ListModulesRequest,
231
+ request_data,
232
+ per_page=per_page,
233
+ page_no=page_no,
234
+ )
235
+
236
+ for module_info in all_modules_info:
237
+ if only_in_app:
238
+ if module_info['app_id'] != self.id:
239
+ continue
240
+ yield Module.from_auth_helper(auth=self.auth_helper, **module_info)
241
+
242
+ def list_installed_module_versions(
243
+ self, filter_by: Dict[str, Any] = {}, page_no: int = None, per_page: int = None
244
+ ) -> Generator[Module, None, None]:
245
+ """Lists all installed module versions in the app.
246
+
247
+ Args:
248
+ filter_by (dict): A dictionary of filters to apply to the list of installed module versions.
249
+ page_no (int): The page number to list.
250
+ per_page (int): The number of items per page.
251
+
252
+ Yields:
253
+ Module: Module objects for the installed module versions in the app.
254
+
255
+ Example:
256
+ >>> from clarifai.client.app import App
257
+ >>> app = App(app_id="app_id", user_id="user_id")
258
+ >>> all_installed_module_versions = list(app.list_installed_module_versions())
259
+
260
+ Note:
261
+ Defaults to 16 per page if page_no is specified and per_page is not specified.
262
+ If both page_no and per_page are None, then lists all the resources.
263
+ """
264
+ request_data = dict(user_app_id=self.user_app_id, **filter_by)
265
+ all_imv_infos = self.list_pages_generator(
266
+ self.STUB.ListInstalledModuleVersions,
267
+ service_pb2.ListInstalledModuleVersionsRequest,
268
+ request_data,
269
+ per_page=per_page,
270
+ page_no=page_no,
271
+ )
272
+ for imv_info in all_imv_infos:
273
+ del imv_info['deploy_url']
274
+ del imv_info['installed_module_version_id'] # TODO: remove this after the backend fix
275
+ yield Module.from_auth_helper(
276
+ auth=self.auth_helper,
277
+ module_id=imv_info['module_version']['module_id'],
278
+ **imv_info,
279
+ )
280
+
281
+ def get_input_count(self) -> int:
282
+ """Get count of all the inputs in the app.
283
+
284
+ Returns:
285
+ input_count: count of inputs in the app.
286
+
287
+ Example:
288
+ >>> from clarifai.client.app import App
289
+ >>> app = App(app_id="app_id", user_id="user_id")
290
+ >>> input_count = app.get_input_count()
291
+ """
292
+ request = service_pb2.GetInputCountRequest(user_app_id=self.user_app_id)
293
+ response = self._grpc_request(self.STUB.GetInputCount, request)
294
+
295
+ if response.status.code != status_code_pb2.SUCCESS:
296
+ raise Exception(response.status)
297
+ self.logger.info("\nGetting App input Counts\n%s", response.status)
298
+
299
+ return response.counts.processed
300
+
301
+ def list_concepts(
302
+ self, page_no: int = None, per_page: int = None
303
+ ) -> Generator[Concept, None, None]:
304
+ """Lists all the concepts for the app.
305
+ Args:
306
+ page_no (int): The page number to list.
307
+ per_page (int): The number of items per page.
308
+
309
+ Yields:
310
+ Concept: Concepts in the app.
311
+
312
+ Example:
313
+ >>> from clarifai.client.app import App
314
+ >>> app = App(app_id="app_id", user_id="user_id")
315
+ >>> all_concepts = list(app.list_concepts())
316
+
317
+ Note:
318
+ Defaults to 16 per page if page_no is specified and per_page is not specified.
319
+ If both page_no and per_page are None, then lists all the resources.
320
+ """
321
+ request_data = dict(user_app_id=self.user_app_id)
322
+ all_concepts_infos = self.list_pages_generator(
323
+ self.STUB.ListConcepts,
324
+ service_pb2.ListConceptsRequest,
325
+ request_data,
326
+ per_page=per_page,
327
+ page_no=page_no,
328
+ )
329
+ for concept_info in all_concepts_infos:
330
+ concept_info['id'] = concept_info.pop('concept_id')
331
+ yield Concept(**concept_info)
332
+
333
+ def search_concept_relations(
334
+ self,
335
+ concept_id: str = None,
336
+ predicate: str = None,
337
+ page_no: int = None,
338
+ per_page: int = None,
339
+ show_tree: bool = False,
340
+ ) -> Generator[ConceptRelation, None, None]:
341
+ """List all the concept relations of the app.
342
+
343
+ Args:
344
+ concept_id (str, optional): The concept ID to filter the concept relations.
345
+ predicate (str, optional): Type of relation to filter the concept relations. For ex : 'hypernym', 'hyponym' or 'synonym'
346
+ page_no (int, optional): The page number to list.
347
+ per_page (int, optional): The number of items per page.
348
+ show_tree (bool, optional): If True, prints out rich tree representation of concept relations.
349
+
350
+ Yields:
351
+ ConceptRelation: ConceptRelations in the app.
352
+
353
+ Example:
354
+ >>> from clarifai.client.app import App
355
+ >>> app = App(app_id="app_id", user_id="user_id")
356
+ >>> all_concept_relations = list(app.search_concept_relations())
357
+
358
+ Note:
359
+ Defaults to 16 per page if page_no is specified and per_page is not specified.
360
+ If both page_no and per_page are None, then lists all the resources.
361
+ """
362
+ request_data = dict(
363
+ user_app_id=self.user_app_id, concept_id=concept_id, predicate=predicate
364
+ )
365
+ all_concept_relations_infos = self.list_pages_generator(
366
+ self.STUB.ListConceptRelations,
367
+ service_pb2.ListConceptRelationsRequest,
368
+ request_data,
369
+ per_page=per_page,
370
+ page_no=page_no,
371
+ )
372
+ relations_dict = {}
373
+ for concept_relation_info in all_concept_relations_infos:
374
+ if show_tree:
375
+ current_subject_concept = concept_relation_info['subject_concept']['id']
376
+ current_object_concept = concept_relation_info['object_concept']['id']
377
+ current_predicate = concept_relation_info['predicate']
378
+ relations_dict = concept_relations_accumulation(
379
+ relations_dict,
380
+ current_subject_concept,
381
+ current_object_concept,
382
+ current_predicate,
383
+ )
384
+ concept_relation_info['id'] = concept_relation_info.pop('concept_relation_id')
385
+ yield ConceptRelation(**concept_relation_info)
386
+ if show_tree:
387
+ display_concept_relations_tree(relations_dict)
388
+
389
+ def list_trainable_model_types(self) -> List[str]:
390
+ """Lists all the trainable model types.
391
+
392
+ Returns:
393
+ templates (List): List all the trainable model types.
394
+
395
+ Example:
396
+ >>> from clarifai.client.app import App
397
+ >>> print(app.list_trainable_model_types())
398
+ """
399
+ return TRAINABLE_MODEL_TYPES
400
+
401
+ def create_dataset(self, dataset_id: str, **kwargs) -> Dataset:
402
+ """Creates a dataset for the app.
403
+
404
+ Args:
405
+ dataset_id (str): The dataset ID for the dataset to create.
406
+ **kwargs: Additional keyword arguments to be passed to the Dataset.
407
+
408
+ Returns:
409
+ Dataset: A Dataset object for the specified dataset ID.
410
+
411
+ Example:
412
+ >>> from clarifai.client.app import App
413
+ >>> app = App(app_id="app_id", user_id="user_id")
414
+ >>> dataset = app.create_dataset(dataset_id="dataset_id")
415
+ """
416
+ request = service_pb2.PostDatasetsRequest(
417
+ user_app_id=self.user_app_id, datasets=[resources_pb2.Dataset(id=dataset_id, **kwargs)]
418
+ )
419
+ response = self._grpc_request(self.STUB.PostDatasets, request)
420
+ if response.status.code != status_code_pb2.SUCCESS:
421
+ raise Exception(response.status)
422
+ self.logger.info("\nDataset created\n%s", response.status)
423
+
424
+ return Dataset.from_auth_helper(self.auth_helper, dataset_id=dataset_id, **kwargs)
425
+
426
+ def create_model(self, model_id: str, **kwargs) -> Model:
427
+ """Creates a model for the app.
428
+
429
+ Args:
430
+ model_id (str): The model ID for the model to create.
431
+ **kwargs: Additional keyword arguments to be passed to the Model.
432
+
433
+ Returns:
434
+ Model: A Model object for the specified model ID.
435
+
436
+ Example:
437
+ >>> from clarifai.client.app import App
438
+ >>> app = App(app_id="app_id", user_id="user_id")
439
+ >>> model = app.create_model(model_id="model_id")
440
+ """
441
+ request = service_pb2.PostModelsRequest(
442
+ user_app_id=self.user_app_id, models=[resources_pb2.Model(id=model_id, **kwargs)]
443
+ )
444
+ response = self._grpc_request(self.STUB.PostModels, request)
445
+ if response.status.code != status_code_pb2.SUCCESS:
446
+ raise Exception(response.status)
447
+ self.logger.info("\nModel created\n%s", response.status)
448
+ kwargs.update(
449
+ {
450
+ 'model_id': model_id,
451
+ 'model_type_id': response.model.model_type_id,
452
+ }
453
+ )
454
+
455
+ return Model.from_auth_helper(auth=self.auth_helper, **kwargs)
456
+
457
+ def _process_workflow_config(self, config_filepath: str):
458
+ with open(config_filepath, 'r') as file:
459
+ workflow_config = yaml.safe_load(file)
460
+
461
+ workflow_config = validate(workflow_config)
462
+ workflow = workflow_config['workflow']
463
+
464
+ # Get all model objects from the workflow nodes.
465
+ all_models = []
466
+ for node in workflow['nodes']:
467
+ output_info = get_yaml_output_info_proto(node['model'].get('output_info', None))
468
+ try:
469
+ model = self.model(
470
+ model_id=node['model']['model_id'],
471
+ model_version={"id": node['model'].get('model_version_id', "")},
472
+ user_id=node['model'].get('user_id', ""),
473
+ app_id=node['model'].get('app_id', ""),
474
+ )
475
+ except Exception as e:
476
+ if "Model does not exist" in str(e):
477
+ model = self.create_model(
478
+ **{k: v for k, v in node['model'].items() if k != 'output_info'}
479
+ )
480
+ model_version = model.create_version(output_info=output_info)
481
+ all_models.append(model_version.model_info)
482
+ continue
483
+
484
+ # If the model version ID is specified, or if the yaml model is the same as the one in the api
485
+ if node["model"].get("model_version_id", "") or is_same_yaml_model(
486
+ model.model_info, node["model"]
487
+ ):
488
+ all_models.append(model.model_info)
489
+ else: # Create a new model version
490
+ model = model.create_version(output_info=output_info)
491
+ all_models.append(model.model_info)
492
+
493
+ # Convert nodes to resources_pb2.WorkflowNodes.
494
+ nodes = []
495
+ for i, yml_node in enumerate(workflow['nodes']):
496
+ node = resources_pb2.WorkflowNode(
497
+ id=yml_node['id'],
498
+ model=all_models[i],
499
+ )
500
+ # Add node inputs if they exist, i.e. if these nodes do not connect directly to the input.
501
+ if yml_node.get("node_inputs"):
502
+ for ni in yml_node.get("node_inputs"):
503
+ node.node_inputs.append(resources_pb2.NodeInput(node_id=ni['node_id']))
504
+ nodes.append(node)
505
+
506
+ return workflow, nodes
507
+
508
+ def create_workflow(
509
+ self, config_filepath: str, generate_new_id: bool = False, display: bool = True
510
+ ) -> Workflow:
511
+ """Creates a workflow for the app.
512
+
513
+ Args:
514
+ config_filepath (str): The path to the yaml workflow config file.
515
+ generate_new_id (bool): If True, generate a new workflow ID.
516
+ display (bool): If True, display the workflow nodes tree.
517
+
518
+ Returns:
519
+ Workflow: A Workflow object for the specified workflow config.
520
+
521
+ Example:
522
+ >>> from clarifai.client.app import App
523
+ >>> app = App(app_id="app_id", user_id="user_id")
524
+ >>> workflow = app.create_workflow(config_filepath="config.yml")
525
+ """
526
+ if not os.path.exists(config_filepath):
527
+ raise UserError(f"Workflow config file not found at {config_filepath}")
528
+
529
+ workflow, nodes = self._process_workflow_config(config_filepath)
530
+
531
+ workflow_id = workflow['id']
532
+ if generate_new_id:
533
+ workflow_id = str(uuid.uuid4())
534
+
535
+ # Create the workflow.
536
+ request = service_pb2.PostWorkflowsRequest(
537
+ user_app_id=self.user_app_id,
538
+ workflows=[resources_pb2.Workflow(id=workflow_id, nodes=nodes)],
539
+ )
540
+
541
+ response = self._grpc_request(self.STUB.PostWorkflows, request)
542
+ if response.status.code != status_code_pb2.SUCCESS:
543
+ raise Exception(response.status)
544
+ self.logger.info("\nWorkflow created\n%s", response.status)
545
+
546
+ dict_response = MessageToDict(response, preserving_proto_field_name=True)
547
+ # Display the workflow nodes tree.
548
+ wf = dict_response["workflows"][0]
549
+ if display:
550
+ display_workflow_tree(wf["nodes"])
551
+ kwargs = self.process_response_keys(wf, "workflow")
552
+
553
+ return Workflow.from_auth_helper(auth=self.auth_helper, **kwargs)
554
+
555
+ def create_module(self, module_id: str, description: str, **kwargs) -> Module:
556
+ """Creates a module for the app.
557
+
558
+ Args:
559
+ module_id (str): The module ID for the module to create.
560
+ description (str): The description of the module to create.
561
+ **kwargs: Additional keyword arguments to be passed to the module.
562
+
563
+ Returns:
564
+ Module: A Module object for the specified module ID.
565
+
566
+ Example:
567
+ >>> from clarifai.client.app import App
568
+ >>> app = App(app_id="app_id", user_id="user_id")
569
+ >>> module = app.create_module(module_id="module_id")
570
+ """
571
+ request = service_pb2.PostModulesRequest(
572
+ user_app_id=self.user_app_id,
573
+ modules=[resources_pb2.Module(id=module_id, description=description, **kwargs)],
574
+ )
575
+ response = self._grpc_request(self.STUB.PostModules, request)
576
+
577
+ if response.status.code != status_code_pb2.SUCCESS:
578
+ raise Exception(response.status)
579
+ self.logger.info("\nModule created\n%s", response.status)
580
+
581
+ return Module.from_auth_helper(auth=self.auth_helper, module_id=module_id, **kwargs)
582
+
583
+ def create_concepts(self, concept_ids: List[str], concepts: List[str] = []) -> None:
584
+ """Add concepts to the app.
585
+
586
+ Args:
587
+ concept_ids (List[str]): List of concept IDs of concepts to add to the app.
588
+ concepts (List[str], optional): List of concepts names of concepts to add to the app.
589
+
590
+ Example:
591
+ >>> from clarifai.client.app import App
592
+ >>> app = App(app_id="app_id", user_id="user_id")
593
+ >>> app.add_concepts(concept_ids=["concept_id_1", "concept_id_2", ..])
594
+ """
595
+ if not concepts:
596
+ concepts = list(concept_ids)
597
+ concepts_to_add = [
598
+ resources_pb2.Concept(id=concept_id, name=concept)
599
+ for concept_id, concept in zip(concept_ids, concepts)
600
+ ]
601
+ request = service_pb2.PostConceptsRequest(
602
+ user_app_id=self.user_app_id, concepts=concepts_to_add
603
+ )
604
+ response = self._grpc_request(self.STUB.PostConcepts, request)
605
+ if response.status.code != status_code_pb2.SUCCESS:
606
+ raise Exception(response.status)
607
+ self.logger.info("\nConcepts added\n%s", response.status)
608
+
609
+ def create_concept_relations(
610
+ self, subject_concept_id: str, object_concept_ids: List[str], predicates: List[str]
611
+ ) -> None:
612
+ """Creates concept relations between concepts of the app.
613
+
614
+ Args:
615
+ subject_concept_id (str): The concept ID of the subject concept.
616
+ object_concept_ids (List[str]): List of concepts IDs of object concepts.
617
+ predicates (List[str]): List of predicates corresponding to each relation between subject and objects.
618
+
619
+ Example:
620
+ >>> from clarifai.client.app import App
621
+ >>> app = App(app_id="app_id", user_id="user_id")
622
+ >>> app.create_concept_relation(subject_concept_id="subject_concept_id", object_concept_ids=["object_concept_id_1", "object_concept_id_2", ..], predicates=["predicate_1", "predicate_2", ..])
623
+ """
624
+ assert len(object_concept_ids) == len(predicates)
625
+ subject_relations = [
626
+ resources_pb2.ConceptRelation(
627
+ object_concept=resources_pb2.Concept(id=object_concept_id), predicate=predicate
628
+ )
629
+ for object_concept_id, predicate in zip(object_concept_ids, predicates)
630
+ ]
631
+ request = service_pb2.PostConceptRelationsRequest(
632
+ user_app_id=self.user_app_id,
633
+ concept_id=subject_concept_id,
634
+ concept_relations=subject_relations,
635
+ )
636
+ response = self._grpc_request(self.STUB.PostConceptRelations, request)
637
+ if response.status.code != status_code_pb2.SUCCESS:
638
+ raise Exception(response.status)
639
+ self.logger.info("\nConcept Relations created\n%s", response.status)
640
+
641
+ def dataset(self, dataset_id: str, dataset_version_id: str = None, **kwargs) -> Dataset:
642
+ """Returns a Dataset object for the existing dataset ID.
643
+
644
+ Args:
645
+ dataset_id (str): The dataset ID for the dataset to interact with.
646
+ dataset_version_id (str): The version ID for the dataset version to interact with.
647
+
648
+ Returns:
649
+ Dataset: A Dataset object for the existing dataset ID.
650
+
651
+ Example:
652
+ >>> from clarifai.client.app import App
653
+ >>> app = App(app_id="app_id", user_id="user_id")
654
+ >>> dataset = app.dataset(dataset_id="dataset_id")
655
+ """
656
+ request = service_pb2.GetDatasetRequest(
657
+ user_app_id=self.user_app_id, dataset_id=dataset_id
658
+ )
659
+ response = self._grpc_request(self.STUB.GetDataset, request)
660
+
661
+ if response.status.code != status_code_pb2.SUCCESS:
662
+ raise Exception(response.status)
663
+ dict_response = MessageToDict(response, preserving_proto_field_name=True)
664
+ kwargs = self.process_response_keys(dict_response['dataset'], 'dataset')
665
+ kwargs['version'] = response.dataset.version if response.dataset.version else None
666
+ kwargs['dataset_version_id'] = dataset_version_id
667
+ return Dataset.from_auth_helper(auth=self.auth_helper, **kwargs)
668
+
669
+ def model(self, model_id: str, model_version: Dict = {'id': ""}, **kwargs) -> Model:
670
+ """Returns a Model object for the existing model ID.
671
+
672
+ Args:
673
+ model_id (str): The model ID for the model to interact with.
674
+ model_version (Dict): The model version ID for the model version to interact with.
675
+
676
+ Returns:
677
+ Model: A Model object for the existing model ID.
678
+
679
+ Example:
680
+ >>> from clarifai.client.app import App
681
+ >>> app = App(app_id="app_id", user_id="user_id")
682
+ >>> model_v1 = app.model(model_id="model_id", model_version={"id":"model_version_id")
683
+ """
684
+ # Change user_app_id based on whether user_id or app_id is specified.
685
+ if kwargs.get("user_id") or kwargs.get("app_id"):
686
+ request = service_pb2.GetModelRequest(
687
+ user_app_id=self.auth_helper.get_user_app_id_proto(
688
+ kwargs.get("user_id"), kwargs.get("app_id")
689
+ ),
690
+ model_id=model_id,
691
+ version_id=model_version["id"],
692
+ )
693
+ else:
694
+ request = service_pb2.GetModelRequest(
695
+ user_app_id=self.user_app_id, model_id=model_id, version_id=model_version["id"]
696
+ )
697
+ response = self._grpc_request(self.STUB.GetModel, request)
698
+
699
+ if response.status.code != status_code_pb2.SUCCESS:
700
+ raise Exception(response.status)
701
+ dict_response = MessageToDict(response, preserving_proto_field_name=True)
702
+
703
+ kwargs = self.process_response_keys(dict_response['model'], 'model')
704
+ kwargs['model_version'] = (
705
+ response.model.model_version if response.model.model_version else None
706
+ )
707
+
708
+ m = Model.from_auth_helper(self.auth_helper, **kwargs)
709
+ return m
710
+
711
+ def workflow(self, workflow_id: str, **kwargs) -> Workflow:
712
+ """Returns a workflow object for the existing workflow ID.
713
+
714
+ Args:
715
+ workflow_id (str): The workflow ID for the workflow to interact with.
716
+
717
+ Returns:
718
+ Workflow: A Workflow object for the existing workflow ID.
719
+
720
+ Example:
721
+ >>> from clarifai.client.app import App
722
+ >>> app = App(app_id="app_id", user_id="user_id")
723
+ >>> workflow = app.workflow(workflow_id="workflow_id")
724
+ """
725
+ request = service_pb2.GetWorkflowRequest(
726
+ user_app_id=self.user_app_id, workflow_id=workflow_id
727
+ )
728
+ response = self._grpc_request(self.STUB.GetWorkflow, request)
729
+
730
+ if response.status.code != status_code_pb2.SUCCESS:
731
+ raise Exception(response.status)
732
+ dict_response = MessageToDict(response, preserving_proto_field_name=True)
733
+ kwargs = self.process_response_keys(dict_response['workflow'], "workflow")
734
+
735
+ return Workflow.from_auth_helper(auth=self.auth_helper, **kwargs)
736
+
737
+ def module(self, module_id: str, **kwargs) -> Module:
738
+ """Returns a Module object for the existing module ID.
739
+
740
+ Args:
741
+ module_id (str): The module ID for the module to interact with.
742
+ module_version_id (str): The module version ID for the module version to interact with.
743
+
744
+ Returns:
745
+ Module: A Module object for the existing module ID.
746
+
747
+ Example:
748
+ >>> from clarifai.client.app import App
749
+ >>> app = App(app_id="app_id", user_id="user_id")
750
+ >>> module = app.module(module_id="module_id")
751
+ """
752
+ request = service_pb2.GetModuleRequest(user_app_id=self.user_app_id, module_id=module_id)
753
+ response = self._grpc_request(self.STUB.GetModule, request)
754
+
755
+ if response.status.code != status_code_pb2.SUCCESS:
756
+ raise Exception(response.status)
757
+ dict_response = MessageToDict(response, preserving_proto_field_name=True)
758
+ kwargs = self.process_response_keys(dict_response['module'], 'module')
759
+
760
+ return Module.from_auth_helper(auth=self.auth_helper, **kwargs)
761
+
762
+ def inputs(
65
763
  self,
66
- user_id=self.user_id,
67
- app_id=self.id,
68
- base=base_url,
69
- pat=pat,
70
- token=token,
71
- root_certificates_path=root_certificates_path)
72
- Lister.__init__(self)
73
-
74
- def list_datasets(self, page_no: int = None,
75
- per_page: int = None) -> Generator[Dataset, None, None]:
76
- """Lists all the datasets for the app.
77
-
78
- Args:
79
- page_no (int): The page number to list.
80
- per_page (int): The number of items per page.
81
-
82
- Yields:
83
- Dataset: Dataset objects for the datasets in the app.
84
-
85
- Example:
86
- >>> from clarifai.client.app import App
87
- >>> app = App(app_id="app_id", user_id="user_id")
88
- >>> all_datasets = list(app.list_datasets())
89
-
90
- Note:
91
- Defaults to 16 per page if page_no is specified and per_page is not specified.
92
- If both page_no and per_page are None, then lists all the resources.
93
- """
94
- request_data = dict(user_app_id=self.user_app_id,)
95
- all_datasets_info = self.list_pages_generator(
96
- self.STUB.ListDatasets,
97
- service_pb2.ListDatasetsRequest,
98
- request_data,
99
- per_page=per_page,
100
- page_no=page_no)
101
- for dataset_info in all_datasets_info:
102
- if 'version' in dataset_info:
103
- dataset_info['version'].pop('metrics', None)
104
- dataset_info['version'].pop('export_info', None)
105
- yield Dataset.from_auth_helper(auth=self.auth_helper, **dataset_info)
106
-
107
- def list_models(self,
108
- filter_by: Dict[str, Any] = {},
109
- only_in_app: bool = True,
110
- page_no: int = None,
111
- per_page: int = None) -> Generator[Model, None, None]:
112
- """Lists all the available models for the user.
113
-
114
- Args:
115
- filter_by (dict): A dictionary of filters to apply to the list of models.
116
- only_in_app (bool): If True, only return models that are in the app.
117
- page_no (int): The page number to list.
118
- per_page (int): The number of items per page.
119
-
120
- Yields:
121
- Model: Model objects for the models in the app.
122
-
123
- Example:
124
- >>> from clarifai.client.user import User
125
- >>> app = User(user_id="user_id").app(app_id="app_id")
126
- >>> all_models = list(app.list_models())
127
-
128
- Note:
129
- Defaults to 16 per page if page_no is specified and per_page is not specified.
130
- If both page_no and per_page are None, then lists all the resources.
131
- """
132
- request_data = dict(user_app_id=self.user_app_id, **filter_by)
133
- all_models_info = self.list_pages_generator(
134
- self.STUB.ListModels,
135
- service_pb2.ListModelsRequest,
136
- request_data,
137
- per_page=per_page,
138
- page_no=page_no)
139
-
140
- for model_info in all_models_info:
141
- if 'model_version' not in list(model_info.keys()):
142
- continue
143
- if only_in_app:
144
- if model_info['app_id'] != self.id:
145
- continue
146
- yield Model.from_auth_helper(auth=self.auth_helper, **model_info)
147
-
148
- def list_workflows(self,
149
- filter_by: Dict[str, Any] = {},
150
- only_in_app: bool = True,
151
- page_no: int = None,
152
- per_page: int = None) -> Generator[Workflow, None, None]:
153
- """Lists all the available workflows for the user.
154
-
155
- Args:
156
- filter_by (dict): A dictionary of filters to apply to the list of workflows.
157
- only_in_app (bool): If True, only return workflows that are in the app.
158
- page_no (int): The page number to list.
159
- per_page (int): The number of items per page.
160
-
161
- Yields:
162
- Workflow: Workflow objects for the workflows in the app.
163
-
164
- Example:
165
- >>> from clarifai.client.app import App
166
- >>> app = App(app_id="app_id", user_id="user_id")
167
- >>> all_workflows = list(app.list_workflows())
168
-
169
- Note:
170
- Defaults to 16 per page if page_no is specified and per_page is not specified.
171
- If both page_no and per_page are None, then lists all the resources.
172
- """
173
- request_data = dict(user_app_id=self.user_app_id, **filter_by)
174
- all_workflows_info = self.list_pages_generator(
175
- self.STUB.ListWorkflows,
176
- service_pb2.ListWorkflowsRequest,
177
- request_data,
178
- per_page=per_page,
179
- page_no=page_no)
180
-
181
- for workflow_info in all_workflows_info:
182
- if only_in_app:
183
- if workflow_info['app_id'] != self.id:
184
- continue
185
- yield Workflow.from_auth_helper(auth=self.auth_helper, **workflow_info)
186
-
187
- def list_modules(self,
188
- filter_by: Dict[str, Any] = {},
189
- only_in_app: bool = True,
190
- page_no: int = None,
191
- per_page: int = None) -> Generator[Module, None, None]:
192
- """Lists all the available modules for the user.
193
-
194
- Args:
195
- filter_by (dict): A dictionary of filters to apply to the list of modules.
196
- only_in_app (bool): If True, only return modules that are in the app.
197
- page_no (int): The page number to list.
198
- per_page (int): The number of items per page.
199
-
200
- Yields:
201
- Module: Module objects for the modules in the app.
202
-
203
- Example:
204
- >>> from clarifai.client.app import App
205
- >>> app = App(app_id="app_id", user_id="user_id")
206
- >>> all_modules = list(app.list_modules())
207
-
208
- Note:
209
- Defaults to 16 per page if page_no is specified and per_page is not specified.
210
- If both page_no and per_page are None, then lists all the resources.
211
- """
212
- request_data = dict(user_app_id=self.user_app_id, **filter_by)
213
- all_modules_info = self.list_pages_generator(
214
- self.STUB.ListModules,
215
- service_pb2.ListModulesRequest,
216
- request_data,
217
- per_page=per_page,
218
- page_no=page_no)
219
-
220
- for module_info in all_modules_info:
221
- if only_in_app:
222
- if module_info['app_id'] != self.id:
223
- continue
224
- yield Module.from_auth_helper(auth=self.auth_helper, **module_info)
225
-
226
- def list_installed_module_versions(self,
227
- filter_by: Dict[str, Any] = {},
228
- page_no: int = None,
229
- per_page: int = None) -> Generator[Module, None, None]:
230
- """Lists all installed module versions in the app.
231
-
232
- Args:
233
- filter_by (dict): A dictionary of filters to apply to the list of installed module versions.
234
- page_no (int): The page number to list.
235
- per_page (int): The number of items per page.
236
-
237
- Yields:
238
- Module: Module objects for the installed module versions in the app.
239
-
240
- Example:
241
- >>> from clarifai.client.app import App
242
- >>> app = App(app_id="app_id", user_id="user_id")
243
- >>> all_installed_module_versions = list(app.list_installed_module_versions())
244
-
245
- Note:
246
- Defaults to 16 per page if page_no is specified and per_page is not specified.
247
- If both page_no and per_page are None, then lists all the resources.
248
- """
249
- request_data = dict(user_app_id=self.user_app_id, **filter_by)
250
- all_imv_infos = self.list_pages_generator(
251
- self.STUB.ListInstalledModuleVersions,
252
- service_pb2.ListInstalledModuleVersionsRequest,
253
- request_data,
254
- per_page=per_page,
255
- page_no=page_no)
256
- for imv_info in all_imv_infos:
257
- del imv_info['deploy_url']
258
- del imv_info['installed_module_version_id'] # TODO: remove this after the backend fix
259
- yield Module.from_auth_helper(
260
- auth=self.auth_helper, module_id=imv_info['module_version']['module_id'], **imv_info)
261
-
262
- def get_input_count(self) -> int:
263
- """Get count of all the inputs in the app.
264
-
265
- Returns:
266
- input_count: count of inputs in the app.
267
-
268
- Example:
269
- >>> from clarifai.client.app import App
270
- >>> app = App(app_id="app_id", user_id="user_id")
271
- >>> input_count = app.get_input_count()
272
- """
273
- request = service_pb2.GetInputCountRequest(user_app_id=self.user_app_id)
274
- response = self._grpc_request(self.STUB.GetInputCount, request)
275
-
276
- if response.status.code != status_code_pb2.SUCCESS:
277
- raise Exception(response.status)
278
- self.logger.info("\nGetting App input Counts\n%s", response.status)
279
-
280
- return response.counts.processed
281
-
282
- def list_concepts(self, page_no: int = None,
283
- per_page: int = None) -> Generator[Concept, None, None]:
284
- """Lists all the concepts for the app.
285
- Args:
286
- page_no (int): The page number to list.
287
- per_page (int): The number of items per page.
288
-
289
- Yields:
290
- Concept: Concepts in the app.
291
-
292
- Example:
293
- >>> from clarifai.client.app import App
294
- >>> app = App(app_id="app_id", user_id="user_id")
295
- >>> all_concepts = list(app.list_concepts())
296
-
297
- Note:
298
- Defaults to 16 per page if page_no is specified and per_page is not specified.
299
- If both page_no and per_page are None, then lists all the resources.
300
- """
301
- request_data = dict(user_app_id=self.user_app_id)
302
- all_concepts_infos = self.list_pages_generator(
303
- self.STUB.ListConcepts,
304
- service_pb2.ListConceptsRequest,
305
- request_data,
306
- per_page=per_page,
307
- page_no=page_no)
308
- for concept_info in all_concepts_infos:
309
- concept_info['id'] = concept_info.pop('concept_id')
310
- yield Concept(**concept_info)
311
-
312
- def search_concept_relations(self,
313
- concept_id: str = None,
314
- predicate: str = None,
315
- page_no: int = None,
316
- per_page: int = None,
317
- show_tree: bool = False) -> Generator[ConceptRelation, None, None]:
318
- """List all the concept relations of the app.
319
-
320
- Args:
321
- concept_id (str, optional): The concept ID to filter the concept relations.
322
- predicate (str, optional): Type of relation to filter the concept relations. For ex : 'hypernym', 'hyponym' or 'synonym'
323
- page_no (int, optional): The page number to list.
324
- per_page (int, optional): The number of items per page.
325
- show_tree (bool, optional): If True, prints out rich tree representation of concept relations.
326
-
327
- Yields:
328
- ConceptRelation: ConceptRelations in the app.
329
-
330
- Example:
331
- >>> from clarifai.client.app import App
332
- >>> app = App(app_id="app_id", user_id="user_id")
333
- >>> all_concept_relations = list(app.search_concept_relations())
334
-
335
- Note:
336
- Defaults to 16 per page if page_no is specified and per_page is not specified.
337
- If both page_no and per_page are None, then lists all the resources.
338
- """
339
- request_data = dict(user_app_id=self.user_app_id, concept_id=concept_id, predicate=predicate)
340
- all_concept_relations_infos = self.list_pages_generator(
341
- self.STUB.ListConceptRelations,
342
- service_pb2.ListConceptRelationsRequest,
343
- request_data,
344
- per_page=per_page,
345
- page_no=page_no)
346
- relations_dict = {}
347
- for concept_relation_info in all_concept_relations_infos:
348
- if show_tree:
349
- current_subject_concept = concept_relation_info['subject_concept']['id']
350
- current_object_concept = concept_relation_info['object_concept']['id']
351
- current_predicate = concept_relation_info['predicate']
352
- relations_dict = concept_relations_accumulation(relations_dict, current_subject_concept,
353
- current_object_concept, current_predicate)
354
- concept_relation_info['id'] = concept_relation_info.pop('concept_relation_id')
355
- yield ConceptRelation(**concept_relation_info)
356
- if show_tree:
357
- display_concept_relations_tree(relations_dict)
358
-
359
- def list_trainable_model_types(self) -> List[str]:
360
- """Lists all the trainable model types.
361
-
362
- Returns:
363
- templates (List): List all the trainable model types.
364
-
365
- Example:
366
- >>> from clarifai.client.app import App
367
- >>> print(app.list_trainable_model_types())
368
- """
369
- return TRAINABLE_MODEL_TYPES
370
-
371
- def create_dataset(self, dataset_id: str, **kwargs) -> Dataset:
372
- """Creates a dataset for the app.
373
-
374
- Args:
375
- dataset_id (str): The dataset ID for the dataset to create.
376
- **kwargs: Additional keyword arguments to be passed to the Dataset.
377
-
378
- Returns:
379
- Dataset: A Dataset object for the specified dataset ID.
380
-
381
- Example:
382
- >>> from clarifai.client.app import App
383
- >>> app = App(app_id="app_id", user_id="user_id")
384
- >>> dataset = app.create_dataset(dataset_id="dataset_id")
385
- """
386
- request = service_pb2.PostDatasetsRequest(
387
- user_app_id=self.user_app_id, datasets=[resources_pb2.Dataset(id=dataset_id, **kwargs)])
388
- response = self._grpc_request(self.STUB.PostDatasets, request)
389
- if response.status.code != status_code_pb2.SUCCESS:
390
- raise Exception(response.status)
391
- self.logger.info("\nDataset created\n%s", response.status)
392
-
393
- return Dataset.from_auth_helper(self.auth_helper, dataset_id=dataset_id, **kwargs)
394
-
395
- def create_model(self, model_id: str, **kwargs) -> Model:
396
- """Creates a model for the app.
397
-
398
- Args:
399
- model_id (str): The model ID for the model to create.
400
- **kwargs: Additional keyword arguments to be passed to the Model.
401
-
402
- Returns:
403
- Model: A Model object for the specified model ID.
404
-
405
- Example:
406
- >>> from clarifai.client.app import App
407
- >>> app = App(app_id="app_id", user_id="user_id")
408
- >>> model = app.create_model(model_id="model_id")
409
- """
410
- request = service_pb2.PostModelsRequest(
411
- user_app_id=self.user_app_id, models=[resources_pb2.Model(id=model_id, **kwargs)])
412
- response = self._grpc_request(self.STUB.PostModels, request)
413
- if response.status.code != status_code_pb2.SUCCESS:
414
- raise Exception(response.status)
415
- self.logger.info("\nModel created\n%s", response.status)
416
- kwargs.update({
417
- 'model_id': model_id,
418
- 'model_type_id': response.model.model_type_id,
419
- })
420
-
421
- return Model.from_auth_helper(auth=self.auth_helper, **kwargs)
422
-
423
- def _process_workflow_config(self, config_filepath: str):
424
- with open(config_filepath, 'r') as file:
425
- workflow_config = yaml.safe_load(file)
426
-
427
- workflow_config = validate(workflow_config)
428
- workflow = workflow_config['workflow']
429
-
430
- # Get all model objects from the workflow nodes.
431
- all_models = []
432
- for node in workflow['nodes']:
433
- output_info = get_yaml_output_info_proto(node['model'].get('output_info', None))
434
- try:
435
- model = self.model(
436
- model_id=node['model']['model_id'],
437
- model_version={"id": node['model'].get('model_version_id', "")},
438
- user_id=node['model'].get('user_id', ""),
439
- app_id=node['model'].get('app_id', ""))
440
- except Exception as e:
441
- if "Model does not exist" in str(e):
442
- model = self.create_model(
443
- **{k: v
444
- for k, v in node['model'].items() if k != 'output_info'})
445
- model_version = model.create_version(output_info=output_info)
446
- all_models.append(model_version.model_info)
447
- continue
448
-
449
- # If the model version ID is specified, or if the yaml model is the same as the one in the api
450
- if node["model"].get("model_version_id", "") or is_same_yaml_model(
451
- model.model_info, node["model"]):
452
- all_models.append(model.model_info)
453
- else: # Create a new model version
454
- model = model.create_version(output_info=output_info)
455
- all_models.append(model.model_info)
456
-
457
- # Convert nodes to resources_pb2.WorkflowNodes.
458
- nodes = []
459
- for i, yml_node in enumerate(workflow['nodes']):
460
- node = resources_pb2.WorkflowNode(
461
- id=yml_node['id'],
462
- model=all_models[i],
463
- )
464
- # Add node inputs if they exist, i.e. if these nodes do not connect directly to the input.
465
- if yml_node.get("node_inputs"):
466
- for ni in yml_node.get("node_inputs"):
467
- node.node_inputs.append(resources_pb2.NodeInput(node_id=ni['node_id']))
468
- nodes.append(node)
469
-
470
- return workflow, nodes
471
-
472
- def create_workflow(self,
473
- config_filepath: str,
474
- generate_new_id: bool = False,
475
- display: bool = True) -> Workflow:
476
- """Creates a workflow for the app.
477
-
478
- Args:
479
- config_filepath (str): The path to the yaml workflow config file.
480
- generate_new_id (bool): If True, generate a new workflow ID.
481
- display (bool): If True, display the workflow nodes tree.
482
-
483
- Returns:
484
- Workflow: A Workflow object for the specified workflow config.
485
-
486
- Example:
487
- >>> from clarifai.client.app import App
488
- >>> app = App(app_id="app_id", user_id="user_id")
489
- >>> workflow = app.create_workflow(config_filepath="config.yml")
490
- """
491
- if not os.path.exists(config_filepath):
492
- raise UserError(f"Workflow config file not found at {config_filepath}")
493
-
494
- workflow, nodes = self._process_workflow_config(config_filepath)
495
-
496
- workflow_id = workflow['id']
497
- if generate_new_id:
498
- workflow_id = str(uuid.uuid4())
499
-
500
- # Create the workflow.
501
- request = service_pb2.PostWorkflowsRequest(
502
- user_app_id=self.user_app_id,
503
- workflows=[resources_pb2.Workflow(id=workflow_id, nodes=nodes)])
504
-
505
- response = self._grpc_request(self.STUB.PostWorkflows, request)
506
- if response.status.code != status_code_pb2.SUCCESS:
507
- raise Exception(response.status)
508
- self.logger.info("\nWorkflow created\n%s", response.status)
509
-
510
- dict_response = MessageToDict(response, preserving_proto_field_name=True)
511
- # Display the workflow nodes tree.
512
- if display:
513
- display_workflow_tree(dict_response["workflows"][0]["nodes"])
514
- kwargs = self.process_response_keys(dict_response[list(dict_response.keys())[1]][0],
515
- "workflow")
516
-
517
- return Workflow.from_auth_helper(auth=self.auth_helper, **kwargs)
518
-
519
- def create_module(self, module_id: str, description: str, **kwargs) -> Module:
520
- """Creates a module for the app.
521
-
522
- Args:
523
- module_id (str): The module ID for the module to create.
524
- description (str): The description of the module to create.
525
- **kwargs: Additional keyword arguments to be passed to the module.
526
-
527
- Returns:
528
- Module: A Module object for the specified module ID.
529
-
530
- Example:
531
- >>> from clarifai.client.app import App
532
- >>> app = App(app_id="app_id", user_id="user_id")
533
- >>> module = app.create_module(module_id="module_id")
534
- """
535
- request = service_pb2.PostModulesRequest(
536
- user_app_id=self.user_app_id,
537
- modules=[resources_pb2.Module(id=module_id, description=description, **kwargs)])
538
- response = self._grpc_request(self.STUB.PostModules, request)
539
-
540
- if response.status.code != status_code_pb2.SUCCESS:
541
- raise Exception(response.status)
542
- self.logger.info("\nModule created\n%s", response.status)
543
-
544
- return Module.from_auth_helper(auth=self.auth_helper, module_id=module_id, **kwargs)
545
-
546
- def create_concepts(self, concept_ids: List[str], concepts: List[str] = []) -> None:
547
- """Add concepts to the app.
548
-
549
- Args:
550
- concept_ids (List[str]): List of concept IDs of concepts to add to the app.
551
- concepts (List[str], optional): List of concepts names of concepts to add to the app.
552
-
553
- Example:
554
- >>> from clarifai.client.app import App
555
- >>> app = App(app_id="app_id", user_id="user_id")
556
- >>> app.add_concepts(concept_ids=["concept_id_1", "concept_id_2", ..])
557
- """
558
- if not concepts:
559
- concepts = list(concept_ids)
560
- concepts_to_add = [
561
- resources_pb2.Concept(id=concept_id, name=concept)
562
- for concept_id, concept in zip(concept_ids, concepts)
563
- ]
564
- request = service_pb2.PostConceptsRequest(
565
- user_app_id=self.user_app_id, concepts=concepts_to_add)
566
- response = self._grpc_request(self.STUB.PostConcepts, request)
567
- if response.status.code != status_code_pb2.SUCCESS:
568
- raise Exception(response.status)
569
- self.logger.info("\nConcepts added\n%s", response.status)
570
-
571
- def create_concept_relations(self, subject_concept_id: str, object_concept_ids: List[str],
572
- predicates: List[str]) -> None:
573
- """Creates concept relations between concepts of the app.
574
-
575
- Args:
576
- subject_concept_id (str): The concept ID of the subject concept.
577
- object_concept_ids (List[str]): List of concepts IDs of object concepts.
578
- predicates (List[str]): List of predicates corresponding to each relation between subject and objects.
579
-
580
- Example:
581
- >>> from clarifai.client.app import App
582
- >>> app = App(app_id="app_id", user_id="user_id")
583
- >>> app.create_concept_relation(subject_concept_id="subject_concept_id", object_concept_ids=["object_concept_id_1", "object_concept_id_2", ..], predicates=["predicate_1", "predicate_2", ..])
584
- """
585
- assert len(object_concept_ids) == len(predicates)
586
- subject_relations = [
587
- resources_pb2.ConceptRelation(
588
- object_concept=resources_pb2.Concept(id=object_concept_id), predicate=predicate)
589
- for object_concept_id, predicate in zip(object_concept_ids, predicates)
590
- ]
591
- request = service_pb2.PostConceptRelationsRequest(
592
- user_app_id=self.user_app_id,
593
- concept_id=subject_concept_id,
594
- concept_relations=subject_relations)
595
- response = self._grpc_request(self.STUB.PostConceptRelations, request)
596
- if response.status.code != status_code_pb2.SUCCESS:
597
- raise Exception(response.status)
598
- self.logger.info("\nConcept Relations created\n%s", response.status)
599
-
600
- def dataset(self, dataset_id: str, dataset_version_id: str = None, **kwargs) -> Dataset:
601
- """Returns a Dataset object for the existing dataset ID.
602
-
603
- Args:
604
- dataset_id (str): The dataset ID for the dataset to interact with.
605
- dataset_version_id (str): The version ID for the dataset version to interact with.
606
-
607
- Returns:
608
- Dataset: A Dataset object for the existing dataset ID.
609
-
610
- Example:
611
- >>> from clarifai.client.app import App
612
- >>> app = App(app_id="app_id", user_id="user_id")
613
- >>> dataset = app.dataset(dataset_id="dataset_id")
614
- """
615
- request = service_pb2.GetDatasetRequest(user_app_id=self.user_app_id, dataset_id=dataset_id)
616
- response = self._grpc_request(self.STUB.GetDataset, request)
617
-
618
- if response.status.code != status_code_pb2.SUCCESS:
619
- raise Exception(response.status)
620
- dict_response = MessageToDict(response, preserving_proto_field_name=True)
621
- kwargs = self.process_response_keys(dict_response[list(dict_response.keys())[1]],
622
- list(dict_response.keys())[1])
623
- kwargs['version'] = response.dataset.version if response.dataset.version else None
624
- kwargs['dataset_version_id'] = dataset_version_id
625
- return Dataset.from_auth_helper(auth=self.auth_helper, **kwargs)
626
-
627
- def model(self, model_id: str, model_version: Dict = {'id': ""}, **kwargs) -> Model:
628
- """Returns a Model object for the existing model ID.
629
-
630
- Args:
631
- model_id (str): The model ID for the model to interact with.
632
- model_version (Dict): The model version ID for the model version to interact with.
633
-
634
- Returns:
635
- Model: A Model object for the existing model ID.
636
-
637
- Example:
638
- >>> from clarifai.client.app import App
639
- >>> app = App(app_id="app_id", user_id="user_id")
640
- >>> model_v1 = app.model(model_id="model_id", model_version={"id":"model_version_id")
641
- """
642
- # Change user_app_id based on whether user_id or app_id is specified.
643
- if kwargs.get("user_id") or kwargs.get("app_id"):
644
- request = service_pb2.GetModelRequest(
645
- user_app_id=self.auth_helper.get_user_app_id_proto(
646
- kwargs.get("user_id"), kwargs.get("app_id")),
647
- model_id=model_id,
648
- version_id=model_version["id"])
649
- else:
650
- request = service_pb2.GetModelRequest(
651
- user_app_id=self.user_app_id, model_id=model_id, version_id=model_version["id"])
652
- response = self._grpc_request(self.STUB.GetModel, request)
653
-
654
- if response.status.code != status_code_pb2.SUCCESS:
655
- raise Exception(response.status)
656
- dict_response = MessageToDict(response, preserving_proto_field_name=True)
657
- kwargs = self.process_response_keys(dict_response['model'], 'model')
658
- kwargs[
659
- 'model_version'] = response.model.model_version if response.model.model_version else None
660
-
661
- return Model.from_auth_helper(self.auth_helper, **kwargs)
662
-
663
- def workflow(self, workflow_id: str, **kwargs) -> Workflow:
664
- """Returns a workflow object for the existing workflow ID.
665
-
666
- Args:
667
- workflow_id (str): The workflow ID for the workflow to interact with.
668
-
669
- Returns:
670
- Workflow: A Workflow object for the existing workflow ID.
671
-
672
- Example:
673
- >>> from clarifai.client.app import App
674
- >>> app = App(app_id="app_id", user_id="user_id")
675
- >>> workflow = app.workflow(workflow_id="workflow_id")
676
- """
677
- request = service_pb2.GetWorkflowRequest(user_app_id=self.user_app_id, workflow_id=workflow_id)
678
- response = self._grpc_request(self.STUB.GetWorkflow, request)
679
-
680
- if response.status.code != status_code_pb2.SUCCESS:
681
- raise Exception(response.status)
682
- dict_response = MessageToDict(response, preserving_proto_field_name=True)
683
- kwargs = self.process_response_keys(dict_response[list(dict_response.keys())[1]],
684
- list(dict_response.keys())[1])
685
-
686
- return Workflow.from_auth_helper(auth=self.auth_helper, **kwargs)
687
-
688
- def module(self, module_id: str, **kwargs) -> Module:
689
- """Returns a Module object for the existing module ID.
690
-
691
- Args:
692
- module_id (str): The module ID for the module to interact with.
693
- module_version_id (str): The module version ID for the module version to interact with.
694
-
695
- Returns:
696
- Module: A Module object for the existing module ID.
697
-
698
- Example:
699
- >>> from clarifai.client.app import App
700
- >>> app = App(app_id="app_id", user_id="user_id")
701
- >>> module = app.module(module_id="module_id")
702
- """
703
- request = service_pb2.GetModuleRequest(user_app_id=self.user_app_id, module_id=module_id)
704
- response = self._grpc_request(self.STUB.GetModule, request)
705
-
706
- if response.status.code != status_code_pb2.SUCCESS:
707
- raise Exception(response.status)
708
- dict_response = MessageToDict(response, preserving_proto_field_name=True)
709
- kwargs = self.process_response_keys(dict_response['module'], 'module')
710
-
711
- return Module.from_auth_helper(auth=self.auth_helper, **kwargs)
712
-
713
- def inputs(self,):
714
- """Returns an Input object.
715
-
716
- Returns:
717
- Inputs: An input object.
718
- """
719
- return Inputs.from_auth_helper(self.auth_helper)
720
-
721
- def patch_dataset(self, dataset_id: str, action: str = 'merge', **kwargs) -> Dataset:
722
- """Patches a dataset for the app.
723
-
724
- Args:
725
- dataset_id (str): The dataset ID for the dataset to create.
726
- action (str): The action to perform on the dataset (merge/overwrite/remove).
727
- **kwargs: Additional keyword arguments to be passed to patch the Dataset.
728
-
729
- Returns:
730
- Dataset: A Dataset object for the specified dataset ID.
731
- """
732
- if "visibility" in kwargs:
733
- kwargs["visibility"] = resources_pb2.Visibility(gettable=kwargs["visibility"])
734
- if "image_url" in kwargs:
735
- kwargs["image"] = resources_pb2.Image(url=kwargs.pop("image_url"))
736
- request = service_pb2.PatchDatasetsRequest(
737
- user_app_id=self.user_app_id,
738
- datasets=[resources_pb2.Dataset(id=dataset_id, **kwargs)],
739
- action=action)
740
- response = self._grpc_request(self.STUB.PatchDatasets, request)
741
- if response.status.code != status_code_pb2.SUCCESS:
742
- raise Exception(response.status)
743
- self.logger.info("\nDataset patched\n%s", response.status)
744
-
745
- return Dataset.from_auth_helper(self.auth_helper, dataset_id=dataset_id, **kwargs)
746
-
747
- def patch_model(self, model_id: str, action: str = 'merge', **kwargs) -> Model:
748
- """Patches a model of the app.
749
-
750
- Args:
751
- model_id (str): The model ID of the model to patch.
752
- action (str): The action to perform on the model (merge/overwrite/remove).
753
- **kwargs: Additional keyword arguments to be passed to patch the Model.
754
-
755
- Returns:
756
- Model: A Model object of the specified model ID.
757
- """
758
- if "visibility" in kwargs:
759
- kwargs["visibility"] = resources_pb2.Visibility(gettable=kwargs["visibility"])
760
- if "image_url" in kwargs:
761
- kwargs["image"] = resources_pb2.Image(url=kwargs.pop("image_url"))
762
- request = service_pb2.PatchModelsRequest(
763
- user_app_id=self.user_app_id,
764
- models=[resources_pb2.Model(id=model_id, **kwargs)],
765
- action=action)
766
- response = self._grpc_request(self.STUB.PatchModels, request)
767
- if response.status.code != status_code_pb2.SUCCESS:
768
- raise Exception(response.status)
769
- self.logger.info("\nModel %s patched successfully\n%s", model_id, response.status)
770
- kwargs.update({
771
- 'model_id': model_id,
772
- })
773
-
774
- return Model.from_auth_helper(self.auth_helper, **kwargs)
775
-
776
- def patch_workflow(self,
777
- workflow_id: str,
778
- action: str = 'merge',
779
- config_filepath: str = None,
780
- **kwargs) -> Workflow:
781
- """Patches a workflow of the app.
782
-
783
- Args:
784
- workflow_id (str): The Workflow ID of the workflow to patch.
785
- action (str): The action to perform on the workflow (merge/overwrite/remove).
786
- config_filepath (str): The path to the yaml workflow config file.
787
- **kwargs: Additional keyword arguments to be passed to patch the Workflow.
788
-
789
- Returns:
790
- Workflow: A Workflow object of the specified workflow ID.
791
- """
792
- if config_filepath:
793
- if not os.path.exists(config_filepath):
794
- raise UserError(f"Workflow config file not found at {config_filepath}")
795
- _, kwargs['nodes'] = self._process_workflow_config(config_filepath)
796
- if "visibility" in kwargs:
797
- kwargs["visibility"] = resources_pb2.Visibility(gettable=kwargs["visibility"])
798
- if "image_url" in kwargs:
799
- kwargs["image"] = resources_pb2.Image(url=kwargs.pop("image_url"))
800
-
801
- request = service_pb2.PatchWorkflowsRequest(
802
- user_app_id=self.user_app_id,
803
- workflows=[resources_pb2.Workflow(id=workflow_id, **kwargs)],
804
- action=action)
805
- response = self._grpc_request(self.STUB.PatchWorkflows, request)
806
- if response.status.code != status_code_pb2.SUCCESS:
807
- raise Exception(response.status)
808
- self.logger.info("\nWorkflow patched\n%s", response.status)
809
- kwargs.update({
810
- 'workflow_id': workflow_id,
811
- })
812
-
813
- return Workflow.from_auth_helper(self.auth_helper, **kwargs)
814
-
815
- def delete_dataset(self, dataset_id: str) -> None:
816
- """Deletes an dataset for the user.
817
-
818
- Args:
819
- dataset_id (str): The dataset ID for the app to delete.
820
-
821
- Example:
822
- >>> from clarifai.client.app import App
823
- >>> app = App(app_id="app_id", user_id="user_id")
824
- >>> app.delete_dataset(dataset_id="dataset_id")
825
- """
826
- request = service_pb2.DeleteDatasetsRequest(
827
- user_app_id=self.user_app_id, dataset_ids=[dataset_id])
828
- response = self._grpc_request(self.STUB.DeleteDatasets, request)
829
-
830
- if response.status.code != status_code_pb2.SUCCESS:
831
- raise Exception(response.status)
832
- self.logger.info("\nDataset Deleted\n%s", response.status)
833
-
834
- def delete_model(self, model_id: str) -> None:
835
- """Deletes an model for the user.
836
-
837
- Args:
838
- model_id (str): The model ID for the app to delete.
839
-
840
- Example:
841
- >>> from clarifai.client.app import App
842
- >>> app = App(app_id="app_id", user_id="user_id")
843
- >>> app.delete_model(model_id="model_id")
844
- """
845
- request = service_pb2.DeleteModelsRequest(user_app_id=self.user_app_id, ids=[model_id])
846
- response = self._grpc_request(self.STUB.DeleteModels, request)
847
-
848
- if response.status.code != status_code_pb2.SUCCESS:
849
- raise Exception(response.status)
850
- self.logger.info("\nModel Deleted\n%s", response.status)
851
-
852
- def delete_workflow(self, workflow_id: str) -> None:
853
- """Deletes an workflow for the user.
854
-
855
- Args:
856
- workflow_id (str): The workflow ID for the app to delete.
857
-
858
- Example:
859
- >>> from clarifai.client.app import App
860
- >>> app = App(app_id="app_id", user_id="user_id")
861
- >>> app.delete_workflow(workflow_id="workflow_id")
862
- """
863
- request = service_pb2.DeleteWorkflowsRequest(user_app_id=self.user_app_id, ids=[workflow_id])
864
- response = self._grpc_request(self.STUB.DeleteWorkflows, request)
865
-
866
- if response.status.code != status_code_pb2.SUCCESS:
867
- raise Exception(response.status)
868
- self.logger.info("\nWorkflow Deleted\n%s", response.status)
869
-
870
- def delete_module(self, module_id: str) -> None:
871
- """Deletes an module for the user.
872
-
873
- Args:
874
- module_id (str): The module ID for the app to delete.
875
-
876
- Example:
877
- >>> from clarifai.client.app import App
878
- >>> app = App(app_id="app_id", user_id="user_id")
879
- >>> app.delete_module(module_id="module_id")
880
- """
881
- request = service_pb2.DeleteModulesRequest(user_app_id=self.user_app_id, ids=[module_id])
882
- response = self._grpc_request(self.STUB.DeleteModules, request)
883
-
884
- if response.status.code != status_code_pb2.SUCCESS:
885
- raise Exception(response.status)
886
- self.logger.info("\nModule Deleted\n%s", response.status)
887
-
888
- def delete_concept_relations(self, concept_id: str,
889
- concept_relation_ids: List[str] = []) -> None:
890
- """Delete concept relations of a concept of the app.
891
-
892
- Args:
893
- concept_id (str): The concept ID of the concept to delete relations for.
894
- concept_relation_ids (List[str], optional): List of concept relation IDs of concept relations.
895
-
896
- Example:
897
- >>> from clarifai.client.app import App
898
- >>> app = App(app_id="app_id", user_id="user_id")
899
- >>> app.delete_concept_relations(concept_id="concept_id", concept_relation_ids=["concept_relation_id_1", "concept_relation_id_2", ..])
900
- """
901
- if not concept_relation_ids:
902
- concept_relation_ids = [
903
- concept_relation.id
904
- for concept_relation in list(self.search_concept_relations(concept_id=concept_id))
905
- ]
906
- request = service_pb2.DeleteConceptRelationsRequest(
907
- user_app_id=self.user_app_id, concept_id=concept_id, ids=concept_relation_ids)
908
- response = self._grpc_request(self.STUB.DeleteConceptRelations, request)
909
- if response.status.code != status_code_pb2.SUCCESS:
910
- raise Exception(response.status)
911
- self.logger.info("\nConcept Relations Deleted\n%s", response.status)
912
-
913
- def search(self, **kwargs) -> Model:
914
- """Returns a Search object for the user and app ID.
915
-
916
- Args:
917
- see the Search class in clarifai.client.search for kwargs.
918
-
919
- Returns:
920
- Search: A Search object for the user and app ID.
921
-
922
- Example:
923
- >>> from clarifai.client.app import App
924
- >>> app = App(app_id="app_id", user_id="user_id")
925
- >>> search_client = app.search(top_k=12, metric="euclidean")
926
- """
927
- kwargs.get("user_id", self.user_app_id.user_id)
928
- kwargs.get("app_id", self.user_app_id.app_id)
929
- return Search.from_auth_helper(auth=self.auth_helper, **kwargs)
930
-
931
- def __getattr__(self, name):
932
- return getattr(self.app_info, name)
933
-
934
- def __str__(self):
935
- init_params = [param for param in self.kwargs.keys()]
936
- attribute_strings = [
937
- f"{param}={getattr(self.app_info, param)}" for param in init_params
938
- if hasattr(self.app_info, param)
939
- ]
940
- return f"Clarifai App Details: \n{', '.join(attribute_strings)}\n"
764
+ ):
765
+ """Returns an Input object.
766
+
767
+ Returns:
768
+ Inputs: An input object.
769
+ """
770
+ return Inputs.from_auth_helper(self.auth_helper)
771
+
772
+ def patch_dataset(self, dataset_id: str, action: str = 'merge', **kwargs) -> Dataset:
773
+ """Patches a dataset for the app.
774
+
775
+ Args:
776
+ dataset_id (str): The dataset ID for the dataset to create.
777
+ action (str): The action to perform on the dataset (merge/overwrite/remove).
778
+ **kwargs: Additional keyword arguments to be passed to patch the Dataset.
779
+
780
+ Returns:
781
+ Dataset: A Dataset object for the specified dataset ID.
782
+ """
783
+ if "visibility" in kwargs:
784
+ kwargs["visibility"] = resources_pb2.Visibility(gettable=kwargs["visibility"])
785
+ if "image_url" in kwargs:
786
+ kwargs["image"] = resources_pb2.Image(url=kwargs.pop("image_url"))
787
+ request = service_pb2.PatchDatasetsRequest(
788
+ user_app_id=self.user_app_id,
789
+ datasets=[resources_pb2.Dataset(id=dataset_id, **kwargs)],
790
+ action=action,
791
+ )
792
+ response = self._grpc_request(self.STUB.PatchDatasets, request)
793
+ if response.status.code != status_code_pb2.SUCCESS:
794
+ raise Exception(response.status)
795
+ self.logger.info("\nDataset patched\n%s", response.status)
796
+
797
+ return Dataset.from_auth_helper(self.auth_helper, dataset_id=dataset_id, **kwargs)
798
+
799
+ def patch_model(self, model_id: str, action: str = 'merge', **kwargs) -> Model:
800
+ """Patches a model of the app.
801
+
802
+ Args:
803
+ model_id (str): The model ID of the model to patch.
804
+ action (str): The action to perform on the model (merge/overwrite/remove).
805
+ **kwargs: Additional keyword arguments to be passed to patch the Model.
806
+
807
+ Returns:
808
+ Model: A Model object of the specified model ID.
809
+ """
810
+ if "visibility" in kwargs:
811
+ kwargs["visibility"] = resources_pb2.Visibility(gettable=kwargs["visibility"])
812
+ if "image_url" in kwargs:
813
+ kwargs["image"] = resources_pb2.Image(url=kwargs.pop("image_url"))
814
+ request = service_pb2.PatchModelsRequest(
815
+ user_app_id=self.user_app_id,
816
+ models=[resources_pb2.Model(id=model_id, **kwargs)],
817
+ action=action,
818
+ )
819
+ response = self._grpc_request(self.STUB.PatchModels, request)
820
+ if response.status.code != status_code_pb2.SUCCESS:
821
+ raise Exception(response.status)
822
+ self.logger.info("\nModel %s patched successfully\n%s", model_id, response.status)
823
+ kwargs.update(
824
+ {
825
+ 'model_id': model_id,
826
+ }
827
+ )
828
+
829
+ return Model.from_auth_helper(self.auth_helper, **kwargs)
830
+
831
+ def patch_workflow(
832
+ self, workflow_id: str, action: str = 'merge', config_filepath: str = None, **kwargs
833
+ ) -> Workflow:
834
+ """Patches a workflow of the app.
835
+
836
+ Args:
837
+ workflow_id (str): The Workflow ID of the workflow to patch.
838
+ action (str): The action to perform on the workflow (merge/overwrite/remove).
839
+ config_filepath (str): The path to the yaml workflow config file.
840
+ **kwargs: Additional keyword arguments to be passed to patch the Workflow.
841
+
842
+ Returns:
843
+ Workflow: A Workflow object of the specified workflow ID.
844
+ """
845
+ if config_filepath:
846
+ if not os.path.exists(config_filepath):
847
+ raise UserError(f"Workflow config file not found at {config_filepath}")
848
+ _, kwargs['nodes'] = self._process_workflow_config(config_filepath)
849
+ if "visibility" in kwargs:
850
+ kwargs["visibility"] = resources_pb2.Visibility(gettable=kwargs["visibility"])
851
+ if "image_url" in kwargs:
852
+ kwargs["image"] = resources_pb2.Image(url=kwargs.pop("image_url"))
853
+
854
+ request = service_pb2.PatchWorkflowsRequest(
855
+ user_app_id=self.user_app_id,
856
+ workflows=[resources_pb2.Workflow(id=workflow_id, **kwargs)],
857
+ action=action,
858
+ )
859
+ response = self._grpc_request(self.STUB.PatchWorkflows, request)
860
+ if response.status.code != status_code_pb2.SUCCESS:
861
+ raise Exception(response.status)
862
+ self.logger.info("\nWorkflow patched\n%s", response.status)
863
+ kwargs.update(
864
+ {
865
+ 'workflow_id': workflow_id,
866
+ }
867
+ )
868
+
869
+ return Workflow.from_auth_helper(self.auth_helper, **kwargs)
870
+
871
+ def delete_dataset(self, dataset_id: str) -> None:
872
+ """Deletes an dataset for the user.
873
+
874
+ Args:
875
+ dataset_id (str): The dataset ID for the app to delete.
876
+
877
+ Example:
878
+ >>> from clarifai.client.app import App
879
+ >>> app = App(app_id="app_id", user_id="user_id")
880
+ >>> app.delete_dataset(dataset_id="dataset_id")
881
+ """
882
+ request = service_pb2.DeleteDatasetsRequest(
883
+ user_app_id=self.user_app_id, dataset_ids=[dataset_id]
884
+ )
885
+ response = self._grpc_request(self.STUB.DeleteDatasets, request)
886
+
887
+ if response.status.code != status_code_pb2.SUCCESS:
888
+ raise Exception(response.status)
889
+ self.logger.info("\nDataset Deleted\n%s", response.status)
890
+
891
+ def delete_model(self, model_id: str) -> None:
892
+ """Deletes an model for the user.
893
+
894
+ Args:
895
+ model_id (str): The model ID for the app to delete.
896
+
897
+ Example:
898
+ >>> from clarifai.client.app import App
899
+ >>> app = App(app_id="app_id", user_id="user_id")
900
+ >>> app.delete_model(model_id="model_id")
901
+ """
902
+ request = service_pb2.DeleteModelsRequest(user_app_id=self.user_app_id, ids=[model_id])
903
+ response = self._grpc_request(self.STUB.DeleteModels, request)
904
+
905
+ if response.status.code != status_code_pb2.SUCCESS:
906
+ raise Exception(response.status)
907
+ self.logger.info("\nModel Deleted\n%s", response.status)
908
+
909
+ def delete_workflow(self, workflow_id: str) -> None:
910
+ """Deletes an workflow for the user.
911
+
912
+ Args:
913
+ workflow_id (str): The workflow ID for the app to delete.
914
+
915
+ Example:
916
+ >>> from clarifai.client.app import App
917
+ >>> app = App(app_id="app_id", user_id="user_id")
918
+ >>> app.delete_workflow(workflow_id="workflow_id")
919
+ """
920
+ request = service_pb2.DeleteWorkflowsRequest(
921
+ user_app_id=self.user_app_id, ids=[workflow_id]
922
+ )
923
+ response = self._grpc_request(self.STUB.DeleteWorkflows, request)
924
+
925
+ if response.status.code != status_code_pb2.SUCCESS:
926
+ raise Exception(response.status)
927
+ self.logger.info("\nWorkflow Deleted\n%s", response.status)
928
+
929
+ def delete_module(self, module_id: str) -> None:
930
+ """Deletes an module for the user.
931
+
932
+ Args:
933
+ module_id (str): The module ID for the app to delete.
934
+
935
+ Example:
936
+ >>> from clarifai.client.app import App
937
+ >>> app = App(app_id="app_id", user_id="user_id")
938
+ >>> app.delete_module(module_id="module_id")
939
+ """
940
+ request = service_pb2.DeleteModulesRequest(user_app_id=self.user_app_id, ids=[module_id])
941
+ response = self._grpc_request(self.STUB.DeleteModules, request)
942
+
943
+ if response.status.code != status_code_pb2.SUCCESS:
944
+ raise Exception(response.status)
945
+ self.logger.info("\nModule Deleted\n%s", response.status)
946
+
947
+ def delete_concept_relations(
948
+ self, concept_id: str, concept_relation_ids: List[str] = []
949
+ ) -> None:
950
+ """Delete concept relations of a concept of the app.
951
+
952
+ Args:
953
+ concept_id (str): The concept ID of the concept to delete relations for.
954
+ concept_relation_ids (List[str], optional): List of concept relation IDs of concept relations.
955
+
956
+ Example:
957
+ >>> from clarifai.client.app import App
958
+ >>> app = App(app_id="app_id", user_id="user_id")
959
+ >>> app.delete_concept_relations(concept_id="concept_id", concept_relation_ids=["concept_relation_id_1", "concept_relation_id_2", ..])
960
+ """
961
+ if not concept_relation_ids:
962
+ concept_relation_ids = [
963
+ concept_relation.id
964
+ for concept_relation in list(self.search_concept_relations(concept_id=concept_id))
965
+ ]
966
+ request = service_pb2.DeleteConceptRelationsRequest(
967
+ user_app_id=self.user_app_id, concept_id=concept_id, ids=concept_relation_ids
968
+ )
969
+ response = self._grpc_request(self.STUB.DeleteConceptRelations, request)
970
+ if response.status.code != status_code_pb2.SUCCESS:
971
+ raise Exception(response.status)
972
+ self.logger.info("\nConcept Relations Deleted\n%s", response.status)
973
+
974
+ def search(self, **kwargs) -> Model:
975
+ """Returns a Search object for the user and app ID.
976
+
977
+ Args:
978
+ see the Search class in clarifai.client.search for kwargs.
979
+
980
+ Returns:
981
+ Search: A Search object for the user and app ID.
982
+
983
+ Example:
984
+ >>> from clarifai.client.app import App
985
+ >>> app = App(app_id="app_id", user_id="user_id")
986
+ >>> search_client = app.search(top_k=12, metric="euclidean")
987
+ """
988
+ kwargs.get("user_id", self.user_app_id.user_id)
989
+ kwargs.get("app_id", self.user_app_id.app_id)
990
+ return Search.from_auth_helper(auth=self.auth_helper, **kwargs)
991
+
992
+ def __getattr__(self, name):
993
+ return getattr(self.app_info, name)
994
+
995
+ def __str__(self):
996
+ init_params = [param for param in self.kwargs.keys()]
997
+ attribute_strings = [
998
+ f"{param}={getattr(self.app_info, param)}"
999
+ for param in init_params
1000
+ if hasattr(self.app_info, param)
1001
+ ]
1002
+ return f"Clarifai App Details: \n{', '.join(attribute_strings)}\n"