clarifai 10.0.1__py3-none-any.whl → 10.1.1__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.
- clarifai/client/app.py +23 -43
- clarifai/client/base.py +46 -4
- clarifai/client/dataset.py +85 -33
- clarifai/client/input.py +35 -7
- clarifai/client/model.py +192 -11
- clarifai/client/module.py +8 -6
- clarifai/client/runner.py +3 -1
- clarifai/client/search.py +6 -3
- clarifai/client/user.py +14 -12
- clarifai/client/workflow.py +8 -5
- clarifai/datasets/upload/features.py +3 -0
- clarifai/datasets/upload/image.py +57 -26
- clarifai/datasets/upload/loaders/README.md +3 -4
- clarifai/datasets/upload/loaders/xview_detection.py +9 -5
- clarifai/datasets/upload/utils.py +23 -7
- clarifai/models/model_serving/README.md +113 -121
- clarifai/models/model_serving/__init__.py +2 -0
- clarifai/models/model_serving/cli/_utils.py +53 -0
- clarifai/models/model_serving/cli/base.py +14 -0
- clarifai/models/model_serving/cli/build.py +79 -0
- clarifai/models/model_serving/cli/clarifai_clis.py +33 -0
- clarifai/models/model_serving/cli/create.py +171 -0
- clarifai/models/model_serving/cli/example_cli.py +34 -0
- clarifai/models/model_serving/cli/login.py +26 -0
- clarifai/models/model_serving/cli/upload.py +182 -0
- clarifai/models/model_serving/constants.py +20 -0
- clarifai/models/model_serving/docs/cli.md +150 -0
- clarifai/models/model_serving/docs/concepts.md +229 -0
- clarifai/models/model_serving/docs/dependencies.md +1 -1
- clarifai/models/model_serving/docs/inference_parameters.md +112 -107
- clarifai/models/model_serving/docs/model_types.md +16 -17
- clarifai/models/model_serving/model_config/__init__.py +4 -2
- clarifai/models/model_serving/model_config/base.py +369 -0
- clarifai/models/model_serving/model_config/config.py +219 -224
- clarifai/models/model_serving/model_config/inference_parameter.py +5 -0
- clarifai/models/model_serving/model_config/model_types_config/multimodal-embedder.yaml +25 -24
- clarifai/models/model_serving/model_config/model_types_config/text-classifier.yaml +19 -18
- clarifai/models/model_serving/model_config/model_types_config/text-embedder.yaml +20 -18
- clarifai/models/model_serving/model_config/model_types_config/text-to-image.yaml +19 -18
- clarifai/models/model_serving/model_config/model_types_config/text-to-text.yaml +19 -18
- clarifai/models/model_serving/model_config/model_types_config/visual-classifier.yaml +22 -18
- clarifai/models/model_serving/model_config/model_types_config/visual-detector.yaml +32 -28
- clarifai/models/model_serving/model_config/model_types_config/visual-embedder.yaml +19 -18
- clarifai/models/model_serving/model_config/model_types_config/visual-segmenter.yaml +19 -18
- clarifai/models/model_serving/{models → model_config}/output.py +8 -0
- clarifai/models/model_serving/model_config/triton/__init__.py +14 -0
- clarifai/models/model_serving/model_config/{serializer.py → triton/serializer.py} +3 -1
- clarifai/models/model_serving/model_config/triton/triton_config.py +182 -0
- clarifai/models/model_serving/{models/model_types.py → model_config/triton/wrappers.py} +4 -4
- clarifai/models/model_serving/{models → repo_build}/__init__.py +2 -0
- clarifai/models/model_serving/repo_build/build.py +198 -0
- clarifai/models/model_serving/repo_build/static_files/_requirements.txt +2 -0
- clarifai/models/model_serving/repo_build/static_files/base_test.py +169 -0
- clarifai/models/model_serving/repo_build/static_files/inference.py +26 -0
- clarifai/models/model_serving/repo_build/static_files/sample_clarifai_config.yaml +25 -0
- clarifai/models/model_serving/repo_build/static_files/test.py +40 -0
- clarifai/models/model_serving/{models/pb_model.py → repo_build/static_files/triton/model.py} +15 -14
- clarifai/models/model_serving/utils.py +21 -0
- clarifai/rag/rag.py +67 -23
- clarifai/rag/utils.py +21 -5
- clarifai/utils/evaluation/__init__.py +427 -0
- clarifai/utils/evaluation/helpers.py +522 -0
- clarifai/utils/logging.py +7 -0
- clarifai/utils/model_train.py +3 -1
- clarifai/versions.py +1 -1
- {clarifai-10.0.1.dist-info → clarifai-10.1.1.dist-info}/METADATA +58 -10
- clarifai-10.1.1.dist-info/RECORD +115 -0
- clarifai-10.1.1.dist-info/entry_points.txt +2 -0
- clarifai/datasets/upload/loaders/coco_segmentation.py +0 -98
- clarifai/models/model_serving/cli/deploy_cli.py +0 -123
- clarifai/models/model_serving/cli/model_zip.py +0 -61
- clarifai/models/model_serving/cli/repository.py +0 -89
- clarifai/models/model_serving/docs/custom_config.md +0 -33
- clarifai/models/model_serving/docs/output.md +0 -28
- clarifai/models/model_serving/models/default_test.py +0 -281
- clarifai/models/model_serving/models/inference.py +0 -50
- clarifai/models/model_serving/models/test.py +0 -64
- clarifai/models/model_serving/pb_model_repository.py +0 -108
- clarifai-10.0.1.dist-info/RECORD +0 -103
- clarifai-10.0.1.dist-info/entry_points.txt +0 -4
- {clarifai-10.0.1.dist-info → clarifai-10.1.1.dist-info}/LICENSE +0 -0
- {clarifai-10.0.1.dist-info → clarifai-10.1.1.dist-info}/WHEEL +0 -0
- {clarifai-10.0.1.dist-info → clarifai-10.1.1.dist-info}/top_level.txt +0 -0
clarifai/client/model.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import os
|
2
2
|
import time
|
3
|
-
from typing import Any, Dict, Generator, List
|
3
|
+
from typing import Any, Dict, Generator, List, Union
|
4
4
|
|
5
5
|
import requests
|
6
6
|
import yaml
|
@@ -32,6 +32,7 @@ class Model(Lister, BaseClient):
|
|
32
32
|
model_version: Dict = {'id': ""},
|
33
33
|
base_url: str = "https://api.clarifai.com",
|
34
34
|
pat: str = None,
|
35
|
+
token: str = None,
|
35
36
|
**kwargs):
|
36
37
|
"""Initializes a Model object.
|
37
38
|
|
@@ -41,6 +42,7 @@ class Model(Lister, BaseClient):
|
|
41
42
|
model_version (dict): The Model Version to interact with.
|
42
43
|
base_url (str): Base API url. Default "https://api.clarifai.com"
|
43
44
|
pat (str): A personal access token for authentication. Can be set as env var CLARIFAI_PAT
|
45
|
+
token (str): A session token for authentication. Accepts either a session token or a pat. Can be set as env var CLARIFAI_SESSION_TOKEN
|
44
46
|
**kwargs: Additional keyword arguments to be passed to the Model.
|
45
47
|
"""
|
46
48
|
if url and model_id:
|
@@ -53,9 +55,10 @@ class Model(Lister, BaseClient):
|
|
53
55
|
kwargs = {'user_id': user_id, 'app_id': app_id}
|
54
56
|
self.kwargs = {**kwargs, 'id': model_id, 'model_version': model_version,}
|
55
57
|
self.model_info = resources_pb2.Model(**self.kwargs)
|
56
|
-
self.logger = get_logger(logger_level="INFO")
|
58
|
+
self.logger = get_logger(logger_level="INFO", name=__name__)
|
57
59
|
self.training_params = {}
|
58
|
-
BaseClient.__init__(
|
60
|
+
BaseClient.__init__(
|
61
|
+
self, user_id=self.user_id, app_id=self.app_id, base=base_url, pat=pat, token=token)
|
59
62
|
Lister.__init__(self)
|
60
63
|
|
61
64
|
def list_training_templates(self) -> List[str]:
|
@@ -212,6 +215,8 @@ class Model(Lister, BaseClient):
|
|
212
215
|
>>> model_params = model.get_params(template='template', yaml_file='model_params.yaml')
|
213
216
|
>>> model.train('model_params.yaml')
|
214
217
|
"""
|
218
|
+
if not self.model_info.model_type_id:
|
219
|
+
self.load_info()
|
215
220
|
if self.model_info.model_type_id not in TRAINABLE_MODEL_TYPES:
|
216
221
|
raise UserError(f"Model type {self.model_info.model_type_id} is not trainable")
|
217
222
|
if not yaml_file and len(self.training_params) == 0:
|
@@ -222,8 +227,10 @@ class Model(Lister, BaseClient):
|
|
222
227
|
params_dict = yaml.safe_load(file)
|
223
228
|
else:
|
224
229
|
params_dict = self.training_params
|
225
|
-
|
226
|
-
|
230
|
+
#getting all the concepts for the model type
|
231
|
+
if self.model_info.model_type_id not in ["clusterer", "text-to-text"]:
|
232
|
+
concepts = self._list_concepts()
|
233
|
+
train_dict = params_parser(params_dict, concepts)
|
227
234
|
request = service_pb2.PostModelVersionsRequest(
|
228
235
|
user_app_id=self.user_app_id,
|
229
236
|
model_id=self.id,
|
@@ -331,7 +338,7 @@ class Model(Lister, BaseClient):
|
|
331
338
|
dict_response = MessageToDict(response, preserving_proto_field_name=True)
|
332
339
|
kwargs = self.process_response_keys(dict_response['model'], 'model')
|
333
340
|
|
334
|
-
return Model(base_url=self.base, pat=self.pat, **kwargs)
|
341
|
+
return Model(base_url=self.base, pat=self.pat, token=self.token, **kwargs)
|
335
342
|
|
336
343
|
def list_versions(self, page_no: int = None,
|
337
344
|
per_page: int = None) -> Generator['Model', None, None]:
|
@@ -373,11 +380,8 @@ class Model(Lister, BaseClient):
|
|
373
380
|
del model_version_info['train_info']['dataset']['version']['metrics']
|
374
381
|
except KeyError:
|
375
382
|
pass
|
376
|
-
yield Model(
|
377
|
-
model_id=self.id,
|
378
|
-
base_url=self.base,
|
379
|
-
pat=self.pat,
|
380
|
-
**dict(self.kwargs, model_version=model_version_info))
|
383
|
+
yield Model.from_auth_helper(
|
384
|
+
model_id=self.id, **dict(self.kwargs, model_version=model_version_info))
|
381
385
|
|
382
386
|
def predict(self, inputs: List[Input], inference_params: Dict = {}, output_config: Dict = {}):
|
383
387
|
"""Predicts the model based on the given inputs.
|
@@ -548,6 +552,17 @@ class Model(Lister, BaseClient):
|
|
548
552
|
resources_pb2.OutputInfo(
|
549
553
|
output_config=resources_pb2.OutputConfig(**output_config), params=params))
|
550
554
|
|
555
|
+
def _list_concepts(self) -> List[str]:
|
556
|
+
"""Lists all the concepts for the model type.
|
557
|
+
|
558
|
+
Returns:
|
559
|
+
concepts (List): List of concepts for the model type.
|
560
|
+
"""
|
561
|
+
request_data = dict(user_app_id=self.user_app_id)
|
562
|
+
all_concepts_infos = self.list_pages_generator(self.STUB.ListConcepts,
|
563
|
+
service_pb2.ListConceptsRequest, request_data)
|
564
|
+
return [concept_info['concept_id'] for concept_info in all_concepts_infos]
|
565
|
+
|
551
566
|
def load_info(self) -> None:
|
552
567
|
"""Loads the model info."""
|
553
568
|
request = service_pb2.GetModelRequest(
|
@@ -576,3 +591,169 @@ class Model(Lister, BaseClient):
|
|
576
591
|
if hasattr(self.model_info, param)
|
577
592
|
]
|
578
593
|
return f"Model Details: \n{', '.join(attribute_strings)}\n"
|
594
|
+
|
595
|
+
def list_evaluations(self) -> resources_pb2.EvalMetrics:
|
596
|
+
"""List all eval_metrics of current model version
|
597
|
+
|
598
|
+
Raises:
|
599
|
+
Exception: Failed to call API
|
600
|
+
|
601
|
+
Returns:
|
602
|
+
resources_pb2.EvalMetrics
|
603
|
+
"""
|
604
|
+
assert self.model_info.model_version.id, "Model version is empty. Please provide `model_version` as arguments or with a URL as the format '{user_id}/{app_id}/models/{your_model_id}/model_version_id/{your_version_model_id}' when initializing."
|
605
|
+
request = service_pb2.ListModelVersionEvaluationsRequest(
|
606
|
+
user_app_id=self.user_app_id,
|
607
|
+
model_id=self.id,
|
608
|
+
model_version_id=self.model_info.model_version.id)
|
609
|
+
response = self._grpc_request(self.STUB.ListModelVersionEvaluations, request)
|
610
|
+
|
611
|
+
if response.status.code != status_code_pb2.SUCCESS:
|
612
|
+
raise Exception(response.status)
|
613
|
+
|
614
|
+
return response.eval_metrics
|
615
|
+
|
616
|
+
def evaluate(self,
|
617
|
+
dataset_id: str,
|
618
|
+
dataset_app_id: str = None,
|
619
|
+
dataset_user_id: str = None,
|
620
|
+
eval_id: str = None,
|
621
|
+
extended_metrics: dict = None,
|
622
|
+
eval_info: dict = None) -> resources_pb2.EvalMetrics:
|
623
|
+
""" Run evaluation
|
624
|
+
|
625
|
+
Args:
|
626
|
+
dataset_id (str): Dataset Id.
|
627
|
+
dataset_app_id (str): App ID for cross app evaluation, leave it as None to use Model App ID. Default is None.
|
628
|
+
dataset_user_id (str): User ID for cross app evaluation, leave it as None to use Model User ID. Default is None.
|
629
|
+
eval_id (str): Specific ID for the evaluation. You must specify this parameter to either overwrite the result with the dataset ID or format your evaluation in an informative manner. If you don't, it will use random ID from system. Default is None.
|
630
|
+
extended_metrics (dict): user custom metrics result. Default is None.
|
631
|
+
eval_info (dict): custom eval info. Default is empty dict.
|
632
|
+
|
633
|
+
Return
|
634
|
+
eval_metrics
|
635
|
+
|
636
|
+
"""
|
637
|
+
assert self.model_info.model_version.id, "Model version is empty. Please provide `model_version` as arguments or with a URL as the format '{user_id}/{app_id}/models/{your_model_id}/model_version_id/{your_version_model_id}' when initializing."
|
638
|
+
metrics = None
|
639
|
+
if isinstance(extended_metrics, dict):
|
640
|
+
metrics = Struct()
|
641
|
+
metrics.update(extended_metrics)
|
642
|
+
metrics = resources_pb2.ExtendedMetrics(user_metrics=metrics)
|
643
|
+
|
644
|
+
eval_info_params = None
|
645
|
+
if isinstance(eval_info, dict):
|
646
|
+
eval_info_params = Struct()
|
647
|
+
eval_info_params.update(eval_info)
|
648
|
+
eval_info_params = resources_pb2.EvalInfo(params=eval_info_params)
|
649
|
+
|
650
|
+
eval_metric = resources_pb2.EvalMetrics(
|
651
|
+
id=eval_id,
|
652
|
+
model=resources_pb2.Model(
|
653
|
+
id=self.id,
|
654
|
+
app_id=self.auth_helper.app_id,
|
655
|
+
user_id=self.auth_helper.user_id,
|
656
|
+
model_version=resources_pb2.ModelVersion(id=self.model_info.model_version.id),
|
657
|
+
),
|
658
|
+
extended_metrics=metrics,
|
659
|
+
ground_truth_dataset=resources_pb2.Dataset(
|
660
|
+
id=dataset_id,
|
661
|
+
app_id=dataset_app_id or self.auth_helper.app_id,
|
662
|
+
user_id=dataset_user_id or self.auth_helper.user_id,
|
663
|
+
),
|
664
|
+
eval_info=eval_info_params,
|
665
|
+
)
|
666
|
+
request = service_pb2.PostEvaluationsRequest(
|
667
|
+
user_app_id=self.user_app_id,
|
668
|
+
eval_metrics=[eval_metric],
|
669
|
+
)
|
670
|
+
response = self._grpc_request(self.STUB.PostEvaluations, request)
|
671
|
+
if response.status.code != status_code_pb2.SUCCESS:
|
672
|
+
raise Exception(response.status)
|
673
|
+
self.logger.info(
|
674
|
+
"\nModel evaluation in progress. Kindly allow a few minutes for completion. Processing time may vary based on the model and dataset sizes."
|
675
|
+
)
|
676
|
+
|
677
|
+
return response.eval_metrics
|
678
|
+
|
679
|
+
def get_eval_by_id(
|
680
|
+
self,
|
681
|
+
eval_id: str,
|
682
|
+
label_counts=False,
|
683
|
+
test_set=False,
|
684
|
+
binary_metrics=False,
|
685
|
+
confusion_matrix=False,
|
686
|
+
metrics_by_class=False,
|
687
|
+
metrics_by_area=False,
|
688
|
+
) -> resources_pb2.EvalMetrics:
|
689
|
+
"""Get detail eval_metrics by eval_id with extra metric fields
|
690
|
+
|
691
|
+
Args:
|
692
|
+
eval_id (str): eval id
|
693
|
+
label_counts (bool, optional): Set True to get label counts. Defaults to False.
|
694
|
+
test_set (bool, optional): Set True to get test set. Defaults to False.
|
695
|
+
binary_metrics (bool, optional): Set True to get binary metric. Defaults to False.
|
696
|
+
confusion_matrix (bool, optional): Set True to get confusion matrix. Defaults to False.
|
697
|
+
metrics_by_class (bool, optional): Set True to get metrics by class. Defaults to False.
|
698
|
+
metrics_by_area (bool, optional): Set True to get metrics by area. Defaults to False.
|
699
|
+
|
700
|
+
Raises:
|
701
|
+
Exception: Failed to call API
|
702
|
+
|
703
|
+
Returns:
|
704
|
+
resources_pb2.EvalMetrics: eval_metrics
|
705
|
+
"""
|
706
|
+
request = service_pb2.GetEvaluationRequest(
|
707
|
+
user_app_id=self.user_app_id,
|
708
|
+
evaluation_id=eval_id,
|
709
|
+
fields=resources_pb2.FieldsValue(
|
710
|
+
label_counts=label_counts,
|
711
|
+
test_set=test_set,
|
712
|
+
binary_metrics=binary_metrics,
|
713
|
+
confusion_matrix=confusion_matrix,
|
714
|
+
metrics_by_class=metrics_by_class,
|
715
|
+
metrics_by_area=metrics_by_area,
|
716
|
+
))
|
717
|
+
response = self._grpc_request(self.STUB.GetEvaluation, request)
|
718
|
+
|
719
|
+
if response.status.code != status_code_pb2.SUCCESS:
|
720
|
+
raise Exception(response.status)
|
721
|
+
|
722
|
+
return response.eval_metrics
|
723
|
+
|
724
|
+
def get_latest_eval(self,
|
725
|
+
label_counts=False,
|
726
|
+
test_set=False,
|
727
|
+
binary_metrics=False,
|
728
|
+
confusion_matrix=False,
|
729
|
+
metrics_by_class=False,
|
730
|
+
metrics_by_area=False) -> Union[resources_pb2.EvalMetrics, None]:
|
731
|
+
"""
|
732
|
+
Run `get_eval_by_id` method with latest `eval_id`
|
733
|
+
|
734
|
+
Args:
|
735
|
+
label_counts (bool, optional): Set True to get label counts. Defaults to False.
|
736
|
+
test_set (bool, optional): Set True to get test set. Defaults to False.
|
737
|
+
binary_metrics (bool, optional): Set True to get binary metric. Defaults to False.
|
738
|
+
confusion_matrix (bool, optional): Set True to get confusion matrix. Defaults to False.
|
739
|
+
metrics_by_class (bool, optional): Set True to get metrics by class. Defaults to False.
|
740
|
+
metrics_by_area (bool, optional): Set True to get metrics by area. Defaults to False.
|
741
|
+
|
742
|
+
Returns:
|
743
|
+
eval_metric if model is evaluated otherwise None.
|
744
|
+
|
745
|
+
"""
|
746
|
+
|
747
|
+
_latest = self.list_evaluations()[0]
|
748
|
+
result = None
|
749
|
+
if _latest.status.code == status_code_pb2.MODEL_EVALUATED:
|
750
|
+
result = self.get_eval_by_id(
|
751
|
+
eval_id=_latest.id,
|
752
|
+
label_counts=label_counts,
|
753
|
+
test_set=test_set,
|
754
|
+
binary_metrics=binary_metrics,
|
755
|
+
confusion_matrix=confusion_matrix,
|
756
|
+
metrics_by_class=metrics_by_class,
|
757
|
+
metrics_by_area=metrics_by_area)
|
758
|
+
|
759
|
+
return result
|
clarifai/client/module.py
CHANGED
@@ -18,6 +18,7 @@ class Module(Lister, BaseClient):
|
|
18
18
|
module_version: Dict = {'id': ""},
|
19
19
|
base_url: str = "https://api.clarifai.com",
|
20
20
|
pat: str = None,
|
21
|
+
token: str = None,
|
21
22
|
**kwargs):
|
22
23
|
"""Initializes a Module object.
|
23
24
|
|
@@ -26,7 +27,8 @@ class Module(Lister, BaseClient):
|
|
26
27
|
module_id (str): The Module ID to interact with.
|
27
28
|
module_version (dict): The Module Version to interact with.
|
28
29
|
base_url (str): Base API url. Default "https://api.clarifai.com"
|
29
|
-
pat (str): A personal access token for authentication. Can be set as env var CLARIFAI_PAT
|
30
|
+
pat (str): A personal access token for authentication. Can be set as env var CLARIFAI_PAT.
|
31
|
+
token (str): A session token for authentication. Accepts either a session token or a pat. Can be set as env var CLARIFAI_SESSION_TOKEN.
|
30
32
|
**kwargs: Additional keyword arguments to be passed to the Module.
|
31
33
|
"""
|
32
34
|
if url and module_id:
|
@@ -40,8 +42,9 @@ class Module(Lister, BaseClient):
|
|
40
42
|
|
41
43
|
self.kwargs = {**kwargs, 'id': module_id, 'module_version': module_version}
|
42
44
|
self.module_info = resources_pb2.Module(**self.kwargs)
|
43
|
-
self.logger = get_logger(logger_level="INFO")
|
44
|
-
BaseClient.__init__(
|
45
|
+
self.logger = get_logger(logger_level="INFO", name=__name__)
|
46
|
+
BaseClient.__init__(
|
47
|
+
self, user_id=self.user_id, app_id=self.app_id, base=base_url, pat=pat, token=token)
|
45
48
|
Lister.__init__(self)
|
46
49
|
|
47
50
|
def list_versions(self, page_no: int = None,
|
@@ -78,10 +81,9 @@ class Module(Lister, BaseClient):
|
|
78
81
|
for module_version_info in all_module_versions_info:
|
79
82
|
module_version_info['id'] = module_version_info['module_version_id']
|
80
83
|
del module_version_info['module_version_id']
|
81
|
-
yield Module(
|
84
|
+
yield Module.from_auth_helper(
|
85
|
+
self.auth_helper,
|
82
86
|
module_id=self.id,
|
83
|
-
base_url=self.base,
|
84
|
-
pat=self.pat,
|
85
87
|
**dict(self.kwargs, module_version=module_version_info))
|
86
88
|
|
87
89
|
def __getattr__(self, name):
|
clarifai/client/runner.py
CHANGED
@@ -39,6 +39,7 @@ class Runner(BaseClient):
|
|
39
39
|
check_runner_exists: bool = True,
|
40
40
|
base_url: str = "https://api.clarifai.com",
|
41
41
|
pat: str = None,
|
42
|
+
token: str = None,
|
42
43
|
num_parallel_polls: int = 4,
|
43
44
|
**kwargs) -> None:
|
44
45
|
"""
|
@@ -47,6 +48,7 @@ class Runner(BaseClient):
|
|
47
48
|
user_id (str): Clarifai User ID
|
48
49
|
base_url (str): Base API url. Default "https://api.clarifai.com"
|
49
50
|
pat (str): A personal access token for authentication. Can be set as env var CLARIFAI_PAT
|
51
|
+
token (str): A session token for authentication. Accepts either a session token or a pat. Can be set as env var CLARIFAI_SESSION_TOKEN
|
50
52
|
num_parallel_polls (int): the max number of threads for parallel run loops to be fetching work from
|
51
53
|
"""
|
52
54
|
user_id = user_id or os.environ.get("CLARIFAI_USER_ID", "")
|
@@ -60,7 +62,7 @@ class Runner(BaseClient):
|
|
60
62
|
self.kwargs = {**kwargs, 'id': runner_id, 'user_id': user_id}
|
61
63
|
self.runner_info = resources_pb2.Runner(**self.kwargs)
|
62
64
|
self.num_parallel_polls = min(10, num_parallel_polls)
|
63
|
-
BaseClient.__init__(self, user_id=self.user_id, app_id="", base=base_url, pat=pat)
|
65
|
+
BaseClient.__init__(self, user_id=self.user_id, app_id="", base=base_url, pat=pat, token=token)
|
64
66
|
|
65
67
|
# Check that the runner exists.
|
66
68
|
if check_runner_exists:
|
clarifai/client/search.py
CHANGED
@@ -23,7 +23,8 @@ class Search(Lister, BaseClient):
|
|
23
23
|
top_k: int = DEFAULT_TOP_K,
|
24
24
|
metric: str = DEFAULT_SEARCH_METRIC,
|
25
25
|
base_url: str = "https://api.clarifai.com",
|
26
|
-
pat: str = None
|
26
|
+
pat: str = None,
|
27
|
+
token: str = None):
|
27
28
|
"""Initialize the Search object.
|
28
29
|
|
29
30
|
Args:
|
@@ -33,6 +34,7 @@ class Search(Lister, BaseClient):
|
|
33
34
|
metric (str, optional): Similarity metric (either 'cosine' or 'euclidean'). Defaults to 'cosine'.
|
34
35
|
base_url (str, optional): Base API url. Defaults to "https://api.clarifai.com".
|
35
36
|
pat (str, optional): A personal access token for authentication. Can be set as env var CLARIFAI_PAT
|
37
|
+
token (str): A session token for authentication. Accepts either a session token or a pat. Can be set as env var CLARIFAI_SESSION_TOKEN
|
36
38
|
|
37
39
|
Raises:
|
38
40
|
UserError: If the metric is not 'cosine' or 'euclidean'.
|
@@ -46,9 +48,10 @@ class Search(Lister, BaseClient):
|
|
46
48
|
self.data_proto = resources_pb2.Data()
|
47
49
|
self.top_k = top_k
|
48
50
|
|
49
|
-
self.inputs = Inputs(user_id=self.user_id, app_id=self.app_id, pat=pat)
|
51
|
+
self.inputs = Inputs(user_id=self.user_id, app_id=self.app_id, pat=pat, token=token)
|
50
52
|
self.rank_filter_schema = get_schema()
|
51
|
-
BaseClient.__init__(
|
53
|
+
BaseClient.__init__(
|
54
|
+
self, user_id=self.user_id, app_id=self.app_id, base=base_url, pat=pat, token=token)
|
52
55
|
Lister.__init__(self, page_size=1000)
|
53
56
|
|
54
57
|
def _get_annot_proto(self, **kwargs):
|
clarifai/client/user.py
CHANGED
@@ -19,6 +19,7 @@ class User(Lister, BaseClient):
|
|
19
19
|
user_id: str = None,
|
20
20
|
base_url: str = "https://api.clarifai.com",
|
21
21
|
pat: str = None,
|
22
|
+
token: str = None,
|
22
23
|
**kwargs):
|
23
24
|
"""Initializes an User object.
|
24
25
|
|
@@ -26,12 +27,13 @@ class User(Lister, BaseClient):
|
|
26
27
|
user_id (str): The user ID for the user to interact with.
|
27
28
|
base_url (str): Base API url. Default "https://api.clarifai.com"
|
28
29
|
pat (str): A personal access token for authentication. Can be set as env var CLARIFAI_PAT
|
30
|
+
token (str): A session token for authentication. Accepts either a session token or a pat. Can be set as env var CLARIFAI_SESSION_TOKEN
|
29
31
|
**kwargs: Additional keyword arguments to be passed to the User.
|
30
32
|
"""
|
31
33
|
self.kwargs = {**kwargs, 'id': user_id}
|
32
34
|
self.user_info = resources_pb2.User(**self.kwargs)
|
33
35
|
self.logger = get_logger(logger_level="INFO", name=__name__)
|
34
|
-
BaseClient.__init__(self, user_id=self.id, app_id="", base=base_url, pat=pat)
|
36
|
+
BaseClient.__init__(self, user_id=self.id, app_id="", base=base_url, pat=pat, token=token)
|
35
37
|
Lister.__init__(self)
|
36
38
|
|
37
39
|
def list_apps(self, filter_by: Dict[str, Any] = {}, page_no: int = None,
|
@@ -62,7 +64,9 @@ class User(Lister, BaseClient):
|
|
62
64
|
per_page=per_page,
|
63
65
|
page_no=page_no)
|
64
66
|
for app_info in all_apps_info:
|
65
|
-
yield App(
|
67
|
+
yield App.from_auth_helper(
|
68
|
+
self.auth_helper,
|
69
|
+
**app_info) #(base_url=self.base, pat=self.pat, token=self.token, **app_info)
|
66
70
|
|
67
71
|
def list_runners(self, filter_by: Dict[str, Any] = {}, page_no: int = None,
|
68
72
|
per_page: int = None) -> Generator[Runner, None, None]:
|
@@ -94,7 +98,8 @@ class User(Lister, BaseClient):
|
|
94
98
|
page_no=page_no)
|
95
99
|
|
96
100
|
for runner_info in all_runners_info:
|
97
|
-
yield Runner(
|
101
|
+
yield Runner.from_auth_helper(
|
102
|
+
auth=self.auth_helper, check_runner_exists=False, **runner_info)
|
98
103
|
|
99
104
|
def create_app(self, app_id: str, base_workflow: str = 'Empty', **kwargs) -> App:
|
100
105
|
"""Creates an app for the user.
|
@@ -120,8 +125,7 @@ class User(Lister, BaseClient):
|
|
120
125
|
if response.status.code != status_code_pb2.SUCCESS:
|
121
126
|
raise Exception(response.status)
|
122
127
|
self.logger.info("\nApp created\n%s", response.status)
|
123
|
-
|
124
|
-
return App(app_id=app_id, **kwargs)
|
128
|
+
return App.from_auth_helper(auth=self.auth_helper, app_id=app_id)
|
125
129
|
|
126
130
|
def create_runner(self, runner_id: str, labels: List[str], description: str) -> Runner:
|
127
131
|
"""Create a runner
|
@@ -151,14 +155,13 @@ class User(Lister, BaseClient):
|
|
151
155
|
raise Exception(response.status)
|
152
156
|
self.logger.info("\nRunner created\n%s", response.status)
|
153
157
|
|
154
|
-
return Runner(
|
158
|
+
return Runner.from_auth_helper(
|
159
|
+
auth=self.auth_helper,
|
155
160
|
runner_id=runner_id,
|
156
161
|
user_id=self.id,
|
157
162
|
labels=labels,
|
158
163
|
description=description,
|
159
|
-
check_runner_exists=False
|
160
|
-
base_url=self.base,
|
161
|
-
pat=self.pat)
|
164
|
+
check_runner_exists=False)
|
162
165
|
|
163
166
|
def app(self, app_id: str, **kwargs) -> App:
|
164
167
|
"""Returns an App object for the specified app ID.
|
@@ -181,8 +184,7 @@ class User(Lister, BaseClient):
|
|
181
184
|
raise Exception(response.status)
|
182
185
|
|
183
186
|
kwargs['user_id'] = self.id
|
184
|
-
|
185
|
-
return App(app_id=app_id, **kwargs)
|
187
|
+
return App.from_auth_helper(auth=self.auth_helper, app_id=app_id, **kwargs)
|
186
188
|
|
187
189
|
def runner(self, runner_id: str) -> Runner:
|
188
190
|
"""Returns a Runner object if exists.
|
@@ -210,7 +212,7 @@ class User(Lister, BaseClient):
|
|
210
212
|
kwargs = self.process_response_keys(dict_response[list(dict_response.keys())[1]],
|
211
213
|
list(dict_response.keys())[1])
|
212
214
|
|
213
|
-
return Runner(
|
215
|
+
return Runner.from_auth_helper(self.auth_helper, check_runner_exists=False, **kwargs)
|
214
216
|
|
215
217
|
def delete_app(self, app_id: str) -> None:
|
216
218
|
"""Deletes an app for the user.
|
clarifai/client/workflow.py
CHANGED
@@ -27,6 +27,7 @@ class Workflow(Lister, BaseClient):
|
|
27
27
|
output_config: Dict = {'min_value': 0},
|
28
28
|
base_url: str = "https://api.clarifai.com",
|
29
29
|
pat: str = None,
|
30
|
+
token: str = None,
|
30
31
|
**kwargs):
|
31
32
|
"""Initializes a Workflow object.
|
32
33
|
|
@@ -40,6 +41,8 @@ class Workflow(Lister, BaseClient):
|
|
40
41
|
select_concepts (list[Concept]): The concepts to select.
|
41
42
|
sample_ms (int): The number of milliseconds to sample.
|
42
43
|
base_url (str): Base API url. Default "https://api.clarifai.com"
|
44
|
+
pat (str): A personal access token for authentication. Can be set as env var CLARIFAI_PAT
|
45
|
+
token (str): A session token for authentication. Accepts either a session token or a pat. Can be set as env var CLARIFAI_SESSION_TOKEN
|
43
46
|
**kwargs: Additional keyword arguments to be passed to the Workflow.
|
44
47
|
"""
|
45
48
|
if url and workflow_id:
|
@@ -54,8 +57,9 @@ class Workflow(Lister, BaseClient):
|
|
54
57
|
self.kwargs = {**kwargs, 'id': workflow_id, 'version': workflow_version}
|
55
58
|
self.output_config = output_config
|
56
59
|
self.workflow_info = resources_pb2.Workflow(**self.kwargs)
|
57
|
-
self.logger = get_logger(logger_level="INFO")
|
58
|
-
BaseClient.__init__(
|
60
|
+
self.logger = get_logger(logger_level="INFO", name=__name__)
|
61
|
+
BaseClient.__init__(
|
62
|
+
self, user_id=self.user_id, app_id=self.app_id, base=base_url, pat=pat, token=token)
|
59
63
|
Lister.__init__(self)
|
60
64
|
|
61
65
|
def predict(self, inputs: List[Input], workflow_state_id: str = None):
|
@@ -206,10 +210,9 @@ class Workflow(Lister, BaseClient):
|
|
206
210
|
for workflow_version_info in all_workflow_versions_info:
|
207
211
|
workflow_version_info['id'] = workflow_version_info['workflow_version_id']
|
208
212
|
del workflow_version_info['workflow_version_id']
|
209
|
-
yield Workflow(
|
213
|
+
yield Workflow.from_auth_helper(
|
214
|
+
auth=self.auth_helper,
|
210
215
|
workflow_id=self.id,
|
211
|
-
base_url=self.base,
|
212
|
-
pat=self.pat,
|
213
216
|
**dict(self.kwargs, version=workflow_version_info))
|
214
217
|
|
215
218
|
def export(self, out_path: str):
|
@@ -20,6 +20,7 @@ class VisualClassificationFeatures:
|
|
20
20
|
geo_info: Optional[List[float]] = None #[Longitude, Latitude]
|
21
21
|
id: Optional[int] = None # image_id
|
22
22
|
metadata: Optional[dict] = None
|
23
|
+
image_bytes: Optional[bytes] = None
|
23
24
|
|
24
25
|
|
25
26
|
@dataclass
|
@@ -31,6 +32,7 @@ class VisualDetectionFeatures:
|
|
31
32
|
geo_info: Optional[List[float]] = None #[Longitude, Latitude]
|
32
33
|
id: Optional[int] = None # image_id
|
33
34
|
metadata: Optional[dict] = None
|
35
|
+
image_bytes: Optional[bytes] = None
|
34
36
|
|
35
37
|
|
36
38
|
@dataclass
|
@@ -42,3 +44,4 @@ class VisualSegmentationFeatures:
|
|
42
44
|
geo_info: Optional[List[float]] = None #[Longitude, Latitude]
|
43
45
|
id: Optional[int] = None # image_id
|
44
46
|
metadata: Optional[dict] = None
|
47
|
+
image_bytes: Optional[bytes] = None
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import os
|
2
|
+
import uuid
|
2
3
|
from concurrent.futures import ThreadPoolExecutor
|
3
4
|
from typing import List, Tuple, Type
|
4
5
|
|
@@ -31,22 +32,34 @@ class VisualClassificationDataset(ClarifaiDataset):
|
|
31
32
|
image_path = data_item.image_path
|
32
33
|
labels = data_item.labels if isinstance(data_item.labels,
|
33
34
|
list) else [data_item.labels] # clarifai concept
|
34
|
-
input_id = f"{self.dataset_id}-{
|
35
|
+
input_id = f"{self.dataset_id}-{uuid.uuid4().hex[:8]}" if data_item.id is None else f"{self.dataset_id}-{str(data_item.id)}"
|
35
36
|
geo_info = data_item.geo_info
|
36
37
|
if data_item.metadata is not None:
|
37
38
|
metadata.update(data_item.metadata)
|
38
|
-
|
39
|
+
elif image_path is not None:
|
39
40
|
metadata.update({"filename": os.path.basename(image_path)})
|
41
|
+
else:
|
42
|
+
metadata = None
|
40
43
|
|
41
44
|
self.all_input_ids[id] = input_id
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
45
|
+
if data_item.image_bytes is not None:
|
46
|
+
input_protos.append(
|
47
|
+
Inputs.get_input_from_bytes(
|
48
|
+
input_id=input_id,
|
49
|
+
image_bytes=data_item.image_bytes,
|
50
|
+
dataset_id=self.dataset_id,
|
51
|
+
labels=labels,
|
52
|
+
geo_info=geo_info,
|
53
|
+
metadata=metadata))
|
54
|
+
else:
|
55
|
+
input_protos.append(
|
56
|
+
Inputs.get_input_from_file(
|
57
|
+
input_id=input_id,
|
58
|
+
image_file=image_path,
|
59
|
+
dataset_id=self.dataset_id,
|
60
|
+
labels=labels,
|
61
|
+
geo_info=geo_info,
|
62
|
+
metadata=metadata))
|
50
63
|
|
51
64
|
with ThreadPoolExecutor(max_workers=4) as executor:
|
52
65
|
futures = [executor.submit(process_data_item, id) for id in batch_input_ids]
|
@@ -79,7 +92,7 @@ class VisualDetectionDataset(ClarifaiDataset):
|
|
79
92
|
image = data_item.image_path
|
80
93
|
labels = data_item.labels # list:[l1,...,ln]
|
81
94
|
bboxes = data_item.bboxes # [[xmin,ymin,xmax,ymax],...,[xmin,ymin,xmax,ymax]]
|
82
|
-
input_id = f"{self.dataset_id}-{
|
95
|
+
input_id = f"{self.dataset_id}-{uuid.uuid4().hex[:8]}" if data_item.id is None else f"{self.dataset_id}-{str(data_item.id)}"
|
83
96
|
if data_item.metadata is not None:
|
84
97
|
metadata.update(data_item.metadata)
|
85
98
|
else:
|
@@ -87,13 +100,22 @@ class VisualDetectionDataset(ClarifaiDataset):
|
|
87
100
|
geo_info = data_item.geo_info
|
88
101
|
|
89
102
|
self.all_input_ids[id] = input_id
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
103
|
+
if data_item.image_bytes is not None:
|
104
|
+
input_protos.append(
|
105
|
+
Inputs.get_input_from_bytes(
|
106
|
+
input_id=input_id,
|
107
|
+
image_bytes=data_item.image_bytes,
|
108
|
+
dataset_id=self.dataset_id,
|
109
|
+
geo_info=geo_info,
|
110
|
+
metadata=metadata))
|
111
|
+
else:
|
112
|
+
input_protos.append(
|
113
|
+
Inputs.get_input_from_file(
|
114
|
+
input_id=input_id,
|
115
|
+
image_file=image,
|
116
|
+
dataset_id=self.dataset_id,
|
117
|
+
geo_info=geo_info,
|
118
|
+
metadata=metadata))
|
97
119
|
# iter over bboxes and labels
|
98
120
|
# one id could have more than one bbox and label
|
99
121
|
for i in range(len(bboxes)):
|
@@ -131,7 +153,7 @@ class VisualSegmentationDataset(ClarifaiDataset):
|
|
131
153
|
image = data_item.image_path
|
132
154
|
labels = data_item.labels
|
133
155
|
_polygons = data_item.polygons # list of polygons: [[[x,y],...,[x,y]],...]
|
134
|
-
input_id = f"{self.dataset_id}-{
|
156
|
+
input_id = f"{self.dataset_id}-{uuid.uuid4().hex[:8]}" if data_item.id is None else f"{self.dataset_id}-{str(data_item.id)}"
|
135
157
|
if data_item.metadata is not None:
|
136
158
|
metadata.update(data_item.metadata)
|
137
159
|
else:
|
@@ -139,13 +161,22 @@ class VisualSegmentationDataset(ClarifaiDataset):
|
|
139
161
|
geo_info = data_item.geo_info
|
140
162
|
|
141
163
|
self.all_input_ids[id] = input_id
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
164
|
+
if data_item.image_bytes is not None:
|
165
|
+
input_protos.append(
|
166
|
+
Inputs.get_input_from_bytes(
|
167
|
+
input_id=input_id,
|
168
|
+
image_bytes=data_item.image_bytes,
|
169
|
+
dataset_id=self.dataset_id,
|
170
|
+
geo_info=geo_info,
|
171
|
+
metadata=metadata))
|
172
|
+
else:
|
173
|
+
input_protos.append(
|
174
|
+
Inputs.get_input_from_file(
|
175
|
+
input_id=input_id,
|
176
|
+
image_file=image,
|
177
|
+
dataset_id=self.dataset_id,
|
178
|
+
geo_info=geo_info,
|
179
|
+
metadata=metadata))
|
149
180
|
|
150
181
|
## Iterate over each masked image and create a proto for upload to clarifai
|
151
182
|
## The length of masks/polygons-list and labels must be equal
|
@@ -8,15 +8,15 @@ If a dataset module exists in the zoo, uploading the specific dataset can be eas
|
|
8
8
|
|
9
9
|
```python
|
10
10
|
from clarifai.client.app import App
|
11
|
-
from clarifai.datasets.upload.loaders.
|
11
|
+
from clarifai.datasets.upload.loaders.coco_detection import COCODetectionDataLoader
|
12
12
|
|
13
13
|
app = App(app_id="", user_id="")
|
14
14
|
# Create a dataset in Clarifai App
|
15
15
|
dataset = app.create_dataset(dataset_id="")
|
16
16
|
# instantiate dataloader object
|
17
|
-
|
17
|
+
coco_det_dataloader = COCODetectionDataLoader(images_dir="", label_filepath="")
|
18
18
|
# execute data upload to Clarifai app dataset
|
19
|
-
dataset.upload_dataset(dataloader=
|
19
|
+
dataset.upload_dataset(dataloader=coco_det_dataloader)
|
20
20
|
```
|
21
21
|
|
22
22
|
## Dataset Loaders
|
@@ -24,7 +24,6 @@ dataset.upload_dataset(dataloader=coco_seg_dataloader)
|
|
24
24
|
| dataset name | task | module name (.py)
|
25
25
|
| --- | --- | ---
|
26
26
|
| [COCO 2017](https://cocodataset.org/#download) | Detection | `coco_detection` |
|
27
|
-
| | Segmentation | `coco_segmentation` |
|
28
27
|
| | Captions | `coco_captions` |
|
29
28
|
|[xVIEW](http://xviewdataset.org/) | Detection | `xview_detection` |
|
30
29
|
| [ImageNet](https://www.image-net.org/) | Classification | `imagenet_classification` |
|