EasyTalk
EasyTalk is a Ruby library that simplifies defining and generating JSON Schema documents, and validates that JSON data conforms to these schemas.
Key Features
- Intuitive Schema Definition: Use Ruby classes and methods to define JSON Schema documents easily.
- JSON Schema Compliance: Implements the JSON Schema specification to ensure compatibility and standards adherence.
- LLM Function Support: Ideal for integrating with Large Language Models (LLMs) such as OpenAI's GPT-3.5-turbo and GPT-4. EasyTalk enables you to effortlessly create JSON Schema documents needed to describe the inputs and outputs of LLM function calls.
- Validation: Validates JSON inputs and outputs against defined schemas to ensure they meet expected formats and types. Write custom validations using ActiveModel's validations.
- Integration with ActiveModel: EasyTalk integrates with ActiveModel to provide additional functionality such as attribute assignment, introspections, validations, translation (i18n), and more.
Inspiration Inspired by Python's Pydantic library, EasyTalk brings similar functionality to the Ruby ecosystem, providing a Ruby-friendly approach to JSON Schema operations.
Example Use:
class User
include EasyTalk::Model
define_schema do
title "User"
description "A user of the system"
property :name, String, description: "The user's name", title: "Full Name"
property :email, :object do
property :address, String, format: "email", description: "The user's email", title: "Email Address"
property :verified, T::Boolean, description: "Whether the email is verified"
end
property :group, String, enum: [1, 2, 3], default: 1, description: "The user's group"
property :age, Integer, minimum: 18, maximum: 100, description: "The user's age"
property :tags, T::Array[String], min_items: 1, unique_item: true, description: "The user's tags"
end
end
Calling User.json_schema
will return the JSON Schema for the User class:
{
"title": "User",
"description": "A user of the system",
"type": "object",
"properties": {
"name": {
"title": "Full Name",
"description": "The user's name",
"type": "string"
},
"email": {
"type": "object",
"properties": {
"address": {
"title": "Email Address",
"description": "The user's email",
"type": "string",
"format": "email"
},
"verified": {
"type": "boolean",
"description": "Whether the email is verified"
}
},
"required": [
"address",
"verified"
]
},
"group": {
"type": "number",
"enum": [1, 2, 3],
"default": 1,
"description": "The user's group"
},
"age": {
"type": "integer",
"minimum": 18,
"maximum": 100,
"description": "The user's age"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true,
"description": "The user's tags"
}
},
"required:": [
"name",
"email",
"group",
"age",
"tags"
]
}
Installation
install the gem by running the following command in your terminal:
$ gem install easy_talk
Usage
Simply include the EasyTalk::Model
module in your Ruby class, define the schema using the define_schema
block and call the json_schema
class method to generate the JSON Schema document.
Schema Definition
In the example above, the define_schema
method is used to add a description and a title to the schema document. The property
method is used to define the properties of the schema document. The property
method accepts the name of the property as a symbol, the type, which can be a generic Ruby type or a Sorbet type, and a hash of constraints as options.
Property Constraints
Property constraints are type-dependent. Refer to the CONSTRAINTS.md file for a list of constraints supported by the JSON Schema generator.
Schema Composition
EasyTalk supports schema composition. You can define a schema for a nested object by defining a new class and including the EasyTalk::Model
module. You can then reference the nested schema in the parent schema using the following special types:
- T::OneOf[Model1, Model2, ...] - The property must match at least one of the specified schemas.
- T::AnyOf[Model1, Model2, ...] - The property can match any of the specified schemas.
- T::AllOf[Model1, Model2, ...] - The property must match all of the specified schemas.
Here is an example where we define a schema for a payment object that can be a credit card, a PayPal account, or a bank transfer. The first three classes represent the schemas for the different payment methods. The Payment
class represents the schema for the payment object where the Details
property can be any of the payment method schemas.
class CreditCard
include EasyTalk::Model
define_schema do
property :CardNumber, String
property :CardType, String, enum: %w[Visa MasterCard AmericanExpress]
property :CardExpMonth, Integer, minimum: 1, maximum: 12
property :CardExpYear, Integer, minimum: Date.today.year, maximum: Date.today.year + 10
property :CardCVV, String, pattern: '^[0-9]{3,4}$'
additional_properties false
end
end
class Paypal
include EasyTalk::Model
define_schema do
property :PaypalEmail, String, format: 'email'
property :PaypalPasswordEncrypted, String
additional_properties false
end
end
class BankTransfer
include EasyTalk::Model
define_schema do
property :BankName, String
property :AccountNumber, String
property :RoutingNumber, String
property :AccountType, String, enum: %w[Checking Savings]
additional_properties false
end
end
class Payment
include EasyTalk::Model
define_schema do
title 'Payment'
description 'Payment info'
property :PaymentMethod, String, enum: %w[CreditCard Paypal BankTransfer]
property :Details, T::AnyOf[CreditCard, Paypal, BankTransfer]
end
end
Type Checking and Schema Constraints
EasyTalk uses Sorbet to perform type checking on the property constraint values. The property
method accepts a type as the second argument. The type can be a Ruby class or a Sorbet type. For example, String
, Integer
, T::Array[String]
, etc.
EasyTalk raises an error if the constraint values do not match the property type. For example, if you specify the enum
constraint with the values [1,2,3], but the property type is String
, EasyTalk will raise a type error.
EasyTalk also raises an error if the constraints are not valid for the property type. For example, if you define a property with a minimum
or a maximum
constraint, but the type is String
, EasyTalk will raise an error.
Schema Validation
EasyTalk does not yet perform JSON validation. So far, it only aims to generate a valid JSON Schema document. You can use the json_schema
method to generate the JSON Schema and use a JSON Schema validator library like JSONSchemer to validate JSON against. See https://json-schema.org/implementations#validators-ruby for a list of JSON Schema validator libraries for Ruby.
The goal is to introduce JSON validation in the near future.
JSON Schema Specifications
EasyTalk is currently very loose about JSON Schema specifications. It does not enforce the use of the latest JSON Schema specifications. Support for the dictionary of JSON Schema keywords varies depending on the keyword. The goal is to have robust support for the latest JSON Schema specifications in the near future.
To learn about the current EasyTalk capabilities, take a look at the spec/easy_talk/examples folder. The examples are used to test the JSON Schema generation.
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and the created tag, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/sergiobayona/easy_talk.
License
The gem is available as open source under the terms of the MIT License.