indexify 0.2.48__py3-none-any.whl → 0.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.
- indexify/{cli.py → cli/cli.py} +75 -82
- indexify/executor/README.md +35 -0
- indexify/executor/api_objects.py +9 -3
- indexify/executor/downloader.py +5 -5
- indexify/executor/executor.py +35 -22
- indexify/executor/function_executor/function_executor.py +14 -3
- indexify/executor/function_executor/function_executor_state.py +13 -10
- indexify/executor/function_executor/invocation_state_client.py +2 -1
- indexify/executor/function_executor/server/subprocess_function_executor_server_factory.py +22 -10
- indexify/executor/function_executor/single_task_runner.py +43 -26
- indexify/executor/function_executor/task_input.py +1 -3
- indexify/executor/task_fetcher.py +5 -7
- indexify/executor/task_reporter.py +3 -5
- indexify/executor/task_runner.py +31 -24
- indexify/function_executor/README.md +18 -0
- indexify/function_executor/handlers/run_function/function_inputs_loader.py +13 -14
- indexify/function_executor/handlers/run_function/handler.py +16 -40
- indexify/function_executor/handlers/run_function/request_validator.py +7 -5
- indexify/function_executor/handlers/run_function/response_helper.py +6 -8
- indexify/function_executor/initialize_request_validator.py +1 -2
- indexify/function_executor/invocation_state/invocation_state_proxy_server.py +1 -1
- indexify/function_executor/invocation_state/proxied_invocation_state.py +1 -3
- indexify/function_executor/main.py +50 -0
- indexify/function_executor/proto/configuration.py +8 -0
- indexify/function_executor/proto/function_executor.proto +9 -4
- indexify/function_executor/proto/function_executor_pb2.py +24 -24
- indexify/function_executor/proto/function_executor_pb2.pyi +24 -4
- indexify/function_executor/server.py +4 -6
- indexify/function_executor/{function_executor_service.py → service.py} +35 -24
- indexify/utils/README.md +3 -0
- indexify/{common_util.py → utils/http_client.py} +2 -2
- indexify/{logging.py → utils/logging.py} +36 -2
- indexify-0.3.1.dist-info/METADATA +38 -0
- indexify-0.3.1.dist-info/RECORD +44 -0
- {indexify-0.2.48.dist-info → indexify-0.3.1.dist-info}/WHEEL +1 -1
- indexify-0.3.1.dist-info/entry_points.txt +4 -0
- indexify/__init__.py +0 -31
- indexify/data_loaders/__init__.py +0 -58
- indexify/data_loaders/local_directory_loader.py +0 -37
- indexify/data_loaders/url_loader.py +0 -52
- indexify/error.py +0 -8
- indexify/functions_sdk/data_objects.py +0 -27
- indexify/functions_sdk/graph.py +0 -364
- indexify/functions_sdk/graph_definition.py +0 -63
- indexify/functions_sdk/graph_validation.py +0 -70
- indexify/functions_sdk/image.py +0 -222
- indexify/functions_sdk/indexify_functions.py +0 -354
- indexify/functions_sdk/invocation_state/invocation_state.py +0 -22
- indexify/functions_sdk/invocation_state/local_invocation_state.py +0 -30
- indexify/functions_sdk/object_serializer.py +0 -68
- indexify/functions_sdk/pipeline.py +0 -33
- indexify/http_client.py +0 -379
- indexify/remote_graph.py +0 -138
- indexify/remote_pipeline.py +0 -25
- indexify/settings.py +0 -1
- indexify-0.2.48.dist-info/LICENSE.txt +0 -201
- indexify-0.2.48.dist-info/METADATA +0 -154
- indexify-0.2.48.dist-info/RECORD +0 -60
- indexify-0.2.48.dist-info/entry_points.txt +0 -3
@@ -1,33 +0,0 @@
|
|
1
|
-
from typing import Union
|
2
|
-
|
3
|
-
from indexify.functions_sdk.indexify_functions import (
|
4
|
-
IndexifyFunction,
|
5
|
-
IndexifyRouter,
|
6
|
-
)
|
7
|
-
|
8
|
-
from .graph import Graph
|
9
|
-
|
10
|
-
|
11
|
-
class Pipeline:
|
12
|
-
def __init__(self, name: str, description: str):
|
13
|
-
self.name = name
|
14
|
-
self.description = description
|
15
|
-
self._graph: Graph = None
|
16
|
-
self._last_step = None
|
17
|
-
|
18
|
-
def add_step(self, function: Union[IndexifyFunction, IndexifyRouter]):
|
19
|
-
if self._graph is None:
|
20
|
-
self._graph = Graph(
|
21
|
-
name=self.name, description=self.description, start_node=function
|
22
|
-
)
|
23
|
-
self._last_step = function
|
24
|
-
return
|
25
|
-
self._graph.add_edge(self._last_step, function)
|
26
|
-
self._last_step = function
|
27
|
-
|
28
|
-
def run(self, **kwargs):
|
29
|
-
invocation_id = self._graph.run(**kwargs)
|
30
|
-
return invocation_id
|
31
|
-
|
32
|
-
def output(self, invocation_id: str, function_name: str):
|
33
|
-
return self._graph.output(invocation_id, function_name)
|
indexify/http_client.py
DELETED
@@ -1,379 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
import os
|
3
|
-
from typing import Any, Dict, List, Optional
|
4
|
-
|
5
|
-
import cloudpickle
|
6
|
-
import httpx
|
7
|
-
from httpx_sse import connect_sse
|
8
|
-
from pydantic import BaseModel, Json
|
9
|
-
from rich import print
|
10
|
-
|
11
|
-
from indexify.common_util import get_httpx_client, get_sync_or_async_client
|
12
|
-
from indexify.error import ApiException, GraphStillProcessing
|
13
|
-
from indexify.functions_sdk.data_objects import IndexifyData
|
14
|
-
from indexify.functions_sdk.graph import ComputeGraphMetadata, Graph
|
15
|
-
from indexify.functions_sdk.indexify_functions import IndexifyFunction
|
16
|
-
from indexify.functions_sdk.object_serializer import get_serializer
|
17
|
-
from indexify.settings import DEFAULT_SERVICE_URL
|
18
|
-
|
19
|
-
|
20
|
-
class InvocationEventPayload(BaseModel):
|
21
|
-
invocation_id: str
|
22
|
-
fn_name: str
|
23
|
-
task_id: str
|
24
|
-
executor_id: Optional[str] = None
|
25
|
-
outcome: Optional[str] = None
|
26
|
-
|
27
|
-
|
28
|
-
class InvocationEvent(BaseModel):
|
29
|
-
event_name: str
|
30
|
-
payload: InvocationEventPayload
|
31
|
-
|
32
|
-
|
33
|
-
class GraphOutputMetadata(BaseModel):
|
34
|
-
id: str
|
35
|
-
compute_fn: str
|
36
|
-
|
37
|
-
|
38
|
-
class GraphOutputs(BaseModel):
|
39
|
-
status: str
|
40
|
-
outputs: List[GraphOutputMetadata]
|
41
|
-
cursor: Optional[str] = None
|
42
|
-
|
43
|
-
|
44
|
-
class IndexifyClient:
|
45
|
-
def __init__(
|
46
|
-
self,
|
47
|
-
service_url: str = DEFAULT_SERVICE_URL,
|
48
|
-
config_path: Optional[str] = None,
|
49
|
-
namespace: str = "default",
|
50
|
-
api_key: Optional[str] = None,
|
51
|
-
**kwargs,
|
52
|
-
):
|
53
|
-
if os.environ.get("INDEXIFY_URL"):
|
54
|
-
print("Using INDEXIFY_URL environment variable to connect to Indexify")
|
55
|
-
service_url = os.environ["INDEXIFY_URL"]
|
56
|
-
|
57
|
-
self.service_url = service_url
|
58
|
-
self._config_path = config_path
|
59
|
-
self._client = get_httpx_client(config_path)
|
60
|
-
|
61
|
-
self.namespace: str = namespace
|
62
|
-
self.compute_graphs: List[Graph] = []
|
63
|
-
self.labels: dict = {}
|
64
|
-
self._service_url = service_url
|
65
|
-
self._timeout = kwargs.get("timeout")
|
66
|
-
self._graphs: Dict[str, Graph] = {}
|
67
|
-
self._api_key = api_key
|
68
|
-
if not self._api_key:
|
69
|
-
print(
|
70
|
-
"API key not provided. Trying to fetch from environment TENSORLAKE_API_KEY variable"
|
71
|
-
)
|
72
|
-
self._api_key = os.getenv("TENSORLAKE_API_KEY")
|
73
|
-
|
74
|
-
def _request(self, method: str, **kwargs) -> httpx.Response:
|
75
|
-
try:
|
76
|
-
response = self._client.request(method, timeout=self._timeout, **kwargs)
|
77
|
-
status_code = str(response.status_code)
|
78
|
-
if status_code.startswith("4"):
|
79
|
-
raise ApiException(
|
80
|
-
"status code: " + status_code + " message: " + response.text
|
81
|
-
)
|
82
|
-
if status_code.startswith("5"):
|
83
|
-
raise ApiException(response.text)
|
84
|
-
except httpx.ConnectError:
|
85
|
-
message = (
|
86
|
-
f"Make sure the server is running and accessible at {self._service_url}"
|
87
|
-
)
|
88
|
-
ex = ApiException(message=message)
|
89
|
-
raise ex
|
90
|
-
return response
|
91
|
-
|
92
|
-
@classmethod
|
93
|
-
def with_mtls(
|
94
|
-
cls,
|
95
|
-
cert_path: str,
|
96
|
-
key_path: str,
|
97
|
-
ca_bundle_path: Optional[str] = None,
|
98
|
-
service_url: str = DEFAULT_SERVICE_URL,
|
99
|
-
*args,
|
100
|
-
**kwargs,
|
101
|
-
) -> "IndexifyClient":
|
102
|
-
"""
|
103
|
-
Create a client with mutual TLS authentication. Also enables HTTP/2,
|
104
|
-
which is required for mTLS.
|
105
|
-
NOTE: mTLS must be enabled on the Indexify service for this to work.
|
106
|
-
|
107
|
-
:param cert_path: Path to the client certificate. Resolution handled by httpx.
|
108
|
-
:param key_path: Path to the client key. Resolution handled by httpx.
|
109
|
-
:param args: Arguments to pass to the httpx.Client constructor
|
110
|
-
:param kwargs: Keyword arguments to pass to the httpx.Client constructor
|
111
|
-
:return: A client with mTLS authentication
|
112
|
-
|
113
|
-
Example usage:
|
114
|
-
```
|
115
|
-
from indexify import IndexifyClient
|
116
|
-
|
117
|
-
client = IndexifyClient.with_mtls(
|
118
|
-
cert_path="/path/to/cert.pem",
|
119
|
-
key_path="/path/to/key.pem",
|
120
|
-
)
|
121
|
-
assert client.heartbeat() == True
|
122
|
-
```
|
123
|
-
"""
|
124
|
-
if not (cert_path and key_path):
|
125
|
-
raise ValueError("Both cert and key must be provided for mTLS")
|
126
|
-
|
127
|
-
client = get_sync_or_async_client(
|
128
|
-
cert_path=cert_path, key_path=key_path, ca_bundle_path=ca_bundle_path
|
129
|
-
)
|
130
|
-
|
131
|
-
indexify_client = IndexifyClient(service_url, *args, **kwargs)
|
132
|
-
indexify_client._client = client
|
133
|
-
return indexify_client
|
134
|
-
|
135
|
-
def _add_api_key(self, kwargs):
|
136
|
-
if self._api_key:
|
137
|
-
if "headers" not in kwargs:
|
138
|
-
kwargs["headers"] = {}
|
139
|
-
kwargs["headers"]["Authorization"] = f"Bearer {self._api_key}"
|
140
|
-
|
141
|
-
def _get(self, endpoint: str, **kwargs) -> httpx.Response:
|
142
|
-
self._add_api_key(kwargs)
|
143
|
-
return self._request("GET", url=f"{self._service_url}/{endpoint}", **kwargs)
|
144
|
-
|
145
|
-
def _post(self, endpoint: str, **kwargs) -> httpx.Response:
|
146
|
-
self._add_api_key(kwargs)
|
147
|
-
return self._request("POST", url=f"{self._service_url}/{endpoint}", **kwargs)
|
148
|
-
|
149
|
-
def _put(self, endpoint: str, **kwargs) -> httpx.Response:
|
150
|
-
self._add_api_key(kwargs)
|
151
|
-
return self._request("PUT", url=f"{self._service_url}/{endpoint}", **kwargs)
|
152
|
-
|
153
|
-
def _delete(self, endpoint: str, **kwargs) -> httpx.Response:
|
154
|
-
self._add_api_key(kwargs)
|
155
|
-
return self._request("DELETE", url=f"{self._service_url}/{endpoint}", **kwargs)
|
156
|
-
|
157
|
-
def _close(self):
|
158
|
-
self._client.close()
|
159
|
-
|
160
|
-
def __enter__(self):
|
161
|
-
return self
|
162
|
-
|
163
|
-
def __exit__(self, exc_type, exc_value, traceback):
|
164
|
-
self.close()
|
165
|
-
|
166
|
-
def register_compute_graph(self, graph: Graph, additional_modules):
|
167
|
-
graph_metadata = graph.definition()
|
168
|
-
serialized_code = cloudpickle.dumps(graph.serialize(additional_modules))
|
169
|
-
response = self._post(
|
170
|
-
f"namespaces/{self.namespace}/compute_graphs",
|
171
|
-
files={"code": serialized_code},
|
172
|
-
data={"compute_graph": graph_metadata.model_dump_json(exclude_none=True)},
|
173
|
-
)
|
174
|
-
response.raise_for_status()
|
175
|
-
self._graphs[graph.name] = graph
|
176
|
-
|
177
|
-
def delete_compute_graph(
|
178
|
-
self,
|
179
|
-
graph_name: str,
|
180
|
-
) -> None:
|
181
|
-
"""
|
182
|
-
Deletes a graph and all of its invocations from the namespace.
|
183
|
-
:param graph_name The name of the graph to delete.
|
184
|
-
WARNING: This operation is irreversible.
|
185
|
-
"""
|
186
|
-
response = self._delete(
|
187
|
-
f"namespaces/{self.namespace}/compute_graphs/{graph_name}",
|
188
|
-
)
|
189
|
-
response.raise_for_status()
|
190
|
-
|
191
|
-
def graphs(self, namespace="default") -> List[ComputeGraphMetadata]:
|
192
|
-
response = self._get(f"namespaces/{namespace}/compute_graphs")
|
193
|
-
graphs = []
|
194
|
-
for graph in response.json()["compute_graphs"]:
|
195
|
-
graphs.append(ComputeGraphMetadata(**graph))
|
196
|
-
|
197
|
-
return graphs
|
198
|
-
|
199
|
-
def graph(self, name: str) -> ComputeGraphMetadata:
|
200
|
-
response = self._get(f"namespaces/{self.namespace}/compute_graphs/{name}")
|
201
|
-
return ComputeGraphMetadata(**response.json())
|
202
|
-
|
203
|
-
def namespaces(self) -> List[str]:
|
204
|
-
response = self._get(f"namespaces")
|
205
|
-
namespaces_dict = response.json()["namespaces"]
|
206
|
-
namespaces = []
|
207
|
-
for item in namespaces_dict:
|
208
|
-
namespaces.append(item["name"])
|
209
|
-
return namespaces
|
210
|
-
|
211
|
-
@classmethod
|
212
|
-
def new_namespace(
|
213
|
-
cls, namespace: str, server_addr: Optional[str] = "http://localhost:8900"
|
214
|
-
):
|
215
|
-
# Create a new client instance with the specified server address
|
216
|
-
client = cls(service_url=server_addr)
|
217
|
-
|
218
|
-
try:
|
219
|
-
# Create the new namespace using the client
|
220
|
-
client.create_namespace(namespace)
|
221
|
-
except ApiException as e:
|
222
|
-
print(f"Failed to create namespace '{namespace}': {e}")
|
223
|
-
raise
|
224
|
-
|
225
|
-
# Set the namespace for the newly created client
|
226
|
-
client.namespace = namespace
|
227
|
-
|
228
|
-
# Return the client instance with the new namespace
|
229
|
-
return client
|
230
|
-
|
231
|
-
def create_namespace(self, namespace: str):
|
232
|
-
self._post("namespaces", json={"name": namespace})
|
233
|
-
|
234
|
-
def logs(
|
235
|
-
self, invocation_id: str, cg_name: str, fn_name: str, task_id: str, file: str
|
236
|
-
) -> Optional[str]:
|
237
|
-
try:
|
238
|
-
response = self._get(
|
239
|
-
f"namespaces/{self.namespace}/compute_graphs/{cg_name}/invocations/{invocation_id}/fn/{fn_name}/tasks/{task_id}/logs/{file}"
|
240
|
-
)
|
241
|
-
response.raise_for_status()
|
242
|
-
return response.content.decode("utf-8")
|
243
|
-
except ApiException as e:
|
244
|
-
print(f"failed to fetch logs: {e}")
|
245
|
-
return None
|
246
|
-
|
247
|
-
def replay_invocations(self, graph: str):
|
248
|
-
self._post(f"namespaces/{self.namespace}/compute_graphs/{graph}/replay")
|
249
|
-
|
250
|
-
def invoke_graph_with_object(
|
251
|
-
self,
|
252
|
-
graph: str,
|
253
|
-
block_until_done: bool = False,
|
254
|
-
input_encoding: str = "cloudpickle",
|
255
|
-
**kwargs,
|
256
|
-
) -> str:
|
257
|
-
serializer = get_serializer(input_encoding)
|
258
|
-
ser_input = serializer.serialize(kwargs)
|
259
|
-
params = {"block_until_finish": block_until_done}
|
260
|
-
kwargs = {
|
261
|
-
"headers": {"Content-Type": serializer.content_type},
|
262
|
-
"data": ser_input,
|
263
|
-
"params": params,
|
264
|
-
}
|
265
|
-
self._add_api_key(kwargs)
|
266
|
-
with get_httpx_client(self._config_path) as client:
|
267
|
-
with connect_sse(
|
268
|
-
client,
|
269
|
-
"POST",
|
270
|
-
f"{self.service_url}/namespaces/{self.namespace}/compute_graphs/{graph}/invoke_object",
|
271
|
-
**kwargs,
|
272
|
-
) as event_source:
|
273
|
-
if not event_source.response.is_success:
|
274
|
-
resp = event_source.response.read().decode("utf-8")
|
275
|
-
raise Exception(f"failed to invoke graph: {resp}")
|
276
|
-
for sse in event_source.iter_sse():
|
277
|
-
obj = json.loads(sse.data)
|
278
|
-
for k, v in obj.items():
|
279
|
-
if k == "id":
|
280
|
-
return v
|
281
|
-
if k == "InvocationFinished":
|
282
|
-
return v["id"]
|
283
|
-
if k == "DiagnosticMessage":
|
284
|
-
message = v.get("message", None)
|
285
|
-
print(
|
286
|
-
f"[bold red]scheduler diagnostic: [/bold red]{message}"
|
287
|
-
)
|
288
|
-
continue
|
289
|
-
event_payload = InvocationEventPayload.model_validate(v)
|
290
|
-
event = InvocationEvent(event_name=k, payload=event_payload)
|
291
|
-
if (
|
292
|
-
event.event_name == "TaskCompleted"
|
293
|
-
and event.payload.outcome == "Failure"
|
294
|
-
):
|
295
|
-
stdout = self.logs(
|
296
|
-
event.payload.invocation_id,
|
297
|
-
graph,
|
298
|
-
event.payload.fn_name,
|
299
|
-
event.payload.task_id,
|
300
|
-
"stdout",
|
301
|
-
)
|
302
|
-
stderr = self.logs(
|
303
|
-
event.payload.invocation_id,
|
304
|
-
graph,
|
305
|
-
event.payload.fn_name,
|
306
|
-
event.payload.task_id,
|
307
|
-
"stderr",
|
308
|
-
)
|
309
|
-
if stdout:
|
310
|
-
print(f"[bold red]stdout[/bold red]: \n {stdout}")
|
311
|
-
if stderr:
|
312
|
-
print(f"[bold red]stderr[/bold red]: \n {stderr}")
|
313
|
-
print(
|
314
|
-
f"[bold green]{event.event_name}[/bold green]: {event.payload}"
|
315
|
-
)
|
316
|
-
raise Exception("invocation ID not returned")
|
317
|
-
|
318
|
-
def _download_output(
|
319
|
-
self,
|
320
|
-
namespace: str,
|
321
|
-
graph: str,
|
322
|
-
invocation_id: str,
|
323
|
-
fn_name: str,
|
324
|
-
output_id: str,
|
325
|
-
) -> IndexifyData:
|
326
|
-
response = self._get(
|
327
|
-
f"namespaces/{namespace}/compute_graphs/{graph}/invocations/{invocation_id}/fn/{fn_name}/output/{output_id}",
|
328
|
-
)
|
329
|
-
response.raise_for_status()
|
330
|
-
content_type = response.headers.get("Content-Type")
|
331
|
-
if content_type == "application/json":
|
332
|
-
encoding = "json"
|
333
|
-
else:
|
334
|
-
encoding = "cloudpickle"
|
335
|
-
return IndexifyData(id=output_id, payload=response.content, encoder=encoding)
|
336
|
-
|
337
|
-
def graph_outputs(
|
338
|
-
self,
|
339
|
-
graph: str,
|
340
|
-
invocation_id: str,
|
341
|
-
fn_name: str,
|
342
|
-
) -> List[Any]:
|
343
|
-
"""
|
344
|
-
Returns the extracted objects by a graph for an ingested object. If the extractor name is provided, only the objects extracted by that extractor are returned.
|
345
|
-
If the extractor name is not provided, all the extracted objects are returned for the input object.
|
346
|
-
graph: str: The name of the graph
|
347
|
-
invocation_id: str: The ID of the invocation.
|
348
|
-
fn_name: Optional[str]: The name of the function whose output is to be returned if provided
|
349
|
-
return: Union[Dict[str, List[Any]], List[Any]]: The extracted objects. If the extractor name is provided, the output is a list of extracted objects by the extractor. If the extractor name is not provided, the output is a dictionary with the extractor name as the key and the extracted objects as the value. If no objects are found, an empty list is returned.
|
350
|
-
"""
|
351
|
-
fn_key = f"{graph}/{fn_name}"
|
352
|
-
response = self._get(
|
353
|
-
f"namespaces/{self.namespace}/compute_graphs/{graph}/invocations/{invocation_id}/outputs",
|
354
|
-
)
|
355
|
-
response.raise_for_status()
|
356
|
-
graph_outputs = GraphOutputs(**response.json())
|
357
|
-
if graph_outputs.status == "pending":
|
358
|
-
raise GraphStillProcessing()
|
359
|
-
outputs = []
|
360
|
-
for output in graph_outputs.outputs:
|
361
|
-
if output.compute_fn == fn_name:
|
362
|
-
indexify_data = self._download_output(
|
363
|
-
self.namespace, graph, invocation_id, fn_name, output.id
|
364
|
-
)
|
365
|
-
serializer = get_serializer(indexify_data.encoder)
|
366
|
-
output = serializer.deserialize(indexify_data.payload)
|
367
|
-
outputs.append(output)
|
368
|
-
return outputs
|
369
|
-
|
370
|
-
def invoke_graph_with_file(
|
371
|
-
self, graph: str, path: str, metadata: Optional[Dict[str, Json]] = None
|
372
|
-
) -> str:
|
373
|
-
"""
|
374
|
-
Invokes a graph with an input file. The file's mimetype is appropriately detected.
|
375
|
-
graph: str: The name of the graph to invoke
|
376
|
-
path: str: The path to the file to be ingested
|
377
|
-
return: str: The ID of the ingested object
|
378
|
-
"""
|
379
|
-
pass
|
indexify/remote_graph.py
DELETED
@@ -1,138 +0,0 @@
|
|
1
|
-
from typing import Any, List, Optional
|
2
|
-
|
3
|
-
from indexify.functions_sdk.graph import ComputeGraphMetadata, Graph
|
4
|
-
from indexify.functions_sdk.graph_definition import ComputeGraphMetadata
|
5
|
-
|
6
|
-
from .http_client import IndexifyClient
|
7
|
-
from .settings import DEFAULT_SERVICE_URL
|
8
|
-
|
9
|
-
|
10
|
-
class RemoteGraph:
|
11
|
-
def __init__(
|
12
|
-
self,
|
13
|
-
name: str,
|
14
|
-
server_url: Optional[str] = DEFAULT_SERVICE_URL,
|
15
|
-
client: Optional[IndexifyClient] = None,
|
16
|
-
):
|
17
|
-
"""
|
18
|
-
Create a handle to call a RemoteGraph by name.
|
19
|
-
|
20
|
-
Note: Use the class methods RemoteGraph.deploy or RemoteGraph.by_name to create a RemoteGraph object.
|
21
|
-
|
22
|
-
:param name: The name of the graph.
|
23
|
-
:param server_url: The URL of the server where the graph will be registered.
|
24
|
-
Not used if client is provided.
|
25
|
-
:param client: The IndexifyClient used to communicate with the server.
|
26
|
-
Preferred over server_url.
|
27
|
-
"""
|
28
|
-
self._name = name
|
29
|
-
if client:
|
30
|
-
self._client = client
|
31
|
-
else:
|
32
|
-
self._client = IndexifyClient(service_url=server_url)
|
33
|
-
|
34
|
-
self._graph_definition: ComputeGraphMetadata = self._client.graph(self._name)
|
35
|
-
|
36
|
-
def run(self, block_until_done: bool = False, **kwargs) -> str:
|
37
|
-
"""
|
38
|
-
Run the graph with the given inputs. The input is for the start function of the graph.
|
39
|
-
|
40
|
-
:param block_until_done: If True, the function will block until the graph execution is complete.
|
41
|
-
:param kwargs: The input to the start function of the graph. Pass the input as keyword arguments.
|
42
|
-
:return: The invocation ID of the graph execution.
|
43
|
-
|
44
|
-
Example:
|
45
|
-
@indexify_function()
|
46
|
-
def foo(x: int) -> int:
|
47
|
-
return x + 1
|
48
|
-
|
49
|
-
remote_graph = RemoteGraph.by_name("test")
|
50
|
-
invocation_id = remote_graph.run(x=1)
|
51
|
-
"""
|
52
|
-
return self._client.invoke_graph_with_object(
|
53
|
-
self._name,
|
54
|
-
block_until_done,
|
55
|
-
self._graph_definition.get_input_encoder(),
|
56
|
-
**kwargs
|
57
|
-
)
|
58
|
-
|
59
|
-
def metadata(self) -> ComputeGraphMetadata:
|
60
|
-
"""
|
61
|
-
Get the metadata of the graph.
|
62
|
-
"""
|
63
|
-
return self._client.graph(self._name)
|
64
|
-
|
65
|
-
def replay_invocations(self):
|
66
|
-
"""
|
67
|
-
Replay all the graph previous runs/invocations on the latest version of the graph.
|
68
|
-
|
69
|
-
This is useful to make all the previous invocations go through
|
70
|
-
an updated graph to take advantage of graph improvements.
|
71
|
-
"""
|
72
|
-
self._client.replay_invocations(self._name)
|
73
|
-
|
74
|
-
@classmethod
|
75
|
-
def deploy(
|
76
|
-
cls,
|
77
|
-
g: Graph,
|
78
|
-
additional_modules=[],
|
79
|
-
server_url: Optional[str] = DEFAULT_SERVICE_URL,
|
80
|
-
client: Optional[IndexifyClient] = None,
|
81
|
-
):
|
82
|
-
"""
|
83
|
-
Create a new RemoteGraph from a local Graph object.
|
84
|
-
|
85
|
-
:param g: The local Graph object.
|
86
|
-
:param additional_modules: List of additional modules to be registered with the graph.
|
87
|
-
Needed for modules that are imported outside of an indexify function.
|
88
|
-
:param server_url: The URL of the server where the graph will be registered.
|
89
|
-
Not used if client is provided.
|
90
|
-
:param client: The IndexifyClient used to communicate with the server.
|
91
|
-
Preferred over server_url.
|
92
|
-
"""
|
93
|
-
g.validate_graph()
|
94
|
-
if not client:
|
95
|
-
client = IndexifyClient(service_url=server_url)
|
96
|
-
client.register_compute_graph(g, additional_modules)
|
97
|
-
return cls(name=g.name, server_url=server_url, client=client)
|
98
|
-
|
99
|
-
@classmethod
|
100
|
-
def by_name(
|
101
|
-
cls,
|
102
|
-
name: str,
|
103
|
-
server_url: Optional[str] = DEFAULT_SERVICE_URL,
|
104
|
-
client: Optional[IndexifyClient] = None,
|
105
|
-
):
|
106
|
-
"""
|
107
|
-
Create a handle to call a RemoteGraph by name.
|
108
|
-
|
109
|
-
:param name: The name of the graph.
|
110
|
-
:param server_url: The URL of the server where the graph will be registered.
|
111
|
-
Not used if client is provided.
|
112
|
-
:param client: The IndexifyClient used to communicate with the server.
|
113
|
-
Preferred over server_url.
|
114
|
-
:return: A RemoteGraph object.
|
115
|
-
"""
|
116
|
-
return cls(name=name, server_url=server_url, client=client)
|
117
|
-
|
118
|
-
def output(
|
119
|
-
self,
|
120
|
-
invocation_id: str,
|
121
|
-
fn_name: str,
|
122
|
-
) -> List[Any]:
|
123
|
-
"""
|
124
|
-
Returns the extracted objects by a graph for an ingested object.
|
125
|
-
|
126
|
-
- If the extractor name is provided, only the objects extracted by that extractor are returned.
|
127
|
-
- If the extractor name is not provided, all the extracted objects are returned for the input object.
|
128
|
-
|
129
|
-
:param invocation_id (str): The ID of the ingested object
|
130
|
-
:param fn_name (Optional[str]): The name of the function whose output is to be returned if provided
|
131
|
-
:return (List[Any]): Output of the function.
|
132
|
-
"""
|
133
|
-
|
134
|
-
return self._client.graph_outputs(
|
135
|
-
graph=self._name,
|
136
|
-
invocation_id=invocation_id,
|
137
|
-
fn_name=fn_name,
|
138
|
-
)
|
indexify/remote_pipeline.py
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
|
-
from indexify.functions_sdk.pipeline import Pipeline
|
4
|
-
|
5
|
-
from .http_client import IndexifyClient
|
6
|
-
from .remote_graph import RemoteGraph
|
7
|
-
|
8
|
-
|
9
|
-
class RemotePipeline(RemoteGraph):
|
10
|
-
@classmethod
|
11
|
-
def deploy(
|
12
|
-
cls,
|
13
|
-
p: Pipeline,
|
14
|
-
additional_modules=[],
|
15
|
-
server_url: Optional[str] = "http://localhost:8900",
|
16
|
-
):
|
17
|
-
"""
|
18
|
-
Create a new RemoteGraph from a local Graph object.
|
19
|
-
:param g: The local Graph object.
|
20
|
-
:param server_url: The URL of the server where the graph will be registered.
|
21
|
-
"""
|
22
|
-
cls.graph = p._graph
|
23
|
-
client = IndexifyClient(service_url=server_url)
|
24
|
-
client.register_compute_graph(p._graph, additional_modules)
|
25
|
-
return cls(name=p._graph.name, server_url=server_url)
|
indexify/settings.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
DEFAULT_SERVICE_URL = "https://api.tensorlake.ai"
|