diff --git a/src/together/cli/api/finetune.py b/src/together/cli/api/finetune.py index f52a14d..c14081e 100644 --- a/src/together/cli/api/finetune.py +++ b/src/together/cli/api/finetune.py @@ -543,3 +543,30 @@ def download( ) click.echo(json.dumps(response.model_dump(exclude_none=True), indent=4)) + + +@fine_tuning.command() +@click.pass_context +@click.argument("fine_tune_id", type=str, required=True) +@click.option("--force", is_flag=True, help="Force deletion without confirmation") +@click.option( + "--quiet", is_flag=True, help="Do not prompt for confirmation before deleting job" +) +def delete( + ctx: click.Context, fine_tune_id: str, force: bool = False, quiet: bool = False +) -> None: + """Delete fine-tuning job""" + client: Together = ctx.obj + + if not quiet: + confirm_response = input( + f"Are you sure you want to delete fine-tuning job {fine_tune_id}? " + "This action cannot be undone. [y/N] " + ) + if confirm_response.lower() != "y": + click.echo("Deletion cancelled") + return + + response = client.fine_tuning.delete(fine_tune_id, force=force) + + click.echo(json.dumps(response.model_dump(exclude_none=True), indent=4)) diff --git a/src/together/resources/finetune.py b/src/together/resources/finetune.py index 3ebe543..2b3a652 100644 --- a/src/together/resources/finetune.py +++ b/src/together/resources/finetune.py @@ -13,6 +13,7 @@ CosineLRScheduler, CosineLRSchedulerArgs, FinetuneCheckpoint, + FinetuneDeleteResponse, FinetuneDownloadResult, FinetuneList, FinetuneListEvents, @@ -570,6 +571,37 @@ def cancel(self, id: str) -> FinetuneResponse: return FinetuneResponse(**response.data) + def delete(self, id: str, force: bool = False) -> FinetuneDeleteResponse: + """ + Method to delete a fine-tuning job + + Args: + id (str): Fine-tune ID to delete. A string that starts with `ft-`. + force (bool, optional): Force deletion. Defaults to False. + + Returns: + FinetuneDeleteResponse: Object containing deletion confirmation message. + """ + + requestor = api_requestor.APIRequestor( + client=self._client, + ) + + params = {"force": str(force).lower()} + + response, _, _ = requestor.request( + options=TogetherRequest( + method="DELETE", + url=f"fine-tunes/{id}", + params=params, + ), + stream=False, + ) + + assert isinstance(response, TogetherResponse) + + return FinetuneDeleteResponse(**response.data) + def list_events(self, id: str) -> FinetuneListEvents: """ Lists events of a fine-tune job @@ -1007,6 +1039,37 @@ async def cancel(self, id: str) -> FinetuneResponse: return FinetuneResponse(**response.data) + async def delete(self, id: str, force: bool = False) -> FinetuneDeleteResponse: + """ + Async method to delete a fine-tuning job + + Args: + id (str): Fine-tune ID to delete. A string that starts with `ft-`. + force (bool, optional): Force deletion. Defaults to False. + + Returns: + FinetuneDeleteResponse: Object containing deletion confirmation message. + """ + + requestor = api_requestor.APIRequestor( + client=self._client, + ) + + params = {"force": str(force).lower()} + + response, _, _ = await requestor.arequest( + options=TogetherRequest( + method="DELETE", + url=f"fine-tunes/{id}", + params=params, + ), + stream=False, + ) + + assert isinstance(response, TogetherResponse) + + return FinetuneDeleteResponse(**response.data) + async def list_events(self, id: str) -> FinetuneListEvents: """ List fine-tuning events diff --git a/src/together/types/__init__.py b/src/together/types/__init__.py index 325e15a..7ce2f96 100644 --- a/src/together/types/__init__.py +++ b/src/together/types/__init__.py @@ -52,6 +52,7 @@ FinetuneListEvents, FinetuneRequest, FinetuneResponse, + FinetuneDeleteResponse, FinetuneTrainingLimits, FullTrainingType, LoRATrainingType, @@ -92,6 +93,7 @@ "FinetuneResponse", "FinetuneList", "FinetuneListEvents", + "FinetuneDeleteResponse", "FinetuneDownloadResult", "FinetuneLRScheduler", "LinearLRScheduler", diff --git a/src/together/types/finetune.py b/src/together/types/finetune.py index 789c19f..52c802b 100644 --- a/src/together/types/finetune.py +++ b/src/together/types/finetune.py @@ -322,6 +322,11 @@ class FinetuneListEvents(BaseModel): data: List[FinetuneEvent] | None = None +class FinetuneDeleteResponse(BaseModel): + # delete message + message: str + + class FinetuneDownloadResult(BaseModel): # object type object: Literal["local"] | None = None