Skip to content

Commit 7212e61

Browse files
ms-jpqmeorphis
authored andcommitted
docs: structured outputs in README (#723)
1 parent eaa5055 commit 7212e61

5 files changed

+108
-0
lines changed

README.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,110 @@ puts(edited.data.first)
112112

113113
Note that you can also pass a raw `IO` descriptor, but this disables retries, as the library can't be sure if the descriptor is a file or pipe (which cannot be rewound).
114114

115+
### [Structured outputs](https://platform.openai.com/docs/guides/structured-outputs) and function calling
116+
117+
This SDK ships with helpers in `OpenAI::BaseModel`, `OpenAI::ArrayOf`, `OpenAI::EnumOf`, and `OpenAI::UnionOf` to help you define the supported JSON schemas used in making structured outputs and function calling requests.
118+
119+
<details>
120+
<summary>Snippet</summary>
121+
122+
```ruby
123+
# Participant model with an optional last_name and an enum for status
124+
class Participant < OpenAI::BaseModel
125+
required :first_name, String
126+
required :last_name, String, nil?: true
127+
required :status, OpenAI::EnumOf[:confirmed, :unconfirmed, :tentative]
128+
end
129+
130+
# CalendarEvent model with a list of participants.
131+
class CalendarEvent < OpenAI::BaseModel
132+
required :name, String
133+
required :date, String
134+
required :participants, OpenAI::ArrayOf[Participant]
135+
end
136+
137+
138+
client = OpenAI::Client.new
139+
140+
response = client.responses.create(
141+
model: "gpt-4o-2024-08-06",
142+
input: [
143+
{role: :system, content: "Extract the event information."},
144+
{
145+
role: :user,
146+
content: <<~CONTENT
147+
Alice Shah and Lena are going to a science fair on Friday at 123 Main St. in San Diego.
148+
They have also invited Jasper Vellani and Talia Groves - Jasper has not responded and Talia said she is thinking about it.
149+
CONTENT
150+
}
151+
],
152+
text: CalendarEvent
153+
)
154+
155+
response
156+
.output
157+
.flat_map { _1.content }
158+
# filter out refusal responses
159+
.grep_v(OpenAI::Models::Responses::ResponseOutputRefusal)
160+
.each do |content|
161+
# parsed is an instance of `CalendarEvent`
162+
pp(content.parsed)
163+
end
164+
```
165+
166+
</details>
167+
168+
See the [examples](https://github.com/openai/openai-ruby/tree/main/examples) directory for more usage examples for helper usage.
169+
170+
To make the equivalent request using raw JSON schema format, you would do the following:
171+
172+
<details>
173+
<summary>Snippet</summary>
174+
175+
```ruby
176+
response = client.responses.create(
177+
model: "gpt-4o-2024-08-06",
178+
input: [
179+
{role: :system, content: "Extract the event information."},
180+
{
181+
role: :user,
182+
content: "..."
183+
}
184+
],
185+
text: {
186+
format: {
187+
type: :json_schema,
188+
name: "CalendarEvent",
189+
strict: true,
190+
schema: {
191+
type: "object",
192+
properties: {
193+
name: {type: "string"},
194+
date: {type: "string"},
195+
participants: {
196+
type: "array",
197+
items: {
198+
type: "object",
199+
properties: {
200+
first_name: {type: "string"},
201+
last_name: {type: %w[string null]},
202+
status: {type: "string", enum: %w[confirmed unconfirmed tentative]}
203+
},
204+
required: %w[first_name last_name status],
205+
additionalProperties: false
206+
}
207+
}
208+
},
209+
required: %w[name date participants],
210+
additionalProperties: false
211+
}
212+
}
213+
}
214+
)
215+
```
216+
217+
</details>
218+
115219
### Handling errors
116220

117221
When the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `OpenAI::Errors::APIError` will be thrown:

examples/structured_outputs_chat_completions.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,6 @@ class CalendarEvent < OpenAI::BaseModel
5151
.choices
5252
.reject { _1.message.refusal }
5353
.each do |choice|
54+
# parsed is an instance of `CalendarEvent`
5455
pp(choice.message.parsed)
5556
end

examples/structured_outputs_chat_completions_function_calling.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,6 @@ class GetWeather < OpenAI::BaseModel
2727
.reject { _1.message.refusal }
2828
.flat_map { _1.message.tool_calls.to_a }
2929
.each do |tool_call|
30+
# parsed is an instance of `GetWeather`
3031
pp(tool_call.function.parsed)
3132
end

examples/structured_outputs_responses.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,6 @@ class CalendarEvent < OpenAI::BaseModel
5151
# filter out refusal responses
5252
.grep_v(OpenAI::Models::Responses::ResponseOutputRefusal)
5353
.each do |content|
54+
# parsed is an instance of `CalendarEvent`
5455
pp(content.parsed)
5556
end

examples/structured_outputs_responses_function_calling.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ class GetWeather < OpenAI::BaseModel
2424
response
2525
.output
2626
.each do |output|
27+
# parsed is an instance of `GetWeather`
2728
pp(output.parsed)
2829
end

0 commit comments

Comments
 (0)