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.
- clarifai/__init__.py +1 -1
- clarifai/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/__pycache__/errors.cpython-310.pyc +0 -0
- clarifai/__pycache__/versions.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/base_cli.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/compute_cluster.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/deployment.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/model.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/model_cli.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/nodepool.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/client/__pycache__/app.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/app.cpython-39.pyc +0 -0
- clarifai/client/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/compute_cluster.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/dataset.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/deployment.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/input.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/lister.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/model.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/module.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/nodepool.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/search.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/user.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/workflow.cpython-310.pyc +0 -0
- clarifai/client/auth/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/client/auth/__pycache__/helper.cpython-310.pyc +0 -0
- clarifai/client/auth/__pycache__/register.cpython-310.pyc +0 -0
- clarifai/client/auth/__pycache__/stub.cpython-310.pyc +0 -0
- clarifai/client/cli/__init__.py +0 -0
- clarifai/client/cli/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/client/cli/__pycache__/base_cli.cpython-310.pyc +0 -0
- clarifai/client/cli/__pycache__/model_cli.cpython-310.pyc +0 -0
- clarifai/client/cli/base_cli.py +88 -0
- clarifai/client/cli/model_cli.py +29 -0
- clarifai/client/model.py +0 -1
- clarifai/client/model_client.py +23 -24
- clarifai/constants/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/dataset.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/input.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/model.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/rag.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/search.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/workflow.cpython-310.pyc +0 -0
- clarifai/datasets/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/datasets/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/datasets/export/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/datasets/export/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/datasets/export/__pycache__/inputs_annotations.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/datasets/upload/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/features.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/image.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/multimodal.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/text.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/utils.cpython-310.pyc +0 -0
- clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/models/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/modules/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/rag/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/rag/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/rag/__pycache__/rag.cpython-310.pyc +0 -0
- clarifai/rag/__pycache__/rag.cpython-39.pyc +0 -0
- clarifai/rag/__pycache__/utils.cpython-310.pyc +0 -0
- clarifai/runners/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/runners/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/runners/dockerfile_template/Dockerfile.cpu.template +31 -0
- clarifai/runners/dockerfile_template/Dockerfile.cuda.template +42 -0
- clarifai/runners/dockerfile_template/Dockerfile.nim +71 -0
- clarifai/runners/dockerfile_template/Dockerfile.template +0 -3
- clarifai/runners/models/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/runners/models/__pycache__/base_typed_model.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/base_typed_model.cpython-39.pyc +0 -0
- clarifai/runners/models/__pycache__/model_class.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_run_locally.cpython-310-pytest-7.1.2.pyc +0 -0
- clarifai/runners/models/__pycache__/model_run_locally.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_runner.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_upload.cpython-310.pyc +0 -0
- clarifai/runners/models/model_builder.py +56 -4
- clarifai/runners/models/model_class.py +40 -17
- clarifai/runners/models/model_class_refract.py +80 -0
- clarifai/runners/models/model_upload.py +607 -0
- clarifai/runners/models/temp.py +25 -0
- clarifai/runners/utils/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/__init__.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/buffered_stream.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/buffered_stream.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/buffered_stream.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/const.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/constants.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/constants.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/constants.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_handler.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_handler.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_handler.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_utils.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_utils.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_utils.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/grpc_server.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/grpc_server.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/grpc_server.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/health.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/health.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/health.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/loader.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/logging.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/logging.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/logging.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/stream_source.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/stream_source.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/url_fetcher.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/url_fetcher.cpython-38.pyc +0 -0
- clarifai/runners/utils/__pycache__/url_fetcher.cpython-39.pyc +0 -0
- clarifai/runners/utils/data_handler.py +271 -210
- clarifai/runners/utils/data_handler_refract.py +213 -0
- clarifai/runners/utils/logger.py +0 -0
- clarifai/runners/utils/method_signatures.py +108 -131
- clarifai/schema/__pycache__/search.cpython-310.pyc +0 -0
- clarifai/urls/__pycache__/helper.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/utils/__pycache__/cli.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/constants.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/logging.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/misc.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/model_train.cpython-310.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/main.cpython-39.pyc +0 -0
- clarifai/workflows/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/workflows/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/workflows/__pycache__/export.cpython-310.pyc +0 -0
- clarifai/workflows/__pycache__/utils.cpython-310.pyc +0 -0
- clarifai/workflows/__pycache__/validate.cpython-310.pyc +0 -0
- {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/METADATA +15 -15
- clarifai-11.1.7rc3.dist-info/RECORD +237 -0
- {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/WHEEL +1 -1
- clarifai/cli/__main__.py~ +0 -4
- clarifai/cli/__pycache__/__main__.cpython-310.pyc +0 -0
- clarifai/client/#model_client.py# +0 -430
- clarifai/client/__pycache__/runner.cpython-310.pyc +0 -0
- clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/datasets/upload/loaders/__pycache__/coco_detection.cpython-310.pyc +0 -0
- clarifai/models/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/__pycache__/constants.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/_utils.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/build.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/create.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/config.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/inference_parameter.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/output.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/triton/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/triton/__pycache__/serializer.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/triton/__pycache__/triton_config.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/triton/__pycache__/wrappers.cpython-310.pyc +0 -0
- clarifai/models/model_serving/repo_build/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/repo_build/__pycache__/build.cpython-310.pyc +0 -0
- clarifai/models/model_serving/repo_build/static_files/__pycache__/base_test.cpython-310-pytest-7.2.0.pyc +0 -0
- clarifai/runners/__pycache__/server.cpython-310.pyc +0 -0
- clarifai/runners/dockerfile_template/Dockerfile.debug +0 -11
- clarifai/runners/dockerfile_template/Dockerfile.debug~ +0 -9
- clarifai/runners/models/__pycache__/model_builder.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_servicer.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_types.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/method_signatures.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/serializers.cpython-310.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/helpers.cpython-310.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/main.cpython-310.pyc +0 -0
- clarifai-11.1.7rc1.dist-info/RECORD +0 -205
- {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/LICENSE +0 -0
- {clarifai-11.1.7rc1.dist-info → clarifai-11.1.7rc3.dist-info}/entry_points.txt +0 -0
- {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
|
-
|
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.
|
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,
|
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.
|
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 = [
|
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,
|
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.
|
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(
|
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.
|
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,
|
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,
|
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.
|
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],
|
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,
|
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()
|