together 0.2.9__tar.gz → 0.2.11__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.
- {together-0.2.9 → together-0.2.11}/PKG-INFO +2 -1
- {together-0.2.9 → together-0.2.11}/pyproject.toml +2 -1
- {together-0.2.9 → together-0.2.11}/src/together/__init__.py +2 -1
- {together-0.2.9 → together-0.2.11}/src/together/complete.py +83 -4
- {together-0.2.9 → together-0.2.11}/src/together/files.py +36 -8
- {together-0.2.9 → together-0.2.11}/src/together/utils.py +25 -28
- {together-0.2.9 → together-0.2.11}/LICENSE +0 -0
- {together-0.2.9 → together-0.2.11}/README.md +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/cli/__init__.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/cli/cli.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/commands/__init__.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/commands/chat.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/commands/complete.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/commands/embeddings.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/commands/files.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/commands/finetune.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/commands/image.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/commands/models.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/embeddings.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/error.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/finetune.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/image.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/models.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/tools/__init__.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/tools/conversation.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/types.py +0 -0
- {together-0.2.9 → together-0.2.11}/src/together/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: together
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.11
|
|
4
4
|
Summary: Python client for Together's Cloud Platform!
|
|
5
5
|
Home-page: https://github.com/togethercomputer/together
|
|
6
6
|
License: Apache-2.0
|
|
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Requires-Dist: aiohttp (>=3.7.4,<4.0.0)
|
|
19
20
|
Requires-Dist: pydantic (>=2.5.0,<3.0.0)
|
|
20
21
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
21
22
|
Requires-Dist: sseclient-py (>=1.7.2,<2.0.0)
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "together"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.11"
|
|
8
8
|
authors = [
|
|
9
9
|
"Together AI <support@together.ai>"
|
|
10
10
|
]
|
|
@@ -27,6 +27,7 @@ tqdm = "^4.66.1"
|
|
|
27
27
|
sseclient-py = "^1.7.2"
|
|
28
28
|
tabulate = "^0.9.0"
|
|
29
29
|
pydantic = "^2.5.0"
|
|
30
|
+
aiohttp = "^3.7.4"
|
|
30
31
|
|
|
31
32
|
[tool.poetry.group.quality]
|
|
32
33
|
optional = true
|
|
@@ -33,7 +33,7 @@ BACKOFF_FACTOR = 0.2
|
|
|
33
33
|
|
|
34
34
|
min_samples = 100
|
|
35
35
|
|
|
36
|
-
from .complete import Complete, Completion
|
|
36
|
+
from .complete import AsyncComplete, Complete, Completion
|
|
37
37
|
from .embeddings import Embeddings
|
|
38
38
|
from .error import *
|
|
39
39
|
from .files import Files
|
|
@@ -77,6 +77,7 @@ __all__ = [
|
|
|
77
77
|
"Models",
|
|
78
78
|
"Complete",
|
|
79
79
|
"Completion",
|
|
80
|
+
"AsyncComplete",
|
|
80
81
|
"Files",
|
|
81
82
|
"Finetune",
|
|
82
83
|
"Image",
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from typing import Any, Dict, Iterator, List, Optional, Union
|
|
3
3
|
|
|
4
|
+
from aiohttp import ClientSession, ClientTimeout
|
|
5
|
+
|
|
4
6
|
import together
|
|
5
7
|
from together.types import TogetherResponse
|
|
6
|
-
from together.utils import create_post_request, get_logger, sse_client
|
|
8
|
+
from together.utils import create_post_request, get_headers, get_logger, sse_client
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
logger = get_logger(str(__name__))
|
|
@@ -12,7 +14,7 @@ logger = get_logger(str(__name__))
|
|
|
12
14
|
class Complete:
|
|
13
15
|
@classmethod
|
|
14
16
|
def create(
|
|
15
|
-
|
|
17
|
+
cls,
|
|
16
18
|
prompt: str,
|
|
17
19
|
model: Optional[str] = "",
|
|
18
20
|
max_tokens: Optional[int] = 128,
|
|
@@ -60,7 +62,7 @@ class Complete:
|
|
|
60
62
|
|
|
61
63
|
@classmethod
|
|
62
64
|
def create_streaming(
|
|
63
|
-
|
|
65
|
+
cls,
|
|
64
66
|
prompt: str,
|
|
65
67
|
model: Optional[str] = "",
|
|
66
68
|
max_tokens: Optional[int] = 128,
|
|
@@ -130,7 +132,7 @@ class Complete:
|
|
|
130
132
|
class Completion:
|
|
131
133
|
@classmethod
|
|
132
134
|
def create(
|
|
133
|
-
|
|
135
|
+
cls,
|
|
134
136
|
prompt: str,
|
|
135
137
|
model: Optional[str] = "",
|
|
136
138
|
max_tokens: Optional[int] = 128,
|
|
@@ -172,3 +174,80 @@ class Completion:
|
|
|
172
174
|
api_key=api_key,
|
|
173
175
|
cast=True,
|
|
174
176
|
)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class AsyncComplete:
|
|
180
|
+
@classmethod
|
|
181
|
+
async def create(
|
|
182
|
+
cls,
|
|
183
|
+
prompt: str,
|
|
184
|
+
model: Optional[str],
|
|
185
|
+
max_tokens: int = 20,
|
|
186
|
+
repetition_penalty: Optional[float] = None,
|
|
187
|
+
stop: Optional[List[str]] = None,
|
|
188
|
+
temperature: Optional[float] = None,
|
|
189
|
+
top_k: Optional[int] = None,
|
|
190
|
+
top_p: Optional[float] = None,
|
|
191
|
+
raw: Optional[bool] = False,
|
|
192
|
+
logprobs: Optional[int] = None,
|
|
193
|
+
safety_model: Optional[str] = None,
|
|
194
|
+
stream: Optional[bool] = False,
|
|
195
|
+
timeout: Optional[int] = 10,
|
|
196
|
+
) -> Any:
|
|
197
|
+
if model == "":
|
|
198
|
+
model = together.default_text_model
|
|
199
|
+
|
|
200
|
+
headers = get_headers()
|
|
201
|
+
|
|
202
|
+
# Provide a default value for timeout if it is None
|
|
203
|
+
timeout = timeout or 10
|
|
204
|
+
client_timeout = ClientTimeout(timeout * 60)
|
|
205
|
+
|
|
206
|
+
parameter_payload = {
|
|
207
|
+
"model": model,
|
|
208
|
+
"prompt": prompt,
|
|
209
|
+
"top_p": top_p,
|
|
210
|
+
"top_k": top_k,
|
|
211
|
+
"temperature": temperature,
|
|
212
|
+
"max_tokens": max_tokens,
|
|
213
|
+
"stop": stop,
|
|
214
|
+
"repetition_penalty": repetition_penalty,
|
|
215
|
+
"logprobs": logprobs,
|
|
216
|
+
"safety_model": safety_model,
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async with ClientSession(headers=headers, timeout=client_timeout) as session:
|
|
220
|
+
async with session.post(
|
|
221
|
+
together.api_base_complete, json=parameter_payload
|
|
222
|
+
) as resp:
|
|
223
|
+
|
|
224
|
+
async def streamer() -> Any:
|
|
225
|
+
# Parse ServerSentEvents
|
|
226
|
+
async for byte_payload in resp.content:
|
|
227
|
+
# Skip line
|
|
228
|
+
if byte_payload == b"\n":
|
|
229
|
+
continue
|
|
230
|
+
|
|
231
|
+
payload = byte_payload.decode("utf-8")
|
|
232
|
+
|
|
233
|
+
# Event data
|
|
234
|
+
if payload.startswith("data:"):
|
|
235
|
+
# Decode payload
|
|
236
|
+
json_payload = json.loads(
|
|
237
|
+
payload.lstrip("data:").rstrip("/n")
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
if raw:
|
|
241
|
+
yield json_payload
|
|
242
|
+
else:
|
|
243
|
+
# Parse payload
|
|
244
|
+
response = TogetherResponse(**json_payload)
|
|
245
|
+
|
|
246
|
+
yield response
|
|
247
|
+
|
|
248
|
+
if stream:
|
|
249
|
+
return await streamer()
|
|
250
|
+
else:
|
|
251
|
+
payload = await resp.json()
|
|
252
|
+
response = TogetherResponse(**payload)
|
|
253
|
+
return response
|
|
@@ -60,6 +60,9 @@ class Files:
|
|
|
60
60
|
f"Invalid file supplied. Failed to upload.\nReport:\n {report_dict}"
|
|
61
61
|
)
|
|
62
62
|
else:
|
|
63
|
+
logger.warning(
|
|
64
|
+
"Caution: File check is disabled. Together.ai will not be able to detect errors in your file."
|
|
65
|
+
)
|
|
63
66
|
report_dict = {}
|
|
64
67
|
|
|
65
68
|
session = requests.Session()
|
|
@@ -256,6 +259,7 @@ def check_json(
|
|
|
256
259
|
if not os.path.isfile(file):
|
|
257
260
|
report_dict["file_present"] = f"File not found at given file path {file}"
|
|
258
261
|
report_dict["is_check_passed"] = False
|
|
262
|
+
return report_dict
|
|
259
263
|
else:
|
|
260
264
|
report_dict["file_present"] = "File found"
|
|
261
265
|
|
|
@@ -266,10 +270,28 @@ def check_json(
|
|
|
266
270
|
"file_size"
|
|
267
271
|
] = f"File size {round(file_size / NUM_BYTES_IN_GB ,3)} GB is greater than our limit of 4.9 GB"
|
|
268
272
|
report_dict["is_check_passed"] = False
|
|
273
|
+
elif file_size == 0:
|
|
274
|
+
report_dict["file_size"] = "File is empty"
|
|
275
|
+
report_dict["is_check_passed"] = False
|
|
276
|
+
return report_dict
|
|
269
277
|
else:
|
|
270
278
|
report_dict["file_size"] = f"File size {round(file_size / (2**30) ,3)} GB"
|
|
271
279
|
|
|
280
|
+
# Check that the file is UTF-8 encoded. If not report where the error occurs.
|
|
281
|
+
try:
|
|
282
|
+
with open(file, "r", encoding="utf-8") as f:
|
|
283
|
+
f.read()
|
|
284
|
+
except UnicodeDecodeError as e:
|
|
285
|
+
report_dict["utf8"] = (
|
|
286
|
+
f"File is not UTF-8 encoded. Error raised: {e}."
|
|
287
|
+
f"See https://docs.together.ai/docs/fine-tuning for more information."
|
|
288
|
+
)
|
|
289
|
+
report_dict["is_check_passed"] = False
|
|
290
|
+
return report_dict
|
|
291
|
+
|
|
272
292
|
with open(file) as f:
|
|
293
|
+
# idx must be instantiated so decode errors (e.g. file is a tar) or empty files are caught
|
|
294
|
+
idx = -1
|
|
273
295
|
try:
|
|
274
296
|
for idx, line in enumerate(f):
|
|
275
297
|
json_line = json.loads(line) # each line in jsonlines should be a json
|
|
@@ -316,14 +338,20 @@ def check_json(
|
|
|
316
338
|
report_dict["num_samples"] = idx + 1
|
|
317
339
|
|
|
318
340
|
except ValueError:
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
341
|
+
if idx < 0:
|
|
342
|
+
report_dict["load_json"] = (
|
|
343
|
+
"Unable to decode file. "
|
|
344
|
+
"File may be empty or in an unsupported format."
|
|
345
|
+
)
|
|
346
|
+
else:
|
|
347
|
+
report_dict["load_json"] = (
|
|
348
|
+
f"File should be a valid jsonlines (.jsonl) with a json in each line."
|
|
349
|
+
'Example of valid json: {"text":"my sample string"}'
|
|
350
|
+
"Valid json not found in one or more lines in file."
|
|
351
|
+
"see https://docs.together.ai/docs/fine-tuning."
|
|
352
|
+
f"The first line where this occur is line {idx+1}, where 1 is the first line."
|
|
353
|
+
f"{str(line)}"
|
|
354
|
+
)
|
|
327
355
|
report_dict["is_check_passed"] = False
|
|
328
356
|
|
|
329
357
|
return report_dict
|
|
@@ -75,6 +75,27 @@ def parse_timestamp(timestamp: str) -> datetime:
|
|
|
75
75
|
raise ValueError("Timestamp does not match any expected format")
|
|
76
76
|
|
|
77
77
|
|
|
78
|
+
def response_status_exception(response: requests.Response) -> None:
|
|
79
|
+
if response.status_code == 429:
|
|
80
|
+
raise together.RateLimitError(
|
|
81
|
+
message="Too many requests received. Please pace your requests."
|
|
82
|
+
)
|
|
83
|
+
elif response.status_code == 500:
|
|
84
|
+
raise Exception("server encountered an unexpected condition")
|
|
85
|
+
elif response.status_code == 401:
|
|
86
|
+
raise Exception("invalid authentication credentials")
|
|
87
|
+
response.raise_for_status()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def get_headers() -> Dict[str, str]:
|
|
91
|
+
headers = {
|
|
92
|
+
"Authorization": f"Bearer {together.api_key}",
|
|
93
|
+
"Content-Type": "application/json",
|
|
94
|
+
"User-Agent": together.user_agent,
|
|
95
|
+
}
|
|
96
|
+
return headers
|
|
97
|
+
|
|
98
|
+
|
|
78
99
|
def create_post_request(
|
|
79
100
|
url: str,
|
|
80
101
|
headers: Optional[Dict[Any, Any]] = None,
|
|
@@ -87,11 +108,7 @@ def create_post_request(
|
|
|
87
108
|
verify_api_key()
|
|
88
109
|
|
|
89
110
|
if not headers:
|
|
90
|
-
headers =
|
|
91
|
-
"Authorization": f"Bearer {api_key or together.api_key}",
|
|
92
|
-
"Content-Type": "application/json",
|
|
93
|
-
"User-Agent": together.user_agent,
|
|
94
|
-
}
|
|
111
|
+
headers = get_headers()
|
|
95
112
|
|
|
96
113
|
# send request
|
|
97
114
|
try:
|
|
@@ -99,15 +116,7 @@ def create_post_request(
|
|
|
99
116
|
except requests.exceptions.RequestException as e:
|
|
100
117
|
raise together.ResponseError(e)
|
|
101
118
|
|
|
102
|
-
|
|
103
|
-
raise together.RateLimitError(
|
|
104
|
-
message="Too many requests received. Please pace your requests."
|
|
105
|
-
)
|
|
106
|
-
elif response.status_code == 500:
|
|
107
|
-
raise Exception("Invalid API key supplied.")
|
|
108
|
-
elif response.status_code == 401:
|
|
109
|
-
raise Exception("API Key not supplied")
|
|
110
|
-
response.raise_for_status()
|
|
119
|
+
response_status_exception(response)
|
|
111
120
|
|
|
112
121
|
return response
|
|
113
122
|
|
|
@@ -127,11 +136,7 @@ def create_get_request(
|
|
|
127
136
|
verify_api_key()
|
|
128
137
|
|
|
129
138
|
if not headers:
|
|
130
|
-
headers =
|
|
131
|
-
"Authorization": f"Bearer {together.api_key}",
|
|
132
|
-
"Content-Type": "application/json",
|
|
133
|
-
"User-Agent": together.user_agent,
|
|
134
|
-
}
|
|
139
|
+
headers = get_headers()
|
|
135
140
|
|
|
136
141
|
# send request
|
|
137
142
|
try:
|
|
@@ -139,15 +144,7 @@ def create_get_request(
|
|
|
139
144
|
except requests.exceptions.RequestException as e:
|
|
140
145
|
raise together.ResponseError(e)
|
|
141
146
|
|
|
142
|
-
|
|
143
|
-
raise together.RateLimitError(
|
|
144
|
-
message="Too many requests received. Please pace your requests."
|
|
145
|
-
)
|
|
146
|
-
elif response.status_code == 500:
|
|
147
|
-
raise Exception("Invalid API key supplied.")
|
|
148
|
-
elif response.status_code == 401:
|
|
149
|
-
raise Exception("API Key not supplied")
|
|
150
|
-
response.raise_for_status()
|
|
147
|
+
response_status_exception(response)
|
|
151
148
|
|
|
152
149
|
return response
|
|
153
150
|
|
|
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
|