Skip to content

Commit d510ae0

Browse files
feat(api): manual updates
force readme update
1 parent c5bc3ca commit d510ae0

File tree

3 files changed

+186
-38
lines changed

3 files changed

+186
-38
lines changed

.stats.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 76
22
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/digitalocean%2Fgradientai-e8b3cbc80e18e4f7f277010349f25e1319156704f359911dc464cc21a0d077a6.yml
33
openapi_spec_hash: c773d792724f5647ae25a5ae4ccec208
4-
config_hash: 651ae9b93d723d383facbf979fd97fee
4+
config_hash: 67ce33bbbf8698b50194d8da5fd009d6

README.md

Lines changed: 84 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,50 @@ async def main() -> None:
120120
asyncio.run(main())
121121
```
122122

123+
## Streaming responses
124+
125+
We provide support for streaming responses using Server Side Events (SSE).
126+
127+
```python
128+
from gradientai import GradientAI
129+
130+
client = GradientAI()
131+
132+
stream = client.chat.completions.create(
133+
messages=[
134+
{
135+
"role": "user",
136+
"content": "What is the capital of France?",
137+
}
138+
],
139+
model="llama3.3-70b-instruct",
140+
stream=True,
141+
)
142+
for completion in stream:
143+
print(completion.choices)
144+
```
145+
146+
The async client uses the exact same interface.
147+
148+
```python
149+
from gradientai import AsyncGradientAI
150+
151+
client = AsyncGradientAI()
152+
153+
stream = await client.chat.completions.create(
154+
messages=[
155+
{
156+
"role": "user",
157+
"content": "What is the capital of France?",
158+
}
159+
],
160+
model="llama3.3-70b-instruct",
161+
stream=True,
162+
)
163+
async for completion in stream:
164+
print(completion.choices)
165+
```
166+
123167
## Using types
124168

125169
Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:
@@ -167,8 +211,14 @@ from gradientai import GradientAI
167211
client = GradientAI()
168212

169213
try:
170-
client.agents.versions.list(
171-
uuid="REPLACE_ME",
214+
client.chat.completions.create(
215+
messages=[
216+
{
217+
"role": "user",
218+
"content": "What is the capital of France?",
219+
}
220+
],
221+
model="llama3.3-70b-instruct",
172222
)
173223
except gradientai.APIConnectionError as e:
174224
print("The server could not be reached")
@@ -212,8 +262,14 @@ client = GradientAI(
212262
)
213263

214264
# Or, configure per-request:
215-
client.with_options(max_retries=5).agents.versions.list(
216-
uuid="REPLACE_ME",
265+
client.with_options(max_retries=5).chat.completions.create(
266+
messages=[
267+
{
268+
"role": "user",
269+
"content": "What is the capital of France?",
270+
}
271+
],
272+
model="llama3.3-70b-instruct",
217273
)
218274
```
219275

@@ -237,8 +293,14 @@ client = GradientAI(
237293
)
238294

239295
# Override per-request:
240-
client.with_options(timeout=5.0).agents.versions.list(
241-
uuid="REPLACE_ME",
296+
client.with_options(timeout=5.0).chat.completions.create(
297+
messages=[
298+
{
299+
"role": "user",
300+
"content": "What is the capital of France?",
301+
}
302+
],
303+
model="llama3.3-70b-instruct",
242304
)
243305
```
244306

@@ -280,13 +342,17 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to
280342
from gradientai import GradientAI
281343

282344
client = GradientAI()
283-
response = client.agents.versions.with_raw_response.list(
284-
uuid="REPLACE_ME",
345+
response = client.chat.completions.with_raw_response.create(
346+
messages=[{
347+
"role": "user",
348+
"content": "What is the capital of France?",
349+
}],
350+
model="llama3.3-70b-instruct",
285351
)
286352
print(response.headers.get('X-My-Header'))
287353

288-
version = response.parse() # get the object that `agents.versions.list()` would have returned
289-
print(version.agent_versions)
354+
completion = response.parse() # get the object that `chat.completions.create()` would have returned
355+
print(completion.choices)
290356
```
291357

292358
These methods return an [`APIResponse`](https://github.com/digitalocean/gradientai-python/tree/main/src/gradientai/_response.py) object.
@@ -300,8 +366,14 @@ The above interface eagerly reads the full response body when you make the reque
300366
To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.
301367

302368
```python
303-
with client.agents.versions.with_streaming_response.list(
304-
uuid="REPLACE_ME",
369+
with client.chat.completions.with_streaming_response.create(
370+
messages=[
371+
{
372+
"role": "user",
373+
"content": "What is the capital of France?",
374+
}
375+
],
376+
model="llama3.3-70b-instruct",
305377
) as response:
306378
print(response.headers.get("X-My-Header"))
307379

tests/test_client.py

Lines changed: 101 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -819,20 +819,36 @@ def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str
819819
@mock.patch("gradientai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
820820
@pytest.mark.respx(base_url=base_url)
821821
def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, client: GradientAI) -> None:
822-
respx_mock.get("/v2/gen-ai/agents/uuid/versions").mock(side_effect=httpx.TimeoutException("Test timeout error"))
822+
respx_mock.post("/chat/completions").mock(side_effect=httpx.TimeoutException("Test timeout error"))
823823

824824
with pytest.raises(APITimeoutError):
825-
client.agents.versions.with_streaming_response.list(uuid="uuid").__enter__()
825+
client.chat.completions.with_streaming_response.create(
826+
messages=[
827+
{
828+
"content": "string",
829+
"role": "system",
830+
}
831+
],
832+
model="llama3-8b-instruct",
833+
).__enter__()
826834

827835
assert _get_open_connections(self.client) == 0
828836

829837
@mock.patch("gradientai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
830838
@pytest.mark.respx(base_url=base_url)
831839
def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client: GradientAI) -> None:
832-
respx_mock.get("/v2/gen-ai/agents/uuid/versions").mock(return_value=httpx.Response(500))
840+
respx_mock.post("/chat/completions").mock(return_value=httpx.Response(500))
833841

834842
with pytest.raises(APIStatusError):
835-
client.agents.versions.with_streaming_response.list(uuid="uuid").__enter__()
843+
client.chat.completions.with_streaming_response.create(
844+
messages=[
845+
{
846+
"content": "string",
847+
"role": "system",
848+
}
849+
],
850+
model="llama3-8b-instruct",
851+
).__enter__()
836852
assert _get_open_connections(self.client) == 0
837853

838854
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -859,9 +875,17 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
859875
return httpx.Response(500)
860876
return httpx.Response(200)
861877

862-
respx_mock.get("/v2/gen-ai/agents/uuid/versions").mock(side_effect=retry_handler)
878+
respx_mock.post("/chat/completions").mock(side_effect=retry_handler)
863879

864-
response = client.agents.versions.with_raw_response.list(uuid="uuid")
880+
response = client.chat.completions.with_raw_response.create(
881+
messages=[
882+
{
883+
"content": "string",
884+
"role": "system",
885+
}
886+
],
887+
model="llama3-8b-instruct",
888+
)
865889

866890
assert response.retries_taken == failures_before_success
867891
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -883,10 +907,17 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
883907
return httpx.Response(500)
884908
return httpx.Response(200)
885909

886-
respx_mock.get("/v2/gen-ai/agents/uuid/versions").mock(side_effect=retry_handler)
910+
respx_mock.post("/chat/completions").mock(side_effect=retry_handler)
887911

888-
response = client.agents.versions.with_raw_response.list(
889-
uuid="uuid", extra_headers={"x-stainless-retry-count": Omit()}
912+
response = client.chat.completions.with_raw_response.create(
913+
messages=[
914+
{
915+
"content": "string",
916+
"role": "system",
917+
}
918+
],
919+
model="llama3-8b-instruct",
920+
extra_headers={"x-stainless-retry-count": Omit()},
890921
)
891922

892923
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -908,10 +939,17 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
908939
return httpx.Response(500)
909940
return httpx.Response(200)
910941

911-
respx_mock.get("/v2/gen-ai/agents/uuid/versions").mock(side_effect=retry_handler)
942+
respx_mock.post("/chat/completions").mock(side_effect=retry_handler)
912943

913-
response = client.agents.versions.with_raw_response.list(
914-
uuid="uuid", extra_headers={"x-stainless-retry-count": "42"}
944+
response = client.chat.completions.with_raw_response.create(
945+
messages=[
946+
{
947+
"content": "string",
948+
"role": "system",
949+
}
950+
],
951+
model="llama3-8b-instruct",
952+
extra_headers={"x-stainless-retry-count": "42"},
915953
)
916954

917955
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
@@ -1734,10 +1772,18 @@ async def test_parse_retry_after_header(self, remaining_retries: int, retry_afte
17341772
async def test_retrying_timeout_errors_doesnt_leak(
17351773
self, respx_mock: MockRouter, async_client: AsyncGradientAI
17361774
) -> None:
1737-
respx_mock.get("/v2/gen-ai/agents/uuid/versions").mock(side_effect=httpx.TimeoutException("Test timeout error"))
1775+
respx_mock.post("/chat/completions").mock(side_effect=httpx.TimeoutException("Test timeout error"))
17381776

17391777
with pytest.raises(APITimeoutError):
1740-
await async_client.agents.versions.with_streaming_response.list(uuid="uuid").__aenter__()
1778+
await async_client.chat.completions.with_streaming_response.create(
1779+
messages=[
1780+
{
1781+
"content": "string",
1782+
"role": "system",
1783+
}
1784+
],
1785+
model="llama3-8b-instruct",
1786+
).__aenter__()
17411787

17421788
assert _get_open_connections(self.client) == 0
17431789

@@ -1746,10 +1792,18 @@ async def test_retrying_timeout_errors_doesnt_leak(
17461792
async def test_retrying_status_errors_doesnt_leak(
17471793
self, respx_mock: MockRouter, async_client: AsyncGradientAI
17481794
) -> None:
1749-
respx_mock.get("/v2/gen-ai/agents/uuid/versions").mock(return_value=httpx.Response(500))
1795+
respx_mock.post("/chat/completions").mock(return_value=httpx.Response(500))
17501796

17511797
with pytest.raises(APIStatusError):
1752-
await async_client.agents.versions.with_streaming_response.list(uuid="uuid").__aenter__()
1798+
await async_client.chat.completions.with_streaming_response.create(
1799+
messages=[
1800+
{
1801+
"content": "string",
1802+
"role": "system",
1803+
}
1804+
],
1805+
model="llama3-8b-instruct",
1806+
).__aenter__()
17531807
assert _get_open_connections(self.client) == 0
17541808

17551809
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -1777,9 +1831,17 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
17771831
return httpx.Response(500)
17781832
return httpx.Response(200)
17791833

1780-
respx_mock.get("/v2/gen-ai/agents/uuid/versions").mock(side_effect=retry_handler)
1834+
respx_mock.post("/chat/completions").mock(side_effect=retry_handler)
17811835

1782-
response = await client.agents.versions.with_raw_response.list(uuid="uuid")
1836+
response = await client.chat.completions.with_raw_response.create(
1837+
messages=[
1838+
{
1839+
"content": "string",
1840+
"role": "system",
1841+
}
1842+
],
1843+
model="llama3-8b-instruct",
1844+
)
17831845

17841846
assert response.retries_taken == failures_before_success
17851847
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -1802,10 +1864,17 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
18021864
return httpx.Response(500)
18031865
return httpx.Response(200)
18041866

1805-
respx_mock.get("/v2/gen-ai/agents/uuid/versions").mock(side_effect=retry_handler)
1867+
respx_mock.post("/chat/completions").mock(side_effect=retry_handler)
18061868

1807-
response = await client.agents.versions.with_raw_response.list(
1808-
uuid="uuid", extra_headers={"x-stainless-retry-count": Omit()}
1869+
response = await client.chat.completions.with_raw_response.create(
1870+
messages=[
1871+
{
1872+
"content": "string",
1873+
"role": "system",
1874+
}
1875+
],
1876+
model="llama3-8b-instruct",
1877+
extra_headers={"x-stainless-retry-count": Omit()},
18091878
)
18101879

18111880
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -1828,10 +1897,17 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
18281897
return httpx.Response(500)
18291898
return httpx.Response(200)
18301899

1831-
respx_mock.get("/v2/gen-ai/agents/uuid/versions").mock(side_effect=retry_handler)
1832-
1833-
response = await client.agents.versions.with_raw_response.list(
1834-
uuid="uuid", extra_headers={"x-stainless-retry-count": "42"}
1900+
respx_mock.post("/chat/completions").mock(side_effect=retry_handler)
1901+
1902+
response = await client.chat.completions.with_raw_response.create(
1903+
messages=[
1904+
{
1905+
"content": "string",
1906+
"role": "system",
1907+
}
1908+
],
1909+
model="llama3-8b-instruct",
1910+
extra_headers={"x-stainless-retry-count": "42"},
18351911
)
18361912

18371913
assert response.http_request.headers.get("x-stainless-retry-count") == "42"

0 commit comments

Comments
 (0)