together 0.2.5__py3-none-any.whl → 0.2.7__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.
together/finetune.py CHANGED
@@ -4,7 +4,9 @@ import urllib.parse
4
4
  from typing import Any, Dict, List, Optional, Union
5
5
 
6
6
  import requests
7
+ from requests.adapters import HTTPAdapter
7
8
  from tqdm import tqdm
9
+ from urllib3.util import Retry
8
10
 
9
11
  import together
10
12
  from together import Files
@@ -28,24 +30,17 @@ class Finetune:
28
30
  def create(
29
31
  self,
30
32
  training_file: str, # training file_id
31
- # validation_file: Optional[str] = None, # validation file_id
32
33
  model: str,
33
34
  n_epochs: int = 1,
34
35
  n_checkpoints: Optional[int] = 1,
35
36
  batch_size: Optional[int] = 32,
36
37
  learning_rate: Optional[float] = 0.00001,
37
- # warmup_steps: Optional[int] = 0,
38
- # train_warmup_steps: Optional[int] = 0,
39
- # seq_length: Optional[int] = 2048,
40
- # seed: Optional[int] = 42,
41
- # fp16: Optional[bool] = True,
42
- # checkpoint_steps: Optional[int] = None,
43
38
  suffix: Optional[
44
39
  str
45
40
  ] = None, # resulting finetuned model name will include the suffix
46
41
  estimate_price: bool = False,
47
42
  wandb_api_key: Optional[str] = None,
48
- confirm_inputs: bool = True,
43
+ confirm_inputs: bool = False,
49
44
  ) -> Dict[Any, Any]:
50
45
  adjusted_inputs = False
51
46
 
@@ -175,24 +170,21 @@ class Finetune:
175
170
  response = create_post_request(
176
171
  together.api_base_finetune, json=parameter_payload
177
172
  )
178
- if not response:
179
- return {}
173
+
180
174
  return response_to_dict(response)
181
175
 
182
176
  @classmethod
183
- def list(self) -> Dict[Any, Any]:
177
+ def list(self) -> Dict[str, List[Dict[str, Any]]]:
184
178
  # send request
185
179
  response = create_get_request(together.api_base_finetune)
186
- if not response:
187
- return {}
180
+
188
181
  return response_to_dict(response)
189
182
 
190
183
  @classmethod
191
- def retrieve(self, fine_tune_id: str) -> Dict[Any, Any]:
184
+ def retrieve(self, fine_tune_id: str) -> Dict[str, Any]:
192
185
  retrieve_url = urllib.parse.urljoin(together.api_base_finetune, fine_tune_id)
193
186
  response = create_get_request(retrieve_url)
194
- if not response:
195
- return {}
187
+
196
188
  return response_to_dict(response)
197
189
 
198
190
  @classmethod
@@ -200,8 +192,7 @@ class Finetune:
200
192
  relative_path = posixpath.join(fine_tune_id, "cancel")
201
193
  retrieve_url = urllib.parse.urljoin(together.api_base_finetune, relative_path)
202
194
  response = create_post_request(retrieve_url)
203
- if not response:
204
- return {}
195
+
205
196
  return response_to_dict(response)
206
197
 
207
198
  @classmethod
@@ -210,8 +201,7 @@ class Finetune:
210
201
  relative_path = posixpath.join(fine_tune_id, "events")
211
202
  retrieve_url = urllib.parse.urljoin(together.api_base_finetune, relative_path)
212
203
  response = create_get_request(retrieve_url)
213
- if not response:
214
- return {}
204
+
215
205
  return response_to_dict(response)
216
206
 
217
207
  @classmethod
@@ -274,16 +264,23 @@ class Finetune:
274
264
  "User-Agent": together.user_agent,
275
265
  }
276
266
 
277
- try:
278
- session = requests.Session()
267
+ session = requests.Session()
268
+
269
+ retry_strategy = Retry(
270
+ total=together.MAX_CONNECTION_RETRIES,
271
+ backoff_factor=together.BACKOFF_FACTOR,
272
+ )
273
+ retry_adapter = HTTPAdapter(max_retries=retry_strategy)
274
+ session.mount("https://", retry_adapter)
279
275
 
276
+ try:
280
277
  response = session.get(model_file_path, headers=headers, stream=True)
281
278
  response.raise_for_status()
282
279
 
283
280
  if output is None:
284
281
  content_type = str(response.headers.get("content-type"))
285
282
 
286
- output = self.retrieve(fine_tune_id)["model_output_path"].split("/")[-1]
283
+ output = self.retrieve(fine_tune_id)["model_output_name"].split("/")[-1]
287
284
 
288
285
  if step != -1:
289
286
  output += f"-checkpoint-{step}"
@@ -311,30 +308,8 @@ class Finetune:
311
308
  "Caution: Downloaded file size does not match remote file size."
312
309
  )
313
310
  except requests.exceptions.RequestException as e: # This is the correct syntax
314
- logger.critical(f"Response error raised: {e}")
315
311
  raise together.ResponseError(e)
312
+ finally:
313
+ session.close()
316
314
 
317
- return output # this should be null
318
-
319
- # def delete_finetune_model(self, model: str) -> Dict[Any, Any]:
320
- # model_url = "https://api.together.xyz/api/models"
321
- # delete_url = urllib.parse.urljoin(model_url, model)
322
-
323
- # headers = {
324
- # "Authorization": f"Bearer {together.api_key}",
325
- # }
326
-
327
- # # send request
328
- # try:
329
- # response = requests.delete(delete_url, headers=headers)
330
- # except requests.exceptions.RequestException as e:
331
- # raise ValueError(f"Error raised by finetune endpoint: {e}")
332
-
333
- # try:
334
- # response_json = dict(response.json())
335
- # except Exception as e:
336
- # raise ValueError(
337
- # f"JSON Error raised. \nResponse status code: {str(response.status_code)}"
338
- # )
339
-
340
- # return response_json
315
+ return output # this should be output file name
together/image.py CHANGED
@@ -39,6 +39,5 @@ class Image:
39
39
  response = create_post_request(
40
40
  together.api_base_complete, json=parameter_payload
41
41
  )
42
- if not response:
43
- return {}
42
+
44
43
  return response_to_dict(response)
together/models.py CHANGED
@@ -18,8 +18,7 @@ class Models:
18
18
  def list(self) -> List[Any]:
19
19
  model_url = urllib.parse.urljoin(together.api_base, "models/info?=")
20
20
  response = create_get_request(model_url)
21
- if not response:
22
- return []
21
+
23
22
  try:
24
23
  response_list = list(response.json())
25
24
  except Exception as e:
@@ -46,8 +45,7 @@ class Models:
46
45
  @classmethod
47
46
  def instances(self) -> Dict[str, bool]:
48
47
  response = create_get_request(together.api_base_instances)
49
- if not response:
50
- return {}
48
+
51
49
  return response_to_dict(response)
52
50
 
53
51
  @classmethod
@@ -56,8 +54,7 @@ class Models:
56
54
  together.api_base_instances, f"start?model={model}"
57
55
  )
58
56
  response = create_post_request(model_url)
59
- if not response:
60
- return {}
57
+
61
58
  return response_to_dict(response)
62
59
 
63
60
  @classmethod
@@ -66,16 +63,14 @@ class Models:
66
63
  together.api_base_instances, f"stop?model={model}"
67
64
  )
68
65
  response = create_post_request(model_url)
69
- if not response:
70
- return {}
66
+
71
67
  return response_to_dict(response)
72
68
 
73
69
  @classmethod
74
70
  def ready(self, model: str) -> List[Any]:
75
71
  ready_url = urllib.parse.urljoin(together.api_base, "models/info?name=" + model)
76
72
  response = create_get_request(ready_url)
77
- if not response:
78
- return []
73
+
79
74
  try:
80
75
  response_list = list(response.json())
81
76
  except Exception as e:
together/utils.py CHANGED
@@ -1,10 +1,10 @@
1
1
  import logging
2
2
  import sys
3
3
  from datetime import datetime
4
- from typing import Any, Dict, Optional, Union
4
+ from typing import Any, Dict, Optional
5
5
 
6
6
  import requests
7
- import sseclient # type: ignore
7
+ import sseclient
8
8
 
9
9
  import together
10
10
 
@@ -53,19 +53,9 @@ def get_logger(
53
53
  return logger
54
54
 
55
55
 
56
- def verify_api_key(logger: Optional[logging.Logger] = None) -> bool:
57
- if logger is None:
58
- logger = get_logger(str(__name__), log_level=together.log_level)
56
+ def verify_api_key() -> None:
59
57
  if together.api_key is None:
60
- msg = (
61
- "TOGETHER_API_KEY not found \n"
62
- "Please set it as an environment variable or set it as together.api_key \n"
63
- "Find your TOGETHER_API_KEY at https://api.together.xyz/settings/api-keys"
64
- )
65
- print(msg)
66
- return False
67
- else:
68
- return True
58
+ raise together.AuthenticationError(together.MISSING_API_KEY_MESSAGE)
69
59
 
70
60
 
71
61
  def extract_time(json_obj: Dict[str, Any]) -> int:
@@ -91,10 +81,9 @@ def create_post_request(
91
81
  json: Optional[Dict[Any, Any]] = None,
92
82
  stream: Optional[bool] = False,
93
83
  check_auth: Optional[bool] = True,
94
- ) -> Union[requests.Response, None]:
84
+ ) -> requests.Response:
95
85
  if check_auth:
96
- if not verify_api_key():
97
- return None
86
+ verify_api_key()
98
87
 
99
88
  if not headers:
100
89
  headers = {
@@ -110,16 +99,20 @@ def create_post_request(
110
99
  raise together.ResponseError(e)
111
100
 
112
101
  if response.status_code == 429:
113
- raise together.InstanceError()
102
+ raise together.RateLimitError(
103
+ message="Too many requests received. Please pace your requests."
104
+ )
114
105
  elif response.status_code == 500:
115
106
  raise Exception("Invalid API key supplied.")
107
+ elif response.status_code == 401:
108
+ raise Exception("API Key not supplied")
116
109
  response.raise_for_status()
117
110
 
118
111
  return response
119
112
 
120
113
 
121
114
  def sse_client(response: requests.Response) -> sseclient.SSEClient:
122
- return sseclient.SSEClient(response)
115
+ return sseclient.SSEClient(response) # type: ignore
123
116
 
124
117
 
125
118
  def create_get_request(
@@ -128,10 +121,9 @@ def create_get_request(
128
121
  json: Optional[Dict[Any, Any]] = None,
129
122
  stream: Optional[bool] = False,
130
123
  check_auth: Optional[bool] = True,
131
- ) -> Union[requests.Response, None]:
124
+ ) -> requests.Response:
132
125
  if check_auth:
133
- if not verify_api_key():
134
- return None
126
+ verify_api_key()
135
127
 
136
128
  if not headers:
137
129
  headers = {
@@ -147,9 +139,13 @@ def create_get_request(
147
139
  raise together.ResponseError(e)
148
140
 
149
141
  if response.status_code == 429:
150
- raise together.InstanceError()
142
+ raise together.RateLimitError(
143
+ message="Too many requests received. Please pace your requests."
144
+ )
151
145
  elif response.status_code == 500:
152
146
  raise Exception("Invalid API key supplied.")
147
+ elif response.status_code == 401:
148
+ raise Exception("API Key not supplied")
153
149
  response.raise_for_status()
154
150
 
155
151
  return response
@@ -173,3 +169,19 @@ def round_to_closest_multiple_of_32(batch_size: Optional[int]) -> int:
173
169
  elif batch_size > 256:
174
170
  return 256
175
171
  return 32 * ((batch_size + 31) // 32)
172
+
173
+
174
+ def bytes_to_human_readable(num: float, suffix: Optional[str] = "B") -> str:
175
+ for unit in ("", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"):
176
+ if abs(num) < 1024.0:
177
+ return f"{num:3.1f}{unit}{suffix}"
178
+ num /= 1024.0
179
+ return f"{num:.1f}Yi{suffix}"
180
+
181
+
182
+ def finetune_price_to_dollars(price: float) -> float:
183
+ return price / 1000000000
184
+
185
+
186
+ def nanodollars_to_dollars(price: int) -> float:
187
+ return (price * 4000) / 1000000000
together/version.py CHANGED
@@ -1 +1,6 @@
1
- VERSION = "0.2.5"
1
+ import importlib.metadata
2
+
3
+
4
+ VERSION = importlib.metadata.version(
5
+ "together"
6
+ ) # gets version number from pyproject.toml