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.
- {clarifai-10.8.9/clarifai.egg-info → clarifai-10.9.1}/PKG-INFO +2 -2
- clarifai-10.9.1/clarifai/__init__.py +1 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/loaders/imagenet_classification.py +5 -1
- clarifai-10.9.1/clarifai/runners/models/model_run_locally.py +194 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/models/model_upload.py +42 -27
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/utils/loader.py +15 -11
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/evaluation/helpers.py +10 -4
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/evaluation/main.py +2 -1
- {clarifai-10.8.9 → clarifai-10.9.1/clarifai.egg-info}/PKG-INFO +2 -2
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai.egg-info/SOURCES.txt +1 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai.egg-info/requires.txt +1 -1
- {clarifai-10.8.9 → clarifai-10.9.1}/requirements.txt +1 -1
- {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_app.py +7 -12
- {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_data_upload.py +35 -2
- clarifai-10.9.1/tests/test_eval.py +129 -0
- clarifai-10.8.9/clarifai/__init__.py +0 -1
- clarifai-10.8.9/tests/test_eval.py +0 -90
- {clarifai-10.8.9 → clarifai-10.9.1}/LICENSE +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/MANIFEST.in +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/README.md +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/cli.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/app.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/auth/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/auth/helper.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/auth/register.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/auth/stub.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/base.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/compute_cluster.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/dataset.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/deployment.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/input.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/lister.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/model.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/module.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/nodepool.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/search.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/user.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/client/workflow.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/base.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/dataset.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/input.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/model.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/rag.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/search.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/constants/workflow.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/export/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/export/inputs_annotations.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/base.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/features.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/image.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/loaders/README.md +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/loaders/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/loaders/coco_captions.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/loaders/coco_detection.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/loaders/xview_detection.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/multimodal.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/text.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/utils.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/errors.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/models/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/models/api.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/modules/README.md +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/modules/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/modules/css.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/modules/pages.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/modules/style.css +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/rag/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/rag/rag.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/rag/utils.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/dockerfile_template/Dockerfile.cpu.template +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/dockerfile_template/Dockerfile.cuda.template +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/models/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/models/base_typed_model.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/models/model_class.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/models/model_runner.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/models/model_servicer.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/server.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/utils/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/utils/data_handler.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/utils/data_utils.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/utils/url_fetcher.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/schema/search.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/urls/helper.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/constants.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/evaluation/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/evaluation/testset_annotation_parser.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/logging.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/misc.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/utils/model_train.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/versions.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/workflows/__init__.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/workflows/export.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/workflows/utils.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai/workflows/validate.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai.egg-info/dependency_links.txt +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai.egg-info/entry_points.txt +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/clarifai.egg-info/top_level.txt +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/pyproject.toml +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/setup.cfg +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/setup.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_auth.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_misc.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_model_predict.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_model_train.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_modules.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_rag.py +0 -0
- {clarifai-10.8.9 → clarifai-10.9.1}/tests/test_search.py +0 -0
- {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.
|
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.
|
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"
|
{clarifai-10.8.9 → clarifai-10.9.1}/clarifai/datasets/upload/loaders/imagenet_classification.py
RENAMED
@@ -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
|
-
|
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
|
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
|
-
|
184
|
-
|
185
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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,
|
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,
|
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.
|
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.
|
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,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) ==
|
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
|
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
|
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
|
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
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/dockerfile_template/Dockerfile.cpu.template
RENAMED
File without changes
|
{clarifai-10.8.9 → clarifai-10.9.1}/clarifai/runners/dockerfile_template/Dockerfile.cuda.template
RENAMED
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
|
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
|
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
|