Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ build-backend = "poetry.masonry.api"

[tool.poetry]
name = "together"
version = "1.5.4"
version = "1.5.5"
authors = ["Together AI <[email protected]>"]
description = "Python client for Together's Cloud Platform!"
readme = "README.md"
Expand Down
28 changes: 13 additions & 15 deletions src/together/resources/finetune.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
TogetherRequest,
TrainingType,
FinetuneLRScheduler,
FinetuneLinearLRScheduler,
FinetuneCosineLRScheduler,
FinetuneLinearLRSchedulerArgs,
FinetuneCosineLRSchedulerArgs,
LinearLRScheduler,
CosineLRScheduler,
LinearLRSchedulerArgs,
CosineLRSchedulerArgs,
TrainingMethodDPO,
TrainingMethodSFT,
FinetuneCheckpoint,
Expand All @@ -50,7 +50,7 @@
}


def createFinetuneRequest(
def create_finetune_request(
model_limits: FinetuneTrainingLimits,
training_file: str,
model: str | None = None,
Expand Down Expand Up @@ -152,21 +152,19 @@ def createFinetuneRequest(
f"training_method must be one of {', '.join(AVAILABLE_TRAINING_METHODS)}"
)

# Default to generic lr scheduler
lrScheduler: FinetuneLRScheduler = FinetuneLRScheduler(lr_scheduler_type="linear")

lr_scheduler: FinetuneLRScheduler
if lr_scheduler_type == "cosine":
if scheduler_num_cycles <= 0.0:
raise ValueError("Number of cycles should be greater than 0")

lrScheduler = FinetuneCosineLRScheduler(
lr_scheduler_args=FinetuneCosineLRSchedulerArgs(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you can see here, we passed lr_scheduler_args despite this field not being defined for FinetuneCosineLRScheduler

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops ty for the catch. I'm actually not sure it didn't have a validation error before...

lr_scheduler = CosineLRScheduler(
lr_scheduler_args=CosineLRSchedulerArgs(
min_lr_ratio=min_lr_ratio, num_cycles=scheduler_num_cycles
),
)
else:
lrScheduler = FinetuneLinearLRScheduler(
lr_scheduler_args=FinetuneLinearLRSchedulerArgs(min_lr_ratio=min_lr_ratio),
lr_scheduler = LinearLRScheduler(
lr_scheduler_args=LinearLRSchedulerArgs(min_lr_ratio=min_lr_ratio),
)

training_method_cls: TrainingMethodSFT | TrainingMethodDPO = TrainingMethodSFT()
Expand All @@ -182,7 +180,7 @@ def createFinetuneRequest(
n_checkpoints=n_checkpoints,
batch_size=batch_size,
learning_rate=learning_rate,
lr_scheduler=lrScheduler,
lr_scheduler=lr_scheduler,
warmup_ratio=warmup_ratio,
max_grad_norm=max_grad_norm,
weight_decay=weight_decay,
Expand Down Expand Up @@ -374,7 +372,7 @@ def create(
pass
model_limits = self.get_model_limits(model=model_name)

finetune_request = createFinetuneRequest(
finetune_request = create_finetune_request(
model_limits=model_limits,
training_file=training_file,
model=model,
Expand Down Expand Up @@ -762,7 +760,7 @@ async def create(
pass
model_limits = await self.get_model_limits(model=model_name)

finetune_request = createFinetuneRequest(
finetune_request = create_finetune_request(
model_limits=model_limits,
training_file=training_file,
model=model,
Expand Down
16 changes: 8 additions & 8 deletions src/together/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@
TrainingMethodDPO,
TrainingMethodSFT,
FinetuneCheckpoint,
FinetuneCosineLRScheduler,
FinetuneCosineLRSchedulerArgs,
CosineLRScheduler,
CosineLRSchedulerArgs,
FinetuneDownloadResult,
FinetuneLinearLRScheduler,
FinetuneLinearLRSchedulerArgs,
LinearLRScheduler,
LinearLRSchedulerArgs,
FinetuneLRScheduler,
FinetuneList,
FinetuneListEvents,
Expand Down Expand Up @@ -72,10 +72,10 @@
"FinetuneListEvents",
"FinetuneDownloadResult",
"FinetuneLRScheduler",
"FinetuneLinearLRScheduler",
"FinetuneLinearLRSchedulerArgs",
"FinetuneCosineLRScheduler",
"FinetuneCosineLRSchedulerArgs",
"LinearLRScheduler",
"LinearLRSchedulerArgs",
"CosineLRScheduler",
"CosineLRSchedulerArgs",
"FileRequest",
"FileResponse",
"FileList",
Expand Down
26 changes: 16 additions & 10 deletions src/together/types/finetune.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from __future__ import annotations

from enum import Enum
from typing import List, Literal, Union
from typing import List, Literal

from pydantic import StrictBool, Field, validator, field_validator, ValidationInfo
from pydantic import StrictBool, Field, field_validator

from together.types.abstract import BaseModel
from together.types.common import (
Expand Down Expand Up @@ -176,7 +176,7 @@ class FinetuneRequest(BaseModel):
# training learning rate
learning_rate: float
# learning rate scheduler type and args
lr_scheduler: FinetuneLinearLRScheduler | FinetuneCosineLRScheduler | None = None
lr_scheduler: LinearLRScheduler | CosineLRScheduler | None = None
# learning rate warmup ratio
warmup_ratio: float
# max gradient norm
Expand Down Expand Up @@ -239,7 +239,7 @@ class FinetuneResponse(BaseModel):
# training learning rate
learning_rate: float | None = None
# learning rate scheduler type and args
lr_scheduler: FinetuneLinearLRScheduler | FinetuneCosineLRScheduler | None = None
lr_scheduler: LinearLRScheduler | CosineLRScheduler | EmptyLRScheduler | None = None
# learning rate warmup ratio
warmup_ratio: float | None = None
# max gradient norm
Expand Down Expand Up @@ -345,11 +345,11 @@ class FinetuneTrainingLimits(BaseModel):
lora_training: FinetuneLoraTrainingLimits | None = None


class FinetuneLinearLRSchedulerArgs(BaseModel):
class LinearLRSchedulerArgs(BaseModel):
min_lr_ratio: float | None = 0.0


class FinetuneCosineLRSchedulerArgs(BaseModel):
class CosineLRSchedulerArgs(BaseModel):
min_lr_ratio: float | None = 0.0
num_cycles: float | None = 0.5

Expand All @@ -358,14 +358,20 @@ class FinetuneLRScheduler(BaseModel):
lr_scheduler_type: str


class FinetuneLinearLRScheduler(FinetuneLRScheduler):
class LinearLRScheduler(FinetuneLRScheduler):
lr_scheduler_type: Literal["linear"] = "linear"
lr_scheduler: FinetuneLinearLRSchedulerArgs | None = None
lr_scheduler_args: LinearLRSchedulerArgs | None = None


class FinetuneCosineLRScheduler(FinetuneLRScheduler):
class CosineLRScheduler(FinetuneLRScheduler):
lr_scheduler_type: Literal["cosine"] = "cosine"
lr_scheduler: FinetuneCosineLRSchedulerArgs | None = None
lr_scheduler_args: CosineLRSchedulerArgs | None = None


# placeholder for old fine-tuning jobs with no lr_scheduler_type specified
class EmptyLRScheduler(FinetuneLRScheduler):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smart! Looks good to me if we have no other options to support old jobs

lr_scheduler_type: Literal[""]
lr_scheduler_args: None = None


class FinetuneCheckpoint(BaseModel):
Expand Down
38 changes: 19 additions & 19 deletions tests/unit/test_finetune_resources.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from together.resources.finetune import createFinetuneRequest
from together.resources.finetune import create_finetune_request
from together.types.finetune import (
FinetuneTrainingLimits,
FinetuneFullTrainingLimits,
Expand Down Expand Up @@ -30,7 +30,7 @@


def test_simple_request():
request = createFinetuneRequest(
request = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
training_file=_TRAINING_FILE,
Expand All @@ -46,7 +46,7 @@ def test_simple_request():


def test_validation_file():
request = createFinetuneRequest(
request = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
training_file=_TRAINING_FILE,
Expand All @@ -61,14 +61,14 @@ def test_no_training_file():
with pytest.raises(
TypeError, match="missing 1 required positional argument: 'training_file'"
):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
)


def test_lora_request():
request = createFinetuneRequest(
request = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
training_file=_TRAINING_FILE,
Expand All @@ -84,7 +84,7 @@ def test_lora_request():


def test_from_checkpoint_request():
request = createFinetuneRequest(
request = create_finetune_request(
model_limits=_MODEL_LIMITS,
training_file=_TRAINING_FILE,
from_checkpoint=_FROM_CHECKPOINT,
Expand All @@ -99,7 +99,7 @@ def test_both_from_checkpoint_model_name():
ValueError,
match="You must specify either a model or a checkpoint to start a job from, not both",
):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
training_file=_TRAINING_FILE,
Expand All @@ -111,7 +111,7 @@ def test_no_from_checkpoint_no_model_name():
with pytest.raises(
ValueError, match="You must specify either a model or a checkpoint"
):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=_MODEL_LIMITS,
training_file=_TRAINING_FILE,
)
Expand All @@ -122,7 +122,7 @@ def test_batch_size_limit():
ValueError,
match="Requested batch size is higher that the maximum allowed value",
):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
training_file=_TRAINING_FILE,
Expand All @@ -132,7 +132,7 @@ def test_batch_size_limit():
with pytest.raises(
ValueError, match="Requested batch size is lower that the minimum allowed value"
):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
training_file=_TRAINING_FILE,
Expand All @@ -143,7 +143,7 @@ def test_batch_size_limit():
ValueError,
match="Requested batch size is higher that the maximum allowed value",
):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
training_file=_TRAINING_FILE,
Expand All @@ -154,7 +154,7 @@ def test_batch_size_limit():
with pytest.raises(
ValueError, match="Requested batch size is lower that the minimum allowed value"
):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
training_file=_TRAINING_FILE,
Expand All @@ -167,7 +167,7 @@ def test_non_lora_model():
with pytest.raises(
ValueError, match="LoRA adapters are not supported for the selected model."
):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=FinetuneTrainingLimits(
max_num_epochs=20,
max_learning_rate=1.0,
Expand All @@ -188,7 +188,7 @@ def test_non_full_model():
with pytest.raises(
ValueError, match="Full training is not supported for the selected model."
):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=FinetuneTrainingLimits(
max_num_epochs=20,
max_learning_rate=1.0,
Expand All @@ -210,7 +210,7 @@ def test_non_full_model():
@pytest.mark.parametrize("warmup_ratio", [-1.0, 2.0])
def test_bad_warmup(warmup_ratio):
with pytest.raises(ValueError, match="Warmup ratio should be between 0 and 1"):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
training_file=_TRAINING_FILE,
Expand All @@ -223,7 +223,7 @@ def test_bad_min_lr_ratio(min_lr_ratio):
with pytest.raises(
ValueError, match="Min learning rate ratio should be between 0 and 1"
):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
training_file=_TRAINING_FILE,
Expand All @@ -234,7 +234,7 @@ def test_bad_min_lr_ratio(min_lr_ratio):
@pytest.mark.parametrize("max_grad_norm", [-1.0, -0.01])
def test_bad_max_grad_norm(max_grad_norm):
with pytest.raises(ValueError, match="Max gradient norm should be non-negative"):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
training_file=_TRAINING_FILE,
Expand All @@ -245,7 +245,7 @@ def test_bad_max_grad_norm(max_grad_norm):
@pytest.mark.parametrize("weight_decay", [-1.0, -0.01])
def test_bad_weight_decay(weight_decay):
with pytest.raises(ValueError, match="Weight decay should be non-negative"):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
training_file=_TRAINING_FILE,
Expand All @@ -255,7 +255,7 @@ def test_bad_weight_decay(weight_decay):

def test_bad_training_method():
with pytest.raises(ValueError, match="training_method must be one of .*"):
_ = createFinetuneRequest(
_ = create_finetune_request(
model_limits=_MODEL_LIMITS,
model=_MODEL_NAME,
training_file=_TRAINING_FILE,
Expand Down