Skip to content

crmne/ruby_llm-schema

Repository files navigation

RubyLLM::Schema

Gem Version Gem Downloads codecov Ruby Style Guide

A Ruby DSL for creating JSON schemas with a clean, Rails-inspired API.

Originally created by Daniel Friis.

Use Cases

JSON Schema is useful wherever Ruby code needs to describe structured data in a portable format.

Some ideal use cases:

  • Defining API request and response shapes
  • Describing configuration files or structured payloads
  • Sharing validation contracts across systems
  • Generating structured output schemas for LLM workflows
  • Defining structured parameters for RubyLLM tools

Simple Example

class PersonSchema < RubyLLM::Schema
  string :name, description: "Person's full name"
  number :age, description: "Age in years", minimum: 0, maximum: 120
  boolean :active, required: false

  object :address do
    string :street
    string :city
    string :country, required: false
  end

  array :tags, of: :string, description: "User tags"

  array :contacts do
    object do
      string :email, format: "email"
      string :phone, required: false
    end
  end

  any_of :status do
    string enum: ["active", "pending", "inactive"]
    null
  end
end

# Usage
schema = PersonSchema.new
puts schema.to_json

RubyLLM structured output

class PersonSchema < RubyLLM::Schema
  string :name, description: "Person's full name"
  integer :age, description: "Person's age in years"
  string :city, required: false, description: "City where they live"
end

# Use it natively with RubyLLM
chat     = RubyLLM.chat
response = chat.with_schema(PersonSchema)
               .ask("Generate a person named Alice who is 30 years old and lives in New York")

# The response is automatically parsed from JSON
puts response.content # => {"name" => "Alice", "age" => 30}
puts response.content.class # => Hash

RubyLLM tools

RubyLLM tools can use schema classes for structured parameters. This is useful when the same argument shape is shared across tools or elsewhere in your app.

class SearchParams < RubyLLM::Schema
  string :query, description: "Search query"
  integer :limit, required: false, description: "Maximum results"
end

class SearchDocuments < RubyLLM::Tool
  desc "Searches internal documents"
  params SearchParams

  def execute(query:, limit: 10)
    DocumentSearch.call(query:, limit:)
  end
end

For tool-specific parameters, define the schema inline with params do ... end.

class Weather < RubyLLM::Tool
  desc "Gets current weather"

  params do
    string :city, description: "City name"
    string :units, enum: %w[celsius fahrenheit], required: false
  end

  def execute(city:, units: "celsius")
    WeatherAPI.current(city:, units:)
  end
end

Installation

Add this line to your application's Gemfile:

gem 'ruby_llm-schema'

And then execute:

bundle install

Or install it yourself as:

gem install ruby_llm-schema

Usage

Three approaches for creating schemas:

Class Inheritance

class PersonSchema < RubyLLM::Schema
  string :name, description: "Person's full name"
  number :age
  boolean :active, required: false

  object :address do
    string :street
    string :city
  end

  array :tags, of: :string
end

schema = PersonSchema.new
puts schema.to_json

Factory Method

PersonSchema = RubyLLM::Schema.create do
  string :name, description: "Person's full name"
  number :age
  boolean :active, required: false

  object :address do
    string :street
    string :city
  end

  array :tags, of: :string
end

schema = PersonSchema.new
puts schema.to_json

Global Helper

require 'ruby_llm/schema'
include RubyLLM::Helpers

person_schema = schema "PersonData", description: "A person object" do
  string :name, description: "Person's full name"
  number :age
  boolean :active, required: false

  object :address do
    string :street
    string :city
  end

  array :tags, of: :string
end

puts person_schema.to_json

Schema Property Types

A schema is a collection of properties, which can be of different types. Each type has its own set of properties you can set.

All property types can (along with the required name key) be set with a description and a required flag (default is true).

string :name, description: "Person's full name"
number :age, description: "Person's age", required: false
boolean :is_active, description: "Whether the person is active"
null :placeholder, description: "A placeholder property"

⚠️ Please consult the LLM provider documentation for any limitations or restrictions. For example, as of now, OpenAI requires all properties to be required. In that case, you can use the any_of method to make a property optional.

any_of :name, description: "Person's full name" do
  string
  null
end

Strings

String types support the following properties:

  • enum: an array of allowed values (e.g. enum: ["on", "off"])
  • pattern: a regex pattern (e.g. pattern: "\\d+")
  • format: a format string (e.g. format: "email")
  • min_length: the minimum length of the string (e.g. min_length: 3)
  • max_length: the maximum length of the string (e.g. max_length: 10)

Please consult the LLM provider documentation for the available formats and patterns.

string :name, description: "Person's full name"
string :email, format: "email"
string :phone, pattern: "\\d+"
string :status, enum: ["on", "off"]
string :code, min_length: 3, max_length: 10

Numbers

Number types support the following properties:

  • multiple_of: a multiple of the number (e.g. multiple_of: 0.01)
  • minimum: the minimum value of the number (e.g. minimum: 0)
  • maximum: the maximum value of the number (e.g. maximum: 100)
number :price, minimum: 0, maximum: 100
number :amount, multiple_of: 0.01

Booleans

boolean :is_active

Boolean types doesn't support any additional properties.

Null

null :placeholder

Null types doesn't support any additional properties.

Arrays

An array is a list of items. You can set the type of the items in the array with the of option or by passing a block with the object method.

An array can have a min_items and max_items option to set the minimum and maximum number of items in the array.

array :tags, of: :string              # Array of strings
array :scores, of: :number            # Array of numbers
array :items, min_items: 1, max_items: 10  # Array with size constraints

array :items do                       # Array of objects
  object do
    string :name
    number :price
  end
end

Objects

Objects types expect a block with the properties of the object.

object :user do
  string :name
  number :age
end

object :settings, description: "User preferences" do
  boolean :notifications
  string :theme, enum: ["light", "dark"]
end

Union Types (anyOf)

Union types are a way to specify that a property can be one of several types.

any_of :value do
  string
  number
  null
end

any_of :identifier do
  string description: "Username"
  number description: "User ID"
end

Schema Definitions and References

You can define sub-schemas and reference them in other schemas, or reference the root schema to generate recursive schemas.

class MySchema < RubyLLM::Schema
  define :location do
    string :latitude
    string :longitude
  end

  # Using a reference in an array
  array :coordinates, of: :location

  # Using a reference in an object via the `reference` option
  object :home_location, reference: :location

  # Using a reference in an object via block
  object :user do
    reference :location
  end

  # Using a reference to the root schema
  object :ui_schema do
    string :element, enum: ["input", "button"]
    string :label
    object :sub_schema, reference: :root
  end
end

Nested Schemas

You can embed existing schema classes directly within objects or arrays for reusable schema composition.

class PersonSchema < RubyLLM::Schema
  string :name
  integer :age
end

class CompanySchema < RubyLLM::Schema
  # Using 'of' parameter
  object :ceo, of: PersonSchema
  array :employees, of: PersonSchema

  # Using Schema.new in block
  object :founder do
    PersonSchema.new
  end
end

schema = CompanySchema.new
schema.to_json_schema
# =>
# {
#    "name":"CompanySchema",
#    "description":"nil",
#    "schema":{
#       "type":"object",
#       "properties":{
#          "ceo":{
#             "type":"object",
#             "properties":{
#                "name":{
#                   "type":"string"
#                },
#                "age":{
#                   "type":"integer"
#                }
#             },
#             "required":[
#                :"name",
#                :"age"
#             ],
#             "additionalProperties":false
#          },
#          "employees":{
#             "type":"array",
#             "items":{
#                "type":"object",
#                "properties":{
#                   "name":{
#                      "type":"string"
#                   },
#                   "age":{
#                      "type":"integer"
#                   }
#                },
#                "required":[
#                   :"name",
#                   :"age"
#                ],
#                "additionalProperties":false
#             }
#          },
#          "founder":{
#             "type":"object",
#             "properties":{
#                "name":{
#                   "type":"string"
#                },
#                "age":{
#                   "type":"integer"
#                }
#             },
#             "required":[
#                :"name",
#                :"age"
#             ],
#             "additionalProperties":false
#          }
#       },
#       "required":[
#          :"ceo",
#          :"employees",
#          :"founder"
#       ],
#       "additionalProperties":false,
#       "strict":true
#    }
# }

JSON Output

schema = PersonSchema.new
schema.to_json_schema
# => {
#   name: "PersonSchema",
#   description: nil,
#   schema: {
#     type: "object",
#     properties: { ... },
#     required: [...],
#     additionalProperties: false,
#     strict: true
#   }
# }

puts schema.to_json  # Pretty JSON string

License

The gem is available as open source under the terms of the MIT License.

About

A simple and clean Ruby DSL for creating JSON schemas.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors