Overview
The Responses API provides a simpler way to interact with OpenAI models by directly creating structured responses without managing chat completions. This approach is ideal for extracting structured data or working with function calling.
Basic Response Creation
The most straightforward way to use the Responses API is with the responses.create method. This example demonstrates extracting structured calendar event information from natural language text.
Define your data models
Create Ruby classes that inherit from OpenAI::BaseModel to define the structure of your expected output:class Location < OpenAI::BaseModel
required :address, String
required :city, String, doc: "City name"
required :postal_code, String, nil?: true
end
class Participant < OpenAI::BaseModel
required :first_name, String
required :last_name, String, nil?: true
required :status, OpenAI::EnumOf[:confirmed, :unconfirmed, :tentative]
end
class CalendarEvent < OpenAI::BaseModel
required :name, String
required :date, String
required :participants, OpenAI::ArrayOf[Participant]
required :optional_participants, OpenAI::ArrayOf[Participant, doc: "who might not show up"], nil?: true
required :is_virtual, OpenAI::Boolean
required :location,
OpenAI::UnionOf[String, Location],
nil?: true,
doc: "Event location"
end
Create a response with structured output
Pass your model class to the text parameter to get structured responses:client = OpenAI::Client.new
response = client.responses.create(
model: "gpt-4o-2024-08-06",
input: [
{role: :system, content: "Extract the event information."},
{
role: :user,
content: <<~CONTENT
Alice Shah and Lena are going to a science fair on Friday at 123 Main St. in San Diego.
They have also invited Jasper Vellani and Talia Groves - Jasper has not responded and Talia said she is thinking about it.
CONTENT
}
],
text: CalendarEvent
)
Access the parsed output
The response automatically parses the output into instances of your model classes:response
.output
.flat_map { _1.content }
# filter out refusal responses
.grep_v(OpenAI::Models::Responses::ResponseOutputRefusal)
.each do |content|
# parsed is an instance of `CalendarEvent`
pp(content.parsed)
end
Complete Example
#!/usr/bin/env ruby
# frozen_string_literal: true
require_relative "../lib/openai"
class Location < OpenAI::BaseModel
required :address, String
required :city, String, doc: "City name"
required :postal_code, String, nil?: true
end
# Participant model with an optional last_name and an enum for status
class Participant < OpenAI::BaseModel
required :first_name, String
required :last_name, String, nil?: true
required :status, OpenAI::EnumOf[:confirmed, :unconfirmed, :tentative]
end
# CalendarEvent model with a list of participants.
class CalendarEvent < OpenAI::BaseModel
required :name, String
required :date, String
required :participants, OpenAI::ArrayOf[Participant]
required :optional_participants, OpenAI::ArrayOf[Participant, doc: "who might not show up"], nil?: true
required :is_virtual, OpenAI::Boolean
required :location,
OpenAI::UnionOf[String, Location],
nil?: true,
doc: "Event location"
end
client = OpenAI::Client.new
response = client.responses.create(
model: "gpt-4o-2024-08-06",
input: [
{role: :system, content: "Extract the event information."},
{
role: :user,
content: <<~CONTENT
Alice Shah and Lena are going to a science fair on Friday at 123 Main St. in San Diego.
They have also invited Jasper Vellani and Talia Groves - Jasper has not responded and Talia said she is thinking about it.
CONTENT
}
],
text: CalendarEvent
)
response
.output
.flat_map { _1.content }
# filter out refusal responses
.grep_v(OpenAI::Models::Responses::ResponseOutputRefusal)
.each do |content|
# parsed is an instance of `CalendarEvent`
pp(content.parsed)
end
Key Concepts
BaseModel Classes
OpenAI::BaseModel is the foundation for defining structured outputs. Use the required method to define fields with their types:
- Simple types:
String, Integer, OpenAI::Boolean
- Enums:
OpenAI::EnumOf[:value1, :value2]
- Arrays:
OpenAI::ArrayOf[Type]
- Unions:
OpenAI::UnionOf[Type1, Type2] for fields that can be multiple types
- Nullable fields: Add
nil?: true to allow nil values
- Documentation: Add
doc: "description" to provide field descriptions
The input parameter accepts either:
- A simple string for single-turn interactions
- An array of message objects with
role and content for multi-turn conversations
The Responses API automatically handles the structured output format, so you don’t need to manually specify JSON schemas or response formats.
Filtering Refusals
Always filter out ResponseOutputRefusal objects when processing outputs to handle cases where the model refuses to generate content:
.grep_v(OpenAI::Models::Responses::ResponseOutputRefusal)