together 1.5.6__tar.gz → 1.5.8__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.
Files changed (66) hide show
  1. {together-1.5.6 → together-1.5.8}/PKG-INFO +1 -1
  2. {together-1.5.6 → together-1.5.8}/pyproject.toml +1 -1
  3. {together-1.5.6 → together-1.5.8}/src/together/cli/api/finetune.py +11 -3
  4. {together-1.5.6 → together-1.5.8}/src/together/resources/finetune.py +74 -77
  5. {together-1.5.6 → together-1.5.8}/src/together/types/chat_completions.py +1 -0
  6. {together-1.5.6 → together-1.5.8}/src/together/types/finetune.py +9 -1
  7. {together-1.5.6 → together-1.5.8}/LICENSE +0 -0
  8. {together-1.5.6 → together-1.5.8}/README.md +0 -0
  9. {together-1.5.6 → together-1.5.8}/src/together/__init__.py +0 -0
  10. {together-1.5.6 → together-1.5.8}/src/together/abstract/__init__.py +0 -0
  11. {together-1.5.6 → together-1.5.8}/src/together/abstract/api_requestor.py +0 -0
  12. {together-1.5.6 → together-1.5.8}/src/together/cli/__init__.py +0 -0
  13. {together-1.5.6 → together-1.5.8}/src/together/cli/api/__init__.py +0 -0
  14. {together-1.5.6 → together-1.5.8}/src/together/cli/api/chat.py +0 -0
  15. {together-1.5.6 → together-1.5.8}/src/together/cli/api/completions.py +0 -0
  16. {together-1.5.6 → together-1.5.8}/src/together/cli/api/endpoints.py +0 -0
  17. {together-1.5.6 → together-1.5.8}/src/together/cli/api/files.py +0 -0
  18. {together-1.5.6 → together-1.5.8}/src/together/cli/api/images.py +0 -0
  19. {together-1.5.6 → together-1.5.8}/src/together/cli/api/models.py +0 -0
  20. {together-1.5.6 → together-1.5.8}/src/together/cli/api/utils.py +0 -0
  21. {together-1.5.6 → together-1.5.8}/src/together/cli/cli.py +0 -0
  22. {together-1.5.6 → together-1.5.8}/src/together/client.py +0 -0
  23. {together-1.5.6 → together-1.5.8}/src/together/constants.py +0 -0
  24. {together-1.5.6 → together-1.5.8}/src/together/error.py +0 -0
  25. {together-1.5.6 → together-1.5.8}/src/together/filemanager.py +0 -0
  26. {together-1.5.6 → together-1.5.8}/src/together/legacy/__init__.py +0 -0
  27. {together-1.5.6 → together-1.5.8}/src/together/legacy/base.py +0 -0
  28. {together-1.5.6 → together-1.5.8}/src/together/legacy/complete.py +0 -0
  29. {together-1.5.6 → together-1.5.8}/src/together/legacy/embeddings.py +0 -0
  30. {together-1.5.6 → together-1.5.8}/src/together/legacy/files.py +0 -0
  31. {together-1.5.6 → together-1.5.8}/src/together/legacy/finetune.py +0 -0
  32. {together-1.5.6 → together-1.5.8}/src/together/legacy/images.py +0 -0
  33. {together-1.5.6 → together-1.5.8}/src/together/legacy/models.py +0 -0
  34. {together-1.5.6 → together-1.5.8}/src/together/resources/__init__.py +0 -0
  35. {together-1.5.6 → together-1.5.8}/src/together/resources/audio/__init__.py +0 -0
  36. {together-1.5.6 → together-1.5.8}/src/together/resources/audio/speech.py +0 -0
  37. {together-1.5.6 → together-1.5.8}/src/together/resources/chat/__init__.py +0 -0
  38. {together-1.5.6 → together-1.5.8}/src/together/resources/chat/completions.py +0 -0
  39. {together-1.5.6 → together-1.5.8}/src/together/resources/code_interpreter.py +0 -0
  40. {together-1.5.6 → together-1.5.8}/src/together/resources/completions.py +0 -0
  41. {together-1.5.6 → together-1.5.8}/src/together/resources/embeddings.py +0 -0
  42. {together-1.5.6 → together-1.5.8}/src/together/resources/endpoints.py +0 -0
  43. {together-1.5.6 → together-1.5.8}/src/together/resources/files.py +0 -0
  44. {together-1.5.6 → together-1.5.8}/src/together/resources/images.py +0 -0
  45. {together-1.5.6 → together-1.5.8}/src/together/resources/models.py +0 -0
  46. {together-1.5.6 → together-1.5.8}/src/together/resources/rerank.py +0 -0
  47. {together-1.5.6 → together-1.5.8}/src/together/together_response.py +0 -0
  48. {together-1.5.6 → together-1.5.8}/src/together/types/__init__.py +0 -0
  49. {together-1.5.6 → together-1.5.8}/src/together/types/abstract.py +0 -0
  50. {together-1.5.6 → together-1.5.8}/src/together/types/audio_speech.py +0 -0
  51. {together-1.5.6 → together-1.5.8}/src/together/types/code_interpreter.py +0 -0
  52. {together-1.5.6 → together-1.5.8}/src/together/types/common.py +0 -0
  53. {together-1.5.6 → together-1.5.8}/src/together/types/completions.py +0 -0
  54. {together-1.5.6 → together-1.5.8}/src/together/types/embeddings.py +0 -0
  55. {together-1.5.6 → together-1.5.8}/src/together/types/endpoints.py +0 -0
  56. {together-1.5.6 → together-1.5.8}/src/together/types/error.py +0 -0
  57. {together-1.5.6 → together-1.5.8}/src/together/types/files.py +0 -0
  58. {together-1.5.6 → together-1.5.8}/src/together/types/images.py +0 -0
  59. {together-1.5.6 → together-1.5.8}/src/together/types/models.py +0 -0
  60. {together-1.5.6 → together-1.5.8}/src/together/types/rerank.py +0 -0
  61. {together-1.5.6 → together-1.5.8}/src/together/utils/__init__.py +0 -0
  62. {together-1.5.6 → together-1.5.8}/src/together/utils/_log.py +0 -0
  63. {together-1.5.6 → together-1.5.8}/src/together/utils/api_helpers.py +0 -0
  64. {together-1.5.6 → together-1.5.8}/src/together/utils/files.py +0 -0
  65. {together-1.5.6 → together-1.5.8}/src/together/utils/tools.py +0 -0
  66. {together-1.5.6 → together-1.5.8}/src/together/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: together
3
- Version: 1.5.6
3
+ Version: 1.5.8
4
4
  Summary: Python client for Together's Cloud Platform!
5
5
  License: Apache-2.0
6
6
  Author: Together AI
@@ -12,7 +12,7 @@ build-backend = "poetry.masonry.api"
12
12
 
13
13
  [tool.poetry]
14
14
  name = "together"
15
- version = "1.5.6"
15
+ version = "1.5.8"
16
16
  authors = ["Together AI <support@together.ai>"]
17
17
  description = "Python client for Together's Cloud Platform!"
18
18
  readme = "README.md"
@@ -258,10 +258,13 @@ def create(
258
258
  raise click.BadParameter(
259
259
  f"LoRA fine-tuning is not supported for the model `{model}`"
260
260
  )
261
-
261
+ if training_method == "dpo":
262
+ default_batch_size = model_limits.lora_training.max_batch_size_dpo
263
+ else:
264
+ default_batch_size = model_limits.lora_training.max_batch_size
262
265
  default_values = {
263
266
  "lora_r": model_limits.lora_training.max_rank,
264
- "batch_size": model_limits.lora_training.max_batch_size,
267
+ "batch_size": default_batch_size,
265
268
  "learning_rate": 1e-3,
266
269
  }
267
270
 
@@ -288,7 +291,12 @@ def create(
288
291
 
289
292
  batch_size_source = ctx.get_parameter_source("batch_size") # type: ignore[attr-defined]
290
293
  if batch_size_source == ParameterSource.DEFAULT:
291
- training_args["batch_size"] = model_limits.full_training.max_batch_size
294
+ if training_method == "dpo":
295
+ training_args["batch_size"] = (
296
+ model_limits.full_training.max_batch_size_dpo
297
+ )
298
+ else:
299
+ training_args["batch_size"] = model_limits.full_training.max_batch_size
292
300
 
293
301
  if n_evals <= 0 and validation_file:
294
302
  log_warn(
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import re
4
4
  from pathlib import Path
5
- from typing import List, Literal
5
+ from typing import Dict, List, Literal
6
6
 
7
7
  from rich import print as rprint
8
8
 
@@ -30,16 +30,8 @@ from together.types import (
30
30
  TrainingMethodSFT,
31
31
  TrainingType,
32
32
  )
33
- from together.types.finetune import (
34
- DownloadCheckpointType,
35
- FinetuneEvent,
36
- FinetuneEventType,
37
- )
38
- from together.utils import (
39
- get_event_step,
40
- log_warn_once,
41
- normalize_key,
42
- )
33
+ from together.types.finetune import DownloadCheckpointType
34
+ from together.utils import log_warn_once, normalize_key
43
35
 
44
36
 
45
37
  _FT_JOB_WITH_STEP_REGEX = r"^ft-[\dabcdef-]+:\d+$"
@@ -102,6 +94,7 @@ def create_finetune_request(
102
94
 
103
95
  training_type: TrainingType = FullTrainingType()
104
96
  max_batch_size: int = 0
97
+ max_batch_size_dpo: int = 0
105
98
  min_batch_size: int = 0
106
99
  if lora:
107
100
  if model_limits.lora_training is None:
@@ -119,7 +112,7 @@ def create_finetune_request(
119
112
 
120
113
  max_batch_size = model_limits.lora_training.max_batch_size
121
114
  min_batch_size = model_limits.lora_training.min_batch_size
122
-
115
+ max_batch_size_dpo = model_limits.lora_training.max_batch_size_dpo
123
116
  else:
124
117
  if model_limits.full_training is None:
125
118
  raise ValueError(
@@ -128,13 +121,24 @@ def create_finetune_request(
128
121
 
129
122
  max_batch_size = model_limits.full_training.max_batch_size
130
123
  min_batch_size = model_limits.full_training.min_batch_size
124
+ max_batch_size_dpo = model_limits.full_training.max_batch_size_dpo
131
125
 
132
- batch_size = batch_size if batch_size != "max" else max_batch_size
126
+ if batch_size == "max":
127
+ if training_method == "dpo":
128
+ batch_size = max_batch_size_dpo
129
+ else:
130
+ batch_size = max_batch_size
133
131
 
134
- if batch_size > max_batch_size:
135
- raise ValueError(
136
- f"Requested batch size of {batch_size} is higher that the maximum allowed value of {max_batch_size}."
137
- )
132
+ if training_method == "sft":
133
+ if batch_size > max_batch_size:
134
+ raise ValueError(
135
+ f"Requested batch size of {batch_size} is higher that the maximum allowed value of {max_batch_size}."
136
+ )
137
+ elif training_method == "dpo":
138
+ if batch_size > max_batch_size_dpo:
139
+ raise ValueError(
140
+ f"Requested batch size of {batch_size} is higher that the maximum allowed value of {max_batch_size_dpo}."
141
+ )
138
142
 
139
143
  if batch_size < min_batch_size:
140
144
  raise ValueError(
@@ -210,68 +214,38 @@ def create_finetune_request(
210
214
  return finetune_request
211
215
 
212
216
 
213
- def _process_checkpoints_from_events(
214
- events: List[FinetuneEvent], id: str
217
+ def _parse_raw_checkpoints(
218
+ checkpoints: List[Dict[str, str]], id: str
215
219
  ) -> List[FinetuneCheckpoint]:
216
220
  """
217
- Helper function to process events and create checkpoint list.
221
+ Helper function to process raw checkpoints and create checkpoint list.
218
222
 
219
223
  Args:
220
- events (List[FinetuneEvent]): List of fine-tune events to process
224
+ checkpoints (List[Dict[str, str]]): List of raw checkpoints metadata
221
225
  id (str): Fine-tune job ID
222
226
 
223
227
  Returns:
224
228
  List[FinetuneCheckpoint]: List of available checkpoints
225
229
  """
226
- checkpoints: List[FinetuneCheckpoint] = []
227
-
228
- for event in events:
229
- event_type = event.type
230
-
231
- if event_type == FinetuneEventType.CHECKPOINT_SAVE:
232
- step = get_event_step(event)
233
- checkpoint_name = f"{id}:{step}" if step is not None else id
234
-
235
- checkpoints.append(
236
- FinetuneCheckpoint(
237
- type=(
238
- f"Intermediate (step {step})"
239
- if step is not None
240
- else "Intermediate"
241
- ),
242
- timestamp=event.created_at,
243
- name=checkpoint_name,
244
- )
245
- )
246
- elif event_type == FinetuneEventType.JOB_COMPLETE:
247
- if hasattr(event, "model_path"):
248
- checkpoints.append(
249
- FinetuneCheckpoint(
250
- type=(
251
- "Final Merged"
252
- if hasattr(event, "adapter_path")
253
- else "Final"
254
- ),
255
- timestamp=event.created_at,
256
- name=id,
257
- )
258
- )
259
230
 
260
- if hasattr(event, "adapter_path"):
261
- checkpoints.append(
262
- FinetuneCheckpoint(
263
- type=(
264
- "Final Adapter" if hasattr(event, "model_path") else "Final"
265
- ),
266
- timestamp=event.created_at,
267
- name=id,
268
- )
269
- )
231
+ parsed_checkpoints = []
232
+ for checkpoint in checkpoints:
233
+ step = checkpoint["step"]
234
+ checkpoint_type = checkpoint["checkpoint_type"]
235
+ checkpoint_name = (
236
+ f"{id}:{step}" if "intermediate" in checkpoint_type.lower() else id
237
+ )
270
238
 
271
- # Sort by timestamp (newest first)
272
- checkpoints.sort(key=lambda x: x.timestamp, reverse=True)
239
+ parsed_checkpoints.append(
240
+ FinetuneCheckpoint(
241
+ type=checkpoint_type,
242
+ timestamp=checkpoint["created_at"],
243
+ name=checkpoint_name,
244
+ )
245
+ )
273
246
 
274
- return checkpoints
247
+ parsed_checkpoints.sort(key=lambda x: x.timestamp, reverse=True)
248
+ return parsed_checkpoints
275
249
 
276
250
 
277
251
  class FineTuning:
@@ -549,8 +523,21 @@ class FineTuning:
549
523
  Returns:
550
524
  List[FinetuneCheckpoint]: List of available checkpoints
551
525
  """
552
- events = self.list_events(id).data or []
553
- return _process_checkpoints_from_events(events, id)
526
+ requestor = api_requestor.APIRequestor(
527
+ client=self._client,
528
+ )
529
+
530
+ response, _, _ = requestor.request(
531
+ options=TogetherRequest(
532
+ method="GET",
533
+ url=f"fine-tunes/{id}/checkpoints",
534
+ ),
535
+ stream=False,
536
+ )
537
+ assert isinstance(response, TogetherResponse)
538
+
539
+ raw_checkpoints = response.data["data"]
540
+ return _parse_raw_checkpoints(raw_checkpoints, id)
554
541
 
555
542
  def download(
556
543
  self,
@@ -924,11 +911,9 @@ class AsyncFineTuning:
924
911
  ),
925
912
  stream=False,
926
913
  )
914
+ assert isinstance(events_response, TogetherResponse)
927
915
 
928
- # FIXME: API returns "data" field with no object type (should be "list")
929
- events_list = FinetuneListEvents(object="list", **events_response.data)
930
-
931
- return events_list
916
+ return FinetuneListEvents(**events_response.data)
932
917
 
933
918
  async def list_checkpoints(self, id: str) -> List[FinetuneCheckpoint]:
934
919
  """
@@ -938,11 +923,23 @@ class AsyncFineTuning:
938
923
  id (str): Unique identifier of the fine-tune job to list checkpoints for
939
924
 
940
925
  Returns:
941
- List[FinetuneCheckpoint]: Object containing list of available checkpoints
926
+ List[FinetuneCheckpoint]: List of available checkpoints
942
927
  """
943
- events_list = await self.list_events(id)
944
- events = events_list.data or []
945
- return _process_checkpoints_from_events(events, id)
928
+ requestor = api_requestor.APIRequestor(
929
+ client=self._client,
930
+ )
931
+
932
+ response, _, _ = await requestor.arequest(
933
+ options=TogetherRequest(
934
+ method="GET",
935
+ url=f"fine-tunes/{id}/checkpoints",
936
+ ),
937
+ stream=False,
938
+ )
939
+ assert isinstance(response, TogetherResponse)
940
+
941
+ raw_checkpoints = response.data["data"]
942
+ return _parse_raw_checkpoints(raw_checkpoints, id)
946
943
 
947
944
  async def download(
948
945
  self, id: str, *, output: str | None = None, checkpoint_step: int = -1
@@ -98,6 +98,7 @@ class ToolChoice(BaseModel):
98
98
 
99
99
  class ToolChoiceEnum(str, Enum):
100
100
  Auto = "auto"
101
+ Required = "required"
101
102
 
102
103
 
103
104
  class ChatCompletionRequest(BaseModel):
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from enum import Enum
4
- from typing import List, Literal
4
+ from typing import List, Literal, Any
5
5
 
6
6
  from pydantic import StrictBool, Field, field_validator
7
7
 
@@ -329,8 +329,16 @@ class FinetuneDownloadResult(BaseModel):
329
329
 
330
330
  class FinetuneFullTrainingLimits(BaseModel):
331
331
  max_batch_size: int
332
+ max_batch_size_dpo: int = -1
332
333
  min_batch_size: int
333
334
 
335
+ def __init__(self, **data: Any) -> None:
336
+ super().__init__(**data)
337
+ if self.max_batch_size_dpo == -1:
338
+ half_max = self.max_batch_size // 2
339
+ rounded_half_max = (half_max // 8) * 8
340
+ self.max_batch_size_dpo = max(self.min_batch_size, rounded_half_max)
341
+
334
342
 
335
343
  class FinetuneLoraTrainingLimits(FinetuneFullTrainingLimits):
336
344
  max_rank: int
File without changes
File without changes
File without changes