ReqLLM.Schema (ReqLLM v1.0.0-rc.3)

View Source

Single schema authority for NimbleOptions ↔ JSON Schema conversion.

This module consolidates all schema conversion logic, providing unified functions for converting keyword schemas to both NimbleOptions compiled schemas and JSON Schema format. Supports all common NimbleOptions types and handles nested schemas.

Core Functions

  • compile/1 - Convert keyword schema to NimbleOptions compiled schema
  • to_json/1 - Convert keyword schema to JSON Schema format

Basic Usage

# Compile keyword schema to NimbleOptions
{:ok, compiled} = ReqLLM.Schema.compile([
  name: [type: :string, required: true, doc: "User name"],
  age: [type: :pos_integer, doc: "User age"]
])

# Convert keyword schema to JSON Schema
json_schema = ReqLLM.Schema.to_json([
  name: [type: :string, required: true, doc: "User name"], 
  age: [type: :pos_integer, doc: "User age"]
])
# => %{
#      "type" => "object",
#      "properties" => %{
#        "name" => %{"type" => "string", "description" => "User name"},
#        "age" => %{"type" => "integer", "minimum" => 1, "description" => "User age"}
#      },
#      "required" => ["name"]
#    }

Supported Types

All common NimbleOptions types are supported:

  • :string - String type
  • :integer - Integer type
  • :pos_integer - Positive integer (adds minimum: 1 constraint)
  • :float - Float/number type
  • :number - Generic number type
  • :boolean - Boolean type
  • {:list, type} - Array of specified type
  • :map - Object type
  • Custom types fall back to string

Nested Schemas

Nested schemas are supported through recursive type handling:

schema = [
  user: [
    type: {:list, :map},
    doc: "List of user objects",
    properties: [
      name: [type: :string, required: true],
      email: [type: :string, required: true]
    ]
  ]
]

Summary

Functions

Compiles a keyword schema to a NimbleOptions compiled schema.

Converts a NimbleOptions type to JSON Schema property definition.

Format a tool into Anthropic tool schema format.

Format a tool into Google tool schema format.

Converts a keyword schema to JSON Schema format.

Format a tool into OpenAI tool schema format.

Validate data against a keyword schema.

Functions

compile(schema)

@spec compile(keyword() | any()) ::
  {:ok, NimbleOptions.t()} | {:error, ReqLLM.Error.t()}

Compiles a keyword schema to a NimbleOptions compiled schema.

Takes a keyword list representing a NimbleOptions schema and compiles it into a validated NimbleOptions schema that can be used for validation.

Parameters

  • schema - A keyword list representing a NimbleOptions schema

Returns

  • {:ok, compiled_schema} - Successfully compiled NimbleOptions schema
  • {:error, error} - Compilation error with details

Examples

iex> ReqLLM.Schema.compile([
...>   name: [type: :string, required: true],
...>   age: [type: :pos_integer, default: 0]
...> ])
{:ok, compiled_schema}

iex> ReqLLM.Schema.compile("invalid")
{:error, %ReqLLM.Error.Invalid.Parameter{}}

nimble_type_to_json_schema(type, opts)

@spec nimble_type_to_json_schema(
  atom() | tuple(),
  keyword()
) :: map()

Converts a NimbleOptions type to JSON Schema property definition.

Takes a NimbleOptions type atom and options, converting them to the corresponding JSON Schema property definition with proper type mapping.

Parameters

  • type - The NimbleOptions type atom (e.g., :string, :integer, {:list, :string})
  • opts - Additional options including :doc for description

Returns

A map representing the JSON Schema property definition.

Examples

iex> ReqLLM.Schema.nimble_type_to_json_schema(:string, doc: "A text field")
%{"type" => "string", "description" => "A text field"}

iex> ReqLLM.Schema.nimble_type_to_json_schema({:list, :integer}, [])
%{"type" => "array", "items" => %{"type" => "integer"}}

iex> ReqLLM.Schema.nimble_type_to_json_schema(:pos_integer, doc: "Positive number")
%{"type" => "integer", "minimum" => 1, "description" => "Positive number"}

to_anthropic_format(tool)

@spec to_anthropic_format(ReqLLM.Tool.t()) :: map()

Format a tool into Anthropic tool schema format.

Parameters

  • tool - A ReqLLM.Tool.t() struct

Returns

A map containing the Anthropic tool schema format.

Examples

iex> tool = %ReqLLM.Tool{
...>   name: "get_weather",
...>   description: "Get current weather",
...>   parameter_schema: [
...>     location: [type: :string, required: true, doc: "City name"]
...>   ],
...>   callback: fn _ -> {:ok, %{}} end
...> }
iex> ReqLLM.Schema.to_anthropic_format(tool)
%{
  "name" => "get_weather",
  "description" => "Get current weather",
  "input_schema" => %{
    "type" => "object",
    "properties" => %{
      "location" => %{"type" => "string", "description" => "City name"}
    },
    "required" => ["location"]
  }
}

to_google_format(tool)

@spec to_google_format(ReqLLM.Tool.t()) :: map()

Format a tool into Google tool schema format.

Parameters

  • tool - A ReqLLM.Tool.t() struct

Returns

A map containing the Google tool schema format.

Examples

iex> tool = %ReqLLM.Tool{
...>   name: "get_weather",
...>   description: "Get current weather",
...>   parameter_schema: [
...>     location: [type: :string, required: true, doc: "City name"]
...>   ],
...>   callback: fn _ -> {:ok, %{}} end
...> }
iex> ReqLLM.Schema.to_google_format(tool)
%{
  "name" => "get_weather",
  "description" => "Get current weather",
  "parameters" => %{
    "type" => "object",
    "properties" => %{
      "location" => %{"type" => "string", "description" => "City name"}
    },
    "required" => ["location"]
  }
}

to_json(schema)

@spec to_json(keyword()) :: map()

Converts a keyword schema to JSON Schema format.

Takes a keyword list of parameter definitions and converts them to a JSON Schema object suitable for LLM tool definitions or structured data schemas.

Parameters

  • schema - Keyword list of parameter definitions

Returns

A map representing the JSON Schema object with properties and required fields.

Examples

iex> ReqLLM.Schema.to_json([
...>   name: [type: :string, required: true, doc: "User name"],
...>   age: [type: :integer, doc: "User age"],
...>   tags: [type: {:list, :string}, default: [], doc: "User tags"]
...> ])
%{
  "type" => "object",
  "properties" => %{
    "name" => %{"type" => "string", "description" => "User name"},
    "age" => %{"type" => "integer", "description" => "User age"},
    "tags" => %{
      "type" => "array", 
      "items" => %{"type" => "string"}, 
      "description" => "User tags"
    }
  },
  "required" => ["name"]
}

iex> ReqLLM.Schema.to_json([])
%{"type" => "object", "properties" => %{}}

to_openai_format(tool)

@spec to_openai_format(ReqLLM.Tool.t()) :: map()

Format a tool into OpenAI tool schema format.

Parameters

  • tool - A ReqLLM.Tool.t() struct

Returns

A map containing the OpenAI tool schema format.

Examples

iex> tool = %ReqLLM.Tool{
...>   name: "get_weather",
...>   description: "Get current weather",
...>   parameter_schema: [
...>     location: [type: :string, required: true, doc: "City name"]
...>   ],
...>   callback: fn _ -> {:ok, %{}} end
...> }
iex> ReqLLM.Schema.to_openai_format(tool)
%{
  "type" => "function",
  "function" => %{
    "name" => "get_weather",
    "description" => "Get current weather",
    "parameters" => %{
      "type" => "object",
      "properties" => %{
        "location" => %{"type" => "string", "description" => "City name"}
      },
      "required" => ["location"]
    }
  }
}

validate(data, schema)

@spec validate(
  map(),
  keyword()
) :: {:ok, keyword()} | {:error, ReqLLM.Error.t()}

Validate data against a keyword schema.

Takes a data map and validates it against a NimbleOptions-style keyword schema. The data is first converted to keyword format for NimbleOptions validation.

Parameters

  • data - Map of data to validate
  • schema - Keyword schema definition

Returns

  • {:ok, validated_data} - Successfully validated data
  • {:error, error} - Validation error with details

Examples

iex> schema = [name: [type: :string, required: true], age: [type: :integer]]
iex> data = %{"name" => "Alice", "age" => 30}
iex> ReqLLM.Schema.validate(data, schema)
{:ok, [name: "Alice", age: 30]}

iex> schema = [name: [type: :string, required: true]]  
iex> data = %{"age" => 30}
iex> ReqLLM.Schema.validate(data, schema)
{:error, %ReqLLM.Error.Validation.Error{...}}