Skip to content

Commit 886b828

Browse files
feat(api): Add Vision endpoint. (#220)
1 parent a06f969 commit 886b828

9 files changed

Lines changed: 442 additions & 2 deletions

File tree

.stats.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
configured_endpoints: 29
1+
configured_endpoints: 30
22
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/writerai%2Fwriter-57a138ff1e8940e627dd0108eb14c25bbeacd70e5f1106f8abd796cba6c51882.yml

api.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,15 @@ from writerai.types.tools import ComprehendMedicalResponse
181181
Methods:
182182

183183
- <code title="post /v1/tools/comprehend/medical">client.tools.comprehend.<a href="./src/writerai/resources/tools/comprehend.py">medical</a>(\*\*<a href="src/writerai/types/tools/comprehend_medical_params.py">params</a>) -> <a href="./src/writerai/types/tools/comprehend_medical_response.py">ComprehendMedicalResponse</a></code>
184+
185+
# Vision
186+
187+
Types:
188+
189+
```python
190+
from writerai.types import VisionRequest, VisionResponse
191+
```
192+
193+
Methods:
194+
195+
- <code title="post /v1/vision">client.vision.<a href="./src/writerai/resources/vision.py">analyze_images</a>(\*\*<a href="src/writerai/types/vision_analyze_images_params.py">params</a>) -> <a href="./src/writerai/types/vision_response.py">VisionResponse</a></code>

src/writerai/_client.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
get_async_library,
2525
)
2626
from ._version import __version__
27-
from .resources import chat, files, graphs, models, completions
27+
from .resources import chat, files, graphs, models, vision, completions
2828
from ._streaming import Stream as Stream, AsyncStream as AsyncStream
2929
from ._exceptions import WriterError, APIStatusError
3030
from ._base_client import (
@@ -46,6 +46,7 @@ class Writer(SyncAPIClient):
4646
graphs: graphs.GraphsResource
4747
files: files.FilesResource
4848
tools: tools.ToolsResource
49+
vision: vision.VisionResource
4950
with_raw_response: WriterWithRawResponse
5051
with_streaming_response: WriterWithStreamedResponse
5152

@@ -112,6 +113,7 @@ def __init__(
112113
self.graphs = graphs.GraphsResource(self)
113114
self.files = files.FilesResource(self)
114115
self.tools = tools.ToolsResource(self)
116+
self.vision = vision.VisionResource(self)
115117
self.with_raw_response = WriterWithRawResponse(self)
116118
self.with_streaming_response = WriterWithStreamedResponse(self)
117119

@@ -228,6 +230,7 @@ class AsyncWriter(AsyncAPIClient):
228230
graphs: graphs.AsyncGraphsResource
229231
files: files.AsyncFilesResource
230232
tools: tools.AsyncToolsResource
233+
vision: vision.AsyncVisionResource
231234
with_raw_response: AsyncWriterWithRawResponse
232235
with_streaming_response: AsyncWriterWithStreamedResponse
233236

@@ -294,6 +297,7 @@ def __init__(
294297
self.graphs = graphs.AsyncGraphsResource(self)
295298
self.files = files.AsyncFilesResource(self)
296299
self.tools = tools.AsyncToolsResource(self)
300+
self.vision = vision.AsyncVisionResource(self)
297301
self.with_raw_response = AsyncWriterWithRawResponse(self)
298302
self.with_streaming_response = AsyncWriterWithStreamedResponse(self)
299303

@@ -411,6 +415,7 @@ def __init__(self, client: Writer) -> None:
411415
self.graphs = graphs.GraphsResourceWithRawResponse(client.graphs)
412416
self.files = files.FilesResourceWithRawResponse(client.files)
413417
self.tools = tools.ToolsResourceWithRawResponse(client.tools)
418+
self.vision = vision.VisionResourceWithRawResponse(client.vision)
414419

415420

416421
class AsyncWriterWithRawResponse:
@@ -422,6 +427,7 @@ def __init__(self, client: AsyncWriter) -> None:
422427
self.graphs = graphs.AsyncGraphsResourceWithRawResponse(client.graphs)
423428
self.files = files.AsyncFilesResourceWithRawResponse(client.files)
424429
self.tools = tools.AsyncToolsResourceWithRawResponse(client.tools)
430+
self.vision = vision.AsyncVisionResourceWithRawResponse(client.vision)
425431

426432

427433
class WriterWithStreamedResponse:
@@ -433,6 +439,7 @@ def __init__(self, client: Writer) -> None:
433439
self.graphs = graphs.GraphsResourceWithStreamingResponse(client.graphs)
434440
self.files = files.FilesResourceWithStreamingResponse(client.files)
435441
self.tools = tools.ToolsResourceWithStreamingResponse(client.tools)
442+
self.vision = vision.VisionResourceWithStreamingResponse(client.vision)
436443

437444

438445
class AsyncWriterWithStreamedResponse:
@@ -444,6 +451,7 @@ def __init__(self, client: AsyncWriter) -> None:
444451
self.graphs = graphs.AsyncGraphsResourceWithStreamingResponse(client.graphs)
445452
self.files = files.AsyncFilesResourceWithStreamingResponse(client.files)
446453
self.tools = tools.AsyncToolsResourceWithStreamingResponse(client.tools)
454+
self.vision = vision.AsyncVisionResourceWithStreamingResponse(client.vision)
447455

448456

449457
Client = Writer

src/writerai/resources/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@
4040
ModelsResourceWithStreamingResponse,
4141
AsyncModelsResourceWithStreamingResponse,
4242
)
43+
from .vision import (
44+
VisionResource,
45+
AsyncVisionResource,
46+
VisionResourceWithRawResponse,
47+
AsyncVisionResourceWithRawResponse,
48+
VisionResourceWithStreamingResponse,
49+
AsyncVisionResourceWithStreamingResponse,
50+
)
4351
from .completions import (
4452
CompletionsResource,
4553
AsyncCompletionsResource,
@@ -100,4 +108,10 @@
100108
"AsyncToolsResourceWithRawResponse",
101109
"ToolsResourceWithStreamingResponse",
102110
"AsyncToolsResourceWithStreamingResponse",
111+
"VisionResource",
112+
"AsyncVisionResource",
113+
"VisionResourceWithRawResponse",
114+
"AsyncVisionResourceWithRawResponse",
115+
"VisionResourceWithStreamingResponse",
116+
"AsyncVisionResourceWithStreamingResponse",
103117
]

src/writerai/resources/vision.py

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
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 Iterable
6+
7+
import httpx
8+
9+
from ..types import vision_analyze_images_params
10+
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
11+
from .._utils import (
12+
maybe_transform,
13+
async_maybe_transform,
14+
)
15+
from .._compat import cached_property
16+
from .._resource import SyncAPIResource, AsyncAPIResource
17+
from .._response import (
18+
to_raw_response_wrapper,
19+
to_streamed_response_wrapper,
20+
async_to_raw_response_wrapper,
21+
async_to_streamed_response_wrapper,
22+
)
23+
from .._base_client import make_request_options
24+
from ..types.vision_response import VisionResponse
25+
26+
__all__ = ["VisionResource", "AsyncVisionResource"]
27+
28+
29+
class VisionResource(SyncAPIResource):
30+
@cached_property
31+
def with_raw_response(self) -> VisionResourceWithRawResponse:
32+
"""
33+
This property can be used as a prefix for any HTTP method call to return
34+
the raw response object instead of the parsed content.
35+
36+
For more information, see https://www.github.com/writer/writer-python#accessing-raw-response-data-eg-headers
37+
"""
38+
return VisionResourceWithRawResponse(self)
39+
40+
@cached_property
41+
def with_streaming_response(self) -> VisionResourceWithStreamingResponse:
42+
"""
43+
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
44+
45+
For more information, see https://www.github.com/writer/writer-python#with_streaming_response
46+
"""
47+
return VisionResourceWithStreamingResponse(self)
48+
49+
def analyze_images(
50+
self,
51+
*,
52+
model: str,
53+
prompt: str,
54+
variables: Iterable[vision_analyze_images_params.Variable],
55+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
56+
# The extra values given here take precedence over values defined on the client or passed to this method.
57+
extra_headers: Headers | None = None,
58+
extra_query: Query | None = None,
59+
extra_body: Body | None = None,
60+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
61+
) -> VisionResponse:
62+
"""
63+
Submit images and a prompt to generate an analysis of the images.
64+
65+
Args:
66+
model: The model to be used for image analysis. Currently only supports
67+
`palmyra-vision`.
68+
69+
prompt: The prompt to use for the image analysis. The prompt must include the name of
70+
each image variable, surrounded by double curly braces (`{{}}`). For example,
71+
`Describe the difference between the image {{image_1}} and the image {{image_2}}`.
72+
73+
extra_headers: Send extra headers
74+
75+
extra_query: Add additional query parameters to the request
76+
77+
extra_body: Add additional JSON properties to the request
78+
79+
timeout: Override the client-level default timeout for this request, in seconds
80+
"""
81+
return self._post(
82+
"/v1/vision",
83+
body=maybe_transform(
84+
{
85+
"model": model,
86+
"prompt": prompt,
87+
"variables": variables,
88+
},
89+
vision_analyze_images_params.VisionAnalyzeImagesParams,
90+
),
91+
options=make_request_options(
92+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
93+
),
94+
cast_to=VisionResponse,
95+
)
96+
97+
98+
class AsyncVisionResource(AsyncAPIResource):
99+
@cached_property
100+
def with_raw_response(self) -> AsyncVisionResourceWithRawResponse:
101+
"""
102+
This property can be used as a prefix for any HTTP method call to return
103+
the raw response object instead of the parsed content.
104+
105+
For more information, see https://www.github.com/writer/writer-python#accessing-raw-response-data-eg-headers
106+
"""
107+
return AsyncVisionResourceWithRawResponse(self)
108+
109+
@cached_property
110+
def with_streaming_response(self) -> AsyncVisionResourceWithStreamingResponse:
111+
"""
112+
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
113+
114+
For more information, see https://www.github.com/writer/writer-python#with_streaming_response
115+
"""
116+
return AsyncVisionResourceWithStreamingResponse(self)
117+
118+
async def analyze_images(
119+
self,
120+
*,
121+
model: str,
122+
prompt: str,
123+
variables: Iterable[vision_analyze_images_params.Variable],
124+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
125+
# The extra values given here take precedence over values defined on the client or passed to this method.
126+
extra_headers: Headers | None = None,
127+
extra_query: Query | None = None,
128+
extra_body: Body | None = None,
129+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
130+
) -> VisionResponse:
131+
"""
132+
Submit images and a prompt to generate an analysis of the images.
133+
134+
Args:
135+
model: The model to be used for image analysis. Currently only supports
136+
`palmyra-vision`.
137+
138+
prompt: The prompt to use for the image analysis. The prompt must include the name of
139+
each image variable, surrounded by double curly braces (`{{}}`). For example,
140+
`Describe the difference between the image {{image_1}} and the image {{image_2}}`.
141+
142+
extra_headers: Send extra headers
143+
144+
extra_query: Add additional query parameters to the request
145+
146+
extra_body: Add additional JSON properties to the request
147+
148+
timeout: Override the client-level default timeout for this request, in seconds
149+
"""
150+
return await self._post(
151+
"/v1/vision",
152+
body=await async_maybe_transform(
153+
{
154+
"model": model,
155+
"prompt": prompt,
156+
"variables": variables,
157+
},
158+
vision_analyze_images_params.VisionAnalyzeImagesParams,
159+
),
160+
options=make_request_options(
161+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
162+
),
163+
cast_to=VisionResponse,
164+
)
165+
166+
167+
class VisionResourceWithRawResponse:
168+
def __init__(self, vision: VisionResource) -> None:
169+
self._vision = vision
170+
171+
self.analyze_images = to_raw_response_wrapper(
172+
vision.analyze_images,
173+
)
174+
175+
176+
class AsyncVisionResourceWithRawResponse:
177+
def __init__(self, vision: AsyncVisionResource) -> None:
178+
self._vision = vision
179+
180+
self.analyze_images = async_to_raw_response_wrapper(
181+
vision.analyze_images,
182+
)
183+
184+
185+
class VisionResourceWithStreamingResponse:
186+
def __init__(self, vision: VisionResource) -> None:
187+
self._vision = vision
188+
189+
self.analyze_images = to_streamed_response_wrapper(
190+
vision.analyze_images,
191+
)
192+
193+
194+
class AsyncVisionResourceWithStreamingResponse:
195+
def __init__(self, vision: AsyncVisionResource) -> None:
196+
self._vision = vision
197+
198+
self.analyze_images = async_to_streamed_response_wrapper(
199+
vision.analyze_images,
200+
)

src/writerai/types/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from .question import Question as Question
2323
from .completion import Completion as Completion
2424
from .chat_completion import ChatCompletion as ChatCompletion
25+
from .vision_response import VisionResponse as VisionResponse
2526
from .chat_chat_params import ChatChatParams as ChatChatParams
2627
from .completion_chunk import CompletionChunk as CompletionChunk
2728
from .file_list_params import FileListParams as FileListParams
@@ -47,6 +48,7 @@
4748
from .tool_parse_pdf_response import ToolParsePdfResponse as ToolParsePdfResponse
4849
from .completion_create_params import CompletionCreateParams as CompletionCreateParams
4950
from .application_list_response import ApplicationListResponse as ApplicationListResponse
51+
from .vision_analyze_images_params import VisionAnalyzeImagesParams as VisionAnalyzeImagesParams
5052
from .application_retrieve_response import ApplicationRetrieveResponse as ApplicationRetrieveResponse
5153
from .graph_add_file_to_graph_params import GraphAddFileToGraphParams as GraphAddFileToGraphParams
5254
from .application_generate_content_chunk import ApplicationGenerateContentChunk as ApplicationGenerateContentChunk
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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 Iterable
6+
from typing_extensions import Required, TypedDict
7+
8+
__all__ = ["VisionAnalyzeImagesParams", "Variable"]
9+
10+
11+
class VisionAnalyzeImagesParams(TypedDict, total=False):
12+
model: Required[str]
13+
"""The model to be used for image analysis.
14+
15+
Currently only supports `palmyra-vision`.
16+
"""
17+
18+
prompt: Required[str]
19+
"""The prompt to use for the image analysis.
20+
21+
The prompt must include the name of each image variable, surrounded by double
22+
curly braces (`{{}}`). For example,
23+
`Describe the difference between the image {{image_1}} and the image {{image_2}}`.
24+
"""
25+
26+
variables: Required[Iterable[Variable]]
27+
28+
29+
class Variable(TypedDict, total=False):
30+
file_id: Required[str]
31+
"""The File ID of the image to be analyzed.
32+
33+
The file must be uploaded to the Writer platform before it can be used in a
34+
vision request.
35+
"""
36+
37+
name: Required[str]
38+
"""The name of the file variable.
39+
40+
You must reference this name in the prompt with double curly braces (`{{}}`).
41+
For example,
42+
`Describe the difference between the image {{image_1}} and the image {{image_2}}`.
43+
"""
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
4+
from .._models import BaseModel
5+
6+
__all__ = ["VisionResponse"]
7+
8+
9+
class VisionResponse(BaseModel):
10+
data: str
11+
"""The result of the image analysis."""

0 commit comments

Comments
 (0)