Skip to content

[FEATURE] Support JSON schema for tool definitions #332

@gjtorikian

Description

@gjtorikian

Scope check

  • This is core LLM communication (not application logic)
  • This benefits most users (not just my use case)
  • This can't be solved in application code with current RubyLLM
  • I read the Contributing Guide

Due diligence

  • I searched existing issues
  • I checked the documentation

What problem does this solve?

Currently, defining tools with RubyLLM requires using a DSL. The DSL for defining parameters really only supports a handful of schema definitions: the name of the property, its type, and whether or not it's required.

I had the need to make a parameter include a default value, and while I could just add to the DSL, it would be more flexible to simply support JSON schemas, just like chatting with output schemas. Supporting JSON schema would resolve the issue of not providing default and allow for the full range of JSON schema properties (enums, min/max values, etc).

Furthermore, while initially investigating this, it seems like several providers each use their own function to format tooling.

Although each provider needs its own formatting, the logic between them often overlaps, making an additive change like this require updates in at least three places.

Proposed solution

First, I would consolidate the various tool assemblages into one module as much as possible.

For actually supporting the schema, I would introduce a function called with_schema, that takes a block whose return should be the schema you expect the tool to have. Something like:

class Weather < RubyLLM::Tool
  with_schema do
    {
      type: 'function',
      name: 'get_weather',
      description: 'Retrieves current weather for the given location.',
      parameters: {
        type: 'object',
        properties: {
          location: {
            type: 'string',
            description: 'City and country e.g. Bogotá, Colombia'
          },
          units: {
            type: 'string',
            enum: %w[
              celsius
              fahrenheit
            ],
            description: 'Units the temperature will be returned in.'
          }
        },
        required: %w[
          location
          units
        ],
        additionalProperties: false
      },
      strict: true
    }
  end

  def execute(latitude:, longitude:)
    # ...
  end
end

I don't mind doing this consolidation work and opening a PR! But I wouldn't take such an undertaking without prior approval. ✌️

Why this belongs in RubyLLM

Because calling tools with JSON schemas is a core feature of these APIs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions