clarifai 11.8.4__py3-none-any.whl → 11.8.5__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__ = "11.8.4"
1
+ __version__ = "11.8.5"
@@ -11,6 +11,7 @@ from clarifai.constants.model import MAX_MODEL_PREDICT_INPUTS
11
11
  from clarifai.errors import UserError
12
12
  from clarifai.runners.utils import code_script, method_signatures
13
13
  from clarifai.runners.utils.method_signatures import (
14
+ RESERVED_PARAM_WITH_PROTO,
14
15
  CompatibilitySerializer,
15
16
  deserialize,
16
17
  get_stream_from_signature,
@@ -204,6 +205,9 @@ class ModelClient:
204
205
 
205
206
  def bind_f(method_name, method_argnames, call_func, async_call_func):
206
207
  def sync_f(*args, **kwargs):
208
+ # Extract with_proto parameter if present
209
+ with_proto = kwargs.pop(RESERVED_PARAM_WITH_PROTO, False)
210
+
207
211
  if len(args) > len(method_argnames):
208
212
  raise TypeError(
209
213
  f"{method_name}() takes {len(method_argnames)} positional arguments but {len(args)} were given"
@@ -221,7 +225,7 @@ class ModelClient:
221
225
  )
222
226
  if is_batch_input_valid and (not is_openai_chat_format(batch_inputs)):
223
227
  # If the batch input is valid, call the function with the batch inputs and the method name
224
- return call_func(batch_inputs, method_name)
228
+ return call_func(batch_inputs, method_name, with_proto=with_proto)
225
229
 
226
230
  for name, arg in zip(
227
231
  method_argnames, args
@@ -229,10 +233,13 @@ class ModelClient:
229
233
  if name in kwargs:
230
234
  raise TypeError(f"Multiple values for argument {name}")
231
235
  kwargs[name] = arg
232
- return call_func(kwargs, method_name)
236
+ return call_func(kwargs, method_name, with_proto=with_proto)
233
237
 
234
238
  async def async_f(*args, **kwargs):
235
239
  # Async version to call the async function
240
+ # Extract with_proto parameter if present
241
+ with_proto = kwargs.pop(RESERVED_PARAM_WITH_PROTO, False)
242
+
236
243
  if len(args) > len(method_argnames):
237
244
  raise TypeError(
238
245
  f"{method_name}() takes {len(method_argnames)} positional arguments but {len(args)} were given"
@@ -249,7 +256,9 @@ class ModelClient:
249
256
  )
250
257
  if is_batch_input_valid and (not is_openai_chat_format(batch_inputs)):
251
258
  # If the batch input is valid, call the function with the batch inputs and the method name
252
- return async_call_func(batch_inputs, method_name)
259
+ return async_call_func(
260
+ batch_inputs, method_name, with_proto=with_proto
261
+ )
253
262
 
254
263
  for name, arg in zip(
255
264
  method_argnames, args
@@ -258,7 +267,7 @@ class ModelClient:
258
267
  raise TypeError(f"Multiple values for argument {name}")
259
268
  kwargs[name] = arg
260
269
 
261
- return async_call_func(kwargs, method_name)
270
+ return async_call_func(kwargs, method_name, with_proto=with_proto)
262
271
 
263
272
  class MethodWrapper:
264
273
  def __call__(self, *args, **kwargs):
@@ -364,6 +373,7 @@ class ModelClient:
364
373
  self,
365
374
  inputs, # TODO set up functions according to fetched signatures?
366
375
  method_name: str = 'predict',
376
+ with_proto: bool = False,
367
377
  ) -> Any:
368
378
  input_signature = self._method_signatures[method_name].input_fields
369
379
  output_signature = self._method_signatures[method_name].output_fields
@@ -385,9 +395,12 @@ class ModelClient:
385
395
  outputs = []
386
396
  for output in response.outputs:
387
397
  outputs.append(deserialize(output.data, output_signature, is_output=True))
388
- if batch_input:
389
- return outputs
390
- return outputs[0]
398
+
399
+ result = outputs if batch_input else outputs[0]
400
+
401
+ if with_proto:
402
+ return result, response
403
+ return result
391
404
 
392
405
  def _predict_by_proto(
393
406
  self,
@@ -448,15 +461,17 @@ class ModelClient:
448
461
  self,
449
462
  inputs,
450
463
  method_name: str = 'predict',
464
+ with_proto: bool = False,
451
465
  ) -> Any:
452
466
  """Asynchronously process inputs and make predictions.
453
467
 
454
468
  Args:
455
469
  inputs: Input data to process
456
470
  method_name (str): Name of the method to call
471
+ with_proto (bool): If True, return both the processed result and the raw protobuf response
457
472
 
458
473
  Returns:
459
- Processed prediction results
474
+ Processed prediction results, optionally with protobuf response
460
475
  """
461
476
  # method_name is set to 'predict' by default, this is because to replicate the input and output signature behaviour of sync to async predict.
462
477
  input_signature = self._method_signatures[method_name].input_fields
@@ -477,7 +492,11 @@ class ModelClient:
477
492
  for output in response.outputs:
478
493
  outputs.append(deserialize(output.data, output_signature, is_output=True))
479
494
 
480
- return outputs if batch_input else outputs[0]
495
+ result = outputs if batch_input else outputs[0]
496
+
497
+ if with_proto:
498
+ return result, response
499
+ return result
481
500
 
482
501
  async def _async_predict_by_proto(
483
502
  self,
@@ -551,6 +570,7 @@ class ModelClient:
551
570
  self,
552
571
  inputs, # TODO set up functions according to fetched signatures?
553
572
  method_name: str = 'generate',
573
+ with_proto: bool = False,
554
574
  ) -> Any:
555
575
  input_signature = self._method_signatures[method_name].input_fields
556
576
  output_signature = self._method_signatures[method_name].output_fields
@@ -572,10 +592,13 @@ class ModelClient:
572
592
  outputs = []
573
593
  for output in response.outputs:
574
594
  outputs.append(deserialize(output.data, output_signature, is_output=True))
575
- if batch_input:
576
- yield outputs
595
+
596
+ result = outputs if batch_input else outputs[0]
597
+
598
+ if with_proto:
599
+ yield result, response
577
600
  else:
578
- yield outputs[0]
601
+ yield result
579
602
 
580
603
  def _generate_by_proto(
581
604
  self,
@@ -641,6 +664,7 @@ class ModelClient:
641
664
  self,
642
665
  inputs,
643
666
  method_name: str = 'generate',
667
+ with_proto: bool = False,
644
668
  ) -> Any:
645
669
  # method_name is set to 'generate' by default, this is because to replicate the input and output signature behaviour of sync to async generate.
646
670
  input_signature = self._method_signatures[method_name].input_fields
@@ -654,18 +678,21 @@ class ModelClient:
654
678
  proto_inputs = []
655
679
  for input in inputs:
656
680
  proto = resources_pb2.Input()
657
- serialize(input, input_signature, proto.data)
658
- proto_inputs.append(proto)
681
+ serialize(input, input_signature, proto.data)
682
+ proto_inputs.append(proto)
659
683
  response_stream = self._async_generate_by_proto(proto_inputs, method_name)
660
684
 
661
685
  async for response in response_stream:
662
686
  outputs = []
663
687
  for output in response.outputs:
664
688
  outputs.append(deserialize(output.data, output_signature, is_output=True))
665
- if batch_input:
666
- yield outputs
689
+
690
+ result = outputs if batch_input else outputs[0]
691
+
692
+ if with_proto:
693
+ yield result, response
667
694
  else:
668
- yield outputs[0]
695
+ yield result
669
696
 
670
697
  async def _async_generate_by_proto(
671
698
  self,
@@ -734,6 +761,7 @@ class ModelClient:
734
761
  self,
735
762
  inputs,
736
763
  method_name: str = 'stream',
764
+ with_proto: bool = False,
737
765
  ) -> Any:
738
766
  input_signature = self._method_signatures[method_name].input_fields
739
767
  output_signature = self._method_signatures[method_name].output_fields
@@ -775,7 +803,12 @@ class ModelClient:
775
803
 
776
804
  for response in response_stream:
777
805
  assert len(response.outputs) == 1, 'streaming methods must have exactly one output'
778
- yield deserialize(response.outputs[0].data, output_signature, is_output=True)
806
+ result = deserialize(response.outputs[0].data, output_signature, is_output=True)
807
+
808
+ if with_proto:
809
+ yield result, response
810
+ else:
811
+ yield result
779
812
 
780
813
  def _req_iterator(
781
814
  self,
@@ -843,6 +876,7 @@ class ModelClient:
843
876
  self,
844
877
  inputs,
845
878
  method_name: str = 'stream',
879
+ with_proto: bool = False,
846
880
  ) -> Any:
847
881
  # method_name is set to 'stream' by default, this is because to replicate the input and output signature behaviour of sync to async stream.
848
882
  input_signature = self._method_signatures[method_name].input_fields
@@ -885,7 +919,12 @@ class ModelClient:
885
919
 
886
920
  async for response in response_stream:
887
921
  assert len(response.outputs) == 1, 'streaming methods must have exactly one output'
888
- yield deserialize(response.outputs[0].data, output_signature, is_output=True)
922
+ result = deserialize(response.outputs[0].data, output_signature, is_output=True)
923
+
924
+ if with_proto:
925
+ yield result, response
926
+ else:
927
+ yield result
889
928
 
890
929
  async def _async_stream_by_proto(
891
930
  self,
@@ -23,6 +23,9 @@ from clarifai.runners.utils.serializers import (
23
23
  TupleSerializer,
24
24
  )
25
25
 
26
+ # Reserved parameter name for protobuf response access
27
+ RESERVED_PARAM_WITH_PROTO = 'with_proto'
28
+
26
29
 
27
30
  def build_function_signature(func):
28
31
  '''
@@ -45,6 +48,12 @@ def build_function_signature(func):
45
48
  input_sigs = []
46
49
  input_streaming = []
47
50
  for p in sig.parameters.values():
51
+ # Validate that user methods don't use reserved parameter names
52
+ if p.name == RESERVED_PARAM_WITH_PROTO:
53
+ raise ValueError(
54
+ f"Parameter name '{RESERVED_PARAM_WITH_PROTO}' is reserved and cannot be used in model methods. "
55
+ f"This parameter is automatically added by the framework to provide access to protobuf responses."
56
+ )
48
57
  model_type_field, _, streaming = build_variable_signature(p.name, p.annotation, p.default)
49
58
  input_sigs.append(model_type_field)
50
59
  input_streaming.append(streaming)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clarifai
3
- Version: 11.8.4
3
+ Version: 11.8.5
4
4
  Home-page: https://github.com/Clarifai/clarifai-python
5
5
  Author: Clarifai
6
6
  Author-email: support@clarifai.com
@@ -1,4 +1,4 @@
1
- clarifai/__init__.py,sha256=l80v8IYM70DFAKN9bwXRrDCRPmv0ykn84eJo3--0MWA,23
1
+ clarifai/__init__.py,sha256=YeRhZlTAJEr8RFN-fAV2vKqehtBKH976kJekvsJO6p0,23
2
2
  clarifai/cli.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  clarifai/errors.py,sha256=GXa6D4v_L404J83jnRNFPH7s-1V9lk7w6Ws99f1g-AY,2772
4
4
  clarifai/versions.py,sha256=ecSuEB_nOL2XSoYHDw2n23XUbm_KPOGjudMXmQrGdS8,224
@@ -25,7 +25,7 @@ clarifai/client/deployment.py,sha256=QBf0tzkKBEpzNgmOEmWUJMOlVWdFEFc70Y44o8y75Gs
25
25
  clarifai/client/input.py,sha256=jpX47qwn7aUBBIEuSSLHF5jk70XaWEh0prD065c9b-E,51205
26
26
  clarifai/client/lister.py,sha256=1YEm2suNxPaJO4x9V5szgD_YX6N_00vgSO-7m0HagY8,2208
27
27
  clarifai/client/model.py,sha256=uOnR1GPOJUoNWDmd_Ja9XJq8oRPa1frTxBQ_ypQXc8Q,93518
28
- clarifai/client/model_client.py,sha256=8N8dRqb5zfFCNxq-jc-YSL19tgS8PpevnxY69G2YzCE,38280
28
+ clarifai/client/model_client.py,sha256=bO9gMIvGRPSrOUKvjMXJmW4-1tb8tHYiHzvaJCZanIk,39609
29
29
  clarifai/client/module.py,sha256=pTcTmR48-VQRCEj3PJK_ZT5YTsYfZDbEjxwJ43rcLMM,4753
30
30
  clarifai/client/nodepool.py,sha256=QDJOMOYrZAG962u-MZWjXOZifjWK8hDgS2zoUn59dZU,16751
31
31
  clarifai/client/pipeline.py,sha256=y4swF2LsTag8l_-CT1jN4RXEwp_YYYkO6P_n97Cq1kg,15961
@@ -94,7 +94,7 @@ clarifai/runners/utils/code_script.py,sha256=-6IgNruIMTYLKJG8EqVWSaZR7lFRBoQ4ufJ
94
94
  clarifai/runners/utils/const.py,sha256=MK7lTzzJKbOiyiUtG_jlJXfz_xNKMn5LjkQ9vjbttXE,1538
95
95
  clarifai/runners/utils/data_utils.py,sha256=HRpMYR2O0OiDpXXhOManLHTeomC4bFnXMHVAiT_12yE,20856
96
96
  clarifai/runners/utils/loader.py,sha256=hQwdRKRLgrunDzLTiqjz2qVdxiL8WQ04PUSwrh-JWZ0,12077
97
- clarifai/runners/utils/method_signatures.py,sha256=qdHaO8ZIgP6BBXXMhMPhcQ46dse-XMP2t4VJCNG7O3Q,18335
97
+ clarifai/runners/utils/method_signatures.py,sha256=wOQnt3WVTnLBg0fhq2AxIb-2zdorYZ5aZPqlIwAybz8,18825
98
98
  clarifai/runners/utils/model_utils.py,sha256=MCYhV_00anptIO1Qtxgzn3DlGI2UHV0ESFT3wLNcAMM,6413
99
99
  clarifai/runners/utils/openai_convertor.py,sha256=ZlIrvvfHttD_DavLvmKZdL8gNq_TQvQtZVnYamwdWz4,8248
100
100
  clarifai/runners/utils/pipeline_validation.py,sha256=GFgFbrlS0UvGXcYTS84CyX7hIVU2CUNVQiMnCAjNfhw,6444
@@ -122,9 +122,9 @@ clarifai/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
122
122
  clarifai/workflows/export.py,sha256=HvUYG9N_-UZoRR0-_tdGbZ950_AeBqawSppgUxQebR0,1913
123
123
  clarifai/workflows/utils.py,sha256=ESL3INcouNcLKCh-nMpfXX-YbtCzX7tz7hT57_RGQ3M,2079
124
124
  clarifai/workflows/validate.py,sha256=UhmukyHkfxiMFrPPeBdUTiCOHQT5-shqivlBYEyKTlU,2931
125
- clarifai-11.8.4.dist-info/licenses/LICENSE,sha256=mUqF_d12-qE2n41g7C5_sq-BMLOcj6CNN-jevr15YHU,555
126
- clarifai-11.8.4.dist-info/METADATA,sha256=mNT5gLQe6QyrWy_kKhF-XCSAqR2F932MDYyTEy8aPQ4,23193
127
- clarifai-11.8.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
128
- clarifai-11.8.4.dist-info/entry_points.txt,sha256=X9FZ4Z-i_r2Ud1RpZ9sNIFYuu_-9fogzCMCRUD9hyX0,51
129
- clarifai-11.8.4.dist-info/top_level.txt,sha256=wUMdCQGjkxaynZ6nZ9FAnvBUCgp5RJUVFSy2j-KYo0s,9
130
- clarifai-11.8.4.dist-info/RECORD,,
125
+ clarifai-11.8.5.dist-info/licenses/LICENSE,sha256=mUqF_d12-qE2n41g7C5_sq-BMLOcj6CNN-jevr15YHU,555
126
+ clarifai-11.8.5.dist-info/METADATA,sha256=PS_M4VLPL1Lpfus2aV0sHGykCjxFxUYKTDydUQaqglI,23193
127
+ clarifai-11.8.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
128
+ clarifai-11.8.5.dist-info/entry_points.txt,sha256=X9FZ4Z-i_r2Ud1RpZ9sNIFYuu_-9fogzCMCRUD9hyX0,51
129
+ clarifai-11.8.5.dist-info/top_level.txt,sha256=wUMdCQGjkxaynZ6nZ9FAnvBUCgp5RJUVFSy2j-KYo0s,9
130
+ clarifai-11.8.5.dist-info/RECORD,,