seekrai 0.4.2__tar.gz → 0.4.4__tar.gz
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.
- {seekrai-0.4.2 → seekrai-0.4.4}/PKG-INFO +1 -1
- {seekrai-0.4.2 → seekrai-0.4.4}/pyproject.toml +1 -1
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/client.py +8 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/filemanager.py +89 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/resources/__init__.py +5 -0
- seekrai-0.4.4/src/seekrai/resources/agents/__init__.py +8 -0
- seekrai-0.4.4/src/seekrai/resources/agents/agent_inference.py +70 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/resources/files.py +50 -0
- seekrai-0.4.4/src/seekrai/resources/ingestion.py +179 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/common.py +7 -2
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/files.py +2 -0
- seekrai-0.4.4/src/seekrai/types/ingestion.py +37 -0
- seekrai-0.4.2/src/seekrai/types/ingestion.py +0 -8
- {seekrai-0.4.2 → seekrai-0.4.4}/LICENSE +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/README.md +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/__init__.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/abstract/__init__.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/abstract/api_requestor.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/constants.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/error.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/resources/alignment.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/resources/chat/__init__.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/resources/chat/completions.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/resources/completions.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/resources/deployments.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/resources/embeddings.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/resources/finetune.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/resources/images.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/resources/models.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/resources/projects.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/seekrflow_response.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/__init__.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/abstract.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/alignment.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/chat_completions.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/completions.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/deployments.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/embeddings.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/error.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/finetune.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/images.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/models.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/types/projects.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/utils/__init__.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/utils/_log.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/utils/api_helpers.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/utils/files.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/utils/tools.py +0 -0
- {seekrai-0.4.2 → seekrai-0.4.4}/src/seekrai/version.py +0 -0
|
@@ -19,8 +19,10 @@ class SeekrFlow:
|
|
|
19
19
|
models: resources.Models
|
|
20
20
|
fine_tuning: resources.FineTuning
|
|
21
21
|
alignment: resources.Alignment
|
|
22
|
+
ingestion: resources.Ingestion
|
|
22
23
|
projects: resources.Projects
|
|
23
24
|
deployments: resources.Deployments
|
|
25
|
+
agents: resources.Agents
|
|
24
26
|
|
|
25
27
|
# client options
|
|
26
28
|
client: SeekrFlowClient
|
|
@@ -81,8 +83,10 @@ class SeekrFlow:
|
|
|
81
83
|
self.models = resources.Models(self.client)
|
|
82
84
|
self.fine_tuning = resources.FineTuning(self.client)
|
|
83
85
|
self.alignment = resources.Alignment(self.client)
|
|
86
|
+
self.ingestion = resources.Ingestion(self.client)
|
|
84
87
|
self.projects = resources.Projects(self.client)
|
|
85
88
|
self.deployments = resources.Deployments(self.client)
|
|
89
|
+
self.agents = resources.Agents(self.client)
|
|
86
90
|
|
|
87
91
|
|
|
88
92
|
class AsyncSeekrFlow:
|
|
@@ -94,8 +98,10 @@ class AsyncSeekrFlow:
|
|
|
94
98
|
models: resources.AsyncModels
|
|
95
99
|
fine_tuning: resources.AsyncFineTuning
|
|
96
100
|
alignment: resources.AsyncAlignment
|
|
101
|
+
ingestion: resources.AsyncIngestion
|
|
97
102
|
projects: resources.AsyncProjects
|
|
98
103
|
deployments: resources.AsyncDeployments
|
|
104
|
+
agents: resources.Agents
|
|
99
105
|
|
|
100
106
|
# client options
|
|
101
107
|
client: SeekrFlowClient
|
|
@@ -156,8 +162,10 @@ class AsyncSeekrFlow:
|
|
|
156
162
|
self.models = resources.AsyncModels(self.client)
|
|
157
163
|
self.fine_tuning = resources.AsyncFineTuning(self.client)
|
|
158
164
|
self.alignment = resources.AsyncAlignment(self.client)
|
|
165
|
+
self.ingestion = resources.AsyncIngestion(self.client)
|
|
159
166
|
self.projects = resources.AsyncProjects(self.client)
|
|
160
167
|
self.deployments = resources.AsyncDeployments(self.client)
|
|
168
|
+
self.agents = resources.Agents(self.client)
|
|
161
169
|
|
|
162
170
|
|
|
163
171
|
Client = SeekrFlow
|
|
@@ -341,3 +341,92 @@ class UploadManager:
|
|
|
341
341
|
assert isinstance(response, SeekrFlowResponse)
|
|
342
342
|
|
|
343
343
|
return FileResponse(**response.data)
|
|
344
|
+
|
|
345
|
+
def bulk_upload(
|
|
346
|
+
self,
|
|
347
|
+
url: str,
|
|
348
|
+
files: list[Path],
|
|
349
|
+
*,
|
|
350
|
+
purpose: FilePurpose,
|
|
351
|
+
redirect: bool = False,
|
|
352
|
+
) -> list[FileResponse]:
|
|
353
|
+
"""
|
|
354
|
+
Upload multiple files in a bulk request.
|
|
355
|
+
|
|
356
|
+
Args:
|
|
357
|
+
url: API endpoint to upload to
|
|
358
|
+
files: List of file paths to upload
|
|
359
|
+
purpose: The purpose of the files
|
|
360
|
+
redirect: Whether to redirect after upload
|
|
361
|
+
|
|
362
|
+
Returns:
|
|
363
|
+
List of FileResponse objects for each uploaded file
|
|
364
|
+
"""
|
|
365
|
+
requestor = api_requestor.APIRequestor(
|
|
366
|
+
client=self._client,
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
# Prepare files for multipart form upload
|
|
370
|
+
# Format needs to be a list of tuples: [('files', (filename, file_stream)), ...]
|
|
371
|
+
files_tuples = []
|
|
372
|
+
file_streams = []
|
|
373
|
+
progress_bars = []
|
|
374
|
+
|
|
375
|
+
try:
|
|
376
|
+
for file_path in files:
|
|
377
|
+
file_size = os.stat(file_path.as_posix()).st_size
|
|
378
|
+
|
|
379
|
+
# Create progress bar
|
|
380
|
+
progress_bar = tqdm(
|
|
381
|
+
total=file_size,
|
|
382
|
+
unit="B",
|
|
383
|
+
unit_scale=True,
|
|
384
|
+
desc=f"Uploading file {file_path.name}",
|
|
385
|
+
disable=bool(DISABLE_TQDM),
|
|
386
|
+
)
|
|
387
|
+
progress_bars.append(progress_bar)
|
|
388
|
+
|
|
389
|
+
# Open file and track for cleanup
|
|
390
|
+
file_stream = file_path.open("rb")
|
|
391
|
+
file_streams.append(file_stream)
|
|
392
|
+
|
|
393
|
+
# Create wrapper for progress tracking
|
|
394
|
+
reader_wrapper = CallbackIOWrapper(
|
|
395
|
+
progress_bar.update, file_stream, "read"
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
# Add to files list as a tuple
|
|
399
|
+
files_tuples.append(("files", (file_path.name, reader_wrapper)))
|
|
400
|
+
|
|
401
|
+
# Make the request
|
|
402
|
+
response, _, _ = requestor.request(
|
|
403
|
+
options=SeekrFlowRequest(
|
|
404
|
+
method="PUT",
|
|
405
|
+
url=url,
|
|
406
|
+
files=files_tuples, # Pass as a list of tuples (field_name, (filename, file_stream))
|
|
407
|
+
params={"purpose": purpose.value},
|
|
408
|
+
allow_redirects=redirect,
|
|
409
|
+
),
|
|
410
|
+
stream=False,
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
414
|
+
|
|
415
|
+
# Parse the response
|
|
416
|
+
if isinstance(response.data, list):
|
|
417
|
+
file_responses = [
|
|
418
|
+
FileResponse(**file_data) for file_data in response.data
|
|
419
|
+
]
|
|
420
|
+
else:
|
|
421
|
+
# Handle case where response might be a single object
|
|
422
|
+
file_responses = [FileResponse(**response.data)]
|
|
423
|
+
|
|
424
|
+
return file_responses
|
|
425
|
+
|
|
426
|
+
finally:
|
|
427
|
+
# Clean up resources
|
|
428
|
+
for file_stream in file_streams:
|
|
429
|
+
file_stream.close()
|
|
430
|
+
|
|
431
|
+
for progress_bar in progress_bars:
|
|
432
|
+
progress_bar.close()
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from seekrai.resources.agents import Agents
|
|
1
2
|
from seekrai.resources.alignment import Alignment, AsyncAlignment
|
|
2
3
|
from seekrai.resources.chat import AsyncChat, Chat
|
|
3
4
|
from seekrai.resources.completions import AsyncCompletions, Completions
|
|
@@ -6,6 +7,7 @@ from seekrai.resources.embeddings import AsyncEmbeddings, Embeddings
|
|
|
6
7
|
from seekrai.resources.files import AsyncFiles, Files
|
|
7
8
|
from seekrai.resources.finetune import AsyncFineTuning, FineTuning
|
|
8
9
|
from seekrai.resources.images import AsyncImages, Images
|
|
10
|
+
from seekrai.resources.ingestion import AsyncIngestion, Ingestion
|
|
9
11
|
from seekrai.resources.models import AsyncModels, Models
|
|
10
12
|
from seekrai.resources.projects import AsyncProjects, Projects
|
|
11
13
|
|
|
@@ -25,10 +27,13 @@ __all__ = [
|
|
|
25
27
|
"Files",
|
|
26
28
|
"AsyncImages",
|
|
27
29
|
"Images",
|
|
30
|
+
"Ingestion",
|
|
31
|
+
"AsyncIngestion",
|
|
28
32
|
"AsyncModels",
|
|
29
33
|
"Models",
|
|
30
34
|
"AsyncProjects",
|
|
31
35
|
"Projects",
|
|
32
36
|
"AsyncDeployments",
|
|
33
37
|
"Deployments",
|
|
38
|
+
"Agents",
|
|
34
39
|
]
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from typing import Any, Dict, Iterator, Union
|
|
2
|
+
|
|
3
|
+
from seekrai.abstract import api_requestor
|
|
4
|
+
from seekrai.seekrflow_response import SeekrFlowResponse
|
|
5
|
+
from seekrai.types import SeekrFlowRequest
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AgentInference:
|
|
9
|
+
def __init__(self, client: Any) -> None:
|
|
10
|
+
self._client = client
|
|
11
|
+
|
|
12
|
+
def run(
|
|
13
|
+
self,
|
|
14
|
+
agent_id: Union[int, str],
|
|
15
|
+
query: str,
|
|
16
|
+
*,
|
|
17
|
+
stream: bool = False,
|
|
18
|
+
thread_id: Union[str, None] = None,
|
|
19
|
+
headers: Union[Dict[str, str], None] = None,
|
|
20
|
+
**model_settings: Any,
|
|
21
|
+
) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]:
|
|
22
|
+
"""
|
|
23
|
+
Run an inference call on a deployed agent.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
agent_id (Union[int, str]): The unique identifier of the deployed agent.
|
|
27
|
+
query (str): The user query or prompt.
|
|
28
|
+
stream (bool, optional): Whether to stream the response. Defaults to False.
|
|
29
|
+
thread_id (str, optional): An optional thread identifier.
|
|
30
|
+
headers (dict, optional): Optional HTTP headers to include in the request.
|
|
31
|
+
If provided, these will be merged with default headers.
|
|
32
|
+
**model_settings: Additional parameters (such as temperature, max_tokens, etc).
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
A dictionary with the response (if non-streaming) or an iterator over response chunks.
|
|
36
|
+
"""
|
|
37
|
+
payload: Dict[str, Any] = {"prompt": query}
|
|
38
|
+
if thread_id is not None:
|
|
39
|
+
payload["thread_id"] = thread_id
|
|
40
|
+
payload.update(model_settings)
|
|
41
|
+
|
|
42
|
+
default_headers = {}
|
|
43
|
+
if self._client.api_key:
|
|
44
|
+
default_headers["x-api-key"] = self._client.api_key
|
|
45
|
+
if self._client.supplied_headers:
|
|
46
|
+
default_headers.update(self._client.supplied_headers)
|
|
47
|
+
|
|
48
|
+
request_headers = default_headers.copy()
|
|
49
|
+
if headers:
|
|
50
|
+
request_headers.update(headers)
|
|
51
|
+
|
|
52
|
+
requestor = api_requestor.APIRequestor(client=self._client)
|
|
53
|
+
endpoint = f"agents/{agent_id}/run"
|
|
54
|
+
|
|
55
|
+
response, _, _ = requestor.request(
|
|
56
|
+
options=SeekrFlowRequest(
|
|
57
|
+
method="POST",
|
|
58
|
+
url=endpoint,
|
|
59
|
+
params=payload,
|
|
60
|
+
headers=request_headers,
|
|
61
|
+
),
|
|
62
|
+
stream=stream,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
if stream:
|
|
66
|
+
assert not isinstance(response, SeekrFlowResponse)
|
|
67
|
+
return (chunk.data for chunk in response)
|
|
68
|
+
else:
|
|
69
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
70
|
+
return response.data
|
|
@@ -71,6 +71,56 @@ class Files:
|
|
|
71
71
|
|
|
72
72
|
return file_response
|
|
73
73
|
|
|
74
|
+
def bulk_upload(
|
|
75
|
+
self,
|
|
76
|
+
files: list[Path | str],
|
|
77
|
+
*,
|
|
78
|
+
purpose: FilePurpose | str = FilePurpose.FineTune,
|
|
79
|
+
) -> list[FileResponse]:
|
|
80
|
+
"""
|
|
81
|
+
Upload multiple files in bulk.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
files: List of file paths to upload
|
|
85
|
+
purpose: The purpose of the files (defaults to FineTune)
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
List of FileResponse objects for each uploaded file
|
|
89
|
+
"""
|
|
90
|
+
if isinstance(purpose, str):
|
|
91
|
+
purpose = FilePurpose(purpose)
|
|
92
|
+
|
|
93
|
+
assert isinstance(purpose, FilePurpose)
|
|
94
|
+
|
|
95
|
+
# Convert string paths to Path objects
|
|
96
|
+
file_paths = [Path(file) if isinstance(file, str) else file for file in files]
|
|
97
|
+
|
|
98
|
+
# Validate all files before uploading (fail fast)
|
|
99
|
+
if purpose == FilePurpose.Alignment:
|
|
100
|
+
for file_path in file_paths:
|
|
101
|
+
file_metadata = self._get_local_file_metadata(file_path)
|
|
102
|
+
suffix = file_metadata["suffix"]
|
|
103
|
+
size = file_metadata["size_bytes"]
|
|
104
|
+
metadata_validation = self.validate_align_file_metadata(
|
|
105
|
+
purpose,
|
|
106
|
+
suffix,
|
|
107
|
+
size,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
if not metadata_validation.is_valid:
|
|
111
|
+
assert metadata_validation.errors is not None # To appease linter
|
|
112
|
+
raise ValueError(
|
|
113
|
+
f"Alignment file metadata validation failed for {file_path.name}: {metadata_validation.errors}"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Upload the files to s3
|
|
117
|
+
upload_manager = UploadManager(self._client)
|
|
118
|
+
file_responses = upload_manager.bulk_upload(
|
|
119
|
+
"flow/bulk_files", file_paths, purpose=purpose, redirect=True
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
return file_responses
|
|
123
|
+
|
|
74
124
|
def list(self) -> FileList:
|
|
75
125
|
requestor = api_requestor.APIRequestor(
|
|
76
126
|
client=self._client,
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from seekrai.abstract import api_requestor
|
|
4
|
+
from seekrai.seekrflow_response import SeekrFlowResponse
|
|
5
|
+
from seekrai.types import (
|
|
6
|
+
SeekrFlowClient,
|
|
7
|
+
SeekrFlowRequest,
|
|
8
|
+
)
|
|
9
|
+
from seekrai.types.ingestion import IngestionList, IngestionRequest, IngestionResponse
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Ingestion:
|
|
13
|
+
def __init__(self, client: SeekrFlowClient) -> None:
|
|
14
|
+
self._client = client
|
|
15
|
+
|
|
16
|
+
def ingest(
|
|
17
|
+
self,
|
|
18
|
+
files: List[str],
|
|
19
|
+
) -> IngestionResponse:
|
|
20
|
+
"""
|
|
21
|
+
Start an ingestion job for the specified files.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
files (List[str]): List of file IDs to ingest.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
IngestionResponse: Object containing information about the created ingestion job.
|
|
28
|
+
"""
|
|
29
|
+
requestor = api_requestor.APIRequestor(
|
|
30
|
+
client=self._client,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
parameter_payload = IngestionRequest(
|
|
34
|
+
files=files,
|
|
35
|
+
).model_dump()
|
|
36
|
+
|
|
37
|
+
response, _, _ = requestor.request(
|
|
38
|
+
options=SeekrFlowRequest(
|
|
39
|
+
method="POST",
|
|
40
|
+
url="flow/alignment/ingestion",
|
|
41
|
+
params=parameter_payload,
|
|
42
|
+
),
|
|
43
|
+
stream=False,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
47
|
+
return IngestionResponse(**response.data)
|
|
48
|
+
|
|
49
|
+
def list(self) -> IngestionList:
|
|
50
|
+
"""
|
|
51
|
+
Lists ingestion job history
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
IngestionList: Object containing a list of ingestion jobs
|
|
55
|
+
"""
|
|
56
|
+
requestor = api_requestor.APIRequestor(
|
|
57
|
+
client=self._client,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
response, _, _ = requestor.request(
|
|
61
|
+
options=SeekrFlowRequest(
|
|
62
|
+
method="GET",
|
|
63
|
+
url="flow/alignment/ingestion",
|
|
64
|
+
),
|
|
65
|
+
stream=False,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
69
|
+
return IngestionList(**response.data)
|
|
70
|
+
|
|
71
|
+
def retrieve(self, id: str) -> IngestionResponse:
|
|
72
|
+
"""
|
|
73
|
+
Retrieves ingestion job details
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
id (str): Ingestion job ID to retrieve.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
IngestionResponse: Object containing information about ingestion job.
|
|
80
|
+
"""
|
|
81
|
+
requestor = api_requestor.APIRequestor(
|
|
82
|
+
client=self._client,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
response, _, _ = requestor.request(
|
|
86
|
+
options=SeekrFlowRequest(
|
|
87
|
+
method="GET",
|
|
88
|
+
url=f"flow/alignment/ingestion/{id}",
|
|
89
|
+
),
|
|
90
|
+
stream=False,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
94
|
+
return IngestionResponse(**response.data)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class AsyncIngestion:
|
|
98
|
+
def __init__(self, client: SeekrFlowClient) -> None:
|
|
99
|
+
self._client = client
|
|
100
|
+
|
|
101
|
+
async def ingest(
|
|
102
|
+
self,
|
|
103
|
+
files: List[str],
|
|
104
|
+
) -> IngestionResponse:
|
|
105
|
+
"""
|
|
106
|
+
Start an ingestion job for the specified files asynchronously.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
files (List[str]): List of file IDs to ingest.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
IngestionResponse: Object containing information about the created ingestion job.
|
|
113
|
+
"""
|
|
114
|
+
requestor = api_requestor.APIRequestor(
|
|
115
|
+
client=self._client,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
parameter_payload = IngestionRequest(
|
|
119
|
+
files=files,
|
|
120
|
+
).model_dump()
|
|
121
|
+
|
|
122
|
+
response, _, _ = await requestor.arequest(
|
|
123
|
+
options=SeekrFlowRequest(
|
|
124
|
+
method="POST",
|
|
125
|
+
url="flow/alignment/ingestion",
|
|
126
|
+
params=parameter_payload,
|
|
127
|
+
),
|
|
128
|
+
stream=False,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
132
|
+
return IngestionResponse(**response.data)
|
|
133
|
+
|
|
134
|
+
async def list(self) -> IngestionList:
|
|
135
|
+
"""
|
|
136
|
+
Lists ingestion job history asynchronously
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
IngestionList: Object containing a list of ingestion jobs
|
|
140
|
+
"""
|
|
141
|
+
requestor = api_requestor.APIRequestor(
|
|
142
|
+
client=self._client,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
response, _, _ = await requestor.arequest(
|
|
146
|
+
options=SeekrFlowRequest(
|
|
147
|
+
method="GET",
|
|
148
|
+
url="flow/alignment/ingestion",
|
|
149
|
+
),
|
|
150
|
+
stream=False,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
154
|
+
return IngestionList(**response.data)
|
|
155
|
+
|
|
156
|
+
async def retrieve(self, id: str) -> IngestionResponse:
|
|
157
|
+
"""
|
|
158
|
+
Retrieves ingestion job details asynchronously
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
id (str): Ingestion job ID to retrieve.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
IngestionResponse: Object containing information about ingestion job.
|
|
165
|
+
"""
|
|
166
|
+
requestor = api_requestor.APIRequestor(
|
|
167
|
+
client=self._client,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
response, _, _ = await requestor.arequest(
|
|
171
|
+
options=SeekrFlowRequest(
|
|
172
|
+
method="GET",
|
|
173
|
+
url=f"flow/alignment/ingestion/{id}",
|
|
174
|
+
),
|
|
175
|
+
stream=False,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
179
|
+
return IngestionResponse(**response.data)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from enum import Enum
|
|
4
|
-
from typing import Any, Dict, List, Optional
|
|
4
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
5
5
|
|
|
6
6
|
from pydantic import ConfigDict, Field
|
|
7
7
|
|
|
@@ -72,6 +72,11 @@ class SeekrFlowRequest(BaseModel):
|
|
|
72
72
|
url: str
|
|
73
73
|
headers: Dict[str, str] | None = None
|
|
74
74
|
params: Dict[str, Any] | None = None
|
|
75
|
-
files:
|
|
75
|
+
files: (
|
|
76
|
+
Dict[str, Any]
|
|
77
|
+
| List[Tuple[str, Tuple[str, Any, Optional[str]]]]
|
|
78
|
+
| List[Tuple[str, Any]]
|
|
79
|
+
| None
|
|
80
|
+
) = None
|
|
76
81
|
allow_redirects: bool = True
|
|
77
82
|
override_headers: bool = False
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import List, Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
9
|
+
from seekrai.types.abstract import BaseModel
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class IngestionJobStatus(Enum):
|
|
13
|
+
QUEUED = "queued"
|
|
14
|
+
RUNNING = "running"
|
|
15
|
+
COMPLETED = "completed"
|
|
16
|
+
FAILED = "failed"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class IngestionRequest(BaseModel):
|
|
20
|
+
files: List[str] = Field(
|
|
21
|
+
default=..., description="List of file ids to use for alignment"
|
|
22
|
+
)
|
|
23
|
+
method: str = Field(default="best", description="Method to use for ingestion")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class IngestionResponse(BaseModel):
|
|
27
|
+
id: str = Field(default=..., description="Ingestion job ID")
|
|
28
|
+
created_at: datetime
|
|
29
|
+
status: IngestionJobStatus
|
|
30
|
+
output_files: List[str]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class IngestionList(BaseModel):
|
|
34
|
+
# object type
|
|
35
|
+
object: Literal["list"] | None = None
|
|
36
|
+
# list of fine-tune job objects
|
|
37
|
+
data: List[IngestionResponse] | None = None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|