Skip to main content

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.
1

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
2

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
)
3

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

Input Format

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)

Build docs developers (and LLMs) love