clarifai 10.9.2__py3-none-any.whl → 10.9.4__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/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "10.9.2"
1
+ __version__ = "10.9.4"
File without changes
clarifai/cli/base.py ADDED
@@ -0,0 +1,74 @@
1
+ import os
2
+
3
+ import click
4
+
5
+ from ..utils.cli import dump_yaml, from_yaml, load_command_modules, set_base_url
6
+
7
+
8
+ @click.group()
9
+ @click.pass_context
10
+ def cli(ctx):
11
+ """Clarifai CLI"""
12
+ ctx.ensure_object(dict)
13
+ config_path = 'config.yaml'
14
+ if os.path.exists(config_path):
15
+ ctx.obj = from_yaml(config_path)
16
+ else:
17
+ ctx.obj = {}
18
+
19
+
20
+ @cli.command()
21
+ @click.option('--config', type=click.Path(), required=False, help='Path to the config file')
22
+ @click.option(
23
+ '-e',
24
+ '--env',
25
+ required=False,
26
+ help='Environment to use, choose from prod, staging and dev',
27
+ type=click.Choice(['prod', 'staging', 'dev']))
28
+ @click.option('--user_id', required=False, help='User ID')
29
+ @click.pass_context
30
+ def login(ctx, config, env, user_id):
31
+ """Login command to set PAT and other configurations."""
32
+
33
+ if config and os.path.exists(config):
34
+ ctx.obj = from_yaml(config)
35
+
36
+ if 'pat' in ctx.obj:
37
+ os.environ["CLARIFAI_PAT"] = ctx.obj['pat']
38
+ click.echo("Loaded PAT from config file.")
39
+ elif 'CLARIFAI_PAT' in os.environ:
40
+ ctx.obj['pat'] = os.environ["CLARIFAI_PAT"]
41
+ click.echo("Loaded PAT from environment variable.")
42
+ else:
43
+ _pat = click.prompt(
44
+ "Get your PAT from https://clarifai.com/settings/security and pass it here", type=str)
45
+ os.environ["CLARIFAI_PAT"] = _pat
46
+ ctx.obj['pat'] = _pat
47
+ click.echo("PAT saved successfully.")
48
+
49
+ if user_id:
50
+ ctx.obj['user_id'] = user_id
51
+ os.environ["CLARIFAI_USER_ID"] = ctx.obj['user_id']
52
+ elif 'user_id' in ctx.obj or 'CLARIFAI_USER_ID' in os.environ:
53
+ ctx.obj['user_id'] = ctx.obj.get('user_id', os.environ["CLARIFAI_USER_ID"])
54
+ os.environ["CLARIFAI_USER_ID"] = ctx.obj['user_id']
55
+
56
+ if env:
57
+ ctx.obj['env'] = env
58
+ ctx.obj['base_url'] = set_base_url(env)
59
+ os.environ["CLARIFAI_API_BASE"] = ctx.obj['base_url']
60
+ elif 'env' in ctx.obj:
61
+ ctx.obj['env'] = ctx.obj.get('env', "prod")
62
+ ctx.obj['base_url'] = set_base_url(ctx.obj['env'])
63
+ os.environ["CLARIFAI_API_BASE"] = ctx.obj['base_url']
64
+ elif 'CLARIFAI_API_BASE' in os.environ:
65
+ ctx.obj['base_url'] = os.environ["CLARIFAI_API_BASE"]
66
+
67
+ dump_yaml(ctx.obj, 'config.yaml')
68
+
69
+
70
+ # Import the CLI commands to register them
71
+ load_command_modules()
72
+
73
+ if __name__ == '__main__':
74
+ cli()
clarifai/cli/model.py ADDED
@@ -0,0 +1,65 @@
1
+ import click
2
+ from clarifai.cli.base import cli
3
+
4
+
5
+ @cli.group()
6
+ def model():
7
+ """Manage models: upload, test locally"""
8
+ pass
9
+
10
+
11
+ @model.command()
12
+ @click.option(
13
+ '--model_path',
14
+ type=click.Path(exists=True),
15
+ required=True,
16
+ help='Path to the model directory.')
17
+ @click.option(
18
+ '--download_checkpoints',
19
+ is_flag=True,
20
+ help=
21
+ 'Flag to download checkpoints before uploading and including them in the tar file that is uploaded. Defaults to False, which will attempt to download them at docker build time.',
22
+ )
23
+ @click.option(
24
+ '--skip_dockerfile',
25
+ is_flag=True,
26
+ help=
27
+ 'Flag to skip generating a dockerfile so that you can manually edit an already created dockerfile.',
28
+ )
29
+ def upload(model_path, download_checkpoints, skip_dockerfile):
30
+ """Upload a model to Clarifai."""
31
+ from clarifai.runners.models import model_upload
32
+
33
+ model_upload.main(model_path, download_checkpoints, skip_dockerfile)
34
+
35
+
36
+ @model.command()
37
+ @click.option(
38
+ '--model_path',
39
+ type=click.Path(exists=True),
40
+ required=True,
41
+ help='Path to the model directory.')
42
+ def test_locally(model_path):
43
+ """Test model locally."""
44
+ try:
45
+ from clarifai.runners.models import model_run_locally
46
+ model_run_locally.main(model_path)
47
+ click.echo(f"Model tested locally from {model_path}.")
48
+ except Exception as e:
49
+ click.echo(f"Failed to test model locally: {e}", err=True)
50
+
51
+
52
+ @model.command()
53
+ @click.option(
54
+ '--model_path',
55
+ type=click.Path(exists=True),
56
+ required=True,
57
+ help='Path to the model directory.')
58
+ def run_locally(model_path):
59
+ """Run model locally and starts a GRPC server to serve the model."""
60
+ try:
61
+ from clarifai.runners.models import model_run_locally
62
+ model_run_locally.main(model_path, run_model_server=True)
63
+ click.echo(f"Model server started locally from {model_path}.")
64
+ except Exception as e:
65
+ click.echo(f"Failed to starts model server locally: {e}", err=True)
@@ -5,11 +5,16 @@ from urllib.parse import urlparse
5
5
 
6
6
  from clarifai_grpc.channel.clarifai_channel import ClarifaiChannel
7
7
  from clarifai_grpc.grpc.api import resources_pb2, service_pb2_grpc
8
+
9
+ from clarifai import __version__
8
10
  from clarifai.utils.constants import CLARIFAI_PAT_ENV_VAR, CLARIFAI_SESSION_TOKEN_ENV_VAR
9
11
 
10
12
  DEFAULT_BASE = "https://api.clarifai.com"
11
13
  DEFAULT_UI = "https://clarifai.com"
12
14
 
15
+ REQUEST_ID_PREFIX_HEADER = "x-clarifai-request-id-prefix"
16
+ REQUEST_ID_PREFIX = f"sdk-python-{__version__}"
17
+
13
18
  # Map from base domain to True / False for whether the base has https or http.
14
19
  # This is filled in get_stub() if it's not in there already.
15
20
  base_https_cache = {}
@@ -136,7 +141,7 @@ class ClarifaiAuthHelper:
136
141
 
137
142
  # Then add in the query params.
138
143
  try:
139
- auth.add_streamlit_query_params(st.experimental_get_query_params())
144
+ auth.add_streamlit_query_params(dict(st.query_params))
140
145
  except Exception as e:
141
146
  st.error(e)
142
147
  st.stop()
@@ -269,9 +274,11 @@ Additionally, these optional params are supported:
269
274
  metadata: the metadata need to send with all grpc API calls in the API client.
270
275
  """
271
276
  if self._pat != "":
272
- return (("authorization", "Key %s" % self._pat),)
277
+ return (("authorization", "Key %s" % self._pat), (REQUEST_ID_PREFIX_HEADER,
278
+ REQUEST_ID_PREFIX))
273
279
  elif self._token != "":
274
- return (("x-clarifai-session-token", self._token),)
280
+ return (("x-clarifai-session-token", self._token), (REQUEST_ID_PREFIX_HEADER,
281
+ REQUEST_ID_PREFIX))
275
282
  else:
276
283
  raise Exception("'token' or 'pat' needed to be provided in the query params or env vars.")
277
284
 
clarifai/client/input.py CHANGED
@@ -100,7 +100,7 @@ class Inputs(Lister, BaseClient):
100
100
  if not label_ids:
101
101
  concepts=[
102
102
  resources_pb2.Concept(
103
- id=f"id-{''.join(_label.split(' '))}", name=_label, value=1.)\
103
+ id=_label, name=_label, value=1.)\
104
104
  for _label in labels
105
105
  ]
106
106
  else:
@@ -516,7 +516,7 @@ class Inputs(Lister, BaseClient):
516
516
  right_col=bbox[2] #x_max
517
517
  )),
518
518
  data=resources_pb2.Data(concepts=[
519
- resources_pb2.Concept(id=f"id-{''.join(label.split(' '))}", name=label, value=1.)
519
+ resources_pb2.Concept(id=label, name=label, value=1.)
520
520
  if not label_id else resources_pb2.Concept(id=label_id, name=label, value=1.)
521
521
  ]))
522
522
  ])
@@ -561,7 +561,7 @@ class Inputs(Lister, BaseClient):
561
561
  visibility="VISIBLE") for _point in polygons
562
562
  ])),
563
563
  data=resources_pb2.Data(concepts=[
564
- resources_pb2.Concept(id=f"id-{''.join(label.split(' '))}", name=label, value=1.)
564
+ resources_pb2.Concept(id=label, name=label, value=1.)
565
565
  if not label_id else resources_pb2.Concept(id=label_id, name=label, value=1.)
566
566
  ]))
567
567
  ])
clarifai/client/model.py CHANGED
@@ -72,6 +72,7 @@ class Model(Lister, BaseClient):
72
72
  self.model_info = resources_pb2.Model(**self.kwargs)
73
73
  self.logger = logger
74
74
  self.training_params = {}
75
+ self.input_types = None
75
76
  BaseClient.__init__(
76
77
  self,
77
78
  user_id=self.user_id,
@@ -450,9 +451,55 @@ class Model(Lister, BaseClient):
450
451
 
451
452
  return response
452
453
 
454
+ def _check_predict_input_type(self, input_type: str) -> None:
455
+ """Checks if the input type is valid for the model.
456
+
457
+ Args:
458
+ input_type (str): The input type to check.
459
+ Returns:
460
+ None
461
+ """
462
+ if not input_type:
463
+ self.load_input_types()
464
+ if len(self.input_types) > 1:
465
+ raise UserError(
466
+ "Model has multiple input types. Please use model.predict() for this multi-modal model."
467
+ )
468
+ else:
469
+ self.input_types = [input_type]
470
+ if self.input_types[0] not in {'image', 'text', 'video', 'audio'}:
471
+ raise UserError(
472
+ f"Got input type {input_type} but expected one of image, text, video, audio.")
473
+
474
+ def load_input_types(self) -> None:
475
+ """Loads the input types for the model.
476
+
477
+ Returns:
478
+ None
479
+
480
+ Example:
481
+ >>> from clarifai.client.model import Model
482
+ >>> model = Model("url") # Example URL: https://clarifai.com/clarifai/main/models/general-image-recognition
483
+ or
484
+ >>> model = Model(model_id='model_id', user_id='user_id', app_id='app_id')
485
+ >>> model.load_input_types()
486
+ """
487
+ if self.input_types:
488
+ return self.input_types
489
+ if self.model_info.model_type_id == "":
490
+ self.load_info()
491
+ request = service_pb2.GetModelTypeRequest(
492
+ user_app_id=self.user_app_id,
493
+ model_type_id=self.model_info.model_type_id,
494
+ )
495
+ response = self._grpc_request(self.STUB.GetModelType, request)
496
+ if response.status.code != status_code_pb2.SUCCESS:
497
+ raise Exception(response.status)
498
+ self.input_types = response.model_type.input_fields
499
+
453
500
  def predict_by_filepath(self,
454
501
  filepath: str,
455
- input_type: str,
502
+ input_type: str = None,
456
503
  compute_cluster_id: str = None,
457
504
  nodepool_id: str = None,
458
505
  deployment_id: str = None,
@@ -462,7 +509,7 @@ class Model(Lister, BaseClient):
462
509
 
463
510
  Args:
464
511
  filepath (str): The filepath to predict.
465
- input_type (str): The type of input. Can be 'image', 'text', 'video' or 'audio.
512
+ input_type (str, optional): The type of input. Can be 'image', 'text', 'video' or 'audio.
466
513
  compute_cluster_id (str): The compute cluster ID to use for the model.
467
514
  nodepool_id (str): The nodepool ID to use for the model.
468
515
  deployment_id (str): The deployment ID to use for the model.
@@ -477,8 +524,8 @@ class Model(Lister, BaseClient):
477
524
  >>> model = Model("url") # Example URL: https://clarifai.com/clarifai/main/models/general-image-recognition
478
525
  or
479
526
  >>> model = Model(model_id='model_id', user_id='user_id', app_id='app_id')
480
- >>> model_prediction = model.predict_by_filepath('/path/to/image.jpg', 'image')
481
- >>> model_prediction = model.predict_by_filepath('/path/to/text.txt', 'text')
527
+ >>> model_prediction = model.predict_by_filepath('/path/to/image.jpg')
528
+ >>> model_prediction = model.predict_by_filepath('/path/to/text.txt')
482
529
  """
483
530
  if not os.path.isfile(filepath):
484
531
  raise UserError('Invalid filepath.')
@@ -491,7 +538,7 @@ class Model(Lister, BaseClient):
491
538
 
492
539
  def predict_by_bytes(self,
493
540
  input_bytes: bytes,
494
- input_type: str,
541
+ input_type: str = None,
495
542
  compute_cluster_id: str = None,
496
543
  nodepool_id: str = None,
497
544
  deployment_id: str = None,
@@ -501,7 +548,7 @@ class Model(Lister, BaseClient):
501
548
 
502
549
  Args:
503
550
  input_bytes (bytes): File Bytes to predict on.
504
- input_type (str): The type of input. Can be 'image', 'text', 'video' or 'audio.
551
+ input_type (str, optional): The type of input. Can be 'image', 'text', 'video' or 'audio.
505
552
  compute_cluster_id (str): The compute cluster ID to use for the model.
506
553
  nodepool_id (str): The nodepool ID to use for the model.
507
554
  deployment_id (str): The deployment ID to use for the model.
@@ -515,22 +562,17 @@ class Model(Lister, BaseClient):
515
562
  >>> from clarifai.client.model import Model
516
563
  >>> model = Model("https://clarifai.com/openai/chat-completion/models/GPT-4")
517
564
  >>> model_prediction = model.predict_by_bytes(b'Write a tweet on future of AI',
518
- input_type='text',
519
565
  inference_params=dict(temperature=str(0.7), max_tokens=30)))
520
566
  """
521
- if input_type not in {'image', 'text', 'video', 'audio'}:
522
- raise UserError(
523
- f"Got input type {input_type} but expected one of image, text, video, audio.")
524
- if not isinstance(input_bytes, bytes):
525
- raise UserError('Invalid bytes.')
567
+ self._check_predict_input_type(input_type)
526
568
 
527
- if input_type == "image":
569
+ if self.input_types[0] == "image":
528
570
  input_proto = Inputs.get_input_from_bytes("", image_bytes=input_bytes)
529
- elif input_type == "text":
571
+ elif self.input_types[0] == "text":
530
572
  input_proto = Inputs.get_input_from_bytes("", text_bytes=input_bytes)
531
- elif input_type == "video":
573
+ elif self.input_types[0] == "video":
532
574
  input_proto = Inputs.get_input_from_bytes("", video_bytes=input_bytes)
533
- elif input_type == "audio":
575
+ elif self.input_types[0] == "audio":
534
576
  input_proto = Inputs.get_input_from_bytes("", audio_bytes=input_bytes)
535
577
 
536
578
  if deployment_id and (compute_cluster_id or nodepool_id):
@@ -553,7 +595,7 @@ class Model(Lister, BaseClient):
553
595
 
554
596
  def predict_by_url(self,
555
597
  url: str,
556
- input_type: str,
598
+ input_type: str = None,
557
599
  compute_cluster_id: str = None,
558
600
  nodepool_id: str = None,
559
601
  deployment_id: str = None,
@@ -563,7 +605,7 @@ class Model(Lister, BaseClient):
563
605
 
564
606
  Args:
565
607
  url (str): The URL to predict.
566
- input_type (str): The type of input. Can be 'image', 'text', 'video' or 'audio.
608
+ input_type (str, optional): The type of input. Can be 'image', 'text', 'video' or 'audio'.
567
609
  compute_cluster_id (str): The compute cluster ID to use for the model.
568
610
  nodepool_id (str): The nodepool ID to use for the model.
569
611
  deployment_id (str): The deployment ID to use for the model.
@@ -578,19 +620,17 @@ class Model(Lister, BaseClient):
578
620
  >>> model = Model("url") # Example URL: https://clarifai.com/clarifai/main/models/general-image-recognition
579
621
  or
580
622
  >>> model = Model(model_id='model_id', user_id='user_id', app_id='app_id')
581
- >>> model_prediction = model.predict_by_url('url', 'image')
623
+ >>> model_prediction = model.predict_by_url('url')
582
624
  """
583
- if input_type not in {'image', 'text', 'video', 'audio'}:
584
- raise UserError(
585
- f"Got input type {input_type} but expected one of image, text, video, audio.")
625
+ self._check_predict_input_type(input_type)
586
626
 
587
- if input_type == "image":
627
+ if self.input_types[0] == "image":
588
628
  input_proto = Inputs.get_input_from_url("", image_url=url)
589
- elif input_type == "text":
629
+ elif self.input_types[0] == "text":
590
630
  input_proto = Inputs.get_input_from_url("", text_url=url)
591
- elif input_type == "video":
631
+ elif self.input_types[0] == "video":
592
632
  input_proto = Inputs.get_input_from_url("", video_url=url)
593
- elif input_type == "audio":
633
+ elif self.input_types[0] == "audio":
594
634
  input_proto = Inputs.get_input_from_url("", audio_url=url)
595
635
 
596
636
  if deployment_id and (compute_cluster_id or nodepool_id):
@@ -668,7 +708,7 @@ class Model(Lister, BaseClient):
668
708
 
669
709
  def generate_by_filepath(self,
670
710
  filepath: str,
671
- input_type: str,
711
+ input_type: str = None,
672
712
  compute_cluster_id: str = None,
673
713
  nodepool_id: str = None,
674
714
  deployment_id: str = None,
@@ -678,7 +718,7 @@ class Model(Lister, BaseClient):
678
718
 
679
719
  Args:
680
720
  filepath (str): The filepath to predict.
681
- input_type (str): The type of input. Can be 'image', 'text', 'video' or 'audio.
721
+ input_type (str, optional): The type of input. Can be 'image', 'text', 'video' or 'audio.
682
722
  compute_cluster_id (str): The compute cluster ID to use for the model.
683
723
  nodepool_id (str): The nodepool ID to use for the model.
684
724
  deployment_id (str): The deployment ID to use for the model.
@@ -713,7 +753,7 @@ class Model(Lister, BaseClient):
713
753
 
714
754
  def generate_by_bytes(self,
715
755
  input_bytes: bytes,
716
- input_type: str,
756
+ input_type: str = None,
717
757
  compute_cluster_id: str = None,
718
758
  nodepool_id: str = None,
719
759
  deployment_id: str = None,
@@ -723,7 +763,7 @@ class Model(Lister, BaseClient):
723
763
 
724
764
  Args:
725
765
  input_bytes (bytes): File Bytes to predict on.
726
- input_type (str): The type of input. Can be 'image', 'text', 'video' or 'audio.
766
+ input_type (str, optional): The type of input. Can be 'image', 'text', 'video' or 'audio.
727
767
  compute_cluster_id (str): The compute cluster ID to use for the model.
728
768
  nodepool_id (str): The nodepool ID to use for the model.
729
769
  deployment_id (str): The deployment ID to use for the model.
@@ -737,24 +777,19 @@ class Model(Lister, BaseClient):
737
777
  >>> from clarifai.client.model import Model
738
778
  >>> model = Model("https://clarifai.com/openai/chat-completion/models/GPT-4")
739
779
  >>> stream_response = model.generate_by_bytes(b'Write a tweet on future of AI',
740
- input_type='text',
741
780
  deployment_id='deployment_id',
742
781
  inference_params=dict(temperature=str(0.7), max_tokens=30)))
743
782
  >>> list_stream_response = [response for response in stream_response]
744
783
  """
745
- if input_type not in {'image', 'text', 'video', 'audio'}:
746
- raise UserError(
747
- f"Got input type {input_type} but expected one of image, text, video, audio.")
748
- if not isinstance(input_bytes, bytes):
749
- raise UserError('Invalid bytes.')
784
+ self._check_predict_input_type(input_type)
750
785
 
751
- if input_type == "image":
786
+ if self.input_types[0] == "image":
752
787
  input_proto = Inputs.get_input_from_bytes("", image_bytes=input_bytes)
753
- elif input_type == "text":
788
+ elif self.input_types[0] == "text":
754
789
  input_proto = Inputs.get_input_from_bytes("", text_bytes=input_bytes)
755
- elif input_type == "video":
790
+ elif self.input_types[0] == "video":
756
791
  input_proto = Inputs.get_input_from_bytes("", video_bytes=input_bytes)
757
- elif input_type == "audio":
792
+ elif self.input_types[0] == "audio":
758
793
  input_proto = Inputs.get_input_from_bytes("", audio_bytes=input_bytes)
759
794
 
760
795
  if deployment_id and (compute_cluster_id or nodepool_id):
@@ -777,7 +812,7 @@ class Model(Lister, BaseClient):
777
812
 
778
813
  def generate_by_url(self,
779
814
  url: str,
780
- input_type: str,
815
+ input_type: str = None,
781
816
  compute_cluster_id: str = None,
782
817
  nodepool_id: str = None,
783
818
  deployment_id: str = None,
@@ -787,7 +822,7 @@ class Model(Lister, BaseClient):
787
822
 
788
823
  Args:
789
824
  url (str): The URL to predict.
790
- input_type (str): The type of input. Can be 'image', 'text', 'video' or 'audio.
825
+ input_type (str, optional): The type of input. Can be 'image', 'text', 'video' or 'audio.
791
826
  compute_cluster_id (str): The compute cluster ID to use for the model.
792
827
  nodepool_id (str): The nodepool ID to use for the model.
793
828
  deployment_id (str): The deployment ID to use for the model.
@@ -802,20 +837,18 @@ class Model(Lister, BaseClient):
802
837
  >>> model = Model("url") # Example URL: https://clarifai.com/clarifai/main/models/general-image-recognition
803
838
  or
804
839
  >>> model = Model(model_id='model_id', user_id='user_id', app_id='app_id')
805
- >>> stream_response = model.generate_by_url('url', 'image', deployment_id='deployment_id')
840
+ >>> stream_response = model.generate_by_url('url', deployment_id='deployment_id')
806
841
  >>> list_stream_response = [response for response in stream_response]
807
842
  """
808
- if input_type not in {'image', 'text', 'video', 'audio'}:
809
- raise UserError(
810
- f"Got input type {input_type} but expected one of image, text, video, audio.")
843
+ self._check_predict_input_type(input_type)
811
844
 
812
- if input_type == "image":
845
+ if self.input_types[0] == "image":
813
846
  input_proto = Inputs.get_input_from_url("", image_url=url)
814
- elif input_type == "text":
847
+ elif self.input_types[0] == "text":
815
848
  input_proto = Inputs.get_input_from_url("", text_url=url)
816
- elif input_type == "video":
849
+ elif self.input_types[0] == "video":
817
850
  input_proto = Inputs.get_input_from_url("", video_url=url)
818
- elif input_type == "audio":
851
+ elif self.input_types[0] == "audio":
819
852
  input_proto = Inputs.get_input_from_url("", audio_url=url)
820
853
 
821
854
  if deployment_id and (compute_cluster_id or nodepool_id):
@@ -893,7 +926,7 @@ class Model(Lister, BaseClient):
893
926
 
894
927
  def stream_by_filepath(self,
895
928
  filepath: str,
896
- input_type: str,
929
+ input_type: str = None,
897
930
  compute_cluster_id: str = None,
898
931
  nodepool_id: str = None,
899
932
  deployment_id: str = None,
@@ -903,7 +936,7 @@ class Model(Lister, BaseClient):
903
936
 
904
937
  Args:
905
938
  filepath (str): The filepath to predict.
906
- input_type (str): The type of input. Can be 'image', 'text', 'video' or 'audio.
939
+ input_type (str, optional): The type of input. Can be 'image', 'text', 'video' or 'audio.
907
940
  compute_cluster_id (str): The compute cluster ID to use for the model.
908
941
  nodepool_id (str): The nodepool ID to use for the model.
909
942
  deployment_id (str): The deployment ID to use for the model.
@@ -916,7 +949,7 @@ class Model(Lister, BaseClient):
916
949
  Example:
917
950
  >>> from clarifai.client.model import Model
918
951
  >>> model = Model("url")
919
- >>> stream_response = model.stream_by_filepath('/path/to/image.jpg', 'image', deployment_id='deployment_id')
952
+ >>> stream_response = model.stream_by_filepath('/path/to/image.jpg', deployment_id='deployment_id')
920
953
  >>> list_stream_response = [response for response in stream_response]
921
954
  """
922
955
  if not os.path.isfile(filepath):
@@ -936,7 +969,7 @@ class Model(Lister, BaseClient):
936
969
 
937
970
  def stream_by_bytes(self,
938
971
  input_bytes_iterator: Iterator[bytes],
939
- input_type: str,
972
+ input_type: str = None,
940
973
  compute_cluster_id: str = None,
941
974
  nodepool_id: str = None,
942
975
  deployment_id: str = None,
@@ -946,7 +979,7 @@ class Model(Lister, BaseClient):
946
979
 
947
980
  Args:
948
981
  input_bytes_iterator (Iterator[bytes]): Iterator of file bytes to predict on.
949
- input_type (str): The type of input. Can be 'image', 'text', 'video' or 'audio.
982
+ input_type (str, optional): The type of input. Can be 'image', 'text', 'video' or 'audio.
950
983
  compute_cluster_id (str): The compute cluster ID to use for the model.
951
984
  nodepool_id (str): The nodepool ID to use for the model.
952
985
  deployment_id (str): The deployment ID to use for the model.
@@ -960,24 +993,21 @@ class Model(Lister, BaseClient):
960
993
  >>> from clarifai.client.model import Model
961
994
  >>> model = Model("https://clarifai.com/openai/chat-completion/models/GPT-4")
962
995
  >>> stream_response = model.stream_by_bytes(iter([b'Write a tweet on future of AI']),
963
- input_type='text',
964
996
  deployment_id='deployment_id',
965
997
  inference_params=dict(temperature=str(0.7), max_tokens=30)))
966
998
  >>> list_stream_response = [response for response in stream_response]
967
999
  """
968
- if input_type not in {'image', 'text', 'video', 'audio'}:
969
- raise UserError(
970
- f"Got input type {input_type} but expected one of image, text, video, audio.")
1000
+ self._check_predict_input_type(input_type)
971
1001
 
972
1002
  def input_generator():
973
1003
  for input_bytes in input_bytes_iterator:
974
- if input_type == "image":
1004
+ if self.input_types[0] == "image":
975
1005
  yield [Inputs.get_input_from_bytes("", image_bytes=input_bytes)]
976
- elif input_type == "text":
1006
+ elif self.input_types[0] == "text":
977
1007
  yield [Inputs.get_input_from_bytes("", text_bytes=input_bytes)]
978
- elif input_type == "video":
1008
+ elif self.input_types[0] == "video":
979
1009
  yield [Inputs.get_input_from_bytes("", video_bytes=input_bytes)]
980
- elif input_type == "audio":
1010
+ elif self.input_types[0] == "audio":
981
1011
  yield [Inputs.get_input_from_bytes("", audio_bytes=input_bytes)]
982
1012
 
983
1013
  if deployment_id and (compute_cluster_id or nodepool_id):
@@ -1000,7 +1030,7 @@ class Model(Lister, BaseClient):
1000
1030
 
1001
1031
  def stream_by_url(self,
1002
1032
  url_iterator: Iterator[str],
1003
- input_type: str,
1033
+ input_type: str = None,
1004
1034
  compute_cluster_id: str = None,
1005
1035
  nodepool_id: str = None,
1006
1036
  deployment_id: str = None,
@@ -1010,7 +1040,7 @@ class Model(Lister, BaseClient):
1010
1040
 
1011
1041
  Args:
1012
1042
  url_iterator (Iterator[str]): Iterator of URLs to predict.
1013
- input_type (str): The type of input. Can be 'image', 'text', 'video' or 'audio.
1043
+ input_type (str, optional): The type of input. Can be 'image', 'text', 'video' or 'audio.
1014
1044
  compute_cluster_id (str): The compute cluster ID to use for the model.
1015
1045
  nodepool_id (str): The nodepool ID to use for the model.
1016
1046
  deployment_id (str): The deployment ID to use for the model.
@@ -1023,22 +1053,20 @@ class Model(Lister, BaseClient):
1023
1053
  Example:
1024
1054
  >>> from clarifai.client.model import Model
1025
1055
  >>> model = Model("url")
1026
- >>> stream_response = model.stream_by_url(iter(['url']), 'image', deployment_id='deployment_id')
1056
+ >>> stream_response = model.stream_by_url(iter(['url']), deployment_id='deployment_id')
1027
1057
  >>> list_stream_response = [response for response in stream_response]
1028
1058
  """
1029
- if input_type not in {'image', 'text', 'video', 'audio'}:
1030
- raise UserError(
1031
- f"Got input type {input_type} but expected one of image, text, video, audio.")
1059
+ self._check_predict_input_type(input_type)
1032
1060
 
1033
1061
  def input_generator():
1034
1062
  for url in url_iterator:
1035
- if input_type == "image":
1063
+ if self.input_types[0] == "image":
1036
1064
  yield [Inputs.get_input_from_url("", image_url=url)]
1037
- elif input_type == "text":
1065
+ elif self.input_types[0] == "text":
1038
1066
  yield [Inputs.get_input_from_url("", text_url=url)]
1039
- elif input_type == "video":
1067
+ elif self.input_types[0] == "video":
1040
1068
  yield [Inputs.get_input_from_url("", video_url=url)]
1041
- elif input_type == "audio":
1069
+ elif self.input_types[0] == "audio":
1042
1070
  yield [Inputs.get_input_from_url("", audio_url=url)]
1043
1071
 
1044
1072
  if deployment_id and (compute_cluster_id or nodepool_id):
@@ -5,10 +5,12 @@ from typing import Dict, Generator, List
5
5
  from clarifai_grpc.grpc.api import resources_pb2, service_pb2
6
6
  from clarifai_grpc.grpc.api.resources_pb2 import Input
7
7
  from clarifai_grpc.grpc.api.status import status_code_pb2
8
+ from google.protobuf.json_format import MessageToDict
8
9
 
9
10
  from clarifai.client.base import BaseClient
10
11
  from clarifai.client.input import Inputs
11
12
  from clarifai.client.lister import Lister
13
+ from clarifai.client.model import Model
12
14
  from clarifai.constants.workflow import MAX_WORKFLOW_PREDICT_INPUTS
13
15
  from clarifai.errors import UserError
14
16
  from clarifai.urls.helper import ClarifaiUrlHelper
@@ -60,6 +62,7 @@ class Workflow(Lister, BaseClient):
60
62
  self.output_config = output_config
61
63
  self.workflow_info = resources_pb2.Workflow(**self.kwargs)
62
64
  self.logger = logger
65
+ self.input_types = None
63
66
  BaseClient.__init__(
64
67
  self,
65
68
  user_id=self.user_id,
@@ -109,20 +112,26 @@ class Workflow(Lister, BaseClient):
109
112
 
110
113
  return response
111
114
 
112
- def predict_by_filepath(self, filepath: str, input_type: str):
115
+ def predict_by_filepath(self, filepath: str, input_type: str = None):
113
116
  """Predicts the workflow based on the given filepath.
114
117
 
115
118
  Args:
116
119
  filepath (str): The filepath to predict.
117
- input_type (str): The type of input. Can be 'image', 'text', 'video' or 'audio.
120
+ input_type (str, optional): The type of input. Can be 'image', 'text', 'video' or 'audio.
118
121
 
119
122
  Example:
120
123
  >>> from clarifai.client.workflow import Workflow
121
124
  >>> workflow = Workflow("url") # Example: https://clarifai.com/clarifai/main/workflows/Face-Sentiment
122
125
  or
123
126
  >>> workflow = Workflow(user_id='user_id', app_id='app_id', workflow_id='workflow_id')
124
- >>> workflow_prediction = workflow.predict_by_filepath('filepath', 'image')
127
+ >>> workflow_prediction = workflow.predict_by_filepath('filepath')
125
128
  """
129
+ if not input_type:
130
+ self.load_info()
131
+ if len(self.input_types) > 1:
132
+ raise UserError("Workflow has multiple input types. Please use workflow.predict().")
133
+ input_type = self.input_types[0]
134
+
126
135
  if input_type not in {'image', 'text', 'video', 'audio'}:
127
136
  raise UserError('Invalid input type it should be image, text, video or audio.')
128
137
  if not os.path.isfile(filepath):
@@ -133,13 +142,19 @@ class Workflow(Lister, BaseClient):
133
142
 
134
143
  return self.predict_by_bytes(file_bytes, input_type)
135
144
 
136
- def predict_by_bytes(self, input_bytes: bytes, input_type: str):
145
+ def predict_by_bytes(self, input_bytes: bytes, input_type: str = None):
137
146
  """Predicts the workflow based on the given bytes.
138
147
 
139
148
  Args:
140
149
  input_bytes (bytes): Bytes to predict on.
141
- input_type (str): The type of input. Can be 'image', 'text', 'video' or 'audio.
150
+ input_type (str, optional): The type of input. Can be 'image', 'text', 'video' or 'audio.
142
151
  """
152
+ if not input_type:
153
+ self.load_info()
154
+ if len(self.input_types) > 1:
155
+ raise UserError("Workflow has multiple input types. Please use workflow.predict().")
156
+ input_type = self.input_types[0]
157
+
143
158
  if input_type not in {'image', 'text', 'video', 'audio'}:
144
159
  raise UserError('Invalid input type it should be image, text, video or audio.')
145
160
  if not isinstance(input_bytes, bytes):
@@ -156,20 +171,26 @@ class Workflow(Lister, BaseClient):
156
171
 
157
172
  return self.predict(inputs=[input_proto])
158
173
 
159
- def predict_by_url(self, url: str, input_type: str):
174
+ def predict_by_url(self, url: str, input_type: str = None):
160
175
  """Predicts the workflow based on the given URL.
161
176
 
162
177
  Args:
163
178
  url (str): The URL to predict.
164
- input_type (str): The type of input. Can be 'image', 'text', 'video' or 'audio.
179
+ input_type (str, optional): The type of input. Can be 'image', 'text', 'video' or 'audio.
165
180
 
166
181
  Example:
167
182
  >>> from clarifai.client.workflow import Workflow
168
183
  >>> workflow = Workflow("url") # Example: https://clarifai.com/clarifai/main/workflows/Face-Sentiment
169
184
  or
170
185
  >>> workflow = Workflow(user_id='user_id', app_id='app_id', workflow_id='workflow_id')
171
- >>> workflow_prediction = workflow.predict_by_url('url', 'image')
186
+ >>> workflow_prediction = workflow.predict_by_url('url')
172
187
  """
188
+ if not input_type:
189
+ self.load_info()
190
+ if len(self.input_types) > 1:
191
+ raise UserError("Workflow has multiple input types. Please use workflow.predict().")
192
+ input_type = self.input_types[0]
193
+
173
194
  if input_type not in {'image', 'text', 'video', 'audio'}:
174
195
  raise UserError('Invalid input type it should be image, text, video or audio.')
175
196
 
@@ -245,6 +266,25 @@ class Workflow(Lister, BaseClient):
245
266
 
246
267
  self.logger.info(f"Exported workflow to {out_path}")
247
268
 
269
+ def load_info(self) -> None:
270
+ """Loads the workflow info."""
271
+ if not self.input_types:
272
+ request = service_pb2.GetWorkflowRequest(user_app_id=self.user_app_id, workflow_id=self.id)
273
+ response = self._grpc_request(self.STUB.GetWorkflow, request)
274
+ if response.status.code != status_code_pb2.SUCCESS:
275
+ raise Exception(f"Workflow Get failed with response {response.status!r}")
276
+
277
+ dict_response = MessageToDict(response, preserving_proto_field_name=True)
278
+ self.kwargs = self.process_response_keys(dict_response['workflow'])
279
+ self.workflow_info = resources_pb2.Workflow(**self.kwargs)
280
+
281
+ model = Model(
282
+ model_id=self.kwargs['nodes'][0]['model']['id'],
283
+ **self.kwargs['nodes'][0]['model'],
284
+ pat=self.pat)
285
+ model.load_input_types()
286
+ self.input_types = model.input_types
287
+
248
288
  def __getattr__(self, name):
249
289
  return getattr(self.workflow_info, name)
250
290
 
@@ -192,9 +192,11 @@ class InputAnnotationDownloader:
192
192
  self._save_video_to_archive(new_archive, hosted_url, file_name)
193
193
  self.num_inputs += 1
194
194
 
195
- if data_dict.get("concepts") or data_dict.get("regions"):
195
+ if data_dict.get("metadata") or data_dict.get("concepts") or data_dict.get("regions"):
196
196
  file_name = os.path.join(split, "annotations", input_.id + ".json")
197
- annot_data = data_dict.get("regions", []) + data_dict.get("concepts", [])
197
+ annot_data = [{
198
+ "metadata": data_dict.get("metadata", {})
199
+ }] + data_dict.get("regions", []) + data_dict.get("concepts", [])
198
200
 
199
201
  self._save_annotation_to_archive(new_archive, annot_data, file_name)
200
202
  self.num_annotations += 1
@@ -143,7 +143,7 @@ class DisplayUploadStatus:
143
143
 
144
144
  for data in dict_response["datasetVersionMetricsGroups"]:
145
145
  if isinstance(data["value"], str):
146
- if data["value"].startswith("id-"):
146
+ if ("type" in data) and (data["type"] == "CONCEPT_ID"):
147
147
  data["metrics"].update({"Concept": data["value"]})
148
148
  data["metrics"].pop("regionLocationMatrix", None)
149
149
  dataset_statistics.append(data["metrics"])
@@ -1,4 +1,3 @@
1
- import argparse
2
1
  import importlib.util
3
2
  import inspect
4
3
  import os
@@ -126,6 +125,7 @@ class ModelRunLocally:
126
125
  runner_id="n/a",
127
126
  nodepool_id="n/a",
128
127
  compute_cluster_id="n/a",
128
+ user_id="n/a",
129
129
  )
130
130
 
131
131
  # send an inference.
@@ -175,22 +175,16 @@ class ModelRunLocally:
175
175
  shutil.rmtree(self.temp_dir)
176
176
 
177
177
 
178
- def main():
179
- parser = argparse.ArgumentParser()
180
- parser.add_argument(
181
- '--model_path', type=str, required=True, help='Path of the model folder to upload')
182
- args = parser.parse_args()
178
+ def main(model_path, run_model_server=False):
183
179
 
184
- model_path = args.model_path
185
180
  manager = ModelRunLocally(model_path)
186
181
  manager.create_temp_venv()
187
182
 
188
183
  try:
189
184
  manager.install_requirements()
190
- manager.test_model()
185
+ if run_model_server:
186
+ manager.run_model_server()
187
+ else:
188
+ manager.test_model()
191
189
  finally:
192
190
  manager.clean_up()
193
-
194
-
195
- if __name__ == "__main__":
196
- main()
@@ -28,7 +28,7 @@ class ModelServicer(service_pb2_grpc.V2Servicer):
28
28
  """
29
29
 
30
30
  # Download any urls that are not already bytes.
31
- ensure_urls_downloaded(self.url_fetcher, request)
31
+ ensure_urls_downloaded(request)
32
32
 
33
33
  try:
34
34
  return self.model_class.predict(request)
@@ -47,7 +47,7 @@ class ModelServicer(service_pb2_grpc.V2Servicer):
47
47
  returns an output.
48
48
  """
49
49
  # Download any urls that are not already bytes.
50
- ensure_urls_downloaded(self.url_fetcher, request)
50
+ ensure_urls_downloaded(request)
51
51
 
52
52
  try:
53
53
  return self.model_class.generate(request)
@@ -71,7 +71,7 @@ class ModelServicer(service_pb2_grpc.V2Servicer):
71
71
 
72
72
  # Download any urls that are not already bytes.
73
73
  for req in request:
74
- ensure_urls_downloaded(self.url_fetcher, req)
74
+ ensure_urls_downloaded(req)
75
75
 
76
76
  try:
77
77
  return self.model_class.stream(request_copy)
@@ -1,4 +1,3 @@
1
- import argparse
2
1
  import os
3
2
  import time
4
3
  from string import Template
@@ -409,11 +408,11 @@ class ModelUploader:
409
408
  return False
410
409
 
411
410
 
412
- def main(folder, download_checkpoints):
411
+ def main(folder, download_checkpoints, skip_dockerfile):
413
412
  uploader = ModelUploader(folder)
414
413
  if download_checkpoints:
415
414
  uploader.download_checkpoints()
416
- if not args.skip_dockerfile:
415
+ if not skip_dockerfile:
417
416
  uploader.create_dockerfile()
418
417
  exists = uploader.check_model_exists()
419
418
  if exists:
@@ -425,25 +424,3 @@ def main(folder, download_checkpoints):
425
424
 
426
425
  input("Press Enter to continue...")
427
426
  uploader.upload_model_version(download_checkpoints)
428
-
429
-
430
- if __name__ == "__main__":
431
- parser = argparse.ArgumentParser()
432
- parser.add_argument(
433
- '--model_path', type=str, help='Path of the model folder to upload', required=True)
434
- # flag to default to not download checkpoints
435
- parser.add_argument(
436
- '--download_checkpoints',
437
- action='store_true',
438
- help=
439
- 'Flag to download checkpoints before uploading and including them in the tar file that is uploaded. Defaults to False, which will attempt to download them at docker build time.',
440
- )
441
- parser.add_argument(
442
- '--skip_dockerfile',
443
- action='store_true',
444
- help=
445
- 'Flag to skip generating a dockerfile so that you can manually edit an already created dockerfile.',
446
- )
447
- args = parser.parse_args()
448
-
449
- main(args.model_path, args.download_checkpoints)
clarifai/utils/cli.py ADDED
@@ -0,0 +1,45 @@
1
+ import importlib
2
+ import os
3
+ import pkgutil
4
+
5
+ import click
6
+ import yaml
7
+
8
+
9
+ def from_yaml(filename: str):
10
+ try:
11
+ with open(filename, 'r') as f:
12
+ return yaml.safe_load(f)
13
+ except yaml.YAMLError as e:
14
+ click.echo(f"Error reading YAML file: {e}", err=True)
15
+ return {}
16
+
17
+
18
+ def dump_yaml(data, filename: str):
19
+ try:
20
+ with open(filename, 'w') as f:
21
+ yaml.dump(data, f)
22
+ except Exception as e:
23
+ click.echo(f"Error writing YAML file: {e}", err=True)
24
+
25
+
26
+ def set_base_url(env):
27
+ environments = {
28
+ 'prod': 'https://api.clarifai.com',
29
+ 'staging': 'https://api-staging.clarifai.com',
30
+ 'dev': 'https://api-dev.clarifai.com'
31
+ }
32
+
33
+ if env in environments:
34
+ return environments[env]
35
+ else:
36
+ raise ValueError("Invalid environment. Please choose from 'prod', 'staging', 'dev'.")
37
+
38
+
39
+ # Dynamically find and import all command modules from the cli directory
40
+ def load_command_modules():
41
+ package_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'cli')
42
+
43
+ for _, module_name, _ in pkgutil.iter_modules([package_dir]):
44
+ if module_name != 'base': # Skip the base.py file itself
45
+ importlib.import_module(f'clarifai.cli.{module_name}')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: clarifai
3
- Version: 10.9.2
3
+ Version: 10.9.4
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.9.4
23
+ Requires-Dist: clarifai-grpc >=10.9.11
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
@@ -33,15 +33,17 @@ Requires-Dist: inquirerpy ==0.3.4
33
33
  Requires-Dist: tabulate >=0.9.0
34
34
  Requires-Dist: protobuf ==5.27.3
35
35
  Requires-Dist: fsspec ==2024.6.1
36
+ Requires-Dist: click ==8.1.7
36
37
  Provides-Extra: all
37
38
  Requires-Dist: pycocotools ==2.0.6 ; extra == 'all'
38
39
 
39
40
  <h1 align="center">
40
- <a href="https://www.clarifai.com/"><img alt="Clarifai" title="Clarifai" src="https://upload.wikimedia.org/wikipedia/commons/b/bc/Clarifai_Logo_FC_Web.png"></a>
41
+ <a href="https://www.clarifai.com/"><img alt="Clarifai" title="Clarifai" src="https://github.com/user-attachments/assets/623b883b-7fe5-4b95-bbfa-8691f5779af4"></a>
41
42
  </h1>
42
43
 
44
+
43
45
  <h2 align="center">
44
- Clarifai Python SDK</a>
46
+ Clarifai Python SDK
45
47
  </h2>
46
48
 
47
49
 
@@ -51,6 +53,8 @@ Clarifai Python SDK</a>
51
53
  </a>
52
54
  <a href="https://pypi.org/project/clarifai" target="_blank"> <img src="https://img.shields.io/pypi/dm/clarifai" alt="PyPI - Downloads">
53
55
  </a>
56
+ <a href="https://img.shields.io/pypi/pyversions/clarifai" target="_blank"> <img src="https://img.shields.io/pypi/pyversions/clarifai" alt="PyPI - Versions">
57
+ </a>
54
58
  </p>
55
59
 
56
60
 
@@ -261,19 +265,19 @@ print(gpt_4_model)
261
265
 
262
266
 
263
267
  # Model Predict
264
- model_prediction = Model("https://clarifai.com/anthropic/completion/models/claude-v2").predict_by_bytes(b"Write a tweet on future of AI", input_type="text")
268
+ model_prediction = Model("https://clarifai.com/anthropic/completion/models/claude-v2").predict_by_bytes(b"Write a tweet on future of AI")
265
269
 
266
270
  # Customizing Model Inference Output
267
- model_prediction = gpt_4_model.predict_by_bytes(b"Write a tweet on future of AI", "text", inference_params=dict(temperature=str(0.7), max_tokens=30))
271
+ model_prediction = gpt_4_model.predict_by_bytes(b"Write a tweet on future of AI", inference_params=dict(temperature=str(0.7), max_tokens=30))
268
272
  # Return predictions having prediction confidence > 0.98
269
- model_prediction = model.predict_by_filepath(filepath="local_filepath", input_type, output_config={"min_value": 0.98}) # Supports image, text, audio, video
273
+ model_prediction = model.predict_by_filepath(filepath="local_filepath", output_config={"min_value": 0.98}) # Supports image, text, audio, video
270
274
 
271
275
  # Supports prediction by url
272
- model_prediction = model.predict_by_url(url="url", input_type) # Supports image, text, audio, video
276
+ model_prediction = model.predict_by_url(url="url") # Supports image, text, audio, video
273
277
 
274
278
  # Return predictions for specified interval of video
275
279
  video_input_proto = [input_obj.get_input_from_url("Input_id", video_url=BEER_VIDEO_URL)]
276
- model_prediction = model.predict(video_input_proto, input_type="video", output_config={"sample_ms": 2000})
280
+ model_prediction = model.predict(video_input_proto, output_config={"sample_ms": 2000})
277
281
  ```
278
282
  #### Model Training
279
283
  ```python
@@ -383,12 +387,12 @@ from clarifai.client.workflow import Workflow
383
387
 
384
388
  # Workflow Predict
385
389
  workflow = Workflow("workflow_url") # Example: https://clarifai.com/clarifai/main/workflows/Face-Sentiment
386
- workflow_prediction = workflow.predict_by_url(url="url", input_type="image") # Supports image, text, audio, video
390
+ workflow_prediction = workflow.predict_by_url(url="url") # Supports image, text, audio, video
387
391
 
388
392
  # Customizing Workflow Inference Output
389
393
  workflow = Workflow(user_id="user_id", app_id="app_id", workflow_id="workflow_id",
390
394
  output_config={"min_value": 0.98}) # Return predictions having prediction confidence > 0.98
391
- workflow_prediction = workflow.predict_by_filepath(filepath="local_filepath", input_type="text") # Supports image, text, audio, video
395
+ workflow_prediction = workflow.predict_by_filepath(filepath="local_filepath") # Supports image, text, audio, video
392
396
  ```
393
397
 
394
398
  #### Workflows Listing
@@ -1,23 +1,26 @@
1
- clarifai/__init__.py,sha256=pIn_ah9SsqsljuRvOukQQ4KCQQ4aaDew3A8OtaeuEqU,23
1
+ clarifai/__init__.py,sha256=60DFxKRLc905eL5FiLBS5Dd9SsZV4LlHGOJDJmZ3CTM,23
2
2
  clarifai/cli.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  clarifai/errors.py,sha256=RwzTajwds51wLD0MVlMC5kcpBnzRpreDLlazPSBZxrg,2605
4
4
  clarifai/versions.py,sha256=jctnczzfGk_S3EnVqb2FjRKfSREkNmvNEwAAa_VoKiQ,222
5
+ clarifai/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ clarifai/cli/base.py,sha256=N3dBmpH6XDSekMvwD_lrMpRe9CuwfR_RkJ612iDir6U,2228
7
+ clarifai/cli/model.py,sha256=O0GZWbTF8ZMNpSn7KTYpMiMsAULAWkTFWBucaLqVcZg,1925
5
8
  clarifai/client/__init__.py,sha256=xI1U0l5AZdRThvQAXCLsd9axxyFzXXJ22m8LHqVjQRU,662
6
9
  clarifai/client/app.py,sha256=6pckYme1urV2YJjLIYfeZ-vH0Z5YSQa51jzIMcEfwug,38342
7
10
  clarifai/client/base.py,sha256=hSHOqkXbSKyaRDeylMMnkhUHCAHhEqno4KI0CXGziBA,7536
8
11
  clarifai/client/compute_cluster.py,sha256=lntZDLVDhS71Yj7mZrgq5uhnAuNPUnj48i3zMSuoUpk,8693
9
12
  clarifai/client/dataset.py,sha256=Xt8M9sP7RLeAqqTu17-8cpupThhkU9n_bl6jXtG_25A,31148
10
13
  clarifai/client/deployment.py,sha256=4gfvUvQY9adFS98B0vP9C5fR9OnDRV2JbUIdAkMymT8,2551
11
- clarifai/client/input.py,sha256=cEVRytrMF1gCgwHLbXlSbPSEQN8uHpUAoKcCdyHO1pc,44406
14
+ clarifai/client/input.py,sha256=smAZqvBEVJlM59PQ3KhqbA6HaKHRNlSyQCcw917SbJ0,44322
12
15
  clarifai/client/lister.py,sha256=03KGMvs5RVyYqxLsSrWhNc34I8kiF1Ph0NeyEwu7nMU,2082
13
- clarifai/client/model.py,sha256=jNTyCxrME4vbU3Qw9nMSFwg4Ud8AuJrsmVYOMLBtbLI,83846
16
+ clarifai/client/model.py,sha256=WmLBPm_rDzbPR_Cxo8gnntBnPiWFt3gYKiiKuJ9lH04,84652
14
17
  clarifai/client/module.py,sha256=FTkm8s9m-EaTKN7g9MnLhGJ9eETUfKG7aWZ3o1RshYs,4204
15
18
  clarifai/client/nodepool.py,sha256=DK8oqswjjrP6TqCqbw7Ge51Z7PxK3XmWZGLeUM3fd_A,10142
16
19
  clarifai/client/search.py,sha256=GaPWN6JmTQGZaCHr6U1yv0zqR6wKFl7i9IVLg2ul1CI,14254
17
20
  clarifai/client/user.py,sha256=0tcOk8_Yd1_ANj9E6sy9mz6s01V3qkmJS7pZVn_zUYo,17637
18
- clarifai/client/workflow.py,sha256=Wm4Fry6lGx8T43sBUqRI7v7sAmuvq_4Jft3vSW8UUJU,10516
21
+ clarifai/client/workflow.py,sha256=BOmA1ilHxsw-yl_ZE1NOEshzV7owavnXTIG2UOD6PuA,12163
19
22
  clarifai/client/auth/__init__.py,sha256=7EwR0NrozkAUwpUnCsqXvE_p0wqx_SelXlSpKShKJK0,136
20
- clarifai/client/auth/helper.py,sha256=BuyI_smxuRq__8RF0Nv3lr_Rmb-CJVEyK4hv60VEV5A,14259
23
+ clarifai/client/auth/helper.py,sha256=1QmQatzVdWDm4J20kgiHioM1lfHlgkGxWboO3z02QAI,14593
21
24
  clarifai/client/auth/register.py,sha256=2CMdBsoVLoTfjyksE6j7BM2tiEc73WKYvxnwDDgNn1k,536
22
25
  clarifai/client/auth/stub.py,sha256=xy4-fV0W8keCgXld4eOVzFQEIKxOktNwtL5bLztReug,4940
23
26
  clarifai/constants/base.py,sha256=ogmFSZYoF0YhGjHg5aiOc3MLqPr_poKAls6xaD0_C3U,89
@@ -29,14 +32,14 @@ clarifai/constants/search.py,sha256=yYEqTaFg-KdnpJE_Ytp-EPVHIIC395iNtZrpVlLIf4o,
29
32
  clarifai/constants/workflow.py,sha256=cECq1xdvf44MCdtK2AbkiuuwhyL-6OWZdQfYbsLKy_o,33
30
33
  clarifai/datasets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
34
  clarifai/datasets/export/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
- clarifai/datasets/export/inputs_annotations.py,sha256=Mwo-wFRIYXsoe13bR2bfsXViA6DlJbWmNuPpD3yHSrE,9701
35
+ clarifai/datasets/export/inputs_annotations.py,sha256=vqe3CBlWTgeBnIoRnjwIRnOj5QmH1480efSk8tv2mCg,9796
33
36
  clarifai/datasets/upload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
37
  clarifai/datasets/upload/base.py,sha256=UIc0ufyIBCrb83_sFpv21L8FshsX4nwsLYQkdlJfzD4,2357
35
38
  clarifai/datasets/upload/features.py,sha256=jv2x7jGZKS-LMt87sEZNBwwOskHbP26XTMjoiaSA5pg,2024
36
39
  clarifai/datasets/upload/image.py,sha256=HlCsfEMu_C4GVecGSv52RUJ6laLW8H64Pfj_FQyX6qg,8580
37
40
  clarifai/datasets/upload/multimodal.py,sha256=2_s4SCotzacVMdnqkM7upSR3Ovxh3b9oW1hSWhKyxO4,2373
38
41
  clarifai/datasets/upload/text.py,sha256=boVJenfQZKf79aXu8CEP4g_ANzX5ROdd06g07O7RnXU,2198
39
- clarifai/datasets/upload/utils.py,sha256=h7mtN9FZXhQQbf47EXczgb-NTY2uOE9AJlE9u4-hDwI,9627
42
+ clarifai/datasets/upload/utils.py,sha256=BerWhq40ZUN30z6VImlc93eZtT-1vI18AMgSOuNzJEM,9647
40
43
  clarifai/datasets/upload/loaders/README.md,sha256=aNRutSCTzLp2ruIZx74ZkN5AxpzwKOxMa7OzabnKpwg,2980
41
44
  clarifai/datasets/upload/loaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
45
  clarifai/datasets/upload/loaders/coco_captions.py,sha256=YfuNXplbdoH8N9ph7RyN9MfJTtOcJBG4ie1ow6-mELA,1516
@@ -60,10 +63,10 @@ clarifai/runners/dockerfile_template/Dockerfile.cuda.template,sha256=8uQp2sX_bIz
60
63
  clarifai/runners/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
64
  clarifai/runners/models/base_typed_model.py,sha256=OnAk08Lo2Y1fGiBc6JJ6UvJ8P435cTsikTNYDkStDpI,7790
62
65
  clarifai/runners/models/model_class.py,sha256=9JSPAr4U4K7xI0kSl-q0mHB06zknm2OR-8XIgBCto94,1611
63
- clarifai/runners/models/model_run_locally.py,sha256=eP_QFx3fuoKbf5VyRm-rfD9k6fLrXG7u1EaWz-Qjr68,6720
66
+ clarifai/runners/models/model_run_locally.py,sha256=xbNcD0TMRlk52cUjJH-qenlkeiwS4YcOeb8eYy7KAEI,6583
64
67
  clarifai/runners/models/model_runner.py,sha256=3vzoastQxkGRDK8T9aojDsLNBb9A3IiKm6YmbFrE9S0,6241
65
- clarifai/runners/models/model_servicer.py,sha256=L5AuqKDZrsKOnv_Fz1Ld4-nzqehltLTsYAS7NIclm1g,2880
66
- clarifai/runners/models/model_upload.py,sha256=7Oi09Y93WUH7EKTzrKf6JQawZzLj3EnmWUDUgHOrFq8,17654
68
+ clarifai/runners/models/model_servicer.py,sha256=X4715PVA5PBurRTYcwSEudg8fShGV6InAF4mmRlRcHg,2826
69
+ clarifai/runners/models/model_upload.py,sha256=cfxHfNbnVLHjF50dDDVdAE5VDDTf8yF1o0HL5Rgvklc,16859
67
70
  clarifai/runners/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
71
  clarifai/runners/utils/data_handler.py,sha256=sxy9zlAgI6ETuxCQhUgEXAn2GCsaW1GxpK6GTaMne0g,6966
69
72
  clarifai/runners/utils/data_utils.py,sha256=R1iQ82TuQ9JwxCJk8yEB1Lyb0BYVhVbWJI9YDi1zGOs,318
@@ -72,6 +75,7 @@ clarifai/runners/utils/url_fetcher.py,sha256=-Hwjb1SURszn7zUVwi4Of0-nrksfZy-uqT4
72
75
  clarifai/schema/search.py,sha256=JjTi8ammJgZZ2OGl4K6tIA4zEJ1Fr2ASZARXavI1j5c,2448
73
76
  clarifai/urls/helper.py,sha256=tjoMGGHuWX68DUB0pk4MEjrmFsClUAQj2jmVEM_Sy78,4751
74
77
  clarifai/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
+ clarifai/utils/cli.py,sha256=avHgpKV3XP5V2L05Gpi458oiKJPV6qD5YSMdam52SlE,1175
75
79
  clarifai/utils/constants.py,sha256=MG_iHnSwNEyUZOpvsrTicNwaT4CIjmlK_Ixk_qqEX8g,142
76
80
  clarifai/utils/logging.py,sha256=rhutBRQJLtkNRz8IErNCgbIpvtl2fQ3D2otYcGqd3-Q,11565
77
81
  clarifai/utils/misc.py,sha256=ptjt1NtteDT0EhrPoyQ7mgWtvoAQ-XNncQaZvNHb0KI,2253
@@ -84,9 +88,9 @@ clarifai/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
84
88
  clarifai/workflows/export.py,sha256=vICRhIreqDSShxLKjHNM2JwzKsf1B4fdXB0ciMcA70k,1945
85
89
  clarifai/workflows/utils.py,sha256=nGeB_yjVgUO9kOeKTg4OBBaBz-AwXI3m-huSVj-9W18,1924
86
90
  clarifai/workflows/validate.py,sha256=yJq03MaJqi5AK3alKGJJBR89xmmjAQ31sVufJUiOqY8,2556
87
- clarifai-10.9.2.dist-info/LICENSE,sha256=mUqF_d12-qE2n41g7C5_sq-BMLOcj6CNN-jevr15YHU,555
88
- clarifai-10.9.2.dist-info/METADATA,sha256=BcdNjVzD08g4xW4RgxN-zkLGLsG2P590d6tAzY4f5ME,19479
89
- clarifai-10.9.2.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
90
- clarifai-10.9.2.dist-info/entry_points.txt,sha256=qZOr_MIPG0dBBE1zringDJS_wXNGTAA_SQ-zcbmDHOw,82
91
- clarifai-10.9.2.dist-info/top_level.txt,sha256=wUMdCQGjkxaynZ6nZ9FAnvBUCgp5RJUVFSy2j-KYo0s,9
92
- clarifai-10.9.2.dist-info/RECORD,,
91
+ clarifai-10.9.4.dist-info/LICENSE,sha256=mUqF_d12-qE2n41g7C5_sq-BMLOcj6CNN-jevr15YHU,555
92
+ clarifai-10.9.4.dist-info/METADATA,sha256=eurSyw4GH8EzpxT4K--6kUzbC4Eo9BuBtw_4VabmMKI,19565
93
+ clarifai-10.9.4.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
94
+ clarifai-10.9.4.dist-info/entry_points.txt,sha256=X9FZ4Z-i_r2Ud1RpZ9sNIFYuu_-9fogzCMCRUD9hyX0,51
95
+ clarifai-10.9.4.dist-info/top_level.txt,sha256=wUMdCQGjkxaynZ6nZ9FAnvBUCgp5RJUVFSy2j-KYo0s,9
96
+ clarifai-10.9.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.1.0)
2
+ Generator: setuptools (75.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ clarifai = clarifai.cli.base:cli
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- clarifai = clarifai.models.model_serving.cli.clarifai_clis:main