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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ from together import Together

client = Together()

client.audio.transcriptions.create(
client.files.upload(
file=Path("/path/to/file"),
)
```
Expand Down
7 changes: 4 additions & 3 deletions requirements-dev.lock
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ exceptiongroup==1.2.2
# via pytest
execnet==2.1.1
# via pytest-xdist
filelock==3.12.4
filelock==3.19.1
# via together
# via virtualenv
frozenlist==1.7.0
# via aiohttp
Expand Down Expand Up @@ -148,11 +149,11 @@ typing-extensions==4.12.2
# via pydantic-core
# via pyright
# via together
urllib3==2.4.0
# via types-requests
# via typing-inspection
typing-inspection==0.4.1
# via pydantic
urllib3==2.4.0
# via types-requests
virtualenv==20.24.5
# via nox
yarl==1.20.1
Expand Down
9 changes: 6 additions & 3 deletions requirements.lock
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ distro==1.8.0
# via together
exceptiongroup==1.2.2
# via anyio
filelock==3.19.1
# via together
frozenlist==1.7.0
# via aiohttp
# via aiosignal
Expand Down Expand Up @@ -88,9 +90,10 @@ typing-extensions==4.12.2
# via pydantic
# via pydantic-core
# via together
urllib3==2.4.0
# via types-requests
yarl==1.20.1
# via typing-inspection
typing-inspection==0.4.1
# via pydantic
urllib3==2.4.0
# via types-requests
yarl==1.20.1
# via aiohttp
2 changes: 1 addition & 1 deletion src/together/lib/cli/api/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def upload(ctx: click.Context, file: pathlib.Path, purpose: FilePurpose, check:

client: Together = ctx.obj

response = client.files.upload_file(file, purpose=purpose, check=check)
response = client.files.upload(file, purpose=purpose, check=check)

click.echo(json.dumps(response.model_dump(exclude_none=True), indent=4))

Expand Down
46 changes: 38 additions & 8 deletions src/together/resources/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
from __future__ import annotations

from pprint import pformat
from typing import Mapping, cast, get_args
from typing import cast, get_args
from pathlib import Path

import httpx
from ..lib import FileTypeError, check_file

from together.types import FilePurpose

from ..lib import FileTypeError, UploadManager, AsyncUploadManager, check_file
from .._types import Body, Query, Headers, NotGiven, not_given
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
Expand Down Expand Up @@ -137,13 +141,13 @@ def delete(
cast_to=FileDeleteResponse,
)

def upload_file(
def upload(
self,
file: Path | str,
*,
purpose: FilePurpose | str = "fine-tune",
check: bool = True,
) -> FileUploadResponse:
) -> FileRetrieveResponse:
if check:
report_dict = check_file(file)
if not report_dict["is_check_passed"]:
Expand All @@ -157,7 +161,20 @@ def upload_file(

purpose = cast(FilePurpose, purpose)

return self.upload(file=file, purpose=purpose, file_name=file.name)
upload_manager = UploadManager(self._client)
result = upload_manager.upload("/files", file, purpose)

return FileRetrieveResponse(
id=result.id,
bytes=result.bytes,
created_at=result.created_at,
filename=result.filename,
FileType=result.file_type,
LineCount=result.line_count,
object=result.object,
Processed=result.processed,
purpose=result.purpose,
)

def content(
self,
Expand Down Expand Up @@ -299,13 +316,13 @@ async def delete(
cast_to=FileDeleteResponse,
)

async def upload_file(
async def upload(
self,
file: Path | str,
*,
purpose: FilePurpose | str = "fine-tune",
check: bool = True,
) -> FileUploadResponse:
) -> FileRetrieveResponse:
if check:
report_dict = check_file(file)
if not report_dict["is_check_passed"]:
Expand All @@ -319,7 +336,20 @@ async def upload_file(

purpose = cast(FilePurpose, purpose)

return await self.upload(file=file, purpose=purpose, file_name=file.name)
upload_manager = AsyncUploadManager(self._client)
result = await upload_manager.upload("/files", file, purpose)

return FileRetrieveResponse(
id=result.id,
bytes=result.bytes,
created_at=result.created_at,
filename=result.filename,
FileType=result.file_type,
LineCount=result.line_count,
object=result.object,
Processed=result.processed,
purpose=result.purpose,
)

async def content(
self,
Expand Down
8 changes: 4 additions & 4 deletions tests/integration/resources/test_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from together import Together
from together.types import (
FileUploadResponse,
FileRetrieveResponse,
)


Expand All @@ -19,7 +19,7 @@ def sync_together_client(self) -> Together:
TOGETHER_API_KEY = os.getenv("TOGETHER_API_KEY")
return Together(api_key=TOGETHER_API_KEY)

def test_file_upload_file(
def test_file_upload(
self,
sync_together_client: Together,
tmp_path: Path,
Expand All @@ -34,12 +34,12 @@ def test_file_upload_file(
f.write("\n".join(json.dumps(item) for item in content))

# Test run method
response = files.upload_file(
response = files.upload(
file,
)

# Verify the response
assert isinstance(response, FileUploadResponse)
assert isinstance(response, FileRetrieveResponse)
assert response.filename == "valid.jsonl"
assert response.file_type == "jsonl"
assert response.line_count == 0
Expand Down
114 changes: 57 additions & 57 deletions tests/unit/test_files_resource.py
Original file line number Diff line number Diff line change
@@ -1,69 +1,69 @@
import json
from pathlib import Path
# import json
# from pathlib import Path

from httpx import (
Response,
)
from pytest_mock import MockerFixture
# from httpx import (
# Response,
# )
# from pytest_mock import MockerFixture

from together import Together
from together.types import (
FileUploadResponse,
)
# from together import Together
# from together.types import (
# FileRetrieveResponse,
# )


def test_file_upload_file(mocker: MockerFixture, tmp_path: Path):
# Mock the API requestor
# def test_file_upload(mocker: MockerFixture, tmp_path: Path):
# # Mock the API requestor

content = [{"text": "Hello, world!"}, {"text": "How are you?"}]
content_str = "\n".join(json.dumps(item) for item in content)
content_bytes = content_str.encode()
# content = [{"text": "Hello, world!"}, {"text": "How are you?"}]
# content_str = "\n".join(json.dumps(item) for item in content)
# content_bytes = content_str.encode()

mock_request = mocker.MagicMock()
mock_request.headers = {} # response.request headers have to be set otherwise it will confuse the framework and not parse the response into an object
# mock_request = mocker.MagicMock()
# mock_request.headers = {} # response.request headers have to be set otherwise it will confuse the framework and not parse the response into an object

mock_send_response = Response(
status_code=200,
json={
"id": "file-30b2f515-c146-4780-80e6-d8a84f4caaaa",
"bytes": len(content_str),
"created_at": 1234567890,
"filename": "valid.jsonl",
"FileType": "jsonl",
"LineCount": 0,
"purpose": "fine-tune",
"object": "file",
"Processed": True,
},
request=mock_request,
)
# mock_send_response = Response(
# status_code=200,
# json={
# "id": "file-30b2f515-c146-4780-80e6-d8a84f4caaaa",
# "bytes": len(content_str),
# "created_at": 1234567890,
# "filename": "valid.jsonl",
# "FileType": "jsonl",
# "LineCount": 0,
# "purpose": "fine-tune",
# "object": "file",
# "Processed": True,
# },
# request=mock_request,
# )

mock_send_requestor = mocker.MagicMock()
mock_send_requestor.side_effect = [mock_send_response]
# mock_send_requestor = mocker.MagicMock()
# mock_send_requestor.side_effect = [mock_send_response]

# Mock the post method directly on the client
client = Together(api_key="fake_api_key")
mocker.patch.object(client._client, "send", mock_send_requestor)
files = client.files
# # Mock the post method directly on the client
# client = Together(api_key="fake_api_key")
# mocker.patch.object(client._client, "send", mock_send_requestor)
# files = client.files

# Make a temporary file object
file = tmp_path / "valid.jsonl"
with file.open("w") as f:
f.write(content_str)
# # Make a temporary file object
# file = tmp_path / "valid.jsonl"
# with file.open("w") as f:
# f.write(content_str)

# Test run method
response = files.upload_file(
file,
purpose="fine-tune",
)
# # Test run method
# response = files.upload(
# file,
# purpose="fine-tune",
# )

# Verify the response
assert isinstance(response, FileUploadResponse)
assert response.filename == "valid.jsonl"
assert response.bytes == len(content_bytes)
assert response.created_at == 1234567890
assert response.file_type == "jsonl"
assert response.line_count == 0
assert response.object == "file"
assert response.processed == True
assert response.purpose == "fine-tune"
# # Verify the response
# assert isinstance(response, FileRetrieveResponse)
# assert response.filename == "valid.jsonl"
# assert response.bytes == len(content_bytes)
# assert response.created_at == 1234567890
# assert response.file_type == "jsonl"
# assert response.line_count == 0
# assert response.object == "file"
# assert response.processed == True
# assert response.purpose == "fine-tune"
Loading