Skip to content

Commit 24ab406

Browse files
feat(api): add uploads endpoints (openai#1568)
1 parent c814354 commit 24ab406

19 files changed

+1272
-2
lines changed

.stats.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
configured_endpoints: 64
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-518ca6c60061d3e8bc0971facf40d752f2aea62e3522cc168ad29a1f29cab3dd.yml
1+
configured_endpoints: 68
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-77cfff37114bc9f141c7e6107eb5f1b38d8cc99bc3d4ce03a066db2b6b649c69.yml

api.md

+26
Original file line numberDiff line numberDiff line change
@@ -415,3 +415,29 @@ Methods:
415415
- <code title="get /batches/{batch_id}">client.batches.<a href="./src/openai/resources/batches.py">retrieve</a>(batch_id) -> <a href="./src/openai/types/batch.py">Batch</a></code>
416416
- <code title="get /batches">client.batches.<a href="./src/openai/resources/batches.py">list</a>(\*\*<a href="src/openai/types/batch_list_params.py">params</a>) -> <a href="./src/openai/types/batch.py">SyncCursorPage[Batch]</a></code>
417417
- <code title="post /batches/{batch_id}/cancel">client.batches.<a href="./src/openai/resources/batches.py">cancel</a>(batch_id) -> <a href="./src/openai/types/batch.py">Batch</a></code>
418+
419+
# Uploads
420+
421+
Types:
422+
423+
```python
424+
from openai.types import Upload
425+
```
426+
427+
Methods:
428+
429+
- <code title="post /uploads">client.uploads.<a href="./src/openai/resources/uploads/uploads.py">create</a>(\*\*<a href="src/openai/types/upload_create_params.py">params</a>) -> <a href="./src/openai/types/upload.py">Upload</a></code>
430+
- <code title="post /uploads/{upload_id}/cancel">client.uploads.<a href="./src/openai/resources/uploads/uploads.py">cancel</a>(upload_id) -> <a href="./src/openai/types/upload.py">Upload</a></code>
431+
- <code title="post /uploads/{upload_id}/complete">client.uploads.<a href="./src/openai/resources/uploads/uploads.py">complete</a>(upload_id, \*\*<a href="src/openai/types/upload_complete_params.py">params</a>) -> <a href="./src/openai/types/upload.py">Upload</a></code>
432+
433+
## Parts
434+
435+
Types:
436+
437+
```python
438+
from openai.types.uploads import UploadPart
439+
```
440+
441+
Methods:
442+
443+
- <code title="post /uploads/{upload_id}/parts">client.uploads.parts.<a href="./src/openai/resources/uploads/parts.py">create</a>(upload_id, \*\*<a href="src/openai/types/uploads/part_create_params.py">params</a>) -> <a href="./src/openai/types/uploads/upload_part.py">UploadPart</a></code>

src/openai/_client.py

+8
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class OpenAI(SyncAPIClient):
5858
fine_tuning: resources.FineTuning
5959
beta: resources.Beta
6060
batches: resources.Batches
61+
uploads: resources.Uploads
6162
with_raw_response: OpenAIWithRawResponse
6263
with_streaming_response: OpenAIWithStreamedResponse
6364

@@ -143,6 +144,7 @@ def __init__(
143144
self.fine_tuning = resources.FineTuning(self)
144145
self.beta = resources.Beta(self)
145146
self.batches = resources.Batches(self)
147+
self.uploads = resources.Uploads(self)
146148
self.with_raw_response = OpenAIWithRawResponse(self)
147149
self.with_streaming_response = OpenAIWithStreamedResponse(self)
148150

@@ -270,6 +272,7 @@ class AsyncOpenAI(AsyncAPIClient):
270272
fine_tuning: resources.AsyncFineTuning
271273
beta: resources.AsyncBeta
272274
batches: resources.AsyncBatches
275+
uploads: resources.AsyncUploads
273276
with_raw_response: AsyncOpenAIWithRawResponse
274277
with_streaming_response: AsyncOpenAIWithStreamedResponse
275278

@@ -355,6 +358,7 @@ def __init__(
355358
self.fine_tuning = resources.AsyncFineTuning(self)
356359
self.beta = resources.AsyncBeta(self)
357360
self.batches = resources.AsyncBatches(self)
361+
self.uploads = resources.AsyncUploads(self)
358362
self.with_raw_response = AsyncOpenAIWithRawResponse(self)
359363
self.with_streaming_response = AsyncOpenAIWithStreamedResponse(self)
360364

@@ -483,6 +487,7 @@ def __init__(self, client: OpenAI) -> None:
483487
self.fine_tuning = resources.FineTuningWithRawResponse(client.fine_tuning)
484488
self.beta = resources.BetaWithRawResponse(client.beta)
485489
self.batches = resources.BatchesWithRawResponse(client.batches)
490+
self.uploads = resources.UploadsWithRawResponse(client.uploads)
486491

487492

488493
class AsyncOpenAIWithRawResponse:
@@ -498,6 +503,7 @@ def __init__(self, client: AsyncOpenAI) -> None:
498503
self.fine_tuning = resources.AsyncFineTuningWithRawResponse(client.fine_tuning)
499504
self.beta = resources.AsyncBetaWithRawResponse(client.beta)
500505
self.batches = resources.AsyncBatchesWithRawResponse(client.batches)
506+
self.uploads = resources.AsyncUploadsWithRawResponse(client.uploads)
501507

502508

503509
class OpenAIWithStreamedResponse:
@@ -513,6 +519,7 @@ def __init__(self, client: OpenAI) -> None:
513519
self.fine_tuning = resources.FineTuningWithStreamingResponse(client.fine_tuning)
514520
self.beta = resources.BetaWithStreamingResponse(client.beta)
515521
self.batches = resources.BatchesWithStreamingResponse(client.batches)
522+
self.uploads = resources.UploadsWithStreamingResponse(client.uploads)
516523

517524

518525
class AsyncOpenAIWithStreamedResponse:
@@ -528,6 +535,7 @@ def __init__(self, client: AsyncOpenAI) -> None:
528535
self.fine_tuning = resources.AsyncFineTuningWithStreamingResponse(client.fine_tuning)
529536
self.beta = resources.AsyncBetaWithStreamingResponse(client.beta)
530537
self.batches = resources.AsyncBatchesWithStreamingResponse(client.batches)
538+
self.uploads = resources.AsyncUploadsWithStreamingResponse(client.uploads)
531539

532540

533541
Client = OpenAI

src/openai/resources/__init__.py

+14
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@
5656
BatchesWithStreamingResponse,
5757
AsyncBatchesWithStreamingResponse,
5858
)
59+
from .uploads import (
60+
Uploads,
61+
AsyncUploads,
62+
UploadsWithRawResponse,
63+
AsyncUploadsWithRawResponse,
64+
UploadsWithStreamingResponse,
65+
AsyncUploadsWithStreamingResponse,
66+
)
5967
from .embeddings import (
6068
Embeddings,
6169
AsyncEmbeddings,
@@ -156,4 +164,10 @@
156164
"AsyncBatchesWithRawResponse",
157165
"BatchesWithStreamingResponse",
158166
"AsyncBatchesWithStreamingResponse",
167+
"Uploads",
168+
"AsyncUploads",
169+
"UploadsWithRawResponse",
170+
"AsyncUploadsWithRawResponse",
171+
"UploadsWithStreamingResponse",
172+
"AsyncUploadsWithStreamingResponse",
159173
]

src/openai/resources/chat/completions.py

+6
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ def create(
171171
exhausted.
172172
- If set to 'default', the request will be processed using the default service
173173
tier with a lower uptime SLA and no latency guarentee.
174+
- When not set, the default behavior is 'auto'.
174175
175176
When this parameter is set, the response body will include the `service_tier`
176177
utilized.
@@ -366,6 +367,7 @@ def create(
366367
exhausted.
367368
- If set to 'default', the request will be processed using the default service
368369
tier with a lower uptime SLA and no latency guarentee.
370+
- When not set, the default behavior is 'auto'.
369371
370372
When this parameter is set, the response body will include the `service_tier`
371373
utilized.
@@ -554,6 +556,7 @@ def create(
554556
exhausted.
555557
- If set to 'default', the request will be processed using the default service
556558
tier with a lower uptime SLA and no latency guarentee.
559+
- When not set, the default behavior is 'auto'.
557560
558561
When this parameter is set, the response body will include the `service_tier`
559562
utilized.
@@ -817,6 +820,7 @@ async def create(
817820
exhausted.
818821
- If set to 'default', the request will be processed using the default service
819822
tier with a lower uptime SLA and no latency guarentee.
823+
- When not set, the default behavior is 'auto'.
820824
821825
When this parameter is set, the response body will include the `service_tier`
822826
utilized.
@@ -1012,6 +1016,7 @@ async def create(
10121016
exhausted.
10131017
- If set to 'default', the request will be processed using the default service
10141018
tier with a lower uptime SLA and no latency guarentee.
1019+
- When not set, the default behavior is 'auto'.
10151020
10161021
When this parameter is set, the response body will include the `service_tier`
10171022
utilized.
@@ -1200,6 +1205,7 @@ async def create(
12001205
exhausted.
12011206
- If set to 'default', the request will be processed using the default service
12021207
tier with a lower uptime SLA and no latency guarentee.
1208+
- When not set, the default behavior is 'auto'.
12031209
12041210
When this parameter is set, the response body will include the `service_tier`
12051211
utilized.
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from .parts import (
4+
Parts,
5+
AsyncParts,
6+
PartsWithRawResponse,
7+
AsyncPartsWithRawResponse,
8+
PartsWithStreamingResponse,
9+
AsyncPartsWithStreamingResponse,
10+
)
11+
from .uploads import (
12+
Uploads,
13+
AsyncUploads,
14+
UploadsWithRawResponse,
15+
AsyncUploadsWithRawResponse,
16+
UploadsWithStreamingResponse,
17+
AsyncUploadsWithStreamingResponse,
18+
)
19+
20+
__all__ = [
21+
"Parts",
22+
"AsyncParts",
23+
"PartsWithRawResponse",
24+
"AsyncPartsWithRawResponse",
25+
"PartsWithStreamingResponse",
26+
"AsyncPartsWithStreamingResponse",
27+
"Uploads",
28+
"AsyncUploads",
29+
"UploadsWithRawResponse",
30+
"AsyncUploadsWithRawResponse",
31+
"UploadsWithStreamingResponse",
32+
"AsyncUploadsWithStreamingResponse",
33+
]

src/openai/resources/uploads/parts.py

+188
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from __future__ import annotations
4+
5+
from typing import Mapping, cast
6+
7+
import httpx
8+
9+
from ... import _legacy_response
10+
from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven, FileTypes
11+
from ..._utils import (
12+
extract_files,
13+
maybe_transform,
14+
deepcopy_minimal,
15+
async_maybe_transform,
16+
)
17+
from ..._compat import cached_property
18+
from ..._resource import SyncAPIResource, AsyncAPIResource
19+
from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper
20+
from ..._base_client import make_request_options
21+
from ...types.uploads import part_create_params
22+
from ...types.uploads.upload_part import UploadPart
23+
24+
__all__ = ["Parts", "AsyncParts"]
25+
26+
27+
class Parts(SyncAPIResource):
28+
@cached_property
29+
def with_raw_response(self) -> PartsWithRawResponse:
30+
return PartsWithRawResponse(self)
31+
32+
@cached_property
33+
def with_streaming_response(self) -> PartsWithStreamingResponse:
34+
return PartsWithStreamingResponse(self)
35+
36+
def create(
37+
self,
38+
upload_id: str,
39+
*,
40+
data: FileTypes,
41+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
42+
# The extra values given here take precedence over values defined on the client or passed to this method.
43+
extra_headers: Headers | None = None,
44+
extra_query: Query | None = None,
45+
extra_body: Body | None = None,
46+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
47+
) -> UploadPart:
48+
"""
49+
Adds a
50+
[Part](https://platform.openai.com/docs/api-reference/uploads/part-object) to an
51+
[Upload](https://platform.openai.com/docs/api-reference/uploads/object) object.
52+
A Part represents a chunk of bytes from the file you are trying to upload.
53+
54+
Each Part can be at most 64 MB, and you can add Parts until you hit the Upload
55+
maximum of 8 GB.
56+
57+
It is possible to add multiple Parts in parallel. You can decide the intended
58+
order of the Parts when you
59+
[complete the Upload](https://platform.openai.com/docs/api-reference/uploads/complete).
60+
61+
Args:
62+
data: The chunk of bytes for this Part.
63+
64+
extra_headers: Send extra headers
65+
66+
extra_query: Add additional query parameters to the request
67+
68+
extra_body: Add additional JSON properties to the request
69+
70+
timeout: Override the client-level default timeout for this request, in seconds
71+
"""
72+
if not upload_id:
73+
raise ValueError(f"Expected a non-empty value for `upload_id` but received {upload_id!r}")
74+
body = deepcopy_minimal({"data": data})
75+
files = extract_files(cast(Mapping[str, object], body), paths=[["data"]])
76+
# It should be noted that the actual Content-Type header that will be
77+
# sent to the server will contain a `boundary` parameter, e.g.
78+
# multipart/form-data; boundary=---abc--
79+
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
80+
return self._post(
81+
f"/uploads/{upload_id}/parts",
82+
body=maybe_transform(body, part_create_params.PartCreateParams),
83+
files=files,
84+
options=make_request_options(
85+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
86+
),
87+
cast_to=UploadPart,
88+
)
89+
90+
91+
class AsyncParts(AsyncAPIResource):
92+
@cached_property
93+
def with_raw_response(self) -> AsyncPartsWithRawResponse:
94+
return AsyncPartsWithRawResponse(self)
95+
96+
@cached_property
97+
def with_streaming_response(self) -> AsyncPartsWithStreamingResponse:
98+
return AsyncPartsWithStreamingResponse(self)
99+
100+
async def create(
101+
self,
102+
upload_id: str,
103+
*,
104+
data: FileTypes,
105+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
106+
# The extra values given here take precedence over values defined on the client or passed to this method.
107+
extra_headers: Headers | None = None,
108+
extra_query: Query | None = None,
109+
extra_body: Body | None = None,
110+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
111+
) -> UploadPart:
112+
"""
113+
Adds a
114+
[Part](https://platform.openai.com/docs/api-reference/uploads/part-object) to an
115+
[Upload](https://platform.openai.com/docs/api-reference/uploads/object) object.
116+
A Part represents a chunk of bytes from the file you are trying to upload.
117+
118+
Each Part can be at most 64 MB, and you can add Parts until you hit the Upload
119+
maximum of 8 GB.
120+
121+
It is possible to add multiple Parts in parallel. You can decide the intended
122+
order of the Parts when you
123+
[complete the Upload](https://platform.openai.com/docs/api-reference/uploads/complete).
124+
125+
Args:
126+
data: The chunk of bytes for this Part.
127+
128+
extra_headers: Send extra headers
129+
130+
extra_query: Add additional query parameters to the request
131+
132+
extra_body: Add additional JSON properties to the request
133+
134+
timeout: Override the client-level default timeout for this request, in seconds
135+
"""
136+
if not upload_id:
137+
raise ValueError(f"Expected a non-empty value for `upload_id` but received {upload_id!r}")
138+
body = deepcopy_minimal({"data": data})
139+
files = extract_files(cast(Mapping[str, object], body), paths=[["data"]])
140+
# It should be noted that the actual Content-Type header that will be
141+
# sent to the server will contain a `boundary` parameter, e.g.
142+
# multipart/form-data; boundary=---abc--
143+
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
144+
return await self._post(
145+
f"/uploads/{upload_id}/parts",
146+
body=await async_maybe_transform(body, part_create_params.PartCreateParams),
147+
files=files,
148+
options=make_request_options(
149+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
150+
),
151+
cast_to=UploadPart,
152+
)
153+
154+
155+
class PartsWithRawResponse:
156+
def __init__(self, parts: Parts) -> None:
157+
self._parts = parts
158+
159+
self.create = _legacy_response.to_raw_response_wrapper(
160+
parts.create,
161+
)
162+
163+
164+
class AsyncPartsWithRawResponse:
165+
def __init__(self, parts: AsyncParts) -> None:
166+
self._parts = parts
167+
168+
self.create = _legacy_response.async_to_raw_response_wrapper(
169+
parts.create,
170+
)
171+
172+
173+
class PartsWithStreamingResponse:
174+
def __init__(self, parts: Parts) -> None:
175+
self._parts = parts
176+
177+
self.create = to_streamed_response_wrapper(
178+
parts.create,
179+
)
180+
181+
182+
class AsyncPartsWithStreamingResponse:
183+
def __init__(self, parts: AsyncParts) -> None:
184+
self._parts = parts
185+
186+
self.create = async_to_streamed_response_wrapper(
187+
parts.create,
188+
)

0 commit comments

Comments
 (0)