seekrai 0.1.1__py3-none-any.whl → 0.2.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.
- seekrai/abstract/api_requestor.py +3 -0
- seekrai/client.py +4 -0
- seekrai/constants.py +1 -1
- seekrai/filemanager.py +11 -22
- seekrai/resources/__init__.py +3 -0
- seekrai/resources/alignment.py +175 -0
- seekrai/resources/files.py +64 -4
- seekrai/resources/models.py +5 -3
- seekrai/types/__init__.py +10 -0
- seekrai/types/alignment.py +39 -0
- seekrai/types/files.py +34 -5
- seekrai/types/finetune.py +7 -4
- {seekrai-0.1.1.dist-info → seekrai-0.2.1.dist-info}/METADATA +2 -3
- {seekrai-0.1.1.dist-info → seekrai-0.2.1.dist-info}/RECORD +17 -15
- {seekrai-0.1.1.dist-info → seekrai-0.2.1.dist-info}/LICENSE +0 -0
- {seekrai-0.1.1.dist-info → seekrai-0.2.1.dist-info}/WHEEL +0 -0
- {seekrai-0.1.1.dist-info → seekrai-0.2.1.dist-info}/entry_points.txt +0 -0
|
@@ -519,6 +519,9 @@ class APIRequestor:
|
|
|
519
519
|
if "text/plain" in rheaders.get("Content-Type", ""):
|
|
520
520
|
data: Dict[str, Any] = {"message": rbody}
|
|
521
521
|
else:
|
|
522
|
+
if rbody.strip().endswith("[DONE]"):
|
|
523
|
+
# TODO
|
|
524
|
+
rbody = rbody.replace("data: [DONE]", "")
|
|
522
525
|
data = json.loads(rbody)
|
|
523
526
|
except (JSONDecodeError, UnicodeDecodeError) as e:
|
|
524
527
|
raise error.APIError(
|
seekrai/client.py
CHANGED
|
@@ -18,6 +18,7 @@ class SeekrFlow:
|
|
|
18
18
|
images: resources.Images
|
|
19
19
|
models: resources.Models
|
|
20
20
|
fine_tuning: resources.FineTuning
|
|
21
|
+
alignment: resources.Alignment
|
|
21
22
|
|
|
22
23
|
# client options
|
|
23
24
|
client: SeekrFlowClient
|
|
@@ -77,6 +78,7 @@ class SeekrFlow:
|
|
|
77
78
|
self.images = resources.Images(self.client)
|
|
78
79
|
self.models = resources.Models(self.client)
|
|
79
80
|
self.fine_tuning = resources.FineTuning(self.client)
|
|
81
|
+
self.alignment = resources.Alignment(self.client)
|
|
80
82
|
|
|
81
83
|
|
|
82
84
|
class AsyncSeekrFlow:
|
|
@@ -87,6 +89,7 @@ class AsyncSeekrFlow:
|
|
|
87
89
|
images: resources.AsyncImages
|
|
88
90
|
models: resources.AsyncModels
|
|
89
91
|
fine_tuning: resources.AsyncFineTuning
|
|
92
|
+
alignment: resources.AsyncAlignment
|
|
90
93
|
|
|
91
94
|
# client options
|
|
92
95
|
client: SeekrFlowClient
|
|
@@ -146,6 +149,7 @@ class AsyncSeekrFlow:
|
|
|
146
149
|
self.images = resources.AsyncImages(self.client)
|
|
147
150
|
self.models = resources.AsyncModels(self.client)
|
|
148
151
|
self.fine_tuning = resources.AsyncFineTuning(self.client)
|
|
152
|
+
self.alignment = resources.AsyncAlignment(self.client)
|
|
149
153
|
|
|
150
154
|
|
|
151
155
|
Client = SeekrFlow
|
seekrai/constants.py
CHANGED
|
@@ -19,7 +19,7 @@ INITIAL_RETRY_DELAY = float(env_or_default("INITIAL_RETRY_DELAY", 0.5))
|
|
|
19
19
|
MAX_RETRY_DELAY = float(env_or_default("MAX_RETRY_DELAY", 8.0))
|
|
20
20
|
|
|
21
21
|
# API defaults
|
|
22
|
-
BASE_URL = env_or_default("BASE_URL", "https://
|
|
22
|
+
BASE_URL = env_or_default("BASE_URL", "https://flow.seekr.com/v1")
|
|
23
23
|
|
|
24
24
|
# Download defaults
|
|
25
25
|
DOWNLOAD_BLOCK_SIZE = int(
|
seekrai/filemanager.py
CHANGED
|
@@ -12,6 +12,7 @@ import httpx
|
|
|
12
12
|
import requests
|
|
13
13
|
from requests.structures import CaseInsensitiveDict
|
|
14
14
|
from tqdm import tqdm
|
|
15
|
+
from tqdm.utils import CallbackIOWrapper
|
|
15
16
|
|
|
16
17
|
import seekrai.utils
|
|
17
18
|
from seekrai.abstract import api_requestor
|
|
@@ -42,15 +43,15 @@ def chmod_and_replace(src: Path, dst: Path) -> None:
|
|
|
42
43
|
# Get umask by creating a temporary file in the cache folder.
|
|
43
44
|
tmp_file = dst.parent / f"tmp_{uuid.uuid4()}"
|
|
44
45
|
|
|
45
|
-
try:
|
|
46
|
-
|
|
46
|
+
# try:
|
|
47
|
+
tmp_file.touch()
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
cache_dir_mode = Path(tmp_file).stat().st_mode
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
os.chmod(src.as_posix(), stat.S_IMODE(cache_dir_mode))
|
|
51
52
|
|
|
52
|
-
finally:
|
|
53
|
-
|
|
53
|
+
# finally:
|
|
54
|
+
# tmp_file.unlink()
|
|
54
55
|
|
|
55
56
|
shutil.move(src.as_posix(), dst.as_posix())
|
|
56
57
|
|
|
@@ -186,10 +187,7 @@ class DownloadManager:
|
|
|
186
187
|
url, output, remote_name, fetch_metadata
|
|
187
188
|
)
|
|
188
189
|
|
|
189
|
-
|
|
190
|
-
lock_path = Path(file_path.as_posix() + ".lock")
|
|
191
|
-
|
|
192
|
-
with tempfile.NamedTemporaryFile() as temp_file:
|
|
190
|
+
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
|
|
193
191
|
response = requestor.request_raw(
|
|
194
192
|
options=SeekrFlowRequest(
|
|
195
193
|
method="GET",
|
|
@@ -201,7 +199,6 @@ class DownloadManager:
|
|
|
201
199
|
try:
|
|
202
200
|
response.raise_for_status()
|
|
203
201
|
except Exception as e:
|
|
204
|
-
os.remove(lock_path)
|
|
205
202
|
raise APIError(
|
|
206
203
|
"Error downloading file", http_status=response.status_code
|
|
207
204
|
) from e
|
|
@@ -234,8 +231,6 @@ class DownloadManager:
|
|
|
234
231
|
# Moves temp file to output file path
|
|
235
232
|
chmod_and_replace(Path(temp_file.name), file_path)
|
|
236
233
|
|
|
237
|
-
os.remove(lock_path)
|
|
238
|
-
|
|
239
234
|
return str(file_path.resolve()), file_size
|
|
240
235
|
|
|
241
236
|
|
|
@@ -323,13 +318,6 @@ class UploadManager:
|
|
|
323
318
|
client=self._client,
|
|
324
319
|
)
|
|
325
320
|
|
|
326
|
-
if redirect:
|
|
327
|
-
if file.suffix not in [".jsonl", ".parquet", ".pt"]:
|
|
328
|
-
raise FileTypeError(
|
|
329
|
-
f"Unknown extension of file {file}. "
|
|
330
|
-
"Only files with extensions .jsonl, .parquet, and .pt are supported."
|
|
331
|
-
)
|
|
332
|
-
|
|
333
321
|
file_size = os.stat(file.as_posix()).st_size
|
|
334
322
|
|
|
335
323
|
with tqdm(
|
|
@@ -338,13 +326,14 @@ class UploadManager:
|
|
|
338
326
|
unit_scale=True,
|
|
339
327
|
desc=f"Uploading file {file.name}",
|
|
340
328
|
disable=bool(DISABLE_TQDM),
|
|
341
|
-
):
|
|
329
|
+
) as t:
|
|
342
330
|
with file.open("rb") as f:
|
|
331
|
+
reader_wrapper = CallbackIOWrapper(t.update, f, "read")
|
|
343
332
|
response, _, _ = requestor.request(
|
|
344
333
|
options=SeekrFlowRequest(
|
|
345
334
|
method="PUT",
|
|
346
335
|
url=url,
|
|
347
|
-
files={"files":
|
|
336
|
+
files={"files": reader_wrapper, "filename": file.name},
|
|
348
337
|
params={"purpose": purpose.value},
|
|
349
338
|
),
|
|
350
339
|
)
|
seekrai/resources/__init__.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from seekrai.resources.alignment import Alignment, AsyncAlignment
|
|
1
2
|
from seekrai.resources.chat import AsyncChat, Chat
|
|
2
3
|
from seekrai.resources.completions import AsyncCompletions, Completions
|
|
3
4
|
from seekrai.resources.embeddings import AsyncEmbeddings, Embeddings
|
|
@@ -8,6 +9,8 @@ from seekrai.resources.models import AsyncModels, Models
|
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
__all__ = [
|
|
12
|
+
"AsyncAlignment",
|
|
13
|
+
"Alignment",
|
|
11
14
|
"AsyncCompletions",
|
|
12
15
|
"Completions",
|
|
13
16
|
"AsyncChat",
|
|
@@ -0,0 +1,175 @@
|
|
|
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
|
+
AlignmentList,
|
|
7
|
+
AlignmentRequest,
|
|
8
|
+
AlignmentResponse,
|
|
9
|
+
SeekrFlowClient,
|
|
10
|
+
SeekrFlowRequest,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Alignment:
|
|
15
|
+
def __init__(self, client: SeekrFlowClient) -> None:
|
|
16
|
+
self._client = client
|
|
17
|
+
|
|
18
|
+
def generate(
|
|
19
|
+
self,
|
|
20
|
+
instructions: str,
|
|
21
|
+
files: List[str],
|
|
22
|
+
) -> AlignmentResponse:
|
|
23
|
+
requestor = api_requestor.APIRequestor(
|
|
24
|
+
client=self._client,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
parameter_payload = AlignmentRequest(
|
|
28
|
+
instructions=instructions,
|
|
29
|
+
files=files,
|
|
30
|
+
).model_dump()
|
|
31
|
+
|
|
32
|
+
response, _, _ = requestor.request(
|
|
33
|
+
options=SeekrFlowRequest(
|
|
34
|
+
method="POST",
|
|
35
|
+
url="flow/alignment/generate",
|
|
36
|
+
params=parameter_payload,
|
|
37
|
+
),
|
|
38
|
+
stream=False,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
42
|
+
return AlignmentResponse(**response.data)
|
|
43
|
+
|
|
44
|
+
def list(self) -> AlignmentList:
|
|
45
|
+
"""
|
|
46
|
+
Lists alignment job history
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
AlignmentList: Object containing a list of alignment jobs
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
requestor = api_requestor.APIRequestor(
|
|
53
|
+
client=self._client,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
response, _, _ = requestor.request(
|
|
57
|
+
options=SeekrFlowRequest(
|
|
58
|
+
method="GET",
|
|
59
|
+
url="flow/alignment",
|
|
60
|
+
),
|
|
61
|
+
stream=False,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
65
|
+
|
|
66
|
+
return AlignmentList(**response.data)
|
|
67
|
+
|
|
68
|
+
def retrieve(self, id: str) -> AlignmentResponse:
|
|
69
|
+
"""
|
|
70
|
+
Retrieves alignment job details
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
id (str): Alignment job ID to retrieve.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
AlignmentResponse: Object containing information about alignment job.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
requestor = api_requestor.APIRequestor(
|
|
80
|
+
client=self._client,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
response, _, _ = requestor.request(
|
|
84
|
+
options=SeekrFlowRequest(
|
|
85
|
+
method="GET",
|
|
86
|
+
url=f"flow/alignment/{id}",
|
|
87
|
+
),
|
|
88
|
+
stream=False,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
92
|
+
|
|
93
|
+
return AlignmentResponse(**response.data)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class AsyncAlignment:
|
|
97
|
+
def __init__(self, client: SeekrFlowClient) -> None:
|
|
98
|
+
self._client = client
|
|
99
|
+
|
|
100
|
+
async def generate(
|
|
101
|
+
self,
|
|
102
|
+
instructions: str,
|
|
103
|
+
files: List[str],
|
|
104
|
+
) -> AlignmentResponse:
|
|
105
|
+
requestor = api_requestor.APIRequestor(
|
|
106
|
+
client=self._client,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
parameter_payload = AlignmentRequest(
|
|
110
|
+
instructions=instructions,
|
|
111
|
+
files=files,
|
|
112
|
+
).model_dump()
|
|
113
|
+
|
|
114
|
+
response, _, _ = await requestor.arequest(
|
|
115
|
+
options=SeekrFlowRequest(
|
|
116
|
+
method="POST",
|
|
117
|
+
url="flow/alignment/generate",
|
|
118
|
+
params=parameter_payload,
|
|
119
|
+
),
|
|
120
|
+
stream=False,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
124
|
+
return AlignmentResponse(**response.data)
|
|
125
|
+
|
|
126
|
+
async def list(self) -> AlignmentList:
|
|
127
|
+
"""
|
|
128
|
+
Lists alignment job history
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
AlignmentList: Object containing a list of alignment jobs
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
requestor = api_requestor.APIRequestor(
|
|
135
|
+
client=self._client,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
response, _, _ = await requestor.arequest(
|
|
139
|
+
options=SeekrFlowRequest(
|
|
140
|
+
method="GET",
|
|
141
|
+
url="flow/alignment",
|
|
142
|
+
),
|
|
143
|
+
stream=False,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
147
|
+
|
|
148
|
+
return AlignmentList(**response.data)
|
|
149
|
+
|
|
150
|
+
async def retrieve(self, id: str) -> AlignmentResponse:
|
|
151
|
+
"""
|
|
152
|
+
Retrieves alignment job details
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
id (str): Alignment job ID to retrieve.
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
AlignmentResponse: Object containing information about alignment job.
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
requestor = api_requestor.APIRequestor(
|
|
162
|
+
client=self._client,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
response, _, _ = await requestor.arequest(
|
|
166
|
+
options=SeekrFlowRequest(
|
|
167
|
+
method="GET",
|
|
168
|
+
url=f"flow/alignment/{id}",
|
|
169
|
+
),
|
|
170
|
+
stream=False,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
assert isinstance(response, SeekrFlowResponse)
|
|
174
|
+
|
|
175
|
+
return AlignmentResponse(**response.data)
|
seekrai/resources/files.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
+
from typing import Any, Dict
|
|
4
5
|
|
|
5
6
|
from seekrai.abstract import api_requestor
|
|
6
7
|
from seekrai.filemanager import DownloadManager, UploadManager
|
|
@@ -14,6 +15,10 @@ from seekrai.types import (
|
|
|
14
15
|
SeekrFlowClient,
|
|
15
16
|
SeekrFlowRequest,
|
|
16
17
|
)
|
|
18
|
+
from seekrai.types.files import (
|
|
19
|
+
AlignFileMetadataValidationReq,
|
|
20
|
+
AlignFileMetadataValidationResp,
|
|
21
|
+
)
|
|
17
22
|
from seekrai.utils import normalize_key
|
|
18
23
|
|
|
19
24
|
|
|
@@ -21,11 +26,18 @@ class Files:
|
|
|
21
26
|
def __init__(self, client: SeekrFlowClient) -> None:
|
|
22
27
|
self._client = client
|
|
23
28
|
|
|
29
|
+
def _get_local_file_metadata(self, file_path: Path) -> Dict[str, Any]:
|
|
30
|
+
suffix = file_path.suffix.lstrip(".")
|
|
31
|
+
size_bytes = int(file_path.stat().st_size)
|
|
32
|
+
return {
|
|
33
|
+
"suffix": suffix,
|
|
34
|
+
"size_bytes": size_bytes,
|
|
35
|
+
"filename": file_path.name,
|
|
36
|
+
}
|
|
37
|
+
|
|
24
38
|
def upload(
|
|
25
39
|
self, file: Path | str, *, purpose: FilePurpose | str = FilePurpose.FineTune
|
|
26
40
|
) -> FileResponse:
|
|
27
|
-
upload_manager = UploadManager(self._client)
|
|
28
|
-
|
|
29
41
|
if isinstance(file, str):
|
|
30
42
|
file = Path(file)
|
|
31
43
|
|
|
@@ -34,7 +46,30 @@ class Files:
|
|
|
34
46
|
|
|
35
47
|
assert isinstance(purpose, FilePurpose)
|
|
36
48
|
|
|
37
|
-
|
|
49
|
+
# Do the metadata validation (fail fast before uploading) for Alignment purpose
|
|
50
|
+
if purpose == FilePurpose.Alignment:
|
|
51
|
+
file_metadata = self._get_local_file_metadata(file)
|
|
52
|
+
suffix = file_metadata["suffix"]
|
|
53
|
+
size = file_metadata["size_bytes"]
|
|
54
|
+
metadata_validation = self.validate_align_file_metadata(
|
|
55
|
+
purpose,
|
|
56
|
+
suffix,
|
|
57
|
+
size,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
if not metadata_validation.is_valid:
|
|
61
|
+
assert metadata_validation.errors is not None # To appease linter
|
|
62
|
+
raise ValueError(
|
|
63
|
+
f"Alignment file metadata validation failed: {metadata_validation.errors}"
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Upload the file to s3
|
|
67
|
+
upload_manager = UploadManager(self._client)
|
|
68
|
+
file_response = upload_manager.upload(
|
|
69
|
+
"flow/files", file, purpose=purpose, redirect=True
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
return file_response
|
|
38
73
|
|
|
39
74
|
def list(self) -> FileList:
|
|
40
75
|
requestor = api_requestor.APIRequestor(
|
|
@@ -87,7 +122,7 @@ class Files:
|
|
|
87
122
|
output = Path(output)
|
|
88
123
|
|
|
89
124
|
downloaded_filename, file_size = download_manager.download(
|
|
90
|
-
f"flow/files/{id}/content", output, normalize_key(
|
|
125
|
+
f"flow/files/{id}/content", output, normalize_key(id)
|
|
91
126
|
)
|
|
92
127
|
|
|
93
128
|
return FileObject(
|
|
@@ -114,6 +149,31 @@ class Files:
|
|
|
114
149
|
|
|
115
150
|
return FileDeleteResponse(**response.data)
|
|
116
151
|
|
|
152
|
+
def validate_align_file_metadata(
|
|
153
|
+
self,
|
|
154
|
+
purpose: FilePurpose,
|
|
155
|
+
suffix: str,
|
|
156
|
+
size: int,
|
|
157
|
+
) -> AlignFileMetadataValidationResp:
|
|
158
|
+
requestor = api_requestor.APIRequestor(client=self._client)
|
|
159
|
+
|
|
160
|
+
request_body = AlignFileMetadataValidationReq(
|
|
161
|
+
purpose=purpose,
|
|
162
|
+
suffix=suffix,
|
|
163
|
+
size=size,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
response, _, _ = requestor.request(
|
|
167
|
+
options=SeekrFlowRequest(
|
|
168
|
+
method="POST",
|
|
169
|
+
url="flow/files/validate_metadata",
|
|
170
|
+
params=request_body.dict(),
|
|
171
|
+
),
|
|
172
|
+
stream=False,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
return AlignFileMetadataValidationResp(**response.data)
|
|
176
|
+
|
|
117
177
|
|
|
118
178
|
class AsyncFiles:
|
|
119
179
|
def __init__(self, client: SeekrFlowClient) -> None:
|
seekrai/resources/models.py
CHANGED
|
@@ -5,6 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
from typing import Any, List
|
|
6
6
|
|
|
7
7
|
from tqdm import tqdm
|
|
8
|
+
from tqdm.utils import CallbackIOWrapper
|
|
8
9
|
|
|
9
10
|
from seekrai.abstract import api_requestor
|
|
10
11
|
from seekrai.constants import DISABLE_TQDM
|
|
@@ -35,15 +36,16 @@ class Models:
|
|
|
35
36
|
total=file_size,
|
|
36
37
|
unit="B",
|
|
37
38
|
unit_scale=True,
|
|
38
|
-
desc=f"Uploading file {file.name}",
|
|
39
|
+
desc=f"Uploading model file {file.name}",
|
|
39
40
|
disable=bool(DISABLE_TQDM),
|
|
40
|
-
):
|
|
41
|
+
) as t:
|
|
41
42
|
with file.open("rb") as f:
|
|
43
|
+
reader_wrapper = CallbackIOWrapper(t.update, f, "read")
|
|
42
44
|
response, _, _ = requestor.request(
|
|
43
45
|
options=SeekrFlowRequest(
|
|
44
46
|
method="PUT",
|
|
45
47
|
url="flow/pt-models",
|
|
46
|
-
files={"files":
|
|
48
|
+
files={"files": reader_wrapper, "filename": file.name},
|
|
47
49
|
params={"purpose": model_type},
|
|
48
50
|
),
|
|
49
51
|
)
|
seekrai/types/__init__.py
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
from seekrai.types.abstract import SeekrFlowClient
|
|
2
|
+
from seekrai.types.alignment import (
|
|
3
|
+
AlignmentJobStatus,
|
|
4
|
+
AlignmentList,
|
|
5
|
+
AlignmentRequest,
|
|
6
|
+
AlignmentResponse,
|
|
7
|
+
)
|
|
2
8
|
from seekrai.types.chat_completions import (
|
|
3
9
|
ChatCompletionChunk,
|
|
4
10
|
ChatCompletionRequest,
|
|
@@ -65,4 +71,8 @@ __all__ = [
|
|
|
65
71
|
"ImageResponse",
|
|
66
72
|
"ModelResponse",
|
|
67
73
|
"ModelList",
|
|
74
|
+
"AlignmentRequest",
|
|
75
|
+
"AlignmentResponse",
|
|
76
|
+
"AlignmentJobStatus",
|
|
77
|
+
"AlignmentList",
|
|
68
78
|
]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import List, Literal, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import Field
|
|
6
|
+
|
|
7
|
+
from seekrai.types.abstract import BaseModel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AlignmentRequest(BaseModel):
|
|
11
|
+
instructions: str = Field(
|
|
12
|
+
default=..., description="Task description/instructions for the alignment task"
|
|
13
|
+
)
|
|
14
|
+
files: List[str] = Field(
|
|
15
|
+
default=..., description="List of file ids to use for alignment"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AlignmentJobStatus(str, Enum):
|
|
20
|
+
STATUS_PENDING = "pending"
|
|
21
|
+
STATUS_QUEUED = "queued"
|
|
22
|
+
STATUS_RUNNING = "running"
|
|
23
|
+
STATUS_CANCEL_REQUESTED = "cancel_requested"
|
|
24
|
+
STATUS_CANCELLED = "cancelled"
|
|
25
|
+
STATUS_FAILED = "failed"
|
|
26
|
+
STATUS_COMPLETED = "completed"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AlignmentResponse(BaseModel):
|
|
30
|
+
id: Optional[str] = Field(default=..., description="Alignment job ID")
|
|
31
|
+
created_at: datetime | None = None
|
|
32
|
+
status: AlignmentJobStatus | None = None
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class AlignmentList(BaseModel):
|
|
36
|
+
# object type
|
|
37
|
+
object: Literal["list"] | None = None
|
|
38
|
+
# list of fine-tune job objects
|
|
39
|
+
data: List[AlignmentResponse] | None = None
|
seekrai/types/files.py
CHANGED
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
from enum import Enum
|
|
5
|
-
from typing import List, Literal
|
|
5
|
+
from typing import List, Literal, Optional, Union
|
|
6
6
|
|
|
7
7
|
from seekrai.types.abstract import BaseModel
|
|
8
8
|
from seekrai.types.common import (
|
|
@@ -13,12 +13,42 @@ from seekrai.types.common import (
|
|
|
13
13
|
class FilePurpose(str, Enum):
|
|
14
14
|
FineTune = "fine-tune"
|
|
15
15
|
PreTrain = "pre-train"
|
|
16
|
+
Alignment = "alignment"
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
class
|
|
19
|
+
class TrainingFileType(str, Enum):
|
|
19
20
|
jsonl = "jsonl"
|
|
20
21
|
parquet = "parquet"
|
|
21
|
-
pytorch = "pt"
|
|
22
|
+
pytorch = "pt" # TODO - this doesnt belong here
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class AlignmentFileType(str, Enum):
|
|
26
|
+
HTML = "html"
|
|
27
|
+
MD = "md"
|
|
28
|
+
RST = "rst"
|
|
29
|
+
RTF = "rtf"
|
|
30
|
+
TXT = "txt"
|
|
31
|
+
XML = "xml"
|
|
32
|
+
JSON = "json"
|
|
33
|
+
JSONL = "jsonl"
|
|
34
|
+
CSV = "csv"
|
|
35
|
+
DOC = "doc"
|
|
36
|
+
DOCX = "docx"
|
|
37
|
+
PDF = "pdf"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
FileType = Union[TrainingFileType, AlignmentFileType]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class AlignFileMetadataValidationReq(BaseModel):
|
|
44
|
+
purpose: str
|
|
45
|
+
suffix: str
|
|
46
|
+
size: int
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class AlignFileMetadataValidationResp(BaseModel):
|
|
50
|
+
is_valid: bool
|
|
51
|
+
errors: Optional[str] = None
|
|
22
52
|
|
|
23
53
|
|
|
24
54
|
class FileRequest(BaseModel):
|
|
@@ -61,8 +91,7 @@ class FileResponse(BaseModel):
|
|
|
61
91
|
filename: str | None = None
|
|
62
92
|
# file byte size
|
|
63
93
|
bytes: int | None = None
|
|
64
|
-
#
|
|
65
|
-
line_count: int | None = None
|
|
94
|
+
created_by: str | None = None # TODO - fix this later
|
|
66
95
|
|
|
67
96
|
|
|
68
97
|
class FileList(BaseModel):
|
seekrai/types/finetune.py
CHANGED
|
@@ -118,7 +118,6 @@ class InfrastructureConfig(BaseModel):
|
|
|
118
118
|
accel_type: AcceleratorType
|
|
119
119
|
n_accel: int
|
|
120
120
|
|
|
121
|
-
|
|
122
121
|
class FinetuneRequest(BaseModel):
|
|
123
122
|
"""
|
|
124
123
|
Fine-tune request type
|
|
@@ -141,14 +140,16 @@ class FinetuneResponse(BaseModel):
|
|
|
141
140
|
# validation_files: str | None = None TODO
|
|
142
141
|
# base model name
|
|
143
142
|
model: str | None = None
|
|
143
|
+
accel_type: AcceleratorType
|
|
144
|
+
n_accel: int
|
|
144
145
|
# number of epochs
|
|
145
|
-
|
|
146
|
+
n_epochs: int | None = None
|
|
146
147
|
# number of checkpoints to save
|
|
147
148
|
# n_checkpoints: int | None = None # TODO
|
|
148
149
|
# training batch size
|
|
149
|
-
|
|
150
|
+
batch_size: int | None = None
|
|
150
151
|
# training learning rate
|
|
151
|
-
|
|
152
|
+
learning_rate: float | None = None
|
|
152
153
|
# number of steps between evals
|
|
153
154
|
# eval_steps: int | None = None TODO
|
|
154
155
|
# is LoRA finetune boolean
|
|
@@ -159,6 +160,8 @@ class FinetuneResponse(BaseModel):
|
|
|
159
160
|
# created/updated datetime stamps
|
|
160
161
|
created_at: datetime | None = None
|
|
161
162
|
# updated_at: str | None = None
|
|
163
|
+
# up to 40 character suffix for output model name
|
|
164
|
+
experiment_name: str | None = None
|
|
162
165
|
# job status
|
|
163
166
|
status: FinetuneJobStatus | None = None
|
|
164
167
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: seekrai
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Python client for SeekrAI
|
|
5
5
|
Home-page: https://gitlab.cb.ntent.com/ml/seekr-py
|
|
6
6
|
License: Apache-2.0
|
|
@@ -17,7 +17,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
17
17
|
Requires-Dist: click (>=8.1.7,<9.0.0)
|
|
18
18
|
Requires-Dist: eval-type-backport (>=0.1.3,<0.3.0)
|
|
19
19
|
Requires-Dist: filelock (>=3.13.1,<4.0.0)
|
|
20
|
-
Requires-Dist: httpx (>=0.27.0,<0.28.0)
|
|
20
|
+
Requires-Dist: httpx[http2] (>=0.27.0,<0.28.0)
|
|
21
21
|
Requires-Dist: numpy (>=1.23.5) ; python_version < "3.12"
|
|
22
22
|
Requires-Dist: numpy (>=1.26.0) ; python_version >= "3.12"
|
|
23
23
|
Requires-Dist: pillow (>=10.3.0,<11.0.0)
|
|
@@ -136,7 +136,6 @@ client = SeekrFlow(api_key=os.environ.get("SEEKR_API_KEY"))
|
|
|
136
136
|
|
|
137
137
|
client.files.upload(file="somedata.parquet") # uploads a file
|
|
138
138
|
client.files.list() # lists all uploaded files
|
|
139
|
-
client.files.retrieve(id="file-d0d318cb-b7d9-493a-bd70-1cfe089d3815") # retrieves a specific file
|
|
140
139
|
client.files.delete(id="file-d0d318cb-b7d9-493a-bd70-1cfe089d3815") # deletes a file
|
|
141
140
|
```
|
|
142
141
|
|
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
seekrai/__init__.py,sha256=HC6iy-IdwqecabH-6a80Lsy9qO2PBToAI0WqEErV41c,935
|
|
2
2
|
seekrai/abstract/__init__.py,sha256=wNiOTW9TJpUgfCJCG-wAbhhWWH2PtoVpAuL3nxvQGps,56
|
|
3
|
-
seekrai/abstract/api_requestor.py,sha256
|
|
4
|
-
seekrai/client.py,sha256=
|
|
5
|
-
seekrai/constants.py,sha256=
|
|
3
|
+
seekrai/abstract/api_requestor.py,sha256=Bij__JWVSmr4AYnrh6ugFYo-48_uYGQodcTDp38pnf4,18169
|
|
4
|
+
seekrai/client.py,sha256=Z7T7cc0_Ess8pchceNdhYyT5RvP9luAuGmTPDz5Y0ss,4976
|
|
5
|
+
seekrai/constants.py,sha256=hoR2iF5te5Ydjt_lxIOSGID4vESIakG4F-3xAWdwxaU,1854
|
|
6
6
|
seekrai/error.py,sha256=rAYL8qEd8INwYMMKvhS-HKeC3QkWL4Wq-zfazFU-zBg,4861
|
|
7
|
-
seekrai/filemanager.py,sha256=
|
|
8
|
-
seekrai/resources/__init__.py,sha256=
|
|
7
|
+
seekrai/filemanager.py,sha256=8RuSzJvELD-fCI2Wd_t0jSKeVrmFwF7E5AzXIgDFxNA,9572
|
|
8
|
+
seekrai/resources/__init__.py,sha256=QpK4dsJoXdMvlA_53fOS2S19Ua0OyLGFBZw_fQrOOvk,799
|
|
9
|
+
seekrai/resources/alignment.py,sha256=6qQm9w0Em0q3zVeOzs8cX3wulr-B-wh4Pcr3pboIeTE,4468
|
|
9
10
|
seekrai/resources/chat/__init__.py,sha256=KmtPupgECtEN80NyvcnSmieTAFXhwmVxhMHP0qhspA4,618
|
|
10
11
|
seekrai/resources/chat/completions.py,sha256=v0Nwr7lJk6d5fZ-s6ut2BLDr9Vay8qGL9ZQLRgyOve0,11047
|
|
11
12
|
seekrai/resources/completions.py,sha256=w3La3zPMlN00y-b-tJwLgvZVH-xK_dKC6ktI5Ggn1us,8564
|
|
12
13
|
seekrai/resources/embeddings.py,sha256=3lohUrkdFqzSg8FgS7p4r87jwjE0NXU1PilWv278quk,2705
|
|
13
|
-
seekrai/resources/files.py,sha256=
|
|
14
|
+
seekrai/resources/files.py,sha256=16FfJFZJjZ10Q38AHvTwE-CtIPpKA0d4zyB52YN14e4,6876
|
|
14
15
|
seekrai/resources/finetune.py,sha256=fXLkVCTnfoeq4TvjhEWQsdIwO247tcpfWCVTlWZczDw,11271
|
|
15
16
|
seekrai/resources/images.py,sha256=E48lAe7YsZ2WXBHR_qz4SF7P4Y-U7t61m_bWNS91pM0,4802
|
|
16
|
-
seekrai/resources/models.py,sha256=
|
|
17
|
+
seekrai/resources/models.py,sha256=Pdd0S0gZdratWcHJPKNb7LkEdUGjr3xNR06W6GDiyxk,5000
|
|
17
18
|
seekrai/seekrflow_response.py,sha256=5RFEQzamDy7sTSDkxSsZQThZ3biNmeCPeHWdrFId5Go,1320
|
|
18
|
-
seekrai/types/__init__.py,sha256=
|
|
19
|
+
seekrai/types/__init__.py,sha256=YUXzhcpwGGDeiV9LxKzwaYne7zI5vl99OMLmCtdSXwY,1779
|
|
19
20
|
seekrai/types/abstract.py,sha256=TqWFQV_6bPblywfCH-r8FCkXWvPkc9KlJ4QVgyrnaMc,642
|
|
21
|
+
seekrai/types/alignment.py,sha256=FCPrACbjDPZ02Q1-1hURehcz2Nu5kPiEFlS_CSbrWUw,1093
|
|
20
22
|
seekrai/types/chat_completions.py,sha256=GgqEcfdjkWecPVZEHRENctQ1SQ6KB4CculxyKhkvnHo,3571
|
|
21
23
|
seekrai/types/common.py,sha256=79fvG60otq-H4QL0OULgmxUAAOKKas4YSYycLDLl7To,1430
|
|
22
24
|
seekrai/types/completions.py,sha256=lm9AFdZR3Xg5AHPkV-qETHikkwMJmkHrLGr5GG-YR-M,2171
|
|
23
25
|
seekrai/types/embeddings.py,sha256=OANoLNOs0aceS8NppVvvcNYQbF7-pAOAmcr30pw64OU,749
|
|
24
26
|
seekrai/types/error.py,sha256=uTKISs9aRC4_6zwirtNkanxepN8KY-SqCq0kNbfZylQ,370
|
|
25
|
-
seekrai/types/files.py,sha256=
|
|
26
|
-
seekrai/types/finetune.py,sha256=
|
|
27
|
+
seekrai/types/files.py,sha256=XmtiM6d9i3tnYS-Kii3QpxZJRqemJi2rvLJ32GsECXQ,2602
|
|
28
|
+
seekrai/types/finetune.py,sha256=z34AtfEgK1keB8dDg21aKonR_Ke6HLYuEFxeiIW1eIg,5960
|
|
27
29
|
seekrai/types/images.py,sha256=Fusj8OhVYFsT8kz636lRGGivLbPXo_ZNgakKwmzJi3U,914
|
|
28
30
|
seekrai/types/models.py,sha256=1ZfW9WwayApkISRizDntjkWhYNv-wkbrRVIfHn2QuC4,1242
|
|
29
31
|
seekrai/utils/__init__.py,sha256=dfbiYEc47EBVRkq6C4O9y6tTGuPuV3LbV3__v01Mbds,658
|
|
@@ -32,8 +34,8 @@ seekrai/utils/api_helpers.py,sha256=0Y8BblNIr9h_R12zdmhkxgTlxgoRkbq84QNi4nNWGu8,
|
|
|
32
34
|
seekrai/utils/files.py,sha256=B61Pwra49MVVWjPtdkx4hBtAuUe9UI63hdNus87Uq0o,7164
|
|
33
35
|
seekrai/utils/tools.py,sha256=jgJTL-dOIouDbEJLdQpQfpXhqaz_poQYS52adyUtBjo,1781
|
|
34
36
|
seekrai/version.py,sha256=q6iGQVFor8zXiPP5F-3vy9TndOxKv5JXbaNJ2kdOQws,125
|
|
35
|
-
seekrai-0.
|
|
36
|
-
seekrai-0.
|
|
37
|
-
seekrai-0.
|
|
38
|
-
seekrai-0.
|
|
39
|
-
seekrai-0.
|
|
37
|
+
seekrai-0.2.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
38
|
+
seekrai-0.2.1.dist-info/METADATA,sha256=xL584gOHacN99txMUOzkGZIAwewv_nGhD6ixs5A6f4M,4748
|
|
39
|
+
seekrai-0.2.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
40
|
+
seekrai-0.2.1.dist-info/entry_points.txt,sha256=N49yOEGi1sK7Xr13F_rkkcOxQ88suyiMoOmRhUHTZ_U,48
|
|
41
|
+
seekrai-0.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|