clarifai 11.1.7rc1__py3-none-any.whl → 11.1.7rc3__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.
Files changed (184) hide show
  1. clarifai/__init__.py +1 -1
  2. clarifai/__pycache__/__init__.cpython-310.pyc +0 -0
  3. clarifai/__pycache__/__init__.cpython-39.pyc +0 -0
  4. clarifai/__pycache__/errors.cpython-310.pyc +0 -0
  5. clarifai/__pycache__/versions.cpython-310.pyc +0 -0
  6. clarifai/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  7. clarifai/cli/__pycache__/base.cpython-310.pyc +0 -0
  8. clarifai/cli/__pycache__/base_cli.cpython-310.pyc +0 -0
  9. clarifai/cli/__pycache__/compute_cluster.cpython-310.pyc +0 -0
  10. clarifai/cli/__pycache__/deployment.cpython-310.pyc +0 -0
  11. clarifai/cli/__pycache__/model.cpython-310.pyc +0 -0
  12. clarifai/cli/__pycache__/model_cli.cpython-310.pyc +0 -0
  13. clarifai/cli/__pycache__/nodepool.cpython-310.pyc +0 -0
  14. clarifai/client/__pycache__/__init__.cpython-310.pyc +0 -0
  15. clarifai/client/__pycache__/__init__.cpython-39.pyc +0 -0
  16. clarifai/client/__pycache__/app.cpython-310.pyc +0 -0
  17. clarifai/client/__pycache__/app.cpython-39.pyc +0 -0
  18. clarifai/client/__pycache__/base.cpython-310.pyc +0 -0
  19. clarifai/client/__pycache__/compute_cluster.cpython-310.pyc +0 -0
  20. clarifai/client/__pycache__/dataset.cpython-310.pyc +0 -0
  21. clarifai/client/__pycache__/deployment.cpython-310.pyc +0 -0
  22. clarifai/client/__pycache__/input.cpython-310.pyc +0 -0
  23. clarifai/client/__pycache__/lister.cpython-310.pyc +0 -0
  24. clarifai/client/__pycache__/model.cpython-310.pyc +0 -0
  25. clarifai/client/__pycache__/module.cpython-310.pyc +0 -0
  26. clarifai/client/__pycache__/nodepool.cpython-310.pyc +0 -0
  27. clarifai/client/__pycache__/search.cpython-310.pyc +0 -0
  28. clarifai/client/__pycache__/user.cpython-310.pyc +0 -0
  29. clarifai/client/__pycache__/workflow.cpython-310.pyc +0 -0
  30. clarifai/client/auth/__pycache__/__init__.cpython-310.pyc +0 -0
  31. clarifai/client/auth/__pycache__/helper.cpython-310.pyc +0 -0
  32. clarifai/client/auth/__pycache__/register.cpython-310.pyc +0 -0
  33. clarifai/client/auth/__pycache__/stub.cpython-310.pyc +0 -0
  34. clarifai/client/cli/__init__.py +0 -0
  35. clarifai/client/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  36. clarifai/client/cli/__pycache__/base_cli.cpython-310.pyc +0 -0
  37. clarifai/client/cli/__pycache__/model_cli.cpython-310.pyc +0 -0
  38. clarifai/client/cli/base_cli.py +88 -0
  39. clarifai/client/cli/model_cli.py +29 -0
  40. clarifai/client/model.py +0 -1
  41. clarifai/client/model_client.py +23 -24
  42. clarifai/constants/__pycache__/base.cpython-310.pyc +0 -0
  43. clarifai/constants/__pycache__/dataset.cpython-310.pyc +0 -0
  44. clarifai/constants/__pycache__/input.cpython-310.pyc +0 -0
  45. clarifai/constants/__pycache__/model.cpython-310.pyc +0 -0
  46. clarifai/constants/__pycache__/rag.cpython-310.pyc +0 -0
  47. clarifai/constants/__pycache__/search.cpython-310.pyc +0 -0
  48. clarifai/constants/__pycache__/workflow.cpython-310.pyc +0 -0
  49. clarifai/datasets/__pycache__/__init__.cpython-310.pyc +0 -0
  50. clarifai/datasets/__pycache__/__init__.cpython-39.pyc +0 -0
  51. clarifai/datasets/export/__pycache__/__init__.cpython-310.pyc +0 -0
  52. clarifai/datasets/export/__pycache__/__init__.cpython-39.pyc +0 -0
  53. clarifai/datasets/export/__pycache__/inputs_annotations.cpython-310.pyc +0 -0
  54. clarifai/datasets/upload/__pycache__/__init__.cpython-310.pyc +0 -0
  55. clarifai/datasets/upload/__pycache__/__init__.cpython-39.pyc +0 -0
  56. clarifai/datasets/upload/__pycache__/base.cpython-310.pyc +0 -0
  57. clarifai/datasets/upload/__pycache__/features.cpython-310.pyc +0 -0
  58. clarifai/datasets/upload/__pycache__/image.cpython-310.pyc +0 -0
  59. clarifai/datasets/upload/__pycache__/multimodal.cpython-310.pyc +0 -0
  60. clarifai/datasets/upload/__pycache__/text.cpython-310.pyc +0 -0
  61. clarifai/datasets/upload/__pycache__/utils.cpython-310.pyc +0 -0
  62. clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-39.pyc +0 -0
  63. clarifai/models/__pycache__/__init__.cpython-39.pyc +0 -0
  64. clarifai/modules/__pycache__/__init__.cpython-39.pyc +0 -0
  65. clarifai/rag/__pycache__/__init__.cpython-310.pyc +0 -0
  66. clarifai/rag/__pycache__/__init__.cpython-39.pyc +0 -0
  67. clarifai/rag/__pycache__/rag.cpython-310.pyc +0 -0
  68. clarifai/rag/__pycache__/rag.cpython-39.pyc +0 -0
  69. clarifai/rag/__pycache__/utils.cpython-310.pyc +0 -0
  70. clarifai/runners/__pycache__/__init__.cpython-310.pyc +0 -0
  71. clarifai/runners/__pycache__/__init__.cpython-39.pyc +0 -0
  72. clarifai/runners/dockerfile_template/Dockerfile.cpu.template +31 -0
  73. clarifai/runners/dockerfile_template/Dockerfile.cuda.template +42 -0
  74. clarifai/runners/dockerfile_template/Dockerfile.nim +71 -0
  75. clarifai/runners/dockerfile_template/Dockerfile.template +0 -3
  76. clarifai/runners/models/__pycache__/__init__.cpython-310.pyc +0 -0
  77. clarifai/runners/models/__pycache__/__init__.cpython-39.pyc +0 -0
  78. clarifai/runners/models/__pycache__/base_typed_model.cpython-310.pyc +0 -0
  79. clarifai/runners/models/__pycache__/base_typed_model.cpython-39.pyc +0 -0
  80. clarifai/runners/models/__pycache__/model_class.cpython-310.pyc +0 -0
  81. clarifai/runners/models/__pycache__/model_run_locally.cpython-310-pytest-7.1.2.pyc +0 -0
  82. clarifai/runners/models/__pycache__/model_run_locally.cpython-310.pyc +0 -0
  83. clarifai/runners/models/__pycache__/model_runner.cpython-310.pyc +0 -0
  84. clarifai/runners/models/__pycache__/model_upload.cpython-310.pyc +0 -0
  85. clarifai/runners/models/model_builder.py +56 -4
  86. clarifai/runners/models/model_class.py +40 -17
  87. clarifai/runners/models/model_class_refract.py +80 -0
  88. clarifai/runners/models/model_upload.py +607 -0
  89. clarifai/runners/models/temp.py +25 -0
  90. clarifai/runners/utils/__pycache__/__init__.cpython-310.pyc +0 -0
  91. clarifai/runners/utils/__pycache__/__init__.cpython-38.pyc +0 -0
  92. clarifai/runners/utils/__pycache__/__init__.cpython-39.pyc +0 -0
  93. clarifai/runners/utils/__pycache__/buffered_stream.cpython-310.pyc +0 -0
  94. clarifai/runners/utils/__pycache__/buffered_stream.cpython-38.pyc +0 -0
  95. clarifai/runners/utils/__pycache__/buffered_stream.cpython-39.pyc +0 -0
  96. clarifai/runners/utils/__pycache__/const.cpython-310.pyc +0 -0
  97. clarifai/runners/utils/__pycache__/constants.cpython-310.pyc +0 -0
  98. clarifai/runners/utils/__pycache__/constants.cpython-38.pyc +0 -0
  99. clarifai/runners/utils/__pycache__/constants.cpython-39.pyc +0 -0
  100. clarifai/runners/utils/__pycache__/data_handler.cpython-310.pyc +0 -0
  101. clarifai/runners/utils/__pycache__/data_handler.cpython-38.pyc +0 -0
  102. clarifai/runners/utils/__pycache__/data_handler.cpython-39.pyc +0 -0
  103. clarifai/runners/utils/__pycache__/data_utils.cpython-310.pyc +0 -0
  104. clarifai/runners/utils/__pycache__/data_utils.cpython-38.pyc +0 -0
  105. clarifai/runners/utils/__pycache__/data_utils.cpython-39.pyc +0 -0
  106. clarifai/runners/utils/__pycache__/grpc_server.cpython-310.pyc +0 -0
  107. clarifai/runners/utils/__pycache__/grpc_server.cpython-38.pyc +0 -0
  108. clarifai/runners/utils/__pycache__/grpc_server.cpython-39.pyc +0 -0
  109. clarifai/runners/utils/__pycache__/health.cpython-310.pyc +0 -0
  110. clarifai/runners/utils/__pycache__/health.cpython-38.pyc +0 -0
  111. clarifai/runners/utils/__pycache__/health.cpython-39.pyc +0 -0
  112. clarifai/runners/utils/__pycache__/loader.cpython-310.pyc +0 -0
  113. clarifai/runners/utils/__pycache__/logging.cpython-310.pyc +0 -0
  114. clarifai/runners/utils/__pycache__/logging.cpython-38.pyc +0 -0
  115. clarifai/runners/utils/__pycache__/logging.cpython-39.pyc +0 -0
  116. clarifai/runners/utils/__pycache__/stream_source.cpython-310.pyc +0 -0
  117. clarifai/runners/utils/__pycache__/stream_source.cpython-39.pyc +0 -0
  118. clarifai/runners/utils/__pycache__/url_fetcher.cpython-310.pyc +0 -0
  119. clarifai/runners/utils/__pycache__/url_fetcher.cpython-38.pyc +0 -0
  120. clarifai/runners/utils/__pycache__/url_fetcher.cpython-39.pyc +0 -0
  121. clarifai/runners/utils/data_handler.py +271 -210
  122. clarifai/runners/utils/data_handler_refract.py +213 -0
  123. clarifai/runners/utils/logger.py +0 -0
  124. clarifai/runners/utils/method_signatures.py +108 -131
  125. clarifai/schema/__pycache__/search.cpython-310.pyc +0 -0
  126. clarifai/urls/__pycache__/helper.cpython-310.pyc +0 -0
  127. clarifai/utils/__pycache__/__init__.cpython-310.pyc +0 -0
  128. clarifai/utils/__pycache__/__init__.cpython-39.pyc +0 -0
  129. clarifai/utils/__pycache__/cli.cpython-310.pyc +0 -0
  130. clarifai/utils/__pycache__/constants.cpython-310.pyc +0 -0
  131. clarifai/utils/__pycache__/logging.cpython-310.pyc +0 -0
  132. clarifai/utils/__pycache__/misc.cpython-310.pyc +0 -0
  133. clarifai/utils/__pycache__/model_train.cpython-310.pyc +0 -0
  134. clarifai/utils/evaluation/__pycache__/__init__.cpython-39.pyc +0 -0
  135. clarifai/utils/evaluation/__pycache__/main.cpython-39.pyc +0 -0
  136. clarifai/workflows/__pycache__/__init__.cpython-310.pyc +0 -0
  137. clarifai/workflows/__pycache__/__init__.cpython-39.pyc +0 -0
  138. clarifai/workflows/__pycache__/export.cpython-310.pyc +0 -0
  139. clarifai/workflows/__pycache__/utils.cpython-310.pyc +0 -0
  140. clarifai/workflows/__pycache__/validate.cpython-310.pyc +0 -0
  141. {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/METADATA +15 -15
  142. clarifai-11.1.7rc3.dist-info/RECORD +237 -0
  143. {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/WHEEL +1 -1
  144. clarifai/cli/__main__.py~ +0 -4
  145. clarifai/cli/__pycache__/__main__.cpython-310.pyc +0 -0
  146. clarifai/client/#model_client.py# +0 -430
  147. clarifai/client/__pycache__/runner.cpython-310.pyc +0 -0
  148. clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-310.pyc +0 -0
  149. clarifai/datasets/upload/loaders/__pycache__/coco_detection.cpython-310.pyc +0 -0
  150. clarifai/models/__pycache__/__init__.cpython-310.pyc +0 -0
  151. clarifai/models/model_serving/__pycache__/__init__.cpython-310.pyc +0 -0
  152. clarifai/models/model_serving/__pycache__/constants.cpython-310.pyc +0 -0
  153. clarifai/models/model_serving/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  154. clarifai/models/model_serving/cli/__pycache__/_utils.cpython-310.pyc +0 -0
  155. clarifai/models/model_serving/cli/__pycache__/base.cpython-310.pyc +0 -0
  156. clarifai/models/model_serving/cli/__pycache__/build.cpython-310.pyc +0 -0
  157. clarifai/models/model_serving/cli/__pycache__/create.cpython-310.pyc +0 -0
  158. clarifai/models/model_serving/model_config/__pycache__/__init__.cpython-310.pyc +0 -0
  159. clarifai/models/model_serving/model_config/__pycache__/base.cpython-310.pyc +0 -0
  160. clarifai/models/model_serving/model_config/__pycache__/config.cpython-310.pyc +0 -0
  161. clarifai/models/model_serving/model_config/__pycache__/inference_parameter.cpython-310.pyc +0 -0
  162. clarifai/models/model_serving/model_config/__pycache__/output.cpython-310.pyc +0 -0
  163. clarifai/models/model_serving/model_config/triton/__pycache__/__init__.cpython-310.pyc +0 -0
  164. clarifai/models/model_serving/model_config/triton/__pycache__/serializer.cpython-310.pyc +0 -0
  165. clarifai/models/model_serving/model_config/triton/__pycache__/triton_config.cpython-310.pyc +0 -0
  166. clarifai/models/model_serving/model_config/triton/__pycache__/wrappers.cpython-310.pyc +0 -0
  167. clarifai/models/model_serving/repo_build/__pycache__/__init__.cpython-310.pyc +0 -0
  168. clarifai/models/model_serving/repo_build/__pycache__/build.cpython-310.pyc +0 -0
  169. clarifai/models/model_serving/repo_build/static_files/__pycache__/base_test.cpython-310-pytest-7.2.0.pyc +0 -0
  170. clarifai/runners/__pycache__/server.cpython-310.pyc +0 -0
  171. clarifai/runners/dockerfile_template/Dockerfile.debug +0 -11
  172. clarifai/runners/dockerfile_template/Dockerfile.debug~ +0 -9
  173. clarifai/runners/models/__pycache__/model_builder.cpython-310.pyc +0 -0
  174. clarifai/runners/models/__pycache__/model_servicer.cpython-310.pyc +0 -0
  175. clarifai/runners/utils/__pycache__/data_types.cpython-310.pyc +0 -0
  176. clarifai/runners/utils/__pycache__/method_signatures.cpython-310.pyc +0 -0
  177. clarifai/runners/utils/__pycache__/serializers.cpython-310.pyc +0 -0
  178. clarifai/utils/evaluation/__pycache__/__init__.cpython-310.pyc +0 -0
  179. clarifai/utils/evaluation/__pycache__/helpers.cpython-310.pyc +0 -0
  180. clarifai/utils/evaluation/__pycache__/main.cpython-310.pyc +0 -0
  181. clarifai-11.1.7rc1.dist-info/RECORD +0 -205
  182. {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/LICENSE +0 -0
  183. {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/entry_points.txt +0 -0
  184. {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,4 @@
1
+ import builtins
1
2
  import importlib
2
3
  import inspect
3
4
  import os
@@ -6,6 +7,7 @@ import sys
6
7
  import tarfile
7
8
  import time
8
9
  from string import Template
10
+ from unittest.mock import MagicMock
9
11
 
10
12
  import yaml
11
13
  from clarifai_grpc.grpc.api import resources_pb2, service_pb2
@@ -80,7 +82,7 @@ class ModelBuilder:
80
82
 
81
83
  def load_model_class(self):
82
84
  """
83
- Import the model class from the model.py file.
85
+ Import the model class from the model.py file, dynamically handling missing dependencies
84
86
  """
85
87
  # look for default model.py file location
86
88
  for loc in ["model.py", "1/model.py"]:
@@ -95,7 +97,29 @@ class ModelBuilder:
95
97
  spec = importlib.util.spec_from_file_location(module_name, model_file)
96
98
  module = importlib.util.module_from_spec(spec)
97
99
  sys.modules[module_name] = module
98
- spec.loader.exec_module(module)
100
+
101
+ original_import = builtins.__import__
102
+
103
+ def custom_import(name, globals=None, locals=None, fromlist=(), level=0):
104
+
105
+ # Allow standard libraries and clarifai
106
+ if self._is_standard_or_clarifai(name):
107
+ return original_import(name, globals, locals, fromlist, level)
108
+
109
+ # Mock all third-party imports to avoid ImportErrors or other issues
110
+ return MagicMock()
111
+
112
+ # Replace the built-in __import__ function with our custom one
113
+ builtins.__import__ = custom_import
114
+
115
+ try:
116
+ spec.loader.exec_module(module)
117
+ except Exception as e:
118
+ logger.error(f"Error loading model.py: {e}")
119
+ raise
120
+ finally:
121
+ # Restore the original __import__ function
122
+ builtins.__import__ = original_import
99
123
 
100
124
  # Find all classes in the model.py file that are subclasses of ModelClass
101
125
  classes = [
@@ -122,6 +146,23 @@ class ModelBuilder:
122
146
  model_class = classes[0]
123
147
  return model_class
124
148
 
149
+ def _is_standard_or_clarifai(self, name):
150
+ """Check if import is from standard library or clarifai"""
151
+ if name.startswith("clarifai"):
152
+ return True
153
+
154
+ # Handle Python <3.10 compatibility
155
+ stdlib_names = getattr(sys, "stdlib_module_names", sys.builtin_module_names)
156
+ if name in stdlib_names:
157
+ return True
158
+
159
+ # Handle submodules (e.g., os.path)
160
+ parts = name.split(".")
161
+ for i in range(1, len(parts)):
162
+ if ".".join(parts[:i]) in stdlib_names:
163
+ return True
164
+ return False
165
+
125
166
  def _validate_folder(self, folder):
126
167
  if folder == ".":
127
168
  folder = "" # will getcwd() next which ends with /
@@ -267,9 +308,18 @@ class ModelBuilder:
267
308
  """
268
309
  model_class = self.load_model_class()
269
310
  method_info = model_class._get_method_info()
270
- signatures = {name: m.signature for name, m in method_info.items()}
311
+ signatures = {name: m.signature for name, m in method_info.values()}
271
312
  return signatures_to_yaml(signatures)
272
313
 
314
+ def get_method_signatures(self):
315
+ """
316
+ Returns the method signatures for the model class.
317
+ """
318
+ model_class = self.load_model_class()
319
+ method_info = model_class._get_method_info()
320
+ signatures = [method.signature for method in method_info.values()]
321
+ return signatures
322
+
273
323
  @property
274
324
  def client(self):
275
325
  if self._client is None:
@@ -548,10 +598,11 @@ class ModelBuilder:
548
598
  logger.info(f"Updated config.yaml with {len(concepts)} concepts.")
549
599
 
550
600
  def get_model_version_proto(self):
551
-
601
+ signatures = self.get_method_signatures()
552
602
  model_version_proto = resources_pb2.ModelVersion(
553
603
  pretrained_model_config=resources_pb2.PretrainedModelConfig(),
554
604
  inference_compute_info=self.inference_compute_info,
605
+ method_signatures=signatures,
555
606
  )
556
607
 
557
608
  model_type_id = self.config.get('model').get('model_type_id')
@@ -739,6 +790,7 @@ class ModelBuilder:
739
790
  model_id=self.model_proto.id,
740
791
  version_id=self.model_version_id,
741
792
  ))
793
+
742
794
  status_code = resp.model_version.status.code
743
795
  logs = self.get_model_build_logs()
744
796
  for log_entry in logs.log_entries:
@@ -8,6 +8,7 @@ from typing import Any, Dict, Iterator, List
8
8
 
9
9
  from clarifai_grpc.grpc.api import resources_pb2, service_pb2
10
10
  from clarifai_grpc.grpc.api.status import status_code_pb2, status_pb2
11
+ from google.protobuf import json_format
11
12
 
12
13
  from clarifai.runners.utils import data_types
13
14
  from clarifai.runners.utils.method_signatures import (build_function_signature, deserialize,
@@ -84,6 +85,7 @@ class ModelClass(ABC):
84
85
  try:
85
86
  # TODO add method name field to proto
86
87
  method_name = 'predict'
88
+ inference_params = get_inference_params(request)
87
89
  if len(request.inputs) > 0 and '_method_name' in request.inputs[0].data.metadata:
88
90
  method_name = request.inputs[0].data.metadata['_method_name']
89
91
  if method_name == '_GET_SIGNATURES': # special case to fetch signatures, TODO add endpoint for this
@@ -94,15 +96,17 @@ class ModelClass(ABC):
94
96
  method_info = method._cf_method_info
95
97
  signature = method_info.signature
96
98
  python_param_types = method_info.python_param_types
97
- inputs = self._convert_input_protos_to_python(request.inputs, signature.inputs,
98
- python_param_types)
99
+ inputs = self._convert_input_protos_to_python(request.inputs, inference_params,
100
+ signature.input_fields, python_param_types)
99
101
  if len(inputs) == 1:
100
102
  inputs = inputs[0]
101
103
  output = method(**inputs)
102
- outputs.append(self._convert_output_to_proto(output, signature.outputs))
104
+ outputs.append(self._convert_output_to_proto(output, signature.output_fields))
103
105
  else:
104
106
  outputs = self._batch_predict(method, inputs)
105
- outputs = [self._convert_output_to_proto(output, signature.outputs) for output in outputs]
107
+ outputs = [
108
+ self._convert_output_to_proto(output, signature.output_fields) for output in outputs
109
+ ]
106
110
 
107
111
  return service_pb2.MultiOutputResponse(
108
112
  outputs=outputs, status=status_pb2.Status(code=status_code_pb2.SUCCESS))
@@ -119,6 +123,7 @@ class ModelClass(ABC):
119
123
  ) -> Iterator[service_pb2.MultiOutputResponse]:
120
124
  try:
121
125
  method_name = 'generate'
126
+ inference_params = get_inference_params(request)
122
127
  if len(request.inputs) > 0 and '_method_name' in request.inputs[0].data.metadata:
123
128
  method_name = request.inputs[0].data.metadata['_method_name']
124
129
  method = getattr(self, method_name)
@@ -126,20 +131,21 @@ class ModelClass(ABC):
126
131
  signature = method_info.signature
127
132
  python_param_types = method_info.python_param_types
128
133
 
129
- inputs = self._convert_input_protos_to_python(request.inputs, signature.inputs,
130
- python_param_types)
134
+ inputs = self._convert_input_protos_to_python(request.inputs, inference_params,
135
+ signature.input_fields, python_param_types)
131
136
  if len(inputs) == 1:
132
137
  inputs = inputs[0]
133
138
  for output in method(**inputs):
134
139
  resp = service_pb2.MultiOutputResponse()
135
- self._convert_output_to_proto(output, signature.outputs, proto=resp.outputs.add())
140
+ self._convert_output_to_proto(output, signature.output_fields, proto=resp.outputs.add())
136
141
  resp.status.code = status_code_pb2.SUCCESS
137
142
  yield resp
138
143
  else:
139
144
  for outputs in self._batch_generate(method, inputs):
140
145
  resp = service_pb2.MultiOutputResponse()
141
146
  for output in outputs:
142
- self._convert_output_to_proto(output, signature.outputs, proto=resp.outputs.add())
147
+ self._convert_output_to_proto(
148
+ output, signature.output_fields, proto=resp.outputs.add())
143
149
  resp.status.code = status_code_pb2.SUCCESS
144
150
  yield resp
145
151
  except Exception as e:
@@ -158,6 +164,7 @@ class ModelClass(ABC):
158
164
  assert len(request.inputs) == 1, "Streaming requires exactly one input"
159
165
 
160
166
  method_name = 'generate'
167
+ inference_params = get_inference_params(request)
161
168
  if len(request.inputs) > 0 and '_method_name' in request.inputs[0].data.metadata:
162
169
  method_name = request.inputs[0].data.metadata['_method_name']
163
170
  method = getattr(self, method_name)
@@ -166,14 +173,14 @@ class ModelClass(ABC):
166
173
  python_param_types = method_info.python_param_types
167
174
 
168
175
  # find the streaming vars in the signature
169
- stream_sig = get_stream_from_signature(signature.inputs)
176
+ stream_sig = get_stream_from_signature(signature.input_fields)
170
177
  if stream_sig is None:
171
178
  raise ValueError("Streaming method must have a Stream input")
172
179
  stream_argname = stream_sig.name
173
180
 
174
181
  # convert all inputs for the first request, including the first stream value
175
- inputs = self._convert_input_protos_to_python(request.inputs, signature.inputs,
176
- python_param_types)
182
+ inputs = self._convert_input_protos_to_python(request.inputs, inference_params,
183
+ signature.input_fields, python_param_types)
177
184
  kwargs = inputs[0]
178
185
 
179
186
  # first streaming item
@@ -184,8 +191,8 @@ class ModelClass(ABC):
184
191
  yield first_item
185
192
  # subsequent streaming items contain only the streaming input
186
193
  for request in request_iterator:
187
- item = self._convert_input_protos_to_python(request.inputs, stream_sig,
188
- python_param_types)
194
+ item = self._convert_input_protos_to_python(request.inputs, inference_params,
195
+ [stream_sig], python_param_types)
189
196
  item = item[0][stream_argname]
190
197
  yield item
191
198
 
@@ -194,7 +201,7 @@ class ModelClass(ABC):
194
201
 
195
202
  for output in method(**kwargs):
196
203
  resp = service_pb2.MultiOutputResponse()
197
- self._convert_output_to_proto(output, signature.outputs, proto=resp.outputs.add())
204
+ self._convert_output_to_proto(output, signature.output_fields, proto=resp.outputs.add())
198
205
  resp.status.code = status_code_pb2.SUCCESS
199
206
  yield resp
200
207
  except Exception as e:
@@ -206,11 +213,13 @@ class ModelClass(ABC):
206
213
  details=str(e),
207
214
  stack_trace=traceback.format_exc().split('\n')))
208
215
 
209
- def _convert_input_protos_to_python(self, inputs: List[resources_pb2.Input], variables_signature,
216
+ def _convert_input_protos_to_python(self, inputs: List[resources_pb2.Input],
217
+ inference_params: dict,
218
+ variables_signature: List[resources_pb2.ModelTypeField],
210
219
  python_param_types) -> List[Dict[str, Any]]:
211
220
  result = []
212
221
  for input in inputs:
213
- kwargs = deserialize(input.data, variables_signature)
222
+ kwargs = deserialize(input.data, variables_signature, inference_params)
214
223
  # dynamic cast to annotated types
215
224
  for k, v in kwargs.items():
216
225
  if k not in python_param_types:
@@ -219,7 +228,9 @@ class ModelClass(ABC):
219
228
  result.append(kwargs)
220
229
  return result
221
230
 
222
- def _convert_output_to_proto(self, output: Any, variables_signature,
231
+ def _convert_output_to_proto(self,
232
+ output: Any,
233
+ variables_signature: List[resources_pb2.ModelTypeField],
223
234
  proto=None) -> resources_pb2.Output:
224
235
  if proto is None:
225
236
  proto = resources_pb2.Output()
@@ -256,6 +267,18 @@ class ModelClass(ABC):
256
267
  return method_info
257
268
 
258
269
 
270
+ # Helper function to get the inference params
271
+ def get_inference_params(request) -> dict:
272
+ """Get the inference params from the request."""
273
+ inference_params = {}
274
+ if request.model.model_version.id != "":
275
+ output_info = request.model.model_version.output_info
276
+ output_info = json_format.MessageToDict(output_info, preserving_proto_field_name=True)
277
+ if "params" in output_info:
278
+ inference_params = output_info["params"]
279
+ return inference_params
280
+
281
+
259
282
  class _MethodInfo:
260
283
 
261
284
  def __init__(self, method):
@@ -0,0 +1,80 @@
1
+ import inspect
2
+ from abc import ABC, abstractmethod
3
+ from concurrent.futures import ThreadPoolExecutor
4
+ from typing import Any, Dict, Iterator, List, get_type_hints
5
+
6
+ from clarifai_grpc.grpc.api import resources_pb2, service_pb2
7
+
8
+ from clarifai.runners.utils.data_handler import Output, kwargs_to_proto, proto_to_kwargs
9
+
10
+
11
+ class ModelClass(ABC):
12
+
13
+ @abstractmethod
14
+ def load_model(self):
15
+ raise NotImplementedError("load_model() not implemented")
16
+
17
+ @abstractmethod
18
+ def predict(self, *args, **kwargs) -> Output:
19
+ raise NotImplementedError("predict() not implemented")
20
+
21
+ @abstractmethod
22
+ def generate(self, *args, **kwargs) -> Iterator[Output]:
23
+ raise NotImplementedError("generate() not implemented")
24
+
25
+ @abstractmethod
26
+ def stream(self, *args, **kwargs) -> Iterator[Output]:
27
+ raise NotImplementedError("stream() not implemented")
28
+
29
+ def batch_predict(self, inputs: List[Dict[str, Any]]) -> List[Output]:
30
+ with ThreadPoolExecutor() as executor:
31
+ return list(executor.map(lambda x: self.predict(**x), inputs))
32
+
33
+ def _process_request(self, request, process_func, is_stream=False):
34
+ inputs = self._convert_proto_to_python(request.inputs)
35
+ if len(inputs) == 1:
36
+ result = process_func(**inputs[0])
37
+ if is_stream:
38
+ return (self._convert_output_to_proto(output) for output in result)
39
+ else:
40
+ return [self._convert_output_to_proto(result)]
41
+ else:
42
+ results = self.batch_predict(inputs) if not is_stream else []
43
+ return [self._convert_output_to_proto(output) for output in results]
44
+
45
+ def predict_wrapper(
46
+ self, request: service_pb2.PostModelOutputsRequest) -> service_pb2.MultiOutputResponse:
47
+ outputs = self._process_request(request, self.predict)
48
+ return service_pb2.MultiOutputResponse(outputs=outputs)
49
+
50
+ def generate_wrapper(self, request: service_pb2.PostModelOutputsRequest
51
+ ) -> Iterator[service_pb2.MultiOutputResponse]:
52
+ outputs = self._process_request(request, self.generate, is_stream=True)
53
+ for output in outputs:
54
+ yield service_pb2.MultiOutputResponse(outputs=[output])
55
+
56
+ def stream_wrapper(self, requests: Iterator[service_pb2.PostModelOutputsRequest]
57
+ ) -> Iterator[service_pb2.MultiOutputResponse]:
58
+ for request in requests:
59
+ outputs = self._process_request(request, self.stream, is_stream=True)
60
+ yield service_pb2.MultiOutputResponse(outputs=outputs)
61
+
62
+ def _convert_proto_to_python(self, inputs: List[resources_pb2.Input]) -> List[Dict[str, Any]]:
63
+ get_type_hints(self.predict)
64
+ required_params = [
65
+ name for name, param in inspect.signature(self.predict).parameters.items()
66
+ if param.default == inspect.Parameter.empty
67
+ ]
68
+ kwargs_list = []
69
+ for input_proto in inputs:
70
+ kwargs = proto_to_kwargs(input_proto.data)
71
+ missing = [name for name in required_params if name not in kwargs]
72
+ if missing:
73
+ raise ValueError(f"Missing required parameters: {missing}")
74
+ kwargs_list.append(kwargs)
75
+ return kwargs_list
76
+
77
+ def _convert_output_to_proto(self, output: Any) -> resources_pb2.Output:
78
+ if isinstance(output, Output):
79
+ return output.to_proto()
80
+ return kwargs_to_proto(**output).outputs.add()