Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 38 additions & 13 deletions lib/ruby_llm/schema/dsl/schema_builders.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,62 @@ module RubyLLM
class Schema
module DSL
module SchemaBuilders
def string_schema(description: nil, enum: nil, min_length: nil, max_length: nil, pattern: nil, format: nil)
{
NOT_GIVEN = Object.new.freeze

def string_schema(description: nil, enum: nil, min_length: nil, max_length: nil, pattern: nil, **options)
format = options.delete(:format)
const = options.delete(:const) { NOT_GIVEN }
raise_unknown_options!("string", options)

add_const({
type: "string",
enum: enum,
description: description,
minLength: min_length,
maxLength: max_length,
pattern: pattern,
format: format
}.compact
}.compact, const)
end

def number_schema(description: nil, minimum: nil, maximum: nil, greater_than: nil, less_than: nil, multiple_of: nil)
{
def number_schema(description: nil, minimum: nil, maximum: nil, greater_than: nil, less_than: nil, **options)
multiple_of = options.delete(:multiple_of)
const = options.delete(:const) { NOT_GIVEN }
raise_unknown_options!("number", options)

add_const({
type: "number",
description: description,
minimum: minimum,
maximum: maximum,
exclusiveMinimum: greater_than,
exclusiveMaximum: less_than,
multipleOf: multiple_of
}.compact
}.compact, const)
end

def integer_schema(description: nil, minimum: nil, maximum: nil, greater_than: nil, less_than: nil, multiple_of: nil)
{
def integer_schema(description: nil, minimum: nil, maximum: nil, greater_than: nil, less_than: nil, **options)
multiple_of = options.delete(:multiple_of)
const = options.delete(:const) { NOT_GIVEN }
raise_unknown_options!("integer", options)

add_const({
type: "integer",
description: description,
minimum: minimum,
maximum: maximum,
exclusiveMinimum: greater_than,
exclusiveMaximum: less_than,
multipleOf: multiple_of
}.compact
}.compact, const)
end

def boolean_schema(description: nil)
{type: "boolean", description: description}.compact
def boolean_schema(description: nil, const: NOT_GIVEN)
add_const({type: "boolean", description: description}.compact, const)
end

def null_schema(description: nil)
{type: "null", description: description}.compact
def null_schema(description: nil, const: NOT_GIVEN)
add_const({type: "null", description: description}.compact, const)
end

def object_schema(description: nil, of: nil, reference: nil, &block)
Expand Down Expand Up @@ -113,6 +127,17 @@ def one_of_schema(description: nil, &block)

private

def add_const(schema, const)
schema[:const] = const unless const.equal?(NOT_GIVEN)
schema
end

def raise_unknown_options!(type, options)
return if options.empty?

raise ArgumentError, "unknown #{type} schema option: #{options.keys.first.inspect}"
end

def determine_array_items(of, &)
return collect_schemas_from_block(&).first if block_given?
return send("#{of}_schema") if primitive_type?(of)
Expand Down
7 changes: 7 additions & 0 deletions spec/ruby_llm/schema/properties/booleans_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,11 @@
properties = schema_class.properties
expect(properties[:enabled]).to eq({type: "boolean", description: "Enabled field"})
end

it "supports boolean const values" do
schema_class.boolean :enabled, const: false

properties = schema_class.properties
expect(properties[:enabled]).to eq({type: "boolean", const: false})
end
end
7 changes: 7 additions & 0 deletions spec/ruby_llm/schema/properties/null_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,11 @@
properties = schema_class.properties
expect(properties[:placeholder]).to eq({type: "null", description: "Null field"})
end

it "supports null const values" do
schema_class.null :deleted_at, const: nil

properties = schema_class.properties
expect(properties[:deleted_at]).to eq({type: "null", const: nil})
end
end
14 changes: 14 additions & 0 deletions spec/ruby_llm/schema/properties/numbers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@
})
end

it "supports number const values" do
schema_class.number :version, const: 1.5

properties = schema_class.properties
expect(properties[:version]).to eq({type: "number", const: 1.5})
end

it "supports number type with description" do
schema_class.number :price, description: "Price field"

Expand All @@ -53,4 +60,11 @@
exclusiveMaximum: 66
})
end

it "supports integer const values" do
schema_class.integer :version, const: 1

properties = schema_class.properties
expect(properties[:version]).to eq({type: "integer", const: 1})
end
end
7 changes: 7 additions & 0 deletions spec/ruby_llm/schema/properties/strings_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
})
end

it "supports string const values" do
schema_class.string :role, const: "admin"

properties = schema_class.properties
expect(properties[:role]).to eq({type: "string", const: "admin"})
end

it "supports string type with additional options" do
schema_class.string :email, format: "email", min_length: 5, max_length: 100, pattern: "\\S+@\\S+", description: "Email field"

Expand Down