clarifai 10.8.9__tar.gz → 10.9.1__tar.gz

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 (113) hide show
  1. {clarifai-10.8.9/clarifai.egg-info → clarifai-10.9.1}/PKG-INFO +2 -2
  2. clarifai-10.9.1/clarifai/__init__.py +1 -0
  3. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/loaders/imagenet_classification.py +5 -1
  4. clarifai-10.9.1/clarifai/runners/models/model_run_locally.py +194 -0
  5. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/models/model_upload.py +42 -27
  6. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/utils/loader.py +15 -11
  7. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/evaluation/helpers.py +10 -4
  8. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/evaluation/main.py +2 -1
  9. {clarifai-10.8.9 → clarifai-10.9.1/clarifai.egg-info}/PKG-INFO +2 -2
  10. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai.egg-info/SOURCES.txt +1 -0
  11. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai.egg-info/requires.txt +1 -1
  12. {clarifai-10.8.9 → clarifai-10.9.1}/requirements.txt +1 -1
  13. {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_app.py +7 -12
  14. {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_data_upload.py +35 -2
  15. clarifai-10.9.1/tests/test_eval.py +129 -0
  16. clarifai-10.8.9/clarifai/__init__.py +0 -1
  17. clarifai-10.8.9/tests/test_eval.py +0 -90
  18. {clarifai-10.8.9 → clarifai-10.9.1}/LICENSE +0 -0
  19. {clarifai-10.8.9 → clarifai-10.9.1}/MANIFEST.in +0 -0
  20. {clarifai-10.8.9 → clarifai-10.9.1}/README.md +0 -0
  21. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/cli.py +0 -0
  22. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/__init__.py +0 -0
  23. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/app.py +0 -0
  24. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/auth/__init__.py +0 -0
  25. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/auth/helper.py +0 -0
  26. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/auth/register.py +0 -0
  27. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/auth/stub.py +0 -0
  28. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/base.py +0 -0
  29. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/compute_cluster.py +0 -0
  30. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/dataset.py +0 -0
  31. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/deployment.py +0 -0
  32. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/input.py +0 -0
  33. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/lister.py +0 -0
  34. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/model.py +0 -0
  35. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/module.py +0 -0
  36. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/nodepool.py +0 -0
  37. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/search.py +0 -0
  38. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/user.py +0 -0
  39. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/workflow.py +0 -0
  40. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/base.py +0 -0
  41. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/dataset.py +0 -0
  42. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/input.py +0 -0
  43. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/model.py +0 -0
  44. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/rag.py +0 -0
  45. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/search.py +0 -0
  46. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/workflow.py +0 -0
  47. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/__init__.py +0 -0
  48. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/export/__init__.py +0 -0
  49. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/export/inputs_annotations.py +0 -0
  50. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/__init__.py +0 -0
  51. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/base.py +0 -0
  52. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/features.py +0 -0
  53. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/image.py +0 -0
  54. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/loaders/README.md +0 -0
  55. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/loaders/__init__.py +0 -0
  56. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/loaders/coco_captions.py +0 -0
  57. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/loaders/coco_detection.py +0 -0
  58. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/loaders/xview_detection.py +0 -0
  59. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/multimodal.py +0 -0
  60. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/text.py +0 -0
  61. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/utils.py +0 -0
  62. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/errors.py +0 -0
  63. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/models/__init__.py +0 -0
  64. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/models/api.py +0 -0
  65. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/modules/README.md +0 -0
  66. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/modules/__init__.py +0 -0
  67. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/modules/css.py +0 -0
  68. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/modules/pages.py +0 -0
  69. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/modules/style.css +0 -0
  70. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/rag/__init__.py +0 -0
  71. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/rag/rag.py +0 -0
  72. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/rag/utils.py +0 -0
  73. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/__init__.py +0 -0
  74. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/dockerfile_template/Dockerfile.cpu.template +0 -0
  75. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/dockerfile_template/Dockerfile.cuda.template +0 -0
  76. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/models/__init__.py +0 -0
  77. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/models/base_typed_model.py +0 -0
  78. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/models/model_class.py +0 -0
  79. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/models/model_runner.py +0 -0
  80. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/models/model_servicer.py +0 -0
  81. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/server.py +0 -0
  82. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/utils/__init__.py +0 -0
  83. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/utils/data_handler.py +0 -0
  84. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/utils/data_utils.py +0 -0
  85. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/utils/url_fetcher.py +0 -0
  86. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/schema/search.py +0 -0
  87. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/urls/helper.py +0 -0
  88. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/__init__.py +0 -0
  89. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/constants.py +0 -0
  90. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/evaluation/__init__.py +0 -0
  91. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/evaluation/testset_annotation_parser.py +0 -0
  92. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/logging.py +0 -0
  93. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/misc.py +0 -0
  94. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/model_train.py +0 -0
  95. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/versions.py +0 -0
  96. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/workflows/__init__.py +0 -0
  97. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/workflows/export.py +0 -0
  98. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/workflows/utils.py +0 -0
  99. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/workflows/validate.py +0 -0
  100. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai.egg-info/dependency_links.txt +0 -0
  101. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai.egg-info/entry_points.txt +0 -0
  102. {clarifai-10.8.9 → clarifai-10.9.1}/clarifai.egg-info/top_level.txt +0 -0
  103. {clarifai-10.8.9 → clarifai-10.9.1}/pyproject.toml +0 -0
  104. {clarifai-10.8.9 → clarifai-10.9.1}/setup.cfg +0 -0
  105. {clarifai-10.8.9 → clarifai-10.9.1}/setup.py +0 -0
  106. {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_auth.py +0 -0
  107. {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_misc.py +0 -0
  108. {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_model_predict.py +0 -0
  109. {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_model_train.py +0 -0
  110. {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_modules.py +0 -0
  111. {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_rag.py +0 -0
  112. {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_search.py +0 -0
  113. {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_stub.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: clarifai
3
- Version: 10.8.9
3
+ Version: 10.9.1
4
4
  Summary: Clarifai Python SDK
5
5
  Home-page: https://github.com/Clarifai/clarifai-python
6
6
  Author: Clarifai
@@ -20,7 +20,7 @@ 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.8.7
23
+ Requires-Dist: clarifai-grpc>=10.8.8
24
24
  Requires-Dist: clarifai-protocol>=0.0.6
25
25
  Requires-Dist: numpy>=1.22.0
26
26
  Requires-Dist: tqdm>=4.65.0
@@ -0,0 +1 @@
1
+ __version__ = "10.9.1"
@@ -24,6 +24,10 @@ class ImageNetDataLoader(ClarifaiDataLoader):
24
24
 
25
25
  self.load_data()
26
26
 
27
+ @property
28
+ def task(self):
29
+ return "visual_classification"
30
+
27
31
  def load_data(self):
28
32
  #Creating label map
29
33
  with open(os.path.join(self.data_dir, "LOC_synset_mapping.txt")) as _file:
@@ -54,5 +58,5 @@ class ImageNetDataLoader(ClarifaiDataLoader):
54
58
  def __getitem__(self, idx):
55
59
  return VisualClassificationFeatures(
56
60
  image_path=self.image_paths[idx],
57
- label=self.concepts[idx],
61
+ labels=self.concepts[idx],
58
62
  id=self.image_paths[idx].split('.')[0].split('/')[-1])
@@ -0,0 +1,194 @@
1
+ import argparse
2
+ import importlib.util
3
+ import inspect
4
+ import os
5
+ import shutil
6
+ import subprocess
7
+ import sys
8
+ import tempfile
9
+ import traceback
10
+ import venv
11
+
12
+ from clarifai_grpc.grpc.api import resources_pb2, service_pb2
13
+ from clarifai_grpc.grpc.api.status import status_code_pb2, status_pb2
14
+ from clarifai_protocol import BaseRunner
15
+
16
+ from clarifai.runners.models.model_upload import ModelUploader
17
+ from clarifai.utils.logging import logger
18
+
19
+
20
+ class ModelRunLocally:
21
+
22
+ def __init__(self, model_path):
23
+ self.model_path = model_path
24
+ self.requirements_file = os.path.join(self.model_path, "requirements.txt")
25
+ self.venv_dir, self.temp_dir = self.create_temp_venv()
26
+ self.python_executable = os.path.join(self.venv_dir, "bin", "python")
27
+
28
+ def create_temp_venv(self):
29
+ """Create a temporary virtual environment."""
30
+ logger.info("Creating temporary virtual environment...")
31
+ temp_dir = tempfile.mkdtemp()
32
+ venv_dir = os.path.join(temp_dir, "venv")
33
+ venv.create(venv_dir, with_pip=True)
34
+
35
+ logger.info(f"Created temporary virtual environment at {venv_dir}")
36
+ return venv_dir, temp_dir
37
+
38
+ def install_requirements(self):
39
+ """Install the dependencies from requirements.txt and Clarifai."""
40
+ pip_executable = os.path.join(self.venv_dir, "bin", "pip")
41
+ try:
42
+ logger.info(
43
+ f"Installing requirements from {self.requirements_file}... in the virtual environment {self.venv_dir}"
44
+ )
45
+ subprocess.check_call([pip_executable, "install", "-r", self.requirements_file])
46
+ logger.info("Installing Clarifai package...")
47
+ subprocess.check_call([pip_executable, "install", "clarifai"])
48
+ logger.info("Requirements installed successfully!")
49
+ except subprocess.CalledProcessError as e:
50
+ logger.error(f"Error installing requirements: {e}")
51
+ self.clean_up()
52
+ sys.exit(1)
53
+
54
+ def _get_model_runner(self):
55
+ """Dynamically import the runner class from the model file."""
56
+
57
+ # import the runner class that to be implement by the user
58
+ runner_path = os.path.join(self.model_path, "1", "model.py")
59
+
60
+ # arbitrary name given to the module to be imported
61
+ module = "runner_module"
62
+
63
+ spec = importlib.util.spec_from_file_location(module, runner_path)
64
+ runner_module = importlib.util.module_from_spec(spec)
65
+ sys.modules[module] = runner_module
66
+ spec.loader.exec_module(runner_module)
67
+
68
+ # Find all classes in the model.py file that are subclasses of BaseRunner
69
+ classes = [
70
+ cls for _, cls in inspect.getmembers(runner_module, inspect.isclass)
71
+ if issubclass(cls, BaseRunner) and cls.__module__ == runner_module.__name__
72
+ ]
73
+
74
+ # Ensure there is exactly one subclass of BaseRunner in the model.py file
75
+ if len(classes) != 1:
76
+ raise Exception("Expected exactly one subclass of BaseRunner, found: {}".format(
77
+ len(classes)))
78
+
79
+ MyRunner = classes[0]
80
+ return MyRunner
81
+
82
+ def _build_request(self):
83
+ """Create a mock inference request for testing the model."""
84
+
85
+ uploader = ModelUploader(self.model_path)
86
+ model_version_proto = uploader.get_model_version_proto()
87
+ model_version_proto.id = "model_version"
88
+
89
+ return service_pb2.PostModelOutputsRequest(
90
+ model=resources_pb2.Model(model_version=model_version_proto),
91
+ inputs=[
92
+ resources_pb2.Input(data=resources_pb2.Data(
93
+ text=resources_pb2.Text(raw="How many people live in new york?"),
94
+ image=resources_pb2.Image(url="https://samples.clarifai.com/metro-north.jpg"),
95
+ audio=resources_pb2.Audio(url="https://samples.clarifai.com/GoodMorning.wav"),
96
+ ))
97
+ ],
98
+ )
99
+
100
+ def _run_model_inference(self, runner):
101
+ """Perform inference using the runner."""
102
+ request = self._build_request()
103
+
104
+ try:
105
+ return runner.predict(request)
106
+ except Exception as e:
107
+ logger.error(f"Model Prediction failed: {e}")
108
+ traceback.print_exc()
109
+ return service_pb2.MultiOutputResponse(status=status_pb2.Status(
110
+ code=status_code_pb2.MODEL_PREDICTION_FAILED,
111
+ description="Prediction failed",
112
+ details="",
113
+ internal_details=str(e),
114
+ ))
115
+
116
+ def _run_test(self):
117
+ """Test the model locally by making a prediction."""
118
+ # validate that we have checkpoints downloaded before constructing MyRunner
119
+ uploader = ModelUploader(self.model_path)
120
+ uploader.download_checkpoints()
121
+ # construct MyRunner which will call load_model()
122
+ MyRunner = self._get_model_runner()
123
+ runner = MyRunner(
124
+ runner_id="n/a",
125
+ nodepool_id="n/a",
126
+ compute_cluster_id="n/a",
127
+ )
128
+ runner.load_model()
129
+
130
+ # send an inference.
131
+ response = self._run_model_inference(runner)
132
+ if response.outputs[0].status.code != status_code_pb2.SUCCESS:
133
+ logger.error(f"Moddel Prediction failed: {response}")
134
+ else:
135
+ logger.info(f"Model Prediction succeeded: {response}")
136
+
137
+ def test_model(self):
138
+ """Test the model by running it locally in the virtual environment."""
139
+ command = [
140
+ self.python_executable,
141
+ "-c",
142
+ f"import sys; sys.path.append('{os.path.dirname(os.path.abspath(__file__))}'); "
143
+ f"from model_run_locally import ModelRunLocally; ModelRunLocally('{self.model_path}')._run_test()",
144
+ ]
145
+ try:
146
+ logger.info("Testing the model locally...")
147
+ subprocess.check_call(command)
148
+ logger.info("Model tested successfully!")
149
+ except subprocess.CalledProcessError as e:
150
+ logger.error(f"Error testing the model: {e}")
151
+ sys.exit(1)
152
+
153
+ # run the model server
154
+ def run_model_server(self):
155
+ """Run the Clarifai Runners's model server."""
156
+
157
+ command = [
158
+ self.python_executable, "-m", "clarifai.runners.server", "--model_path", self.model_path,
159
+ "--start_dev_server"
160
+ ]
161
+ try:
162
+ logger.info(f"Starting model server with model at {self.model_path}...")
163
+ subprocess.check_call(command)
164
+ logger.info("Model server started successfully!")
165
+ except subprocess.CalledProcessError as e:
166
+ logger.error(f"Error running model server: {e}")
167
+ self.clean_up()
168
+ sys.exit(1)
169
+
170
+ def clean_up(self):
171
+ """Clean up the temporary virtual environment."""
172
+ if os.path.exists(self.temp_dir):
173
+ logger.info("Cleaning up temporary virtual environment...")
174
+ shutil.rmtree(self.temp_dir)
175
+
176
+
177
+ def main():
178
+ parser = argparse.ArgumentParser()
179
+ parser.add_argument(
180
+ '--model_path', type=str, required=True, help='Path of the model folder to upload')
181
+ args = parser.parse_args()
182
+
183
+ model_path = args.model_path
184
+ manager = ModelRunLocally(model_path)
185
+
186
+ try:
187
+ manager.install_requirements()
188
+ manager.test_model()
189
+ finally:
190
+ manager.clean_up()
191
+
192
+
193
+ if __name__ == "__main__":
194
+ main()
@@ -10,7 +10,7 @@ from google.protobuf import json_format
10
10
  from rich import print
11
11
 
12
12
  from clarifai.client import BaseClient
13
- from clarifai.runners.utils.loader import HuggingFaceLoarder
13
+ from clarifai.runners.utils.loader import HuggingFaceLoader
14
14
  from clarifai.urls.helper import ClarifaiUrlHelper
15
15
  from clarifai.utils.logging import logger
16
16
 
@@ -59,6 +59,27 @@ class ModelUploader:
59
59
  config = yaml.safe_load(file)
60
60
  return config
61
61
 
62
+ def _validate_config_checkpoints(self):
63
+ if not self.config.get("checkpoints"):
64
+ logger.info("No checkpoints specified in the config file")
65
+ return None
66
+
67
+ assert "type" in self.config.get("checkpoints"), "No loader type specified in the config file"
68
+ loader_type = self.config.get("checkpoints").get("type")
69
+ if not loader_type:
70
+ logger.info("No loader type specified in the config file for checkpoints")
71
+ assert loader_type == "huggingface", "Only huggingface loader supported for now"
72
+ if loader_type == "huggingface":
73
+ assert "repo_id" in self.config.get("checkpoints"), "No repo_id specified in the config file"
74
+ repo_id = self.config.get("checkpoints").get("repo_id")
75
+
76
+ # prefer env var for HF_TOKEN but if not provided then use the one from config.yaml if any.
77
+ if 'HF_TOKEN' in os.environ:
78
+ hf_token = os.environ['HF_TOKEN']
79
+ else:
80
+ hf_token = self.config.get("checkpoints").get("hf_token", None)
81
+ return repo_id, hf_token
82
+
62
83
  @property
63
84
  def client(self):
64
85
  if self._client is None:
@@ -180,27 +201,9 @@ class ModelUploader:
180
201
  return f"{self.folder}.tar.gz"
181
202
 
182
203
  def download_checkpoints(self):
183
- if not self.config.get("checkpoints"):
184
- logger.info("No checkpoints specified in the config file")
185
- return
186
-
187
- assert "type" in self.config.get("checkpoints"), "No loader type specified in the config file"
188
- loader_type = self.config.get("checkpoints").get("type")
189
- if not loader_type:
190
- logger.info("No loader type specified in the config file for checkpoints")
191
- assert loader_type == "huggingface", "Only huggingface loader supported for now"
192
- if loader_type == "huggingface":
193
- assert "repo_id" in self.config.get("checkpoints"), "No repo_id specified in the config file"
194
- repo_id = self.config.get("checkpoints").get("repo_id")
195
-
196
- # prefer env var for HF_TOKEN but if not provided then use the one from config.yaml if any.
197
- if 'HF_TOKEN' in os.environ:
198
- hf_token = os.environ['HF_TOKEN']
199
- else:
200
- hf_token = self.config.get("checkpoints").get("hf_token", None)
201
- assert hf_token != 'hf_token', "The default 'hf_token' is not valid. Please provide a valid token or leave that field out of config.yaml if not needed."
202
- loader = HuggingFaceLoarder(repo_id=repo_id, token=hf_token)
203
-
204
+ repo_id, hf_token = self._validate_config_checkpoints()
205
+ if repo_id and hf_token:
206
+ loader = HuggingFaceLoader(repo_id=repo_id, token=hf_token)
204
207
  success = loader.download_checkpoints(self.checkpoint_path)
205
208
 
206
209
  if not success:
@@ -232,7 +235,7 @@ class ModelUploader:
232
235
  concepts = config.get('concepts')
233
236
  logger.info(f"Updated config.yaml with {len(concepts)} concepts.")
234
237
 
235
- def _get_model_version_proto(self):
238
+ def get_model_version_proto(self):
236
239
 
237
240
  model_version_proto = resources_pb2.ModelVersion(
238
241
  pretrained_model_config=resources_pb2.PretrainedModelConfig(),
@@ -242,8 +245,7 @@ class ModelUploader:
242
245
  model_type_id = self.config.get('model').get('model_type_id')
243
246
  if model_type_id in self.CONCEPTS_REQUIRED_MODEL_TYPE:
244
247
 
245
- loader = HuggingFaceLoarder()
246
- labels = loader.fetch_labels(self.checkpoint_path)
248
+ labels = HuggingFaceLoader.fetch_labels(self.checkpoint_path)
247
249
  # sort the concepts by id and then update the config file
248
250
  labels = sorted(labels.items(), key=lambda x: int(x[0]))
249
251
 
@@ -258,6 +260,21 @@ class ModelUploader:
258
260
  file_path = f"{self.folder}.tar.gz"
259
261
  logger.info(f"Will tar it into file: {file_path}")
260
262
 
263
+ model_type_id = self.config.get('model').get('model_type_id')
264
+ repo_id, hf_token = self._validate_config_checkpoints()
265
+
266
+ loader = HuggingFaceLoader(repo_id=repo_id, token=hf_token)
267
+
268
+ if not download_checkpoints and not loader.validate_download(self.checkpoint_path) and (
269
+ model_type_id in self.CONCEPTS_REQUIRED_MODEL_TYPE) and 'concepts' not in self.config:
270
+ logger.error(
271
+ f"Model type {model_type_id} requires concepts to be specified in the config file or download the model checkpoints to infer the concepts."
272
+ )
273
+ input("Press Enter to download the checkpoints to infer the concepts and continue...")
274
+ self.download_checkpoints()
275
+
276
+ model_version_proto = self.get_model_version_proto()
277
+
261
278
  if download_checkpoints:
262
279
  tar_cmd = f"tar --exclude=*~ -czvf {self.tar_file} -C {self.folder} ."
263
280
  else: # we don't want to send the checkpoints up even if they are in the folder.
@@ -268,8 +285,6 @@ class ModelUploader:
268
285
  os.system(tar_cmd)
269
286
  logger.info("Tarring complete, about to start upload.")
270
287
 
271
- model_version_proto = self._get_model_version_proto()
272
-
273
288
  file_size = os.path.getsize(self.tar_file)
274
289
  logger.info(f"Size of the tar is: {file_size} bytes")
275
290
 
@@ -6,7 +6,9 @@ import subprocess
6
6
  from clarifai.utils.logging import logger
7
7
 
8
8
 
9
- class HuggingFaceLoarder:
9
+ class HuggingFaceLoader:
10
+
11
+ HF_DOWNLOAD_TEXT = "The 'huggingface_hub' package is not installed. Please install it using 'pip install huggingface_hub'."
10
12
 
11
13
  def __init__(self, repo_id=None, token=None):
12
14
  self.repo_id = repo_id
@@ -14,9 +16,7 @@ class HuggingFaceLoarder:
14
16
  if token:
15
17
  try:
16
18
  if importlib.util.find_spec("huggingface_hub") is None:
17
- raise ImportError(
18
- "The 'huggingface_hub' package is not installed. Please install it using 'pip install huggingface_hub'."
19
- )
19
+ raise ImportError(self.HF_DOWNLOAD_TEXT)
20
20
  os.environ['HF_TOKEN'] = token
21
21
  subprocess.run(f'huggingface-cli login --token={os.environ["HF_TOKEN"]}', shell=True)
22
22
  except Exception as e:
@@ -27,9 +27,7 @@ class HuggingFaceLoarder:
27
27
  try:
28
28
  from huggingface_hub import snapshot_download
29
29
  except ImportError:
30
- raise ImportError(
31
- "The 'huggingface_hub' package is not installed. Please install it using 'pip install huggingface_hub'."
32
- )
30
+ raise ImportError(self.HF_DOWNLOAD_TEXT)
33
31
  if os.path.exists(checkpoint_path) and self.validate_download(checkpoint_path):
34
32
  logger.info("Checkpoints already exist")
35
33
  return True
@@ -54,20 +52,26 @@ class HuggingFaceLoarder:
54
52
 
55
53
  def validate_hf_model(self,):
56
54
  # check if model exists on HF
57
-
58
- from huggingface_hub import file_exists, repo_exists
55
+ try:
56
+ from huggingface_hub import file_exists, repo_exists
57
+ except ImportError:
58
+ raise ImportError(self.HF_DOWNLOAD_TEXT)
59
59
  return repo_exists(self.repo_id) and file_exists(self.repo_id, 'config.json')
60
60
 
61
61
  def validate_download(self, checkpoint_path: str):
62
62
  # check if model exists on HF
63
- from huggingface_hub import list_repo_files
63
+ try:
64
+ from huggingface_hub import list_repo_files
65
+ except ImportError:
66
+ raise ImportError(self.HF_DOWNLOAD_TEXT)
64
67
  checkpoint_dir_files = [
65
68
  f for dp, dn, fn in os.walk(os.path.expanduser(checkpoint_path)) for f in fn
66
69
  ]
67
70
  return (len(checkpoint_dir_files) >= len(list_repo_files(self.repo_id))) and len(
68
71
  list_repo_files(self.repo_id)) > 0
69
72
 
70
- def fetch_labels(self, checkpoint_path: str):
73
+ @staticmethod
74
+ def fetch_labels(checkpoint_path: str):
71
75
  # Fetch labels for classification, detection and segmentation models
72
76
  config_path = os.path.join(checkpoint_path, 'config.json')
73
77
  with open(config_path, 'r') as f:
@@ -58,13 +58,16 @@ class _BaseEvalResultHandler:
58
58
  model: Model
59
59
  eval_data: List[resources_pb2.EvalMetrics] = field(default_factory=list)
60
60
 
61
- def evaluate_and_wait(self, dataset: Dataset):
61
+ def evaluate_and_wait(self, dataset: Dataset, eval_info: dict = None):
62
62
  from tqdm import tqdm
63
63
  dataset_id = dataset.id
64
64
  dataset_app_id = dataset.app_id
65
65
  dataset_user_id = dataset.user_id
66
66
  _ = self.model.evaluate(
67
- dataset_id=dataset_id, dataset_app_id=dataset_app_id, dataset_user_id=dataset_user_id)
67
+ dataset_id=dataset_id,
68
+ dataset_app_id=dataset_app_id,
69
+ dataset_user_id=dataset_user_id,
70
+ eval_info=eval_info)
68
71
  latest_eval = self.model.list_evaluations()[0]
69
72
  excepted = 10
70
73
  desc = f"Please wait for the evaluation process between model {self.get_model_name()} and dataset {dataset_user_id}/{dataset_app_id}/{dataset_id} to complete."
@@ -83,7 +86,10 @@ class _BaseEvalResultHandler:
83
86
  f"Model has failed to evaluate \n {latest_eval.status}.\nPlease check your dataset inputs!"
84
87
  )
85
88
 
86
- def find_eval_id(self, datasets: List[Dataset] = [], attempt_evaluate: bool = False):
89
+ def find_eval_id(self,
90
+ datasets: List[Dataset] = [],
91
+ attempt_evaluate: bool = False,
92
+ eval_info: dict = None):
87
93
  list_eval_outputs = self.model.list_evaluations()
88
94
  self.eval_data = []
89
95
  for dataset in datasets:
@@ -117,7 +123,7 @@ class _BaseEvalResultHandler:
117
123
  # if not evaluated, but user wants to proceed it
118
124
  if not _is_found:
119
125
  if attempt_evaluate:
120
- self.eval_data.append(self.evaluate_and_wait(dataset))
126
+ self.eval_data.append(self.evaluate_and_wait(dataset, eval_info=eval_info))
121
127
  # otherwise raise error
122
128
  else:
123
129
  raise Exception(
@@ -53,6 +53,7 @@ class EvalResultCompare:
53
53
  models: Union[List[Model], List[str]],
54
54
  datasets: Union[Dataset, List[Dataset], str, List[str]],
55
55
  attempt_evaluate: bool = False,
56
+ eval_info: dict = None,
56
57
  auth_kwargs: dict = {}):
57
58
  assert isinstance(models, list), ValueError("Expected list")
58
59
 
@@ -97,7 +98,7 @@ class EvalResultCompare:
97
98
  assert self.model_type == model_type, f"Can not compare when model types are different, {self.model_type} != {model_type}"
98
99
  m = make_handler_by_type(model_type)(model=model)
99
100
  logger.info(f"* {m.get_model_name(pretify=True)}")
100
- m.find_eval_id(datasets=datasets, attempt_evaluate=attempt_evaluate)
101
+ m.find_eval_id(datasets=datasets, attempt_evaluate=attempt_evaluate, eval_info=eval_info)
101
102
  self._eval_handlers.append(m)
102
103
 
103
104
  @property
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: clarifai
3
- Version: 10.8.9
3
+ Version: 10.9.1
4
4
  Summary: Clarifai Python SDK
5
5
  Home-page: https://github.com/Clarifai/clarifai-python
6
6
  Author: Clarifai
@@ -20,7 +20,7 @@ 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.8.7
23
+ Requires-Dist: clarifai-grpc>=10.8.8
24
24
  Requires-Dist: clarifai-protocol>=0.0.6
25
25
  Requires-Dist: numpy>=1.22.0
26
26
  Requires-Dist: tqdm>=4.65.0
@@ -72,6 +72,7 @@ clarifai/runners/dockerfile_template/Dockerfile.cuda.template
72
72
  clarifai/runners/models/__init__.py
73
73
  clarifai/runners/models/base_typed_model.py
74
74
  clarifai/runners/models/model_class.py
75
+ clarifai/runners/models/model_run_locally.py
75
76
  clarifai/runners/models/model_runner.py
76
77
  clarifai/runners/models/model_servicer.py
77
78
  clarifai/runners/models/model_upload.py
@@ -1,4 +1,4 @@
1
- clarifai-grpc>=10.8.7
1
+ clarifai-grpc>=10.8.8
2
2
  clarifai-protocol>=0.0.6
3
3
  numpy>=1.22.0
4
4
  tqdm>=4.65.0
@@ -1,4 +1,4 @@
1
- clarifai-grpc>=10.8.7
1
+ clarifai-grpc>=10.8.8
2
2
  clarifai-protocol>=0.0.6
3
3
  numpy>=1.22.0
4
4
  tqdm>=4.65.0
@@ -1,6 +1,5 @@
1
1
  import logging
2
2
  import os
3
- import time
4
3
  import uuid
5
4
 
6
5
  import pytest
@@ -79,6 +78,11 @@ class TestApp:
79
78
  all_apps = list(client.list_apps())
80
79
  assert len(all_apps) > 0
81
80
 
81
+ # TODO To resolve `Insufficient scopes` error
82
+ # def test_app_input_count(self, app):
83
+ # input_count = app.get_input_count()
84
+ # assert input_count == 41
85
+
82
86
  def test_get_model(self, client):
83
87
  model = client.app(app_id=MAIN_APP_ID).model(model_id=GENERAL_MODEL_ID)
84
88
  versions = list(model.list_versions())
@@ -126,8 +130,9 @@ class TestApp:
126
130
 
127
131
  def test_get_dataset(self, create_app):
128
132
  dataset = create_app.dataset(dataset_id=CREATE_DATASET_ID)
133
+ dataset.create_version()
129
134
  versions = list(dataset.list_versions())
130
- assert len(versions) == 0 #test for list_versions
135
+ assert len(versions) == 1 #test for list_versions
131
136
  assert dataset.id == CREATE_DATASET_ID and dataset.app_id == CREATE_APP_ID and dataset.user_id == CREATE_APP_USER_ID
132
137
 
133
138
  def test_get_module(self, create_app):
@@ -144,16 +149,6 @@ class TestApp:
144
149
  all_concept_relations = list(create_app.search_concept_relations(show_tree=True))
145
150
  assert len(all_concept_relations) == 1
146
151
 
147
- def test_export_dataset(self, create_app):
148
- dataset = create_app.dataset(dataset_id=CREATE_DATASET_ID)
149
- dataset_demo_version = dataset.create_version()
150
- versions = list(dataset.list_versions())
151
- time.sleep(5)
152
- dataset_demo_version.export(save_path='tests/output_demo.zip')
153
- assert len(versions) == 1 #test for create_version
154
- assert os.path.exists('tests/output_demo.zip') is True
155
- os.remove('tests/output_demo.zip')
156
-
157
152
  def test_patch_app(self, caplog):
158
153
  with caplog.at_level(logging.INFO):
159
154
  User(user_id=CREATE_APP_USER_ID).patch_app(
@@ -1,11 +1,14 @@
1
1
  import logging
2
2
  import os
3
+ import time
3
4
  import uuid
4
5
 
5
6
  import pytest
6
7
  from google.protobuf.struct_pb2 import Struct
7
8
 
8
9
  from clarifai.client.user import User
10
+ from clarifai.datasets.upload.loaders.coco_detection import COCODetectionDataLoader
11
+ from clarifai.datasets.upload.loaders.imagenet_classification import ImageNetDataLoader
9
12
  from clarifai.datasets.upload.utils import load_module_dataloader
10
13
 
11
14
  CREATE_APP_USER_ID = os.environ["CLARIFAI_USER_ID"]
@@ -25,6 +28,8 @@ AUDIO_FILE_PATH = os.path.dirname(__file__) + "/assets/sample.mp3"
25
28
  CSV_FILE_PATH = os.path.dirname(__file__) + "/assets/sample.csv"
26
29
  FOLDER_PATH = os.path.dirname(__file__) + "/assets/test"
27
30
  MODULE_DIR = os.path.dirname(__file__) + "/assets/voc"
31
+ COCO_DET_DIR = os.path.dirname(__file__) + "/assets/coco_detection"
32
+ IMAGENET_DIR = os.path.dirname(__file__) + "/assets/imagenet_classification"
28
33
  TEXTS_FOLDER_PATH = os.path.dirname(__file__) + "/assets/sample_texts"
29
34
 
30
35
 
@@ -230,14 +235,42 @@ class Testdataupload:
230
235
 
231
236
  def test_upload_dataset(self, caplog):
232
237
  dataloader = load_module_dataloader(module_dir=MODULE_DIR, split="train")
233
- self.dataset.upload_dataset(dataloader)
238
+ self.dataset.upload_dataset(dataloader, get_upload_status=True, log_warnings=True)
234
239
  uploaded_inputs = list(self.input_object.list_inputs())
235
240
  annotations = list(self.input_object.list_annotations(batch_input=uploaded_inputs))
236
241
  with caplog.at_level(logging.INFO):
237
242
  self.input_object.delete_inputs(uploaded_inputs)
238
243
  assert "Inputs Deleted" in caplog.text # Testing delete inputs action
239
244
  assert len(uploaded_inputs) == 10 # 3 inputs are uploaded from the folder
240
- assert len(annotations) == 28 # Test for list annotatoins
245
+ assert len(annotations) == 28 # Test for list annotations
246
+
247
+ def test_upload_coco_dataset(self, caplog):
248
+ dataloader = COCODetectionDataLoader(
249
+ images_dir=os.path.join(COCO_DET_DIR, "images"),
250
+ label_filepath=os.path.join(COCO_DET_DIR, "instances_default.json"))
251
+ self.dataset.upload_dataset(dataloader)
252
+ uploaded_inputs = list(self.input_object.list_inputs())
253
+ annotations = list(self.input_object.list_annotations(batch_input=uploaded_inputs))
254
+ with caplog.at_level(logging.INFO):
255
+ self.input_object.delete_inputs(uploaded_inputs)
256
+ assert "Inputs Deleted" in caplog.text # Testing delete inputs action
257
+ assert len(uploaded_inputs) == 3 # 3 inputs are uploaded from the folder
258
+ assert len(annotations) == 7 # Test for list annotations
259
+
260
+ def test_upload_imagenet_dataset(self):
261
+ dataloader = ImageNetDataLoader(data_dir=IMAGENET_DIR)
262
+ self.dataset.upload_dataset(dataloader)
263
+ uploaded_inputs = list(self.input_object.list_inputs())
264
+ annotations = list(self.input_object.list_annotations(batch_input=uploaded_inputs))
265
+ assert len(uploaded_inputs) == 10 # 10 inputs are uploaded from the folder
266
+ assert len(annotations) == 10 # Test for list annotations
267
+
268
+ def test_export_dataset(self):
269
+ dataset_demo_version = self.dataset.create_version()
270
+ time.sleep(5)
271
+ dataset_demo_version.export(save_path='tests/output_demo.zip')
272
+ assert os.path.exists('tests/output_demo.zip') is True
273
+ os.remove('tests/output_demo.zip')
241
274
 
242
275
  @classmethod
243
276
  def teardown_class(self):
@@ -0,0 +1,129 @@
1
+ import logging
2
+ import os
3
+ import time
4
+ import uuid
5
+
6
+ import pytest
7
+ from clarifai_grpc.grpc.api.status import status_code_pb2
8
+
9
+ from clarifai.client.user import User
10
+ from clarifai.utils.evaluation import EvalResultCompare
11
+
12
+ CREATE_APP_USER_ID = os.environ["CLARIFAI_USER_ID"]
13
+ NOW = uuid.uuid4().hex[:10]
14
+ CREATE_APP_ID = f"ci_input_app_{NOW}"
15
+ CREATE_DATASET_ID = "ci_input_test_dataset"
16
+ CREATE_DATASET_NEW_ID = "ci_input_test_dataset_new"
17
+ CREATE_MODEL_ID = "ci_input_test_model_1"
18
+ CSV_FILE_PATH = os.path.dirname(__file__) + "/assets/sample.csv"
19
+
20
+
21
+ def create_app():
22
+ client = User(user_id=CREATE_APP_USER_ID)
23
+ return client.create_app(app_id=CREATE_APP_ID, base_workflow="Universal")
24
+
25
+
26
+ @pytest.mark.requires_secrets
27
+ class TestEval:
28
+ """Tests for model evaluating.
29
+ """
30
+
31
+ @classmethod
32
+ def setup_class(self):
33
+ self.app = create_app()
34
+ self.input_object = self.app.inputs()
35
+ self.dataset = self.app.create_dataset(dataset_id=CREATE_DATASET_ID)
36
+ self.dataset_new = self.app.create_dataset(dataset_id=CREATE_DATASET_NEW_ID)
37
+ self.model = self.app.create_model(
38
+ model_id=CREATE_MODEL_ID, model_type_id='embedding-classifier')
39
+
40
+ def test_evaluate(self, caplog):
41
+ # Prepare dataset
42
+ self.dataset.upload_from_csv(
43
+ csv_path=CSV_FILE_PATH, input_type='text', csv_type='raw', labels=True)
44
+ dataset_version = self.dataset.create_version()
45
+ self.dataset_new.upload_from_csv(
46
+ csv_path=CSV_FILE_PATH, input_type='text', csv_type='raw', labels=True)
47
+ self.dataset_new.create_version()
48
+ concepts = [concept.id for concept in self.app.list_concepts()]
49
+ # Prepare for training
50
+ self.model.get_params(save_to='tests/assets/model_params_for_eval.yaml')
51
+ assert len(concepts) == 2 #test data upload for training
52
+ self.model.update_params(
53
+ dataset_id=CREATE_DATASET_ID,
54
+ concepts=concepts,
55
+ dataset_version_id=dataset_version.version.id)
56
+ with caplog.at_level(logging.INFO):
57
+ model_version_id = self.model.train()
58
+ assert "Model Training Started" in caplog.text #test model training
59
+
60
+ while True:
61
+ status = self.model.training_status(version_id=model_version_id, training_logs=True)
62
+ if status.code == 21106: #MODEL_TRAINING_FAILED
63
+ break
64
+ elif status.code == 21100: #MODEL_TRAINED
65
+ break
66
+ else:
67
+ time.sleep(2)
68
+
69
+ # Test eval
70
+ ## Test list eval
71
+ all_evals = self.model.list_evaluations()
72
+ assert len(all_evals) == 0
73
+
74
+ ## Test evaluate
75
+ self.model.evaluate(dataset=self.dataset, eval_id="one", eval_info={"use_kfold": False})
76
+ all_evals = self.model.list_evaluations()
77
+ assert len(all_evals) == 1
78
+
79
+ ## Test get_eval_by_id
80
+ time.time()
81
+ while True:
82
+ response1 = self.model.get_eval_by_id("one")
83
+ if (response1.status.code == status_code_pb2.MODEL_EVALUATED):
84
+ break
85
+ else:
86
+ time.sleep(2)
87
+
88
+ ## Test get_eval_by_dataset
89
+ dataset_eval = self.model.get_eval_by_dataset(dataset=self.dataset)
90
+ assert dataset_eval[0].id == "one" and dataset_eval[0].status.code == status_code_pb2.MODEL_EVALUATED
91
+
92
+ ## Test get_raw_eval
93
+ with pytest.raises(Exception) as e:
94
+ self.model.get_raw_eval(dataset=self.dataset)
95
+ assert "method only supports model types ['visual-classifier', 'text-classifier', 'visual-detector']" in str(
96
+ e.value).lower()
97
+
98
+ ## Test get_latest_eval
99
+ current_eval = self.model.get_latest_eval(
100
+ label_counts=True,
101
+ test_set=True,
102
+ binary_metrics=True,
103
+ confusion_matrix=True,
104
+ metrics_by_area=True,
105
+ metrics_by_class=True)
106
+ assert current_eval.id == "one" and current_eval.status.code == status_code_pb2.MODEL_EVALUATED
107
+
108
+ ## Test EvalResultCompare
109
+ eval_result = EvalResultCompare(
110
+ models=[self.model],
111
+ datasets=[self.dataset, self.dataset_new],
112
+ attempt_evaluate=True,
113
+ eval_info={
114
+ "use_kfold": False
115
+ })
116
+ eval_result.all('tests/eval/', overwrite=True)
117
+ assert os.path.exists('tests/eval/conf-0.5') is True
118
+
119
+ # cleanup
120
+ with caplog.at_level(logging.INFO):
121
+ self.model.delete_version(version_id=model_version_id)
122
+ assert "Model Version Deleted" in caplog.text #test model version deletion
123
+ os.remove('tests/assets/model_params_for_eval.yaml')
124
+
125
+ @classmethod
126
+ def teardown_class(self):
127
+ self.app.delete_model(model_id=CREATE_MODEL_ID)
128
+ self.app.delete_dataset(dataset_id=CREATE_DATASET_ID)
129
+ User(user_id=CREATE_APP_USER_ID).delete_app(app_id=CREATE_APP_ID)
@@ -1 +0,0 @@
1
- __version__ = "10.8.9"
@@ -1,90 +0,0 @@
1
- import logging
2
- import os
3
- import uuid
4
-
5
- import pytest
6
-
7
- from clarifai.client.user import User
8
-
9
- CREATE_APP_USER_ID = os.environ["CLARIFAI_USER_ID"]
10
- NOW = uuid.uuid4().hex[:10]
11
- CREATE_APP_ID = f"ci_input_app_{NOW}"
12
- CREATE_DATASET_ID = "ci_input_test_dataset"
13
- CREATE_MODEL_ID = "ci_input_test_model_1"
14
- CSV_FILE_PATH = os.path.dirname(__file__) + "/assets/sample.csv"
15
-
16
-
17
- def create_app():
18
- client = User(user_id=CREATE_APP_USER_ID)
19
- return client.create_app(app_id=CREATE_APP_ID, base_workflow="Empty")
20
-
21
-
22
- @pytest.mark.requires_secrets
23
- class TestEval:
24
- """Tests for model evaluating.
25
- """
26
-
27
- @classmethod
28
- def setup_class(self):
29
- self.app = create_app()
30
- self.input_object = self.app.inputs()
31
- self.dataset = self.app.create_dataset(dataset_id=CREATE_DATASET_ID)
32
- self.model = self.app.create_model(model_id=CREATE_MODEL_ID, model_type_id='text-classifier')
33
-
34
- def test_evaluate(self, caplog):
35
- # Prepare dataset
36
- self.dataset.upload_from_csv(
37
- csv_path=CSV_FILE_PATH, input_type='text', csv_type='raw', labels=True)
38
- dataset_version = self.dataset.create_version()
39
- concepts = [concept.id for concept in self.app.list_concepts()]
40
- # Prepare for training
41
- self.model.get_params(
42
- template='HF_GPTNeo_125m_lora', save_to='tests/assets/model_params_for_eval.yaml')
43
- param_info = self.model.get_param_info(param='tokenizer_config')
44
- assert param_info['param'] == 'tokenizer_config' #test get param info
45
- assert len(concepts) == 2 #test data upload for training
46
- self.model.update_params(
47
- dataset_id=CREATE_DATASET_ID,
48
- concepts=concepts,
49
- dataset_version_id=dataset_version.version.id)
50
- with caplog.at_level(logging.INFO):
51
- model_version_id = self.model.train()
52
- assert "Model Training Started" in caplog.text #test model training
53
-
54
- # Test eval
55
- ## Test list eval
56
- with pytest.raises(Exception) as e:
57
- self.model.list_evaluations()
58
- assert "model version is empty" in str(e.value).lower()
59
-
60
- self.model.model_info.model_version.id = model_version_id
61
- with pytest.raises(Exception) as e:
62
- self.model.list_evaluations()
63
- assert "model not yet trained" in str(e.value).lower()
64
- ## Test evaluate
65
- with pytest.raises(Exception) as e:
66
- self.model.evaluate(dataset_id=CREATE_DATASET_ID)
67
- assert "model not yet trained" in str(e.value).lower()
68
-
69
- ## Test get eval
70
- with pytest.raises(Exception) as e:
71
- self.model.get_latest_eval(
72
- label_counts=True,
73
- test_set=True,
74
- binary_metrics=True,
75
- confusion_matrix=True,
76
- metrics_by_area=True,
77
- metrics_by_class=True)
78
- assert "model not yet trained" in str(e.value).lower()
79
-
80
- # cleanup
81
- with caplog.at_level(logging.INFO):
82
- self.model.delete_version(version_id=model_version_id)
83
- assert "Model Version Deleted" in caplog.text #test model version deletion
84
- os.remove('tests/assets/model_params_for_eval.yaml')
85
-
86
- @classmethod
87
- def teardown_class(self):
88
- self.app.delete_dataset(dataset_id=CREATE_DATASET_ID)
89
- self.app.delete_model(model_id=CREATE_MODEL_ID)
90
- User(user_id=CREATE_APP_USER_ID).delete_app(app_id=CREATE_APP_ID)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes