clarifai 10.11.0__py3-none-any.whl → 10.11.2rc1__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 (164) hide show
  1. clarifai/__init__.py +1 -1
  2. clarifai/__pycache__/__init__.cpython-310.pyc +0 -0
  3. clarifai/__pycache__/errors.cpython-310.pyc +0 -0
  4. clarifai/__pycache__/versions.cpython-310.pyc +0 -0
  5. clarifai/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  6. clarifai/cli/__pycache__/base.cpython-310.pyc +0 -0
  7. clarifai/cli/__pycache__/compute_cluster.cpython-310.pyc +0 -0
  8. clarifai/cli/__pycache__/deployment.cpython-310.pyc +0 -0
  9. clarifai/cli/__pycache__/model.cpython-310.pyc +0 -0
  10. clarifai/cli/__pycache__/nodepool.cpython-310.pyc +0 -0
  11. clarifai/cli/model.py +206 -10
  12. clarifai/client/__pycache__/__init__.cpython-310.pyc +0 -0
  13. clarifai/client/__pycache__/app.cpython-310.pyc +0 -0
  14. clarifai/client/__pycache__/base.cpython-310.pyc +0 -0
  15. clarifai/client/__pycache__/dataset.cpython-310.pyc +0 -0
  16. clarifai/client/__pycache__/input.cpython-310.pyc +0 -0
  17. clarifai/client/__pycache__/lister.cpython-310.pyc +0 -0
  18. clarifai/client/__pycache__/model.cpython-310.pyc +0 -0
  19. clarifai/client/__pycache__/module.cpython-310.pyc +0 -0
  20. clarifai/client/__pycache__/runner.cpython-310.pyc +0 -0
  21. clarifai/client/__pycache__/search.cpython-310.pyc +0 -0
  22. clarifai/client/__pycache__/user.cpython-310.pyc +0 -0
  23. clarifai/client/__pycache__/workflow.cpython-310.pyc +0 -0
  24. clarifai/client/auth/__pycache__/__init__.cpython-310.pyc +0 -0
  25. clarifai/client/auth/__pycache__/helper.cpython-310.pyc +0 -0
  26. clarifai/client/auth/__pycache__/register.cpython-310.pyc +0 -0
  27. clarifai/client/auth/__pycache__/stub.cpython-310.pyc +0 -0
  28. clarifai/client/dataset.py +4 -4
  29. clarifai/client/model.py +94 -13
  30. clarifai/constants/__pycache__/dataset.cpython-310.pyc +0 -0
  31. clarifai/constants/__pycache__/model.cpython-310.pyc +0 -0
  32. clarifai/constants/__pycache__/search.cpython-310.pyc +0 -0
  33. clarifai/datasets/__pycache__/__init__.cpython-310.pyc +0 -0
  34. clarifai/datasets/export/__pycache__/__init__.cpython-310.pyc +0 -0
  35. clarifai/datasets/export/__pycache__/inputs_annotations.cpython-310.pyc +0 -0
  36. clarifai/datasets/upload/__pycache__/__init__.cpython-310.pyc +0 -0
  37. clarifai/datasets/upload/__pycache__/base.cpython-310.pyc +0 -0
  38. clarifai/datasets/upload/__pycache__/features.cpython-310.pyc +0 -0
  39. clarifai/datasets/upload/__pycache__/image.cpython-310.pyc +0 -0
  40. clarifai/datasets/upload/__pycache__/text.cpython-310.pyc +0 -0
  41. clarifai/datasets/upload/__pycache__/utils.cpython-310.pyc +0 -0
  42. clarifai/datasets/upload/features.py +1 -1
  43. clarifai/datasets/upload/multimodal.py +2 -1
  44. clarifai/datasets/upload/text.py +3 -2
  45. clarifai/models/__pycache__/__init__.cpython-310.pyc +0 -0
  46. clarifai/models/model_serving/README.md +158 -0
  47. clarifai/models/model_serving/__init__.py +14 -0
  48. clarifai/models/model_serving/__pycache__/__init__.cpython-310.pyc +0 -0
  49. clarifai/models/model_serving/__pycache__/constants.cpython-310.pyc +0 -0
  50. clarifai/models/model_serving/cli/__init__.py +12 -0
  51. clarifai/models/model_serving/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  52. clarifai/models/model_serving/cli/__pycache__/_utils.cpython-310.pyc +0 -0
  53. clarifai/models/model_serving/cli/__pycache__/base.cpython-310.pyc +0 -0
  54. clarifai/models/model_serving/cli/__pycache__/build.cpython-310.pyc +0 -0
  55. clarifai/models/model_serving/cli/__pycache__/create.cpython-310.pyc +0 -0
  56. clarifai/models/model_serving/cli/_utils.py +53 -0
  57. clarifai/models/model_serving/cli/base.py +14 -0
  58. clarifai/models/model_serving/cli/build.py +79 -0
  59. clarifai/models/model_serving/cli/clarifai_clis.py +33 -0
  60. clarifai/models/model_serving/cli/create.py +171 -0
  61. clarifai/models/model_serving/cli/example_cli.py +34 -0
  62. clarifai/models/model_serving/cli/login.py +26 -0
  63. clarifai/models/model_serving/cli/upload.py +183 -0
  64. clarifai/models/model_serving/constants.py +21 -0
  65. clarifai/models/model_serving/docs/cli.md +161 -0
  66. clarifai/models/model_serving/docs/concepts.md +229 -0
  67. clarifai/models/model_serving/docs/dependencies.md +11 -0
  68. clarifai/models/model_serving/docs/inference_parameters.md +139 -0
  69. clarifai/models/model_serving/docs/model_types.md +19 -0
  70. clarifai/models/model_serving/model_config/__init__.py +16 -0
  71. clarifai/models/model_serving/model_config/__pycache__/__init__.cpython-310.pyc +0 -0
  72. clarifai/models/model_serving/model_config/__pycache__/base.cpython-310.pyc +0 -0
  73. clarifai/models/model_serving/model_config/__pycache__/config.cpython-310.pyc +0 -0
  74. clarifai/models/model_serving/model_config/__pycache__/inference_parameter.cpython-310.pyc +0 -0
  75. clarifai/models/model_serving/model_config/__pycache__/output.cpython-310.pyc +0 -0
  76. clarifai/models/model_serving/model_config/base.py +369 -0
  77. clarifai/models/model_serving/model_config/config.py +312 -0
  78. clarifai/models/model_serving/model_config/inference_parameter.py +129 -0
  79. clarifai/models/model_serving/model_config/model_types_config/multimodal-embedder.yaml +25 -0
  80. clarifai/models/model_serving/model_config/model_types_config/text-classifier.yaml +19 -0
  81. clarifai/models/model_serving/model_config/model_types_config/text-embedder.yaml +20 -0
  82. clarifai/models/model_serving/model_config/model_types_config/text-to-image.yaml +19 -0
  83. clarifai/models/model_serving/model_config/model_types_config/text-to-text.yaml +19 -0
  84. clarifai/models/model_serving/model_config/model_types_config/visual-classifier.yaml +22 -0
  85. clarifai/models/model_serving/model_config/model_types_config/visual-detector.yaml +32 -0
  86. clarifai/models/model_serving/model_config/model_types_config/visual-embedder.yaml +19 -0
  87. clarifai/models/model_serving/model_config/model_types_config/visual-segmenter.yaml +19 -0
  88. clarifai/models/model_serving/model_config/output.py +133 -0
  89. clarifai/models/model_serving/model_config/triton/__init__.py +14 -0
  90. clarifai/models/model_serving/model_config/triton/__pycache__/__init__.cpython-310.pyc +0 -0
  91. clarifai/models/model_serving/model_config/triton/__pycache__/serializer.cpython-310.pyc +0 -0
  92. clarifai/models/model_serving/model_config/triton/__pycache__/triton_config.cpython-310.pyc +0 -0
  93. clarifai/models/model_serving/model_config/triton/__pycache__/wrappers.cpython-310.pyc +0 -0
  94. clarifai/models/model_serving/model_config/triton/serializer.py +136 -0
  95. clarifai/models/model_serving/model_config/triton/triton_config.py +182 -0
  96. clarifai/models/model_serving/model_config/triton/wrappers.py +281 -0
  97. clarifai/models/model_serving/repo_build/__init__.py +14 -0
  98. clarifai/models/model_serving/repo_build/__pycache__/__init__.cpython-310.pyc +0 -0
  99. clarifai/models/model_serving/repo_build/__pycache__/build.cpython-310.pyc +0 -0
  100. clarifai/models/model_serving/repo_build/build.py +198 -0
  101. clarifai/models/model_serving/repo_build/static_files/__pycache__/base_test.cpython-310-pytest-7.2.0.pyc +0 -0
  102. clarifai/models/model_serving/repo_build/static_files/_requirements.txt +2 -0
  103. clarifai/models/model_serving/repo_build/static_files/base_test.py +169 -0
  104. clarifai/models/model_serving/repo_build/static_files/inference.py +26 -0
  105. clarifai/models/model_serving/repo_build/static_files/sample_clarifai_config.yaml +25 -0
  106. clarifai/models/model_serving/repo_build/static_files/test.py +40 -0
  107. clarifai/models/model_serving/repo_build/static_files/triton/model.py +75 -0
  108. clarifai/models/model_serving/utils.py +31 -0
  109. clarifai/rag/__pycache__/__init__.cpython-310.pyc +0 -0
  110. clarifai/rag/__pycache__/rag.cpython-310.pyc +0 -0
  111. clarifai/rag/__pycache__/utils.cpython-310.pyc +0 -0
  112. clarifai/rag/rag.py +6 -2
  113. clarifai/runners/__pycache__/__init__.cpython-310.pyc +0 -0
  114. clarifai/runners/__pycache__/server.cpython-310.pyc +0 -0
  115. clarifai/runners/deepgram_live_transcribe.py +98 -0
  116. clarifai/runners/deepgram_live_transcribe.py~ +98 -0
  117. clarifai/runners/deepgram_runner.py +131 -0
  118. clarifai/runners/deepgram_runner.py~ +130 -0
  119. clarifai/runners/dockerfile_template/Dockerfile.cpu.template +31 -0
  120. clarifai/runners/dockerfile_template/Dockerfile.cuda.template +79 -0
  121. clarifai/runners/dockerfile_template/Dockerfile.template +2 -0
  122. clarifai/runners/example_llama2.py~ +72 -0
  123. clarifai/runners/matt_example.py +89 -0
  124. clarifai/runners/matt_example.py~ +87 -0
  125. clarifai/runners/matt_llm_example.py +129 -0
  126. clarifai/runners/matt_llm_example.py~ +128 -0
  127. clarifai/runners/models/__pycache__/__init__.cpython-310.pyc +0 -0
  128. clarifai/runners/models/__pycache__/base_typed_model.cpython-310.pyc +0 -0
  129. clarifai/runners/models/__pycache__/model_class.cpython-310.pyc +0 -0
  130. clarifai/runners/models/__pycache__/model_run_locally.cpython-310.pyc +0 -0
  131. clarifai/runners/models/__pycache__/model_runner.cpython-310.pyc +0 -0
  132. clarifai/runners/models/__pycache__/model_servicer.cpython-310.pyc +0 -0
  133. clarifai/runners/models/__pycache__/model_upload.cpython-310.pyc +0 -0
  134. clarifai/runners/models/model_run_locally.py +358 -33
  135. clarifai/runners/models/model_upload.py +116 -65
  136. clarifai/runners/server.py +2 -0
  137. clarifai/runners/utils/__pycache__/__init__.cpython-310.pyc +0 -0
  138. clarifai/runners/utils/__pycache__/const.cpython-310.pyc +0 -0
  139. clarifai/runners/utils/__pycache__/data_handler.cpython-310.pyc +0 -0
  140. clarifai/runners/utils/__pycache__/data_utils.cpython-310.pyc +0 -0
  141. clarifai/runners/utils/__pycache__/loader.cpython-310.pyc +0 -0
  142. clarifai/runners/utils/__pycache__/logging.cpython-310.pyc +0 -0
  143. clarifai/runners/utils/__pycache__/url_fetcher.cpython-310.pyc +0 -0
  144. clarifai/runners/utils/const.py +42 -0
  145. clarifai/runners/utils/loader.py +31 -16
  146. clarifai/runners/utils/logging.py +6 -0
  147. clarifai/schema/__pycache__/search.cpython-310.pyc +0 -0
  148. clarifai/urls/__pycache__/helper.cpython-310.pyc +0 -0
  149. clarifai/utils/__pycache__/__init__.cpython-310.pyc +0 -0
  150. clarifai/utils/__pycache__/logging.cpython-310.pyc +0 -0
  151. clarifai/utils/__pycache__/misc.cpython-310.pyc +0 -0
  152. clarifai/utils/__pycache__/model_train.cpython-310.pyc +0 -0
  153. clarifai/utils/logging.py +7 -0
  154. clarifai/workflows/__pycache__/__init__.cpython-310.pyc +0 -0
  155. clarifai/workflows/__pycache__/export.cpython-310.pyc +0 -0
  156. clarifai/workflows/__pycache__/utils.cpython-310.pyc +0 -0
  157. clarifai/workflows/__pycache__/validate.cpython-310.pyc +0 -0
  158. {clarifai-10.11.0.dist-info → clarifai-10.11.2rc1.dist-info}/METADATA +86 -16
  159. clarifai-10.11.2rc1.dist-info/RECORD +242 -0
  160. {clarifai-10.11.0.dist-info → clarifai-10.11.2rc1.dist-info}/WHEEL +1 -1
  161. clarifai-10.11.0.dist-info/RECORD +0 -99
  162. {clarifai-10.11.0.dist-info → clarifai-10.11.2rc1.dist-info}/LICENSE +0 -0
  163. {clarifai-10.11.0.dist-info → clarifai-10.11.2rc1.dist-info}/entry_points.txt +0 -0
  164. {clarifai-10.11.0.dist-info → clarifai-10.11.2rc1.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,6 @@
1
1
  import os
2
2
  import re
3
+ import sys
3
4
  import time
4
5
  from string import Template
5
6
 
@@ -8,8 +9,12 @@ from clarifai_grpc.grpc.api import resources_pb2, service_pb2
8
9
  from clarifai_grpc.grpc.api.status import status_code_pb2
9
10
  from google.protobuf import json_format
10
11
  from rich import print
12
+ from rich.markup import escape
11
13
 
12
14
  from clarifai.client import BaseClient
15
+ from clarifai.runners.utils.const import (AVAILABLE_PYTHON_IMAGES, AVAILABLE_TORCH_IMAGES,
16
+ CONCEPTS_REQUIRED_MODEL_TYPE, DEFAULT_PYTHON_VERSION,
17
+ PYTHON_BASE_IMAGE, TORCH_BASE_IMAGE)
13
18
  from clarifai.runners.utils.loader import HuggingFaceLoader
14
19
  from clarifai.urls.helper import ClarifaiUrlHelper
15
20
  from clarifai.utils.logging import logger
@@ -23,53 +28,18 @@ def _clear_line(n: int = 1) -> None:
23
28
 
24
29
 
25
30
  class ModelUploader:
26
- DEFAULT_PYTHON_VERSION = 3.11
27
- DEFAULT_TORCH_VERSION = '2.4.0'
28
- DEFAULT_CUDA_VERSION = '124'
29
- # List of available torch images for matrix
30
- '''
31
- python_version: ['3.8', '3.9', '3.10', '3.11']
32
- torch_version: ['2.0.0', '2.1.0', '2.2.0', '2.3.0', '2.4.0', '2.4.1', '2.5.0']
33
- cuda_version: ['124']
34
- '''
35
- AVAILABLE_TORCH_IMAGES = [
36
- '2.0.0-py3.8-cuda124',
37
- '2.0.0-py3.9-cuda124',
38
- '2.0.0-py3.10-cuda124',
39
- '2.0.0-py3.11-cuda124',
40
- '2.1.0-py3.8-cuda124',
41
- '2.1.0-py3.9-cuda124',
42
- '2.1.0-py3.10-cuda124',
43
- '2.1.0-py3.11-cuda124',
44
- '2.2.0-py3.8-cuda124',
45
- '2.2.0-py3.9-cuda124',
46
- '2.2.0-py3.10-cuda124',
47
- '2.2.0-py3.11-cuda124',
48
- '2.3.0-py3.8-cuda124',
49
- '2.3.0-py3.9-cuda124',
50
- '2.3.0-py3.10-cuda124',
51
- '2.3.0-py3.11-cuda124',
52
- '2.4.0-py3.8-cuda124',
53
- '2.4.0-py3.9-cuda124',
54
- '2.4.0-py3.10-cuda124',
55
- '2.4.0-py3.11-cuda124',
56
- '2.4.1-py3.8-cuda124',
57
- '2.4.1-py3.9-cuda124',
58
- '2.4.1-py3.10-cuda124',
59
- '2.4.1-py3.11-cuda124',
60
- ]
61
- AVAILABLE_PYTHON_IMAGES = ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
62
- PYTHON_BASE_IMAGE = 'public.ecr.aws/clarifai-models/python-base:{python_version}'
63
- TORCH_BASE_IMAGE = 'public.ecr.aws/clarifai-models/torch:{torch_version}-py{python_version}-cuda{cuda_version}'
64
-
65
- CONCEPTS_REQUIRED_MODEL_TYPE = [
66
- 'visual-classifier', 'visual-detector', 'visual-segmenter', 'text-classifier'
67
- ]
68
-
69
- def __init__(self, folder: str):
31
+
32
+ def __init__(self, folder: str, validate_api_ids: bool = True):
33
+ """
34
+ :param folder: The folder containing the model.py, config.yaml, requirements.txt and
35
+ checkpoints.
36
+ :param validate_api_ids: Whether to validate the user_id and app_id in the config file.
37
+ """
70
38
  self._client = None
71
39
  self.folder = self._validate_folder(folder)
72
40
  self.config = self._load_config(os.path.join(self.folder, 'config.yaml'))
41
+ self.validate_api_ids = validate_api_ids
42
+ self._validate_config()
73
43
  self.model_proto = self._get_model_proto()
74
44
  self.model_id = self.model_proto.id
75
45
  self.model_version_id = None
@@ -108,13 +78,64 @@ class ModelUploader:
108
78
  assert "repo_id" in self.config.get("checkpoints"), "No repo_id specified in the config file"
109
79
  repo_id = self.config.get("checkpoints").get("repo_id")
110
80
 
111
- # prefer env var for HF_TOKEN but if not provided then use the one from config.yaml if any.
112
- if 'HF_TOKEN' in os.environ:
113
- hf_token = os.environ['HF_TOKEN']
114
- else:
115
- hf_token = self.config.get("checkpoints").get("hf_token", None)
81
+ # get from config.yaml otherwise fall back to HF_TOKEN env var.
82
+ hf_token = self.config.get("checkpoints").get("hf_token", os.environ.get("HF_TOKEN", None))
116
83
  return repo_id, hf_token
117
84
 
85
+ def _check_app_exists(self):
86
+ if not self.validate_api_ids:
87
+ return True
88
+ resp = self.client.STUB.GetApp(service_pb2.GetAppRequest(user_app_id=self.client.user_app_id))
89
+ if resp.status.code == status_code_pb2.SUCCESS:
90
+ return True
91
+ return False
92
+
93
+ def _validate_config_model(self):
94
+ assert "model" in self.config, "model section not found in the config file"
95
+ model = self.config.get('model')
96
+ assert "user_id" in model, "user_id not found in the config file"
97
+ assert "app_id" in model, "app_id not found in the config file"
98
+ assert "model_type_id" in model, "model_type_id not found in the config file"
99
+ assert "id" in model, "model_id not found in the config file"
100
+ if '.' in model.get('id'):
101
+ logger.error(
102
+ "Model ID cannot contain '.', please remove it from the model_id in the config file")
103
+ sys.exit(1)
104
+
105
+ assert model.get('user_id') != "", "user_id cannot be empty in the config file"
106
+ assert model.get('app_id') != "", "app_id cannot be empty in the config file"
107
+ assert model.get('model_type_id') != "", "model_type_id cannot be empty in the config file"
108
+ assert model.get('id') != "", "model_id cannot be empty in the config file"
109
+
110
+ if not self._check_app_exists():
111
+ logger.error(
112
+ f"App {self.client.user_app_id.app_id} not found for user {self.client.user_app_id.user_id}"
113
+ )
114
+ sys.exit(1)
115
+
116
+ def _validate_config(self):
117
+ self._validate_config_model()
118
+
119
+ if self.config.get("checkpoints"):
120
+ self._validate_config_checkpoints()
121
+
122
+ assert "inference_compute_info" in self.config, "inference_compute_info not found in the config file"
123
+
124
+ if self.config.get("concepts"):
125
+ model_type_id = self.config.get('model').get('model_type_id')
126
+ assert model_type_id in CONCEPTS_REQUIRED_MODEL_TYPE, f"Model type {model_type_id} not supported for concepts"
127
+
128
+ if self.config.get("checkpoints"):
129
+ _, hf_token = self._validate_config_checkpoints()
130
+
131
+ if hf_token:
132
+ is_valid_token = HuggingFaceLoader.validate_hftoken(hf_token)
133
+ if not is_valid_token:
134
+ logger.error(
135
+ "Invalid Hugging Face token provided in the config file, this might cause issues with downloading the restricted model checkpoints."
136
+ )
137
+ logger.info("Continuing without Hugging Face token")
138
+
118
139
  @property
119
140
  def client(self):
120
141
  if self._client is None:
@@ -233,33 +254,35 @@ class ModelUploader:
233
254
  build_info = self.config.get('build_info', {})
234
255
  if 'python_version' in build_info:
235
256
  python_version = build_info['python_version']
236
- if python_version not in self.AVAILABLE_PYTHON_IMAGES:
257
+ if python_version not in AVAILABLE_PYTHON_IMAGES:
237
258
  logger.error(
238
- f"Python version {python_version} not supported, please use one of the following versions: {self.AVAILABLE_PYTHON_IMAGES}"
259
+ f"Python version {python_version} not supported, please use one of the following versions: {AVAILABLE_PYTHON_IMAGES}"
239
260
  )
240
261
  return
241
262
  logger.info(
242
263
  f"Using Python version {python_version} from the config file to build the Dockerfile")
243
264
  else:
244
265
  logger.info(
245
- f"Python version not found in the config file, using default Python version: {self.DEFAULT_PYTHON_VERSION}"
266
+ f"Python version not found in the config file, using default Python version: {DEFAULT_PYTHON_VERSION}"
246
267
  )
247
- python_version = self.DEFAULT_PYTHON_VERSION
268
+ python_version = DEFAULT_PYTHON_VERSION
248
269
 
249
- base_image = self.PYTHON_BASE_IMAGE.format(python_version=python_version)
270
+ base_image = PYTHON_BASE_IMAGE.format(python_version=python_version)
250
271
 
251
272
  # Parse the requirements.txt file to determine the base image
252
273
  dependencies = self._parse_requirements()
253
274
  if 'torch' in dependencies and dependencies['torch']:
254
275
  torch_version = dependencies['torch']
255
276
 
256
- for image in self.AVAILABLE_TORCH_IMAGES:
277
+ for image in AVAILABLE_TORCH_IMAGES:
257
278
  if torch_version in image and f'py{python_version}' in image:
258
- base_image = self.TORCH_BASE_IMAGE.format(
279
+ cuda_version = image.split('-')[-1].replace('cuda', '')
280
+ base_image = TORCH_BASE_IMAGE.format(
259
281
  torch_version=torch_version,
260
282
  python_version=python_version,
261
- cuda_version=self.DEFAULT_CUDA_VERSION)
262
- logger.info(f"Using Torch version {torch_version} base image to build the Docker image")
283
+ cuda_version=cuda_version,
284
+ )
285
+ logger.info(f"Using Torch version {torch_version} base image to build the Docker image")
263
286
  break
264
287
 
265
288
  # Replace placeholders with actual values
@@ -296,6 +319,7 @@ class ModelUploader:
296
319
 
297
320
  if not success:
298
321
  logger.error(f"Failed to download checkpoints for model {repo_id}")
322
+ sys.exit(1)
299
323
  else:
300
324
  logger.info(f"Downloaded checkpoints for model {repo_id}")
301
325
  return success
@@ -314,7 +338,7 @@ class ModelUploader:
314
338
  config = yaml.safe_load(file)
315
339
  model = config.get('model')
316
340
  model_type_id = model.get('model_type_id')
317
- assert model_type_id in self.CONCEPTS_REQUIRED_MODEL_TYPE, f"Model type {model_type_id} not supported for concepts"
341
+ assert model_type_id in CONCEPTS_REQUIRED_MODEL_TYPE, f"Model type {model_type_id} not supported for concepts"
318
342
  concept_protos = self._concepts_protos_from_concepts(labels)
319
343
 
320
344
  config['concepts'] = [{'id': concept.id, 'name': concept.name} for concept in concept_protos]
@@ -332,7 +356,7 @@ class ModelUploader:
332
356
  )
333
357
 
334
358
  model_type_id = self.config.get('model').get('model_type_id')
335
- if model_type_id in self.CONCEPTS_REQUIRED_MODEL_TYPE:
359
+ if model_type_id in CONCEPTS_REQUIRED_MODEL_TYPE:
336
360
 
337
361
  if 'concepts' in self.config:
338
362
  labels = self.config.get('concepts')
@@ -347,7 +371,10 @@ class ModelUploader:
347
371
  labels = sorted(labels.items(), key=lambda x: int(x[0]))
348
372
 
349
373
  config_file = os.path.join(self.folder, 'config.yaml')
350
- self.hf_labels_to_config(labels, config_file)
374
+ try:
375
+ self.hf_labels_to_config(labels, config_file)
376
+ except Exception as e:
377
+ logger.error(f"Failed to update the config.yaml file with the concepts: {e}")
351
378
 
352
379
  model_version_proto.output_info.data.concepts.extend(
353
380
  self._concepts_protos_from_concepts(labels))
@@ -359,7 +386,7 @@ class ModelUploader:
359
386
 
360
387
  model_type_id = self.config.get('model').get('model_type_id')
361
388
 
362
- if (model_type_id in self.CONCEPTS_REQUIRED_MODEL_TYPE) and 'concepts' not in self.config:
389
+ if (model_type_id in CONCEPTS_REQUIRED_MODEL_TYPE) and 'concepts' not in self.config:
363
390
  logger.info(
364
391
  f"Model type {model_type_id} requires concepts to be specified in the config.yaml file.."
365
392
  )
@@ -387,10 +414,10 @@ class ModelUploader:
387
414
  model_version_proto = self.get_model_version_proto()
388
415
 
389
416
  if download_checkpoints:
390
- tar_cmd = f"tar --exclude=*~ -czvf {self.tar_file} -C {self.folder} ."
417
+ tar_cmd = f"tar --exclude=*~ --exclude={self.tar_file} -czvf {self.tar_file} -C {self.folder} ."
391
418
  else: # we don't want to send the checkpoints up even if they are in the folder.
392
419
  logger.info(f"Skipping {self.checkpoint_path} in the tar file that is uploaded.")
393
- tar_cmd = f"tar --exclude={self.checkpoint_suffix} --exclude=*~ -czvf {self.tar_file} -C {self.folder} ."
420
+ tar_cmd = f"tar --exclude={self.checkpoint_suffix} --exclude=*~ --exclude={self.tar_file} -czvf {self.tar_file} -C {self.folder} ."
394
421
  # Tar the folder
395
422
  logger.debug(tar_cmd)
396
423
  os.system(tar_cmd)
@@ -400,6 +427,9 @@ class ModelUploader:
400
427
  logger.info(f"Size of the tar is: {file_size} bytes")
401
428
 
402
429
  self.maybe_create_model()
430
+ if not self.check_model_exists():
431
+ logger.error(f"Failed to create model: {self.model_proto.id}")
432
+ sys.exit(1)
403
433
 
404
434
  for response in self.client.STUB.PostModelVersionsUpload(
405
435
  self.model_version_stream_upload_iterator(model_version_proto, file_path),):
@@ -464,7 +494,7 @@ class ModelUploader:
464
494
  file_size = os.path.getsize(file_path)
465
495
  logger.info(f"Uploading model version of model {self.model_proto.id}")
466
496
  logger.info(f"Using file '{os.path.basename(file_path)}' of size: {file_size} bytes")
467
- return service_pb2.PostModelVersionsUploadRequest(
497
+ result = service_pb2.PostModelVersionsUploadRequest(
468
498
  upload_config=service_pb2.PostModelVersionsUploadConfig(
469
499
  user_app_id=self.client.user_app_id,
470
500
  model_id=self.model_proto.id,
@@ -472,9 +502,23 @@ class ModelUploader:
472
502
  total_size=file_size,
473
503
  is_v3=self.is_v3,
474
504
  ))
505
+ return result
506
+
507
+ def get_model_build_logs(self):
508
+ logs_request = service_pb2.ListLogEntriesRequest(
509
+ log_type="builder",
510
+ user_app_id=self.client.user_app_id,
511
+ model_id=self.model_proto.id,
512
+ model_version_id=self.model_version_id,
513
+ page=1,
514
+ per_page=50)
515
+ response = self.client.STUB.ListLogEntries(logs_request)
516
+
517
+ return response
475
518
 
476
519
  def monitor_model_build(self):
477
520
  st = time.time()
521
+ seen_logs = set() # To avoid duplicate log messages
478
522
  while True:
479
523
  resp = self.client.STUB.GetModelVersion(
480
524
  service_pb2.GetModelVersionRequest(
@@ -485,6 +529,13 @@ class ModelUploader:
485
529
  status_code = resp.model_version.status.code
486
530
  if status_code == status_code_pb2.MODEL_BUILDING:
487
531
  print(f"Model is building... (elapsed {time.time() - st:.1f}s)", end='\r', flush=True)
532
+
533
+ # Fetch and display the logs
534
+ logs = self.get_model_build_logs()
535
+ for log_entry in logs.log_entries:
536
+ if log_entry.url not in seen_logs:
537
+ seen_logs.add(log_entry.url)
538
+ print(f"Model Building Logs...: {escape(log_entry.message.strip())}")
488
539
  time.sleep(1)
489
540
  elif status_code == status_code_pb2.MODEL_TRAINED:
490
541
  logger.info(f"\nModel build complete! (elapsed {time.time() - st:.1f}s)")
@@ -108,6 +108,7 @@ def main():
108
108
  runner_id="n/a",
109
109
  nodepool_id="n/a",
110
110
  compute_cluster_id="n/a",
111
+ user_id="n/a",
111
112
  health_check_port=None, # not needed when running local server
112
113
  )
113
114
 
@@ -127,6 +128,7 @@ def main():
127
128
  service_pb2_grpc.add_V2Servicer_to_server(servicer, server)
128
129
  server.start()
129
130
  logger.info("Started server on port %s", parsed_args.port)
131
+ logger.info(f"Access the model at http://localhost:{parsed_args.port}")
130
132
  server.wait_for_termination()
131
133
  else: # start the runner with the proper env variables and as a runner protocol.
132
134
 
@@ -0,0 +1,42 @@
1
+ import os
2
+
3
+ registry = os.environ.get('CLARIFAI_BASE_IMAGE_REGISTRY', 'public.ecr.aws/clarifai-models')
4
+
5
+ PYTHON_BASE_IMAGE = registry + '/python-base:{python_version}'
6
+ TORCH_BASE_IMAGE = registry + '/torch:{torch_version}-py{python_version}-cuda{cuda_version}'
7
+
8
+ # List of available python base images
9
+ AVAILABLE_PYTHON_IMAGES = ['3.11', '3.12', '3.13']
10
+
11
+ DEFAULT_PYTHON_VERSION = 3.12
12
+
13
+ # List of available torch images
14
+ AVAILABLE_TORCH_IMAGES = [
15
+ '2.2.2-py3.11-cuda121',
16
+ '2.3.1-py3.11-cuda121',
17
+ '2.4.0-py3.11-cuda121',
18
+ '2.4.0-py3.11-cuda124',
19
+ '2.4.1-py3.11-cuda121',
20
+ '2.4.1-py3.11-cuda124',
21
+ '2.5.1-py3.11-cuda121',
22
+ '2.5.1-py3.11-cuda124',
23
+ '2.2.2-py3.12-cuda121',
24
+ '2.3.1-py3.12-cuda121',
25
+ '2.4.0-py3.12-cuda121',
26
+ '2.4.0-py3.12-cuda124',
27
+ '2.4.1-py3.12-cuda121',
28
+ '2.4.1-py3.12-cuda124',
29
+ '2.5.1-py3.12-cuda121',
30
+ '2.5.1-py3.12-cuda124',
31
+ # '2.2.2-py3.13-cuda121',
32
+ # '2.3.1-py3.13-cuda121',
33
+ # '2.4.0-py3.13-cuda121',
34
+ # '2.4.0-py3.13-cuda124',
35
+ # '2.4.1-py3.13-cuda121',
36
+ # '2.4.1-py3.13-cuda124',
37
+ # '2.5.1-py3.13-cuda121',
38
+ # '2.5.1-py3.13-cuda124',
39
+ ]
40
+ CONCEPTS_REQUIRED_MODEL_TYPE = [
41
+ 'visual-classifier', 'visual-detector', 'visual-segmenter', 'text-classifier'
42
+ ]
@@ -14,26 +14,32 @@ class HuggingFaceLoader:
14
14
  self.repo_id = repo_id
15
15
  self.token = token
16
16
  if token:
17
- try:
18
- if importlib.util.find_spec("huggingface_hub") is None:
19
- raise ImportError(self.HF_DOWNLOAD_TEXT)
20
- os.environ['HF_TOKEN'] = token
21
- from huggingface_hub import HfApi
22
-
23
- api = HfApi()
24
- api.whoami(token=token)
25
-
17
+ if self.validate_hftoken(token):
26
18
  subprocess.run(f'huggingface-cli login --token={os.environ["HF_TOKEN"]}', shell=True)
27
- except Exception as e:
28
- logger.error(
29
- f"Error setting up Hugging Face token, please make sure you have the correct token: {e}"
30
- )
19
+ logger.info("Hugging Face token validated")
20
+ else:
31
21
  logger.info("Continuing without Hugging Face token")
32
22
 
23
+ @classmethod
24
+ def validate_hftoken(cls, hf_token: str):
25
+ try:
26
+ if importlib.util.find_spec("huggingface_hub") is None:
27
+ raise ImportError(cls.HF_DOWNLOAD_TEXT)
28
+ os.environ['HF_TOKEN'] = hf_token
29
+ from huggingface_hub import HfApi
30
+
31
+ api = HfApi()
32
+ api.whoami(token=hf_token)
33
+ return True
34
+ except Exception as e:
35
+ logger.error(
36
+ f"Error setting up Hugging Face token, please make sure you have the correct token: {e}")
37
+ return False
38
+
33
39
  def download_checkpoints(self, checkpoint_path: str):
34
40
  # throw error if huggingface_hub wasn't installed
35
41
  try:
36
- from huggingface_hub import snapshot_download
42
+ from huggingface_hub import list_repo_files, snapshot_download
37
43
  except ImportError:
38
44
  raise ImportError(self.HF_DOWNLOAD_TEXT)
39
45
  if os.path.exists(checkpoint_path) and self.validate_download(checkpoint_path):
@@ -46,10 +52,19 @@ class HuggingFaceLoader:
46
52
  if not is_hf_model_exists:
47
53
  logger.error("Model %s not found on Hugging Face" % (self.repo_id))
48
54
  return False
55
+
56
+ ignore_patterns = None # Download everything.
57
+ repo_files = list_repo_files(repo_id=self.repo_id, token=self.token)
58
+ if any(f.endswith(".safetensors") for f in repo_files):
59
+ logger.info(f"SafeTensors found in {self.repo_id}, downloading only .safetensors files.")
60
+ ignore_patterns = ["**/original/*", "**/*.pth", "**/*.bin"]
49
61
  snapshot_download(
50
- repo_id=self.repo_id, local_dir=checkpoint_path, local_dir_use_symlinks=False)
62
+ repo_id=self.repo_id,
63
+ local_dir=checkpoint_path,
64
+ local_dir_use_symlinks=False,
65
+ ignore_patterns=ignore_patterns)
51
66
  except Exception as e:
52
- logger.exception(f"Error downloading model checkpoints {e}")
67
+ logger.error(f"Error downloading model checkpoints {e}")
53
68
  return False
54
69
  finally:
55
70
  is_downloaded = self.validate_download(checkpoint_path)
@@ -0,0 +1,6 @@
1
+ import os
2
+
3
+ from clarifai.utils.logging import get_logger
4
+
5
+ logger_level = os.environ.get("LOG_LEVEL", "INFO")
6
+ logger = get_logger(logger_level, __name__)
clarifai/utils/logging.py CHANGED
@@ -282,6 +282,11 @@ class JsonFormatter(logging.Formatter):
282
282
  except Exception:
283
283
  self.source_host = ""
284
284
 
285
+ self.extra_blacklist_fields = []
286
+ extra_blacklist_fields = os.getenv('EXTRA_JSON_LOGGER_BLACKLIST_FIELDS', None)
287
+ if extra_blacklist_fields:
288
+ self.extra_blacklist_fields = extra_blacklist_fields.split(",")
289
+
285
290
  def _build_fields(self, defaults, fields):
286
291
  """Return provided fields including any in defaults
287
292
  """
@@ -302,6 +307,8 @@ class JsonFormatter(logging.Formatter):
302
307
  msg = record.getMessage()
303
308
  for k in FIELD_BLACKLIST:
304
309
  fields.pop(k, None)
310
+ for k in self.extra_blacklist_fields:
311
+ fields.pop(k, None)
305
312
  # Rename 'levelname' to 'level' and make the value lowercase to match Go logs
306
313
  level = fields.pop('levelname', None)
307
314
  if level:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: clarifai
3
- Version: 10.11.0
3
+ Version: 10.11.2rc1
4
4
  Summary: Clarifai Python SDK
5
5
  Home-page: https://github.com/Clarifai/clarifai-python
6
6
  Author: Clarifai
@@ -20,22 +20,21 @@ Classifier: Operating System :: OS Independent
20
20
  Requires-Python: >=3.8
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: clarifai-grpc>=10.10.2
24
- Requires-Dist: clarifai-protocol>=0.0.6
25
- Requires-Dist: numpy>=1.22.0
26
- Requires-Dist: tqdm>=4.65.0
27
- Requires-Dist: tritonclient>=2.34.0
28
- Requires-Dist: rich>=13.4.2
29
- Requires-Dist: PyYAML>=6.0.1
30
- Requires-Dist: schema==0.7.5
31
- Requires-Dist: Pillow>=9.5.0
32
- Requires-Dist: inquirerpy==0.3.4
33
- Requires-Dist: tabulate>=0.9.0
34
- Requires-Dist: protobuf==5.27.3
35
- Requires-Dist: fsspec==2024.6.1
36
- Requires-Dist: click==8.1.7
23
+ Requires-Dist: clarifai-grpc >=11.0.0
24
+ Requires-Dist: clarifai-protocol >=0.0.14
25
+ Requires-Dist: numpy >=1.22.0
26
+ Requires-Dist: tqdm >=4.65.0
27
+ Requires-Dist: tritonclient >=2.34.0
28
+ Requires-Dist: rich >=13.4.2
29
+ Requires-Dist: PyYAML >=6.0.1
30
+ Requires-Dist: schema ==0.7.5
31
+ Requires-Dist: Pillow >=9.5.0
32
+ Requires-Dist: inquirerpy ==0.3.4
33
+ Requires-Dist: tabulate >=0.9.0
34
+ Requires-Dist: fsspec ==2024.6.1
35
+ Requires-Dist: click ==8.1.7
37
36
  Provides-Extra: all
38
- Requires-Dist: pycocotools==2.0.6; extra == "all"
37
+ Requires-Dist: pycocotools ==2.0.6 ; extra == 'all'
39
38
 
40
39
  <h1 align="center">
41
40
  <a href="https://www.clarifai.com/"><img alt="Clarifai" title="Clarifai" src="https://github.com/user-attachments/assets/623b883b-7fe5-4b95-bbfa-8691f5779af4"></a>
@@ -73,6 +72,10 @@ Give the repo a star ⭐
73
72
 
74
73
  * **[Installation](#rocket-installation)**
75
74
  * **[Getting Started](#memo-getting-started)**
75
+ * **[Compute Orchestration](#rocket-compute-orchestration)**
76
+ * [Cluster Operations](#cluster-operations)
77
+ * [Nodepool Operations](#nodepool-operations)
78
+ * [Depolyment Operations](#deployment-operations)
76
79
  * **[Interacting with Datasets](#floppy_disk-interacting-with-datasets)**
77
80
  * **[Interacting with Inputs](#floppy_disk-interacting-with-inputs)**
78
81
  * [Input Upload](#input-upload)
@@ -157,6 +160,73 @@ client = User(user_id="user_id", pat="your personal access token")
157
160
  ```
158
161
 
159
162
 
163
+ ## :rocket: Compute Orchestration
164
+
165
+ Clarifai’s Compute Orchestration offers a streamlined solution for managing the infrastructure required for training, deploying, and scaling machine learning models and workflows.
166
+
167
+ This flexible system supports any compute instance — across various hardware providers and deployment methods — and provides automatic scaling to match workload demands. [More Details](https://www.clarifai.com/products/compute-orchestration)
168
+
169
+ #### Cluster Operations
170
+ ```python
171
+ from clarifai.client.user import User
172
+ client = User(user_id="user_id",base_url="https://api.clarifai.com")
173
+
174
+ # Create a new compute cluster
175
+ compute_cluster = client.create_compute_cluster(compute_cluster_id="demo-id",config_filepath="computer_cluster_config.yaml")
176
+
177
+ # List Clusters
178
+ all_compute_clusters = list(client.list_compute_clusters())
179
+ print(all_compute_clusters)
180
+ ```
181
+ ##### [Example Cluster Config](https://github.com/Clarifai/examples/blob/main/ComputeOrchestration/configs/compute_cluster_config.yaml)
182
+
183
+
184
+
185
+ #### Nodepool Operations
186
+ ```python
187
+ from clarifai.client.compute_cluster import ComputeCluster
188
+
189
+ # Initialize the ComputeCluster instance
190
+ compute_cluster = ComputeCluster(user_id="user_id",compute_cluster_id="demo-id")
191
+
192
+ # Create a new nodepool
193
+ nodepool = compute_cluster.create_nodepool(nodepool_id="demo-nodepool-id",config_filepath="nodepool_config.yaml")
194
+
195
+ #Get a nodepool
196
+ nodepool = compute_cluster.nodepool(nodepool_id="demo-nodepool-id")
197
+ print(nodepool)
198
+
199
+ # List nodepools
200
+ all_nodepools = list(compute_cluster.list_nodepools())
201
+ print(all_nodepools)
202
+ ```
203
+ ##### [Example Nodepool config](https://github.com/Clarifai/examples/blob/main/ComputeOrchestration/configs/nodepool_config.yaml)
204
+
205
+ #### Deployment Operations
206
+ ```python
207
+ from clarifai.client.nodepool import Nodepool
208
+
209
+ # Initialize the Nodepool instance
210
+ nodepool = Nodepool(user_id="user_id",nodepool_id="demo-nodepool-id")
211
+
212
+ # Create a new deployment
213
+ deployment = nodepool.create_deployment(deployment_id="demo-deployment-id",config_filepath="deployment_config.yaml")
214
+
215
+ #Get a deployment
216
+ deployment = nodepool.deployment(nodepool_id="demo-deployment-id")
217
+ print(deployment)
218
+
219
+ # List deployments
220
+ all_deployments = list(nodepool.list_deployments())
221
+ print(all_deployments)
222
+
223
+ ```
224
+ ##### [Example Deployment config](https://github.com/Clarifai/examples/blob/main/ComputeOrchestration/configs/deployment_config.yaml)
225
+
226
+ #### Compute Orchestration CLI Operations
227
+ Refer Here: https://github.com/Clarifai/clarifai-python/tree/master/clarifai/cli
228
+
229
+
160
230
  ## :floppy_disk: Interacting with Datasets
161
231
 
162
232
  Clarifai datasets help in managing datasets used for model training and evaluation. It provides functionalities like creating datasets,uploading datasets, retrying failed uploads from logs and exporting datasets as .zip files.