clarifai 10.2.1__py3-none-any.whl → 10.3.1__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/client/app.py +15 -7
- clarifai/client/auth/helper.py +12 -2
- clarifai/client/base.py +14 -4
- clarifai/client/dataset.py +15 -2
- clarifai/client/input.py +14 -1
- clarifai/client/model.py +512 -29
- clarifai/client/module.py +9 -1
- clarifai/client/search.py +100 -17
- clarifai/client/user.py +22 -14
- clarifai/client/workflow.py +9 -1
- clarifai/constants/input.py +1 -0
- clarifai/constants/search.py +2 -1
- clarifai/models/model_serving/README.md +3 -0
- clarifai/models/model_serving/cli/upload.py +65 -68
- clarifai/models/model_serving/docs/cli.md +17 -6
- clarifai/rag/rag.py +1 -1
- clarifai/rag/utils.py +1 -1
- clarifai/utils/evaluation/__init__.py +2 -426
- clarifai/utils/evaluation/main.py +426 -0
- clarifai/utils/evaluation/testset_annotation_parser.py +150 -0
- clarifai/versions.py +1 -1
- {clarifai-10.2.1.dist-info → clarifai-10.3.1.dist-info}/METADATA +29 -12
- {clarifai-10.2.1.dist-info → clarifai-10.3.1.dist-info}/RECORD +27 -28
- {clarifai-10.2.1.dist-info → clarifai-10.3.1.dist-info}/WHEEL +1 -1
- clarifai/client/runner.py +0 -234
- clarifai/runners/__init__.py +0 -0
- clarifai/runners/example.py +0 -40
- clarifai/runners/example_llama2.py +0 -81
- {clarifai-10.2.1.dist-info → clarifai-10.3.1.dist-info}/LICENSE +0 -0
- {clarifai-10.2.1.dist-info → clarifai-10.3.1.dist-info}/entry_points.txt +0 -0
- {clarifai-10.2.1.dist-info → clarifai-10.3.1.dist-info}/top_level.txt +0 -0
clarifai/client/module.py
CHANGED
@@ -19,6 +19,7 @@ class Module(Lister, BaseClient):
|
|
19
19
|
base_url: str = "https://api.clarifai.com",
|
20
20
|
pat: str = None,
|
21
21
|
token: str = None,
|
22
|
+
root_certificates_path: str = None,
|
22
23
|
**kwargs):
|
23
24
|
"""Initializes a Module object.
|
24
25
|
|
@@ -29,6 +30,7 @@ class Module(Lister, BaseClient):
|
|
29
30
|
base_url (str): Base API url. Default "https://api.clarifai.com"
|
30
31
|
pat (str): A personal access token for authentication. Can be set as env var CLARIFAI_PAT.
|
31
32
|
token (str): A session token for authentication. Accepts either a session token or a pat. Can be set as env var CLARIFAI_SESSION_TOKEN.
|
33
|
+
root_certificates_path (str): Path to the SSL root certificates file, used to establish secure gRPC connections.
|
32
34
|
**kwargs: Additional keyword arguments to be passed to the Module.
|
33
35
|
"""
|
34
36
|
if url and module_id:
|
@@ -44,7 +46,13 @@ class Module(Lister, BaseClient):
|
|
44
46
|
self.module_info = resources_pb2.Module(**self.kwargs)
|
45
47
|
self.logger = get_logger(logger_level="INFO", name=__name__)
|
46
48
|
BaseClient.__init__(
|
47
|
-
self,
|
49
|
+
self,
|
50
|
+
user_id=self.user_id,
|
51
|
+
app_id=self.app_id,
|
52
|
+
base=base_url,
|
53
|
+
pat=pat,
|
54
|
+
token=token,
|
55
|
+
root_certificates_path=root_certificates_path)
|
48
56
|
Lister.__init__(self)
|
49
57
|
|
50
58
|
def list_versions(self, page_no: int = None,
|
clarifai/client/search.py
CHANGED
@@ -10,7 +10,8 @@ from schema import SchemaError
|
|
10
10
|
from clarifai.client.base import BaseClient
|
11
11
|
from clarifai.client.input import Inputs
|
12
12
|
from clarifai.client.lister import Lister
|
13
|
-
from clarifai.constants.search import DEFAULT_SEARCH_METRIC,
|
13
|
+
from clarifai.constants.search import (DEFAULT_SEARCH_ALGORITHM, DEFAULT_SEARCH_METRIC,
|
14
|
+
DEFAULT_TOP_K)
|
14
15
|
from clarifai.errors import UserError
|
15
16
|
from clarifai.schema.search import get_schema
|
16
17
|
|
@@ -20,11 +21,14 @@ class Search(Lister, BaseClient):
|
|
20
21
|
def __init__(self,
|
21
22
|
user_id: str,
|
22
23
|
app_id: str,
|
23
|
-
top_k: int =
|
24
|
+
top_k: int = None,
|
24
25
|
metric: str = DEFAULT_SEARCH_METRIC,
|
26
|
+
algorithm: str = DEFAULT_SEARCH_ALGORITHM,
|
27
|
+
pagination: bool = False,
|
25
28
|
base_url: str = "https://api.clarifai.com",
|
26
29
|
pat: str = None,
|
27
|
-
token: str = None
|
30
|
+
token: str = None,
|
31
|
+
root_certificates_path: str = None):
|
28
32
|
"""Initialize the Search object.
|
29
33
|
|
30
34
|
Args:
|
@@ -32,27 +36,47 @@ class Search(Lister, BaseClient):
|
|
32
36
|
app_id (str): App ID.
|
33
37
|
top_k (int, optional): Top K results to retrieve. Defaults to 10.
|
34
38
|
metric (str, optional): Similarity metric (either 'cosine' or 'euclidean'). Defaults to 'cosine'.
|
39
|
+
alogrithm (str, optional): Search algorithm (either 'nearest_neighbor' or 'brute_force'). Defaults to 'nearest_neighbor'.
|
40
|
+
pagination (bool, optional): Enable pagination. Defaults to False.
|
35
41
|
base_url (str, optional): Base API url. Defaults to "https://api.clarifai.com".
|
36
42
|
pat (str, optional): A personal access token for authentication. Can be set as env var CLARIFAI_PAT
|
37
43
|
token (str): A session token for authentication. Accepts either a session token or a pat. Can be set as env var CLARIFAI_SESSION_TOKEN
|
44
|
+
root_certificates_path (str): Path to the SSL root certificates file, used to establish secure gRPC connections.
|
38
45
|
|
39
46
|
Raises:
|
40
47
|
UserError: If the metric is not 'cosine' or 'euclidean'.
|
48
|
+
UserError: If the algorithm is not 'nearest_neighbor' or 'brute_force'.
|
41
49
|
"""
|
42
50
|
if metric not in ["cosine", "euclidean"]:
|
43
51
|
raise UserError("Metric should be either cosine or euclidean")
|
52
|
+
if algorithm not in ["nearest_neighbor", "brute_force"]:
|
53
|
+
raise UserError("Algorithm should be either nearest_neighbor or brute_force")
|
54
|
+
if metric == "cosine" and algorithm == "nearest_neighbor":
|
55
|
+
raise UserError("Cosine distance metric is not supported with nearest neighbor algorithm")
|
56
|
+
if top_k and pagination:
|
57
|
+
raise UserError(
|
58
|
+
"top_k and pagination cannot be used together. Please set pagination to False.")
|
59
|
+
if not top_k and not pagination:
|
60
|
+
top_k = DEFAULT_TOP_K
|
44
61
|
|
45
62
|
self.user_id = user_id
|
46
63
|
self.app_id = app_id
|
47
64
|
self.metric_distance = dict(cosine="COSINE_DISTANCE", euclidean="EUCLIDEAN_DISTANCE")[metric]
|
65
|
+
self.algorithm = algorithm
|
48
66
|
self.data_proto = resources_pb2.Data()
|
49
67
|
self.top_k = top_k
|
50
|
-
|
68
|
+
self.pagination = pagination
|
51
69
|
self.inputs = Inputs(
|
52
70
|
user_id=self.user_id, app_id=self.app_id, pat=pat, token=token, base_url=base_url)
|
53
71
|
self.rank_filter_schema = get_schema()
|
54
72
|
BaseClient.__init__(
|
55
|
-
self,
|
73
|
+
self,
|
74
|
+
user_id=self.user_id,
|
75
|
+
app_id=self.app_id,
|
76
|
+
base=base_url,
|
77
|
+
pat=pat,
|
78
|
+
token=token,
|
79
|
+
root_certificates_path=root_certificates_path)
|
56
80
|
Lister.__init__(self, page_size=1000)
|
57
81
|
|
58
82
|
def _get_annot_proto(self, **kwargs):
|
@@ -151,9 +175,8 @@ class Search(Lister, BaseClient):
|
|
151
175
|
geo_point=resources_pb2.GeoPoint(longitude=longitude, latitude=latitude),
|
152
176
|
geo_limit=resources_pb2.GeoLimit(type="withinKilometers", value=geo_limit))
|
153
177
|
|
154
|
-
def
|
155
|
-
|
156
|
-
request_data: Dict[str, Any]) -> Generator[Dict[str, Any], None, None]:
|
178
|
+
def _list_topk_generator(self, endpoint: Callable[..., Any], proto_message: Any,
|
179
|
+
request_data: Dict[str, Any]) -> Generator[Dict[str, Any], None, None]:
|
157
180
|
"""Lists all pages of a resource.
|
158
181
|
|
159
182
|
Args:
|
@@ -191,12 +214,61 @@ class Search(Lister, BaseClient):
|
|
191
214
|
total_hits += per_page
|
192
215
|
yield response
|
193
216
|
|
194
|
-
def
|
217
|
+
def _list_all_pages_generator(self,
|
218
|
+
endpoint: Callable,
|
219
|
+
proto_message: Any,
|
220
|
+
request_data: Dict[str, Any],
|
221
|
+
page_no: int = None,
|
222
|
+
per_page: int = None) -> Generator[Dict[str, Any], None, None]:
|
223
|
+
"""Lists pages of a resource.
|
224
|
+
|
225
|
+
Args:
|
226
|
+
endpoint (Callable): The endpoint to call.
|
227
|
+
proto_message (Any): The proto message to use.
|
228
|
+
request_data (dict): The request data to use.
|
229
|
+
page_no (int): The page number to list.
|
230
|
+
per_page (int): The number of items per page.
|
231
|
+
|
232
|
+
Yields:
|
233
|
+
response_dict: The next item in the listing.
|
234
|
+
"""
|
235
|
+
page = 1 if not page_no else page_no
|
236
|
+
if page_no and not per_page:
|
237
|
+
per_page = self.default_page_size
|
238
|
+
while True:
|
239
|
+
request_data['pagination'] = service_pb2.Pagination(page=page, per_page=per_page)
|
240
|
+
response = self._grpc_request(endpoint, proto_message(**request_data))
|
241
|
+
dict_response = MessageToDict(response, preserving_proto_field_name=True)
|
242
|
+
if response.status.code != status_code_pb2.SUCCESS:
|
243
|
+
if "page * perPage cannot exceed" in str(response.status.details):
|
244
|
+
msg = (f"Your pagination is set to {page_no*per_page}. "
|
245
|
+
f"The current pagination settings exceed the limit. Please reach out to "
|
246
|
+
f"support@clarifai.com to request an increase for your use case.\n"
|
247
|
+
f"req_id: {response.status.req_id}")
|
248
|
+
raise UserError(msg)
|
249
|
+
else:
|
250
|
+
raise Exception(f"Listing failed with response {response!r}")
|
251
|
+
if 'hits' not in list(dict_response.keys()):
|
252
|
+
break
|
253
|
+
yield response
|
254
|
+
if page_no is not None or per_page is not None:
|
255
|
+
break
|
256
|
+
page += 1
|
257
|
+
|
258
|
+
def query(
|
259
|
+
self,
|
260
|
+
ranks=[{}],
|
261
|
+
filters=[{}],
|
262
|
+
page_no: int = None,
|
263
|
+
per_page: int = None,
|
264
|
+
):
|
195
265
|
"""Perform a query with rank and filters.
|
196
266
|
|
197
267
|
Args:
|
198
268
|
ranks (List[Dict], optional): List of rank parameters. Defaults to [{}].
|
199
269
|
filters (List[Dict], optional): List of filter parameters. Defaults to [{}].
|
270
|
+
page_no (int): The page number to list.
|
271
|
+
per_page (int): The number of items per page.
|
200
272
|
|
201
273
|
Returns:
|
202
274
|
Generator[Dict[str, Any], None, None]: A generator of query results.
|
@@ -209,13 +281,16 @@ class Search(Lister, BaseClient):
|
|
209
281
|
|
210
282
|
Vector search over inputs
|
211
283
|
>>> from clarifai.client.search import Search
|
212
|
-
>>> search = Search(user_id='user_id', app_id='app_id'
|
213
|
-
>>> res = search.query(ranks=[{'image_url': 'https://samples.clarifai.com/dog.tiff'}])
|
284
|
+
>>> search = Search(user_id='user_id', app_id='app_id' , metric='cosine', pagination=True)
|
285
|
+
>>> res = search.query(ranks=[{'image_url': 'https://samples.clarifai.com/dog.tiff'}],page_no=2, per_page=5)
|
214
286
|
|
215
287
|
Note:
|
216
288
|
For schema of rank and filter, please refer to [schema](https://github.com/Clarifai/clarifai-python/tree/master/clarifai/schema/search.py).
|
217
289
|
For more detailed search examples, please refer to [examples](https://github.com/Clarifai/examples/tree/main/search).
|
218
290
|
"""
|
291
|
+
if not self.pagination and (per_page or page_no):
|
292
|
+
raise UserError("Pagination settings are only available when pagination is enabled."
|
293
|
+
"Please set Search(pagination=True) while initializing Search().")
|
219
294
|
try:
|
220
295
|
self.rank_filter_schema.validate(ranks)
|
221
296
|
self.rank_filter_schema.validate(filters)
|
@@ -241,11 +316,15 @@ class Search(Lister, BaseClient):
|
|
241
316
|
searches=[
|
242
317
|
resources_pb2.Search(
|
243
318
|
query=resources_pb2.Query(ranks=all_ranks, filters=all_filters),
|
319
|
+
algorithm=self.algorithm,
|
244
320
|
metric=self.metric_distance)
|
245
321
|
])
|
246
|
-
|
247
|
-
|
248
|
-
|
322
|
+
if self.pagination:
|
323
|
+
return self._list_all_pages_generator(self.STUB.PostInputsSearches,
|
324
|
+
service_pb2.PostInputsSearchesRequest, request_data,
|
325
|
+
page_no, per_page)
|
326
|
+
return self._list_topk_generator(self.STUB.PostInputsSearches,
|
327
|
+
service_pb2.PostInputsSearchesRequest, request_data)
|
249
328
|
|
250
329
|
# Calls PostAnnotationsSearches for annotation ranks, filters
|
251
330
|
filters_annot_proto = []
|
@@ -261,8 +340,12 @@ class Search(Lister, BaseClient):
|
|
261
340
|
searches=[
|
262
341
|
resources_pb2.Search(
|
263
342
|
query=resources_pb2.Query(ranks=all_ranks, filters=all_filters),
|
343
|
+
algorithm=self.algorithm,
|
264
344
|
metric=self.metric_distance)
|
265
345
|
])
|
266
|
-
|
267
|
-
|
268
|
-
|
346
|
+
if self.pagination:
|
347
|
+
return self._list_all_pages_generator(self.STUB.PostAnnotationsSearches,
|
348
|
+
service_pb2.PostAnnotationsSearchesRequest,
|
349
|
+
request_data, page_no, per_page)
|
350
|
+
return self._list_topk_generator(self.STUB.PostAnnotationsSearches,
|
351
|
+
service_pb2.PostAnnotationsSearchesRequest, request_data)
|
clarifai/client/user.py
CHANGED
@@ -7,7 +7,6 @@ from google.protobuf.json_format import MessageToDict
|
|
7
7
|
from clarifai.client.app import App
|
8
8
|
from clarifai.client.base import BaseClient
|
9
9
|
from clarifai.client.lister import Lister
|
10
|
-
from clarifai.client.runner import Runner
|
11
10
|
from clarifai.errors import UserError
|
12
11
|
from clarifai.utils.logging import get_logger
|
13
12
|
|
@@ -20,6 +19,7 @@ class User(Lister, BaseClient):
|
|
20
19
|
base_url: str = "https://api.clarifai.com",
|
21
20
|
pat: str = None,
|
22
21
|
token: str = None,
|
22
|
+
root_certificates_path: str = None,
|
23
23
|
**kwargs):
|
24
24
|
"""Initializes an User object.
|
25
25
|
|
@@ -28,12 +28,20 @@ class User(Lister, BaseClient):
|
|
28
28
|
base_url (str): Base API url. Default "https://api.clarifai.com"
|
29
29
|
pat (str): A personal access token for authentication. Can be set as env var CLARIFAI_PAT
|
30
30
|
token (str): A session token for authentication. Accepts either a session token or a pat. Can be set as env var CLARIFAI_SESSION_TOKEN
|
31
|
+
root_certificates_path (str): Path to the SSL root certificates file, used to establish secure gRPC connections.
|
31
32
|
**kwargs: Additional keyword arguments to be passed to the User.
|
32
33
|
"""
|
33
34
|
self.kwargs = {**kwargs, 'id': user_id}
|
34
35
|
self.user_info = resources_pb2.User(**self.kwargs)
|
35
36
|
self.logger = get_logger(logger_level="INFO", name=__name__)
|
36
|
-
BaseClient.__init__(
|
37
|
+
BaseClient.__init__(
|
38
|
+
self,
|
39
|
+
user_id=self.id,
|
40
|
+
app_id="",
|
41
|
+
base=base_url,
|
42
|
+
pat=pat,
|
43
|
+
token=token,
|
44
|
+
root_certificates_path=root_certificates_path)
|
37
45
|
Lister.__init__(self)
|
38
46
|
|
39
47
|
def list_apps(self, filter_by: Dict[str, Any] = {}, page_no: int = None,
|
@@ -69,7 +77,7 @@ class User(Lister, BaseClient):
|
|
69
77
|
**app_info) #(base_url=self.base, pat=self.pat, token=self.token, **app_info)
|
70
78
|
|
71
79
|
def list_runners(self, filter_by: Dict[str, Any] = {}, page_no: int = None,
|
72
|
-
per_page: int = None) -> Generator[
|
80
|
+
per_page: int = None) -> Generator[dict, None, None]:
|
73
81
|
"""List all runners for the user
|
74
82
|
|
75
83
|
Args:
|
@@ -78,7 +86,7 @@ class User(Lister, BaseClient):
|
|
78
86
|
per_page (int): The number of items per page.
|
79
87
|
|
80
88
|
Yields:
|
81
|
-
|
89
|
+
Dict: Dictionaries containing information about the runners.
|
82
90
|
|
83
91
|
Example:
|
84
92
|
>>> from clarifai.client.user import User
|
@@ -98,8 +106,7 @@ class User(Lister, BaseClient):
|
|
98
106
|
page_no=page_no)
|
99
107
|
|
100
108
|
for runner_info in all_runners_info:
|
101
|
-
yield
|
102
|
-
auth=self.auth_helper, check_runner_exists=False, **runner_info)
|
109
|
+
yield dict(auth=self.auth_helper, check_runner_exists=False, **runner_info)
|
103
110
|
|
104
111
|
def create_app(self, app_id: str, base_workflow: str = 'Empty', **kwargs) -> App:
|
105
112
|
"""Creates an app for the user.
|
@@ -127,7 +134,7 @@ class User(Lister, BaseClient):
|
|
127
134
|
self.logger.info("\nApp created\n%s", response.status)
|
128
135
|
return App.from_auth_helper(auth=self.auth_helper, app_id=app_id)
|
129
136
|
|
130
|
-
def create_runner(self, runner_id: str, labels: List[str], description: str) ->
|
137
|
+
def create_runner(self, runner_id: str, labels: List[str], description: str) -> dict:
|
131
138
|
"""Create a runner
|
132
139
|
|
133
140
|
Args:
|
@@ -136,13 +143,14 @@ class User(Lister, BaseClient):
|
|
136
143
|
description (str): Description of Runner
|
137
144
|
|
138
145
|
Returns:
|
139
|
-
|
146
|
+
Dict: A dictionary containing information about the specified Runner ID.
|
140
147
|
|
141
148
|
Example:
|
142
149
|
>>> from clarifai.client.user import User
|
143
150
|
>>> client = User(user_id="user_id")
|
144
|
-
>>>
|
151
|
+
>>> runner_info = client.create_runner(runner_id="runner_id", labels=["label to link runner"], description="laptop runner")
|
145
152
|
"""
|
153
|
+
|
146
154
|
if not isinstance(labels, List):
|
147
155
|
raise UserError("Labels must be a List of strings")
|
148
156
|
|
@@ -155,7 +163,7 @@ class User(Lister, BaseClient):
|
|
155
163
|
raise Exception(response.status)
|
156
164
|
self.logger.info("\nRunner created\n%s", response.status)
|
157
165
|
|
158
|
-
return
|
166
|
+
return dict(
|
159
167
|
auth=self.auth_helper,
|
160
168
|
runner_id=runner_id,
|
161
169
|
user_id=self.id,
|
@@ -186,19 +194,19 @@ class User(Lister, BaseClient):
|
|
186
194
|
kwargs['user_id'] = self.id
|
187
195
|
return App.from_auth_helper(auth=self.auth_helper, app_id=app_id, **kwargs)
|
188
196
|
|
189
|
-
def runner(self, runner_id: str) ->
|
197
|
+
def runner(self, runner_id: str) -> dict:
|
190
198
|
"""Returns a Runner object if exists.
|
191
199
|
|
192
200
|
Args:
|
193
201
|
runner_id (str): The runner ID to interact with
|
194
202
|
|
195
203
|
Returns:
|
196
|
-
|
204
|
+
Dict: A dictionary containing information about the existing runner ID.
|
197
205
|
|
198
206
|
Example:
|
199
207
|
>>> from clarifai.client.user import User
|
200
208
|
>>> client = User(user_id="user_id")
|
201
|
-
>>>
|
209
|
+
>>> runner_info = client.runner(runner_id="runner_id")
|
202
210
|
"""
|
203
211
|
request = service_pb2.GetRunnerRequest(user_app_id=self.user_app_id, runner_id=runner_id)
|
204
212
|
response = self._grpc_request(self.STUB.GetRunner, request)
|
@@ -212,7 +220,7 @@ class User(Lister, BaseClient):
|
|
212
220
|
kwargs = self.process_response_keys(dict_response[list(dict_response.keys())[1]],
|
213
221
|
list(dict_response.keys())[1])
|
214
222
|
|
215
|
-
return
|
223
|
+
return dict(self.auth_helper, check_runner_exists=False, **kwargs)
|
216
224
|
|
217
225
|
def delete_app(self, app_id: str) -> None:
|
218
226
|
"""Deletes an app for the user.
|
clarifai/client/workflow.py
CHANGED
@@ -28,6 +28,7 @@ class Workflow(Lister, BaseClient):
|
|
28
28
|
base_url: str = "https://api.clarifai.com",
|
29
29
|
pat: str = None,
|
30
30
|
token: str = None,
|
31
|
+
root_certificates_path: str = None,
|
31
32
|
**kwargs):
|
32
33
|
"""Initializes a Workflow object.
|
33
34
|
|
@@ -43,6 +44,7 @@ class Workflow(Lister, BaseClient):
|
|
43
44
|
base_url (str): Base API url. Default "https://api.clarifai.com"
|
44
45
|
pat (str): A personal access token for authentication. Can be set as env var CLARIFAI_PAT
|
45
46
|
token (str): A session token for authentication. Accepts either a session token or a pat. Can be set as env var CLARIFAI_SESSION_TOKEN
|
47
|
+
root_certificates_path (str): Path to the SSL root certificates file, used to establish secure gRPC connections.
|
46
48
|
**kwargs: Additional keyword arguments to be passed to the Workflow.
|
47
49
|
"""
|
48
50
|
if url and workflow_id:
|
@@ -59,7 +61,13 @@ class Workflow(Lister, BaseClient):
|
|
59
61
|
self.workflow_info = resources_pb2.Workflow(**self.kwargs)
|
60
62
|
self.logger = get_logger(logger_level="INFO", name=__name__)
|
61
63
|
BaseClient.__init__(
|
62
|
-
self,
|
64
|
+
self,
|
65
|
+
user_id=self.user_id,
|
66
|
+
app_id=self.app_id,
|
67
|
+
base=base_url,
|
68
|
+
pat=pat,
|
69
|
+
token=token,
|
70
|
+
root_certificates_path=root_certificates_path)
|
63
71
|
Lister.__init__(self)
|
64
72
|
|
65
73
|
def predict(self, inputs: List[Input], workflow_state_id: str = None):
|
@@ -0,0 +1 @@
|
|
1
|
+
MAX_UPLOAD_BATCH_SIZE = 128
|
clarifai/constants/search.py
CHANGED
@@ -141,6 +141,9 @@ Get your PAT from https://clarifai.com/settings/security and pass it here: <inse
|
|
141
141
|
Upload
|
142
142
|
|
143
143
|
```bash
|
144
|
+
# upload built file directly
|
145
|
+
$ clarifai upload model <your-working-dir> --user-app <your_user_id>/<your_app_id> --id <your_model_id>
|
146
|
+
# or using direct download url of cloud storage
|
144
147
|
$ clarifai upload model --url <url> --user-app <your_user_id>/<your_app_id> --id <your_model_id>
|
145
148
|
```
|
146
149
|
|
@@ -14,14 +14,11 @@
|
|
14
14
|
import argparse
|
15
15
|
import os
|
16
16
|
import subprocess
|
17
|
-
from typing import Union
|
18
17
|
|
19
|
-
from clarifai.
|
20
|
-
from clarifai.models.api import Models
|
21
|
-
from clarifai.models.model_serving.model_config import (MODEL_TYPES, get_model_config,
|
22
|
-
load_user_config)
|
18
|
+
from clarifai.models.model_serving.model_config import get_model_config, load_user_config
|
23
19
|
from clarifai.models.model_serving.model_config.inference_parameter import InferParamManager
|
24
20
|
|
21
|
+
from ..constants import BUILT_MODEL_EXT
|
25
22
|
from ..utils import login
|
26
23
|
from .base import BaseClarifaiCli
|
27
24
|
|
@@ -51,7 +48,9 @@ class UploadModelSubCli(BaseClarifaiCli):
|
|
51
48
|
"Path to working dir to get clarifai_config.yaml or path to yaml. Default is current directory",
|
52
49
|
default=".")
|
53
50
|
upload_parser.add_argument(
|
54
|
-
"--url", type=str, required=
|
51
|
+
"--url", type=str, required=False, help="Direct download url of zip file", default=None)
|
52
|
+
upload_parser.add_argument(
|
53
|
+
"--file", type=str, required=False, help="Local built file", default=None)
|
55
54
|
upload_parser.add_argument("--id", type=str, required=False, help="Model ID")
|
56
55
|
upload_parser.add_argument(
|
57
56
|
"--user-app",
|
@@ -62,7 +61,10 @@ class UploadModelSubCli(BaseClarifaiCli):
|
|
62
61
|
"--no-test",
|
63
62
|
action="store_true",
|
64
63
|
help="Trigger this flag to skip testing before uploading")
|
65
|
-
|
64
|
+
upload_parser.add_argument(
|
65
|
+
"--no-resume",
|
66
|
+
action="store_true",
|
67
|
+
help="Trigger this flag to not resume uploading local file")
|
66
68
|
upload_parser.add_argument(
|
67
69
|
"--update-version",
|
68
70
|
action="store_true",
|
@@ -73,10 +75,13 @@ class UploadModelSubCli(BaseClarifaiCli):
|
|
73
75
|
|
74
76
|
def __init__(self, args: argparse.Namespace) -> None:
|
75
77
|
self.no_test = args.no_test
|
78
|
+
self.no_resume = args.no_resume
|
76
79
|
|
77
80
|
working_dir_or_config = args.path
|
78
81
|
# if input a config file, then not running test
|
79
82
|
if working_dir_or_config.endswith(".yaml"):
|
83
|
+
# to folder
|
84
|
+
working_dir_or_config = os.path.split(working_dir_or_config)[0]
|
80
85
|
config_yaml_path = working_dir_or_config
|
81
86
|
self.test_path = None
|
82
87
|
self.no_test = True
|
@@ -89,12 +94,27 @@ class UploadModelSubCli(BaseClarifaiCli):
|
|
89
94
|
f"`{config_yaml_path}` does not exist")
|
90
95
|
self.config = load_user_config(cfg_path=config_yaml_path)
|
91
96
|
|
97
|
+
self.file = args.file
|
98
|
+
self.url = args.url
|
99
|
+
if self.file:
|
100
|
+
assert self.url, ValueError("Provide either file or url, but got both.")
|
101
|
+
assert os.path.exists(self.file), FileNotFoundError
|
102
|
+
elif self.url:
|
103
|
+
assert self.url.startswith("http") or self.url.startswith(
|
104
|
+
"s3"), f"Invalid url supported http or s3 url. Got {self.url}"
|
105
|
+
self.file = None
|
106
|
+
else:
|
107
|
+
for _fname in os.listdir(working_dir_or_config):
|
108
|
+
if _fname.endswith(BUILT_MODEL_EXT):
|
109
|
+
self.file = os.path.join(working_dir_or_config, _fname)
|
110
|
+
break
|
111
|
+
assert self.file, ValueError(
|
112
|
+
f"Not using url/file but also not found built file with extension {BUILT_MODEL_EXT}")
|
113
|
+
|
92
114
|
self.user_id, self.app_id = "", ""
|
93
115
|
user_app = args.user_app
|
94
116
|
self.url: str = args.url
|
95
117
|
self.update_version = args.update_version
|
96
|
-
assert self.url.startswith("http") or self.url.startswith(
|
97
|
-
"s3"), f"Invalid url supported http or s3 url. Got {self.url}"
|
98
118
|
|
99
119
|
clarifai_cfg = self.config.clarifai_model
|
100
120
|
self.url: str = args.url
|
@@ -111,17 +131,10 @@ class UploadModelSubCli(BaseClarifaiCli):
|
|
111
131
|
) == 2, f"id must be combination of user_id and app_id separated by `/`, e.g. <user_id>/<app_id>. Got {args.id}"
|
112
132
|
self.user_id, self.app_id = user_app
|
113
133
|
|
114
|
-
if self.user_id:
|
115
|
-
os.environ["CLARIFAI_USER_ID"] = self.user_id
|
116
|
-
if self.app_id:
|
117
|
-
os.environ["CLARIFAI_APP_ID"] = self.app_id
|
118
|
-
|
119
|
-
_user_id = os.environ.get("CLARIFAI_USER_ID", None)
|
120
|
-
_app_id = os.environ.get("CLARIFAI_APP_ID", None)
|
121
|
-
assert _user_id or _app_id, f"Missing user-id or app-id, got user-id {_user_id} and app-id {_app_id}"
|
122
134
|
login()
|
123
135
|
|
124
136
|
def run(self):
|
137
|
+
from clarifai.client import App, Model
|
125
138
|
|
126
139
|
# Run test before uploading
|
127
140
|
if not self.no_test:
|
@@ -129,54 +142,38 @@ class UploadModelSubCli(BaseClarifaiCli):
|
|
129
142
|
result = subprocess.run(f"pytest -s --log-level=INFO {self.test_path}", shell=True)
|
130
143
|
assert result.returncode == 0, "Test has failed. Please make sure no error exists in your code."
|
131
144
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
def
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
# post model
|
168
|
-
resp = model_api.upload_model(
|
169
|
-
model_id=model_id,
|
170
|
-
model_zip_url=model_url,
|
171
|
-
model_type=model_type,
|
172
|
-
input=clarifai_key_map.input_fields_map,
|
173
|
-
outputs=clarifai_key_map.output_fields_map,
|
174
|
-
description=desc,
|
175
|
-
param_specs=inference_parameters)
|
176
|
-
# response
|
177
|
-
if resp["status"]["code"] != "SUCCESS":
|
178
|
-
raise Exception("Post models failed, details: {}, {}".format(resp["status"]["description"],
|
179
|
-
resp["status"]["details"]))
|
180
|
-
else:
|
181
|
-
print("Success!")
|
182
|
-
print(f'Model version: {resp["model"]["model_version"]["id"]}')
|
145
|
+
clarifai_key_map = get_model_config(model_type=self.type).clarifai_model.field_maps
|
146
|
+
# inference parameters
|
147
|
+
inference_parameters = None
|
148
|
+
if isinstance(self.infer_param, str) and os.path.isfile(self.infer_param):
|
149
|
+
inference_parameters = InferParamManager(json_path=self.infer_param).get_list_params()
|
150
|
+
inputs = clarifai_key_map.input_fields_map
|
151
|
+
outputs = clarifai_key_map.output_fields_map
|
152
|
+
|
153
|
+
# if updating new version of existing model
|
154
|
+
def update_version():
|
155
|
+
model = Model(model_id=self.id, app_id=self.app_id)
|
156
|
+
if self.url:
|
157
|
+
model.create_version_by_url(
|
158
|
+
url=self.url,
|
159
|
+
input_field_maps=inputs,
|
160
|
+
output_field_maps=outputs,
|
161
|
+
inference_parameter_configs=inference_parameters,
|
162
|
+
description=self.desc)
|
163
|
+
elif self.file:
|
164
|
+
model.create_version_by_file(
|
165
|
+
file_path=self.file,
|
166
|
+
input_field_maps=inputs,
|
167
|
+
output_field_maps=outputs,
|
168
|
+
inference_parameter_configs=inference_parameters,
|
169
|
+
no_resume=self.no_resume,
|
170
|
+
description=self.desc)
|
171
|
+
else:
|
172
|
+
raise ValueError
|
173
|
+
|
174
|
+
if self.update_version:
|
175
|
+
update_version()
|
176
|
+
else:
|
177
|
+
# creating new model
|
178
|
+
_ = App(app_id=self.app_id).create_model(self.id, model_type_id=self.type)
|
179
|
+
update_version()
|
@@ -127,7 +127,15 @@ optional arguments:
|
|
127
127
|
|
128
128
|
5. Upload
|
129
129
|
|
130
|
-
This step will
|
130
|
+
This step will execute test.py in the specified working directory by default before proceeding with the build. You can upload your built file directly from the working directory to the platform or upload it to cloud storage and provide the direct URL during the upload process.
|
131
|
+
|
132
|
+
Use the following command to upload your built file directly to the platform. It will upload the `*.clarifai` file. *Note*: Only support file size from 5MiB to 5GiB
|
133
|
+
|
134
|
+
```bash
|
135
|
+
$ clarifai upload model <your_working_dir>
|
136
|
+
```
|
137
|
+
|
138
|
+
or upload with direct download url
|
131
139
|
|
132
140
|
```bash
|
133
141
|
$ clarifai upload model <your_working_dir> --url <your url>
|
@@ -141,10 +149,13 @@ positional arguments:
|
|
141
149
|
path Path to working dir to get clarifai_config.yaml or path to yaml. Default is current directory
|
142
150
|
|
143
151
|
optional arguments:
|
144
|
-
--
|
145
|
-
--
|
146
|
-
--
|
147
|
-
--
|
148
|
-
--
|
152
|
+
-h, --help show this help message and exit
|
153
|
+
--url URL Direct download url of zip file
|
154
|
+
--file FILE Local built file
|
155
|
+
--id ID Model ID
|
156
|
+
--user-app USER_APP User ID and App ID separated by '/', e.g., <user_id>/<app_id>
|
157
|
+
--no-test Trigger this flag to skip testing before uploading
|
158
|
+
--no-resume Trigger this flag to not resume uploading local file
|
159
|
+
--update-version Update exist model with new version
|
149
160
|
|
150
161
|
```
|
clarifai/rag/rag.py
CHANGED
@@ -110,7 +110,7 @@ class RAG:
|
|
110
110
|
prompter_model_params = {"params": params}
|
111
111
|
|
112
112
|
## Create rag-prompter model and version
|
113
|
-
model_id = f"prompter-{workflow_id}" if workflow_id is not None else f"rag-prompter-{now_ts}"
|
113
|
+
model_id = f"prompter-{workflow_id}-{now_ts}" if workflow_id is not None else f"rag-prompter-{now_ts}"
|
114
114
|
prompter_model = app.create_model(model_id=model_id, model_type_id="rag-prompter")
|
115
115
|
prompter_model = prompter_model.create_version(output_info=prompter_model_params)
|
116
116
|
|
clarifai/rag/utils.py
CHANGED
@@ -67,7 +67,7 @@ def load_documents(file_path: str = None, folder_path: str = None, url: str = No
|
|
67
67
|
#document loaders for folderpath
|
68
68
|
if folder_path:
|
69
69
|
documents = SimpleDirectoryReader(
|
70
|
-
input_dir=Path(folder_path), required_exts=[".pdf", ".docx"]).load_data()
|
70
|
+
input_dir=Path(folder_path), required_exts=[".pdf", ".docx", ".txt"]).load_data()
|
71
71
|
|
72
72
|
#document loaders for url
|
73
73
|
if url:
|