clarifai 11.2.3rc5__py3-none-any.whl → 11.2.3rc7__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.2.3rc5"
1
+ __version__ = "11.2.3rc7"
@@ -1,6 +1,5 @@
1
1
  import inspect
2
2
  import itertools
3
- import json
4
3
  import logging
5
4
  import os
6
5
  import traceback
@@ -12,6 +11,7 @@ from clarifai_grpc.grpc.api.status import status_code_pb2, status_pb2
12
11
  from google.protobuf import json_format
13
12
 
14
13
  from clarifai.runners.utils import data_types
14
+ from clarifai.runners.utils.data_utils import DataConverter
15
15
  from clarifai.runners.utils.method_signatures import (build_function_signature, deserialize,
16
16
  get_stream_from_signature, serialize,
17
17
  signatures_to_json)
@@ -71,163 +71,6 @@ class ModelClass(ABC):
71
71
  output.data.text.raw = signatures_to_json(signatures)
72
72
  return resp
73
73
 
74
- def _is_data_set(self, data_msg):
75
- # Singular message fields
76
- singular_fields = [
77
- "image", "video", "metadata", "geo", "text", "audio", "ndarray"
78
- ]
79
- for field in singular_fields:
80
- if data_msg.HasField(field):
81
- return True
82
-
83
- # Repeated fields
84
- repeated_fields = [
85
- "concepts", "colors", "clusters", "embeddings", "regions", "frames",
86
- "tracks", "time_segments", "hits", "heatmaps", "parts"
87
- ]
88
- for field in repeated_fields:
89
- if getattr(data_msg, field): # checks if the list is not empty
90
- return True
91
-
92
- # Scalar fields (proto3 default: 0 for numbers, empty for strings/bytes, False for bool)
93
- if (
94
- data_msg.int_value != 0 or
95
- data_msg.float_value != 0.0 or
96
- data_msg.bytes_value != b"" or
97
- data_msg.bool_value is True or
98
- data_msg.string_value != ""
99
- ):
100
- return True
101
-
102
- return False
103
-
104
-
105
- def _convert_input_data_to_new_format(
106
- self, data: resources_pb2.Data,
107
- input_fields: List[resources_pb2.ModelTypeField]) -> resources_pb2.Data:
108
- """Convert input data to new format."""
109
- new_data = resources_pb2.Data()
110
- for field in input_fields:
111
- part_data = self._convert_field(data, field)
112
- if self._is_data_set(part_data):
113
- # if the field is set, add it to the new data part
114
- part = new_data.parts.add()
115
- part.id = field.name
116
- part.data.CopyFrom(part_data)
117
- else:
118
- if field.required:
119
- raise ValueError(f"Field {field.name} is required but not set")
120
- return new_data
121
-
122
- def _convert_field(self, old_data: resources_pb2.Data,
123
- field: resources_pb2.ModelTypeField) -> resources_pb2.Data:
124
- data_type = field.type
125
- new_data = resources_pb2.Data()
126
- if data_type == resources_pb2.ModelTypeField.DataType.STR:
127
- if old_data.HasField('text'):
128
- new_data.string_value = old_data.text.raw
129
- return new_data
130
- elif data_type == resources_pb2.ModelTypeField.DataType.IMAGE:
131
- if old_data.HasField('image'):
132
- new_data.image.CopyFrom(old_data.image)
133
- return new_data
134
- elif data_type == resources_pb2.ModelTypeField.DataType.VIDEO:
135
- if old_data.HasField('video'):
136
- new_data.video.CopyFrom(old_data.video)
137
- return new_data
138
- elif data_type == resources_pb2.ModelTypeField.DataType.BOOL:
139
- if old_data.HasField('bool_value'):
140
- new_data.bool_value = old_data.bool_value
141
- return new_data
142
- elif data_type == resources_pb2.ModelTypeField.DataType.INT:
143
- if old_data.HasField('int_value'):
144
- new_data.int_value = old_data.int_value
145
- return new_data
146
- elif data_type == resources_pb2.ModelTypeField.DataType.FLOAT:
147
- if old_data.HasField('float_value'):
148
- new_data.float_value = old_data.float_value
149
- return new_data
150
- elif data_type == resources_pb2.ModelTypeField.DataType.BYTES:
151
- if old_data.HasField('bytes_value'):
152
- new_data.bytes_value = old_data.bytes_value
153
- return new_data
154
- elif data_type == resources_pb2.ModelTypeField.DataType.NDARRAY:
155
- if old_data.HasField('ndarray'):
156
- new_data.ndarray.CopyFrom(old_data.ndarray)
157
- return new_data
158
- elif data_type == resources_pb2.ModelTypeField.DataType.TEXT:
159
- if old_data.HasField('text'):
160
- new_data.text.CopyFrom(old_data.text)
161
- return new_data
162
- elif data_type == resources_pb2.ModelTypeField.DataType.AUDIO:
163
- if old_data.HasField('audio'):
164
- new_data.audio.CopyFrom(old_data.audio)
165
- return new_data
166
- elif data_type == resources_pb2.ModelTypeField.DataType.CONCEPT:
167
- if old_data.concepts:
168
- new_data.concepts.extend(old_data.concepts)
169
- return new_data
170
- elif data_type == resources_pb2.ModelTypeField.DataType.REGION:
171
- if old_data.regions:
172
- new_data.regions.extend(old_data.regions)
173
- return new_data
174
- elif data_type == resources_pb2.ModelTypeField.DataType.FRAME:
175
- if old_data.frames:
176
- new_data.frames.extend(old_data.frames)
177
- return new_data
178
- elif data_type == resources_pb2.ModelTypeField.DataType.LIST:
179
- new_data = resources_pb2.Data()
180
- if not field.type_args:
181
- raise ValueError("LIST type requires type_args")
182
- element_field = field.type_args[0]
183
- if element_field in (resources_pb2.ModelTypeField.DataType.CONCEPT,
184
- resources_pb2.ModelTypeField.DataType.REGION,
185
- resources_pb2.ModelTypeField.DataType.FRAME):
186
- # convert to new format
187
- element_data = self._convert_field(old_data, element_field)
188
- # part = new_data.parts.add()
189
- # part.data.CopyFrom(element_data)
190
- return element_data
191
- else:
192
- return new_data
193
- # raise ValueError(f"Unsupported data type: {data_type}")
194
-
195
- def is_old_format(self, data: resources_pb2.Data) -> bool:
196
- """Check if the Data proto is in the old format (without parts)."""
197
- if len(data.parts) > 0:
198
- return False # New format uses parts
199
-
200
- # Check if any singular field is set
201
- singular_fields = [
202
- 'image', 'video', 'metadata', 'geo', 'text', 'audio', 'ndarray', 'int_value',
203
- 'float_value', 'bytes_value', 'bool_value', 'string_value'
204
- ]
205
- for field in singular_fields:
206
- if data.HasField(field):
207
- return True
208
-
209
- # Check if any repeated field has elements
210
- repeated_fields = [
211
- 'concepts', 'colors', 'clusters', 'embeddings', 'regions', 'frames', 'tracks',
212
- 'time_segments', 'hits', 'heatmaps'
213
- ]
214
- for field in repeated_fields:
215
- if getattr(data, field):
216
- return True
217
-
218
- return False
219
-
220
- def _convert_output_data_to_old_format(self, data: resources_pb2.Data) -> resources_pb2.Data:
221
- """Convert output data to old format."""
222
- old_data = resources_pb2.Data()
223
- part_data = data.parts[0].data
224
- # Handle text.raw specially (common case for text outputs)
225
- old_data = part_data
226
- if old_data.string_value:
227
- old_data.text.raw = old_data.string_value
228
-
229
- return old_data
230
-
231
74
  def _batch_predict(self, method, inputs: List[Dict[str, Any]]) -> List[Any]:
232
75
  """Batch predict method for multiple inputs."""
233
76
  outputs = []
@@ -261,10 +104,11 @@ class ModelClass(ABC):
261
104
  python_param_types = method_info.python_param_types
262
105
  for input in request.inputs:
263
106
  # check if input is in old format
264
- is_convert = self.is_old_format(input.data)
107
+ is_convert = DataConverter.is_old_format(input.data)
265
108
  if is_convert:
266
109
  # convert to new format
267
- new_data = self._convert_input_data_to_new_format(input.data, signature.input_fields)
110
+ new_data = DataConverter.convert_input_data_to_new_format(input.data,
111
+ signature.input_fields)
268
112
  input.data.CopyFrom(new_data)
269
113
  # convert inputs to python types
270
114
  inputs = self._convert_input_protos_to_python(request.inputs, inference_params,
@@ -307,10 +151,11 @@ class ModelClass(ABC):
307
151
  python_param_types = method_info.python_param_types
308
152
  for input in request.inputs:
309
153
  # check if input is in old format
310
- is_convert = self.is_old_format(input.data)
154
+ is_convert = DataConverter.is_old_format(input.data)
311
155
  if is_convert:
312
156
  # convert to new format
313
- new_data = self._convert_input_data_to_new_format(input.data, signature.input_fields)
157
+ new_data = DataConverter.convert_input_data_to_new_format(input.data,
158
+ signature.input_fields)
314
159
  input.data.CopyFrom(new_data)
315
160
  inputs = self._convert_input_protos_to_python(request.inputs, inference_params,
316
161
  signature.input_fields, python_param_types)
@@ -368,10 +213,11 @@ class ModelClass(ABC):
368
213
 
369
214
  for input in request.inputs:
370
215
  # check if input is in old format
371
- is_convert = self.is_old_format(input.data)
216
+ is_convert = DataConverter.is_old_format(input.data)
372
217
  if is_convert:
373
218
  # convert to new format
374
- new_data = self._convert_input_data_to_new_format(input.data, signature.input_fields)
219
+ new_data = DataConverter.convert_input_data_to_new_format(input.data,
220
+ signature.input_fields)
375
221
  input.data.CopyFrom(new_data)
376
222
  # convert all inputs for the first request, including the first stream value
377
223
  inputs = self._convert_input_protos_to_python(request.inputs, inference_params,
@@ -445,7 +291,7 @@ class ModelClass(ABC):
445
291
  serialize({'return': output}, variables_signature, proto.data, is_output=True)
446
292
  if convert_old_format:
447
293
  # convert to old format
448
- data = self._convert_output_data_to_old_format(proto.data)
294
+ data = DataConverter.convert_output_data_to_old_format(proto.data)
449
295
  proto.data.CopyFrom(data)
450
296
  proto.status.code = status_code_pb2.SUCCESS
451
297
  if hasattr(self, "_prompt_tokens") and self._prompt_tokens is not None:
@@ -1,5 +1,7 @@
1
1
  from io import BytesIO
2
+ from typing import List
2
3
 
4
+ from clarifai_grpc.grpc.api import resources_pb2
3
5
  from clarifai_grpc.grpc.api.resources_pb2 import ModelTypeEnumOption
4
6
  from clarifai_grpc.grpc.api.resources_pb2 import ModelTypeField as InputFieldProto
5
7
  from clarifai_grpc.grpc.api.resources_pb2 import ModelTypeRangeInfo
@@ -178,3 +180,158 @@ class InputField(MessageData):
178
180
  import json
179
181
  proto.default = json.dumps(default)
180
182
  return proto
183
+
184
+
185
+ class DataConverter:
186
+ """A class that can be used to convert data to and from a specific format."""
187
+
188
+ @classmethod
189
+ def convert_input_data_to_new_format(
190
+ cls, data: resources_pb2.Data,
191
+ input_fields: List[resources_pb2.ModelTypeField]) -> resources_pb2.Data:
192
+ """Convert input data to new format."""
193
+ new_data = resources_pb2.Data()
194
+ for field in input_fields:
195
+ part_data = cls._convert_field(data, field)
196
+ if cls._is_data_set(part_data):
197
+ # if the field is set, add it to the new data part
198
+ part = new_data.parts.add()
199
+ part.id = field.name
200
+ part.data.CopyFrom(part_data)
201
+ else:
202
+ if field.required:
203
+ raise ValueError(f"Field {field.name} is required but not set")
204
+ return new_data
205
+
206
+ @classmethod
207
+ def _convert_field(cls, old_data: resources_pb2.Data,
208
+ field: resources_pb2.ModelTypeField) -> resources_pb2.Data:
209
+ data_type = field.type
210
+ new_data = resources_pb2.Data()
211
+ if data_type == resources_pb2.ModelTypeField.DataType.STR:
212
+ if old_data.HasField('text'):
213
+ new_data.string_value = old_data.text.raw
214
+ return new_data
215
+ elif data_type == resources_pb2.ModelTypeField.DataType.IMAGE:
216
+ if old_data.HasField('image'):
217
+ new_data.image.CopyFrom(old_data.image)
218
+ return new_data
219
+ elif data_type == resources_pb2.ModelTypeField.DataType.VIDEO:
220
+ if old_data.HasField('video'):
221
+ new_data.video.CopyFrom(old_data.video)
222
+ return new_data
223
+ elif data_type == resources_pb2.ModelTypeField.DataType.BOOL:
224
+ if old_data.bool_value != False:
225
+ new_data.bool_value = old_data.bool_value
226
+ return new_data
227
+ elif data_type == resources_pb2.ModelTypeField.DataType.INT:
228
+ if old_data.int_value != 0:
229
+ new_data.int_value = old_data.int_value
230
+ return new_data
231
+ elif data_type == resources_pb2.ModelTypeField.DataType.FLOAT:
232
+ if old_data.float_value != 0.0:
233
+ new_data.float_value = old_data.float_value
234
+ return new_data
235
+ elif data_type == resources_pb2.ModelTypeField.DataType.BYTES:
236
+ if old_data.bytes_value != b"":
237
+ new_data.bytes_value = old_data.bytes_value
238
+ return new_data
239
+ elif data_type == resources_pb2.ModelTypeField.DataType.NDARRAY:
240
+ if old_data.HasField('ndarray'):
241
+ new_data.ndarray.CopyFrom(old_data.ndarray)
242
+ return new_data
243
+ elif data_type == resources_pb2.ModelTypeField.DataType.TEXT:
244
+ if old_data.HasField('text'):
245
+ new_data.text.CopyFrom(old_data.text)
246
+ return new_data
247
+ elif data_type == resources_pb2.ModelTypeField.DataType.AUDIO:
248
+ if old_data.HasField('audio'):
249
+ new_data.audio.CopyFrom(old_data.audio)
250
+ return new_data
251
+ elif data_type == resources_pb2.ModelTypeField.DataType.CONCEPT:
252
+ if old_data.concepts:
253
+ new_data.concepts.extend(old_data.concepts)
254
+ return new_data
255
+ elif data_type == resources_pb2.ModelTypeField.DataType.REGION:
256
+ if old_data.regions:
257
+ new_data.regions.extend(old_data.regions)
258
+ return new_data
259
+ elif data_type == resources_pb2.ModelTypeField.DataType.FRAME:
260
+ if old_data.frames:
261
+ new_data.frames.extend(old_data.frames)
262
+ return new_data
263
+ elif data_type == resources_pb2.ModelTypeField.DataType.LIST:
264
+ if not field.type_args:
265
+ raise ValueError("LIST type requires type_args")
266
+ element_field = field.type_args[0]
267
+ if element_field in (resources_pb2.ModelTypeField.DataType.CONCEPT,
268
+ resources_pb2.ModelTypeField.DataType.REGION,
269
+ resources_pb2.ModelTypeField.DataType.FRAME):
270
+ # convert to new format
271
+ new_data = cls._convert_field(old_data, element_field)
272
+ return new_data
273
+ else:
274
+ return new_data
275
+ # raise ValueError(f"Unsupported data type: {data_type}")
276
+
277
+ @classmethod
278
+ def is_old_format(cls, data: resources_pb2.Data) -> bool:
279
+ """Check if the Data proto is in the old format (without parts)."""
280
+ if len(data.parts) > 0:
281
+ return False # New format uses parts
282
+
283
+ # Check if any singular field is set
284
+ singular_fields = [
285
+ 'image', 'video', 'metadata', 'geo', 'text', 'audio', 'ndarray', 'int_value',
286
+ 'float_value', 'bytes_value', 'bool_value', 'string_value'
287
+ ]
288
+ for field in singular_fields:
289
+ if data.HasField(field):
290
+ return True
291
+
292
+ # Check if any repeated field has elements
293
+ repeated_fields = [
294
+ 'concepts', 'colors', 'clusters', 'embeddings', 'regions', 'frames', 'tracks',
295
+ 'time_segments', 'hits', 'heatmaps'
296
+ ]
297
+ for field in repeated_fields:
298
+ if getattr(data, field):
299
+ return True
300
+
301
+ return False
302
+
303
+ @classmethod
304
+ def convert_output_data_to_old_format(cls, data: resources_pb2.Data) -> resources_pb2.Data:
305
+ """Convert output data to old format."""
306
+ old_data = resources_pb2.Data()
307
+ part_data = data.parts[0].data
308
+ # Handle text.raw specially (common case for text outputs)
309
+ old_data = part_data
310
+ if old_data.string_value:
311
+ old_data.text.raw = old_data.string_value
312
+
313
+ return old_data
314
+
315
+ @classmethod
316
+ def _is_data_set(cls, data_msg):
317
+ # Singular message fields
318
+ singular_fields = ["image", "video", "metadata", "geo", "text", "audio", "ndarray"]
319
+ for field in singular_fields:
320
+ if data_msg.HasField(field):
321
+ return True
322
+
323
+ # Repeated fields
324
+ repeated_fields = [
325
+ "concepts", "colors", "clusters", "embeddings", "regions", "frames", "tracks",
326
+ "time_segments", "hits", "heatmaps", "parts"
327
+ ]
328
+ for field in repeated_fields:
329
+ if getattr(data_msg, field): # checks if the list is not empty
330
+ return True
331
+
332
+ # Scalar fields (proto3 default: 0 for numbers, empty for strings/bytes, False for bool)
333
+ if (data_msg.int_value != 0 or data_msg.float_value != 0.0 or data_msg.bytes_value != b"" or
334
+ data_msg.bool_value is True or data_msg.string_value != ""):
335
+ return True
336
+
337
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: clarifai
3
- Version: 11.2.3rc5
3
+ Version: 11.2.3rc7
4
4
  Summary: Clarifai Python SDK
5
5
  Home-page: https://github.com/Clarifai/clarifai-python
6
6
  Author: Clarifai
@@ -1,4 +1,4 @@
1
- clarifai/__init__.py,sha256=3owdEcoZvJ80nDEku3Fx06-8DotYBYlixS7OPTQzrAY,26
1
+ clarifai/__init__.py,sha256=h2DeEucugdY0uLWmoAofTR6ESxYfmPbOqpFlfRxLZKU,26
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
@@ -139,7 +139,7 @@ clarifai/runners/dockerfile_template/Dockerfile.template,sha256=5cjv7U8PmWa3DB_5
139
139
  clarifai/runners/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
140
140
  clarifai/runners/models/base_typed_model.py,sha256=0QCWxch8CcyJSKvE1D4PILd2RSnQZHTmx4DXlQQ6dpo,7856
141
141
  clarifai/runners/models/model_builder.py,sha256=vJXYrxBwuayanMquAPwFOv9z7U5EQ2aIdppl8DfTGgQ,36900
142
- clarifai/runners/models/model_class.py,sha256=xVjcs6j3QhwHH73XVE4KUuHCrzXvC_snbw4_eeSfjuc,20436
142
+ clarifai/runners/models/model_class.py,sha256=3pS-OQA0cvaWQ0IB2M3K-kylp1gtY2V9il_J8Mb_kOM,14662
143
143
  clarifai/runners/models/model_class_refract.py,sha256=HxuozxSW7ag5yWCPxjNwgLArQ6dORhyGXlnpPaZz2-c,3211
144
144
  clarifai/runners/models/model_run_locally.py,sha256=m5uLlXpWVGuQIJv-XBt-sHGx1gD8w6d77f9b85DOZqs,18170
145
145
  clarifai/runners/models/model_runner.py,sha256=T4Qn_x0vky7XdeS54bvipzEmKZMra1tQdAu_u01yyjc,6503
@@ -161,7 +161,7 @@ clarifai/runners/utils/const.py,sha256=bwj-Pcw558-pasdIFbNhnkn-9oiCdojYH1fNTTUG2
161
161
  clarifai/runners/utils/data_handler.py,sha256=b7k6MWYPXSgjrfw6wsDf82xFYa0D7UjYmjE4mw5HzHM,8499
162
162
  clarifai/runners/utils/data_handler_refract.py,sha256=3M-V4hkOoF-9Ix4hE6ocXWiTJPc9dewtu6FMtddd-jQ,6343
163
163
  clarifai/runners/utils/data_types.py,sha256=bFRKVl2s6Mmx0bQn_lKwbqxBET9wtIEf0Tk6PAIc6ko,12465
164
- clarifai/runners/utils/data_utils.py,sha256=RoPsi5szPvYLxU5DSO0ZmF-zA33QH7mJpQhZ7It4Y4Q,5289
164
+ clarifai/runners/utils/data_utils.py,sha256=7njBh0-_WzwvLgwd-JkALt9s6rjvhEEPgkWn5qAMyfo,11350
165
165
  clarifai/runners/utils/loader.py,sha256=SgNHMwRmCCymFQm8aDp73NmIUHhM-N60CBlTKbPzmVc,7470
166
166
  clarifai/runners/utils/logger.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
167
167
  clarifai/runners/utils/method_signatures.py,sha256=mr0d0hs-og2icwZn7DmiZqzOMnEqY-ZBW0mheselsZE,18134
@@ -230,9 +230,9 @@ clarifai/workflows/__pycache__/__init__.cpython-39.pyc,sha256=9nA--jULSW7OFrYOcs
230
230
  clarifai/workflows/__pycache__/export.cpython-310.pyc,sha256=phEGwi2gAojCUhRTqjZVeTDn7Gk6LCVBeSTjAj4m9iY,2418
231
231
  clarifai/workflows/__pycache__/utils.cpython-310.pyc,sha256=M9_KTM7GOOS5SPrWwAzqHDqyGvgKi3xuSGvyw6MNf-I,1925
232
232
  clarifai/workflows/__pycache__/validate.cpython-310.pyc,sha256=c18Jgp_-CAm8RD_tmUpDCPoqZeexaoWELG0yBzb9rjw,2149
233
- clarifai-11.2.3rc5.dist-info/LICENSE,sha256=mUqF_d12-qE2n41g7C5_sq-BMLOcj6CNN-jevr15YHU,555
234
- clarifai-11.2.3rc5.dist-info/METADATA,sha256=XLjcksPpc2jWTJiBK1Za4ilNuX_W4zjmzPL3JTIfMMc,22453
235
- clarifai-11.2.3rc5.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
236
- clarifai-11.2.3rc5.dist-info/entry_points.txt,sha256=X9FZ4Z-i_r2Ud1RpZ9sNIFYuu_-9fogzCMCRUD9hyX0,51
237
- clarifai-11.2.3rc5.dist-info/top_level.txt,sha256=wUMdCQGjkxaynZ6nZ9FAnvBUCgp5RJUVFSy2j-KYo0s,9
238
- clarifai-11.2.3rc5.dist-info/RECORD,,
233
+ clarifai-11.2.3rc7.dist-info/LICENSE,sha256=mUqF_d12-qE2n41g7C5_sq-BMLOcj6CNN-jevr15YHU,555
234
+ clarifai-11.2.3rc7.dist-info/METADATA,sha256=P-5SeZiUhgGMdQ3p3t25w-N295aclXp5sZQ0jM5tcuc,22453
235
+ clarifai-11.2.3rc7.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
236
+ clarifai-11.2.3rc7.dist-info/entry_points.txt,sha256=X9FZ4Z-i_r2Ud1RpZ9sNIFYuu_-9fogzCMCRUD9hyX0,51
237
+ clarifai-11.2.3rc7.dist-info/top_level.txt,sha256=wUMdCQGjkxaynZ6nZ9FAnvBUCgp5RJUVFSy2j-KYo0s,9
238
+ clarifai-11.2.3rc7.dist-info/RECORD,,