Skip to content

Commit

Permalink
Example using dry-schema to produce JSON schema
Browse files Browse the repository at this point in the history
  • Loading branch information
drnic committed Apr 21, 2024
1 parent 437cd2a commit 5a83fe3
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 1 deletion.
29 changes: 29 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,33 @@ GEM
bigdecimal
rexml
drb (2.2.1)
dry-configurable (1.1.0)
dry-core (~> 1.0, < 2)
zeitwerk (~> 2.6)
dry-core (1.0.1)
concurrent-ruby (~> 1.0)
zeitwerk (~> 2.6)
dry-inflector (1.0.0)
dry-initializer (3.1.1)
dry-logic (1.5.0)
concurrent-ruby (~> 1.0)
dry-core (~> 1.0, < 2)
zeitwerk (~> 2.6)
dry-schema (1.13.3)
concurrent-ruby (~> 1.0)
dry-configurable (~> 1.0, >= 1.0.1)
dry-core (~> 1.0, < 2)
dry-initializer (~> 3.0)
dry-logic (>= 1.4, < 2)
dry-types (>= 1.7, < 2)
zeitwerk (~> 2.6)
dry-types (1.7.2)
bigdecimal (~> 3.0)
concurrent-ruby (~> 1.0)
dry-core (~> 1.0)
dry-inflector (~> 1.0)
dry-logic (~> 1.4)
zeitwerk (~> 2.6)
faraday (2.9.0)
faraday-net_http (>= 2.0, < 3.2)
faraday-net_http (3.1.0)
Expand Down Expand Up @@ -94,12 +121,14 @@ GEM
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
zeitwerk (2.6.13)

PLATFORMS
arm64-darwin-22
ruby

DEPENDENCIES
dry-schema (~> 1.13)
groq!
minitest (~> 5.16)
rake (~> 13.0)
Expand Down
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ end

The output might looks similar to:

```plain
> User message: Hello, world!
Assistant reply with model llama3-8b-8192:
Assistant reply with model llama3-70b-8192:
Expand Down Expand Up @@ -219,6 +220,33 @@ JSON.parse(response["content"])
# => {"number"=>7}
```

### Using dry-schema with JSON mode

As a bonus, the `S` or `System` helper can take a `json_schema:` argument and the system message will include the `JSON` keyword and the formatted schema in its content.

For example, if you're using [dry-schema](https://dry-rb.org/gems/dry-schema/1.13/extensions/json_schema/) with its `:json_schema` extension you can use Ruby to describe JSON schema.

```ruby
require "dry-schema"
Dry::Schema.load_extensions(:json_schema)

person_schema_defn = Dry::Schema.JSON do
required(:name).filled(:string)
optional(:age).filled(:integer)
optional(:email).filled(:string)
end
person_schema - person_schema_defn.json_schema

response = @client.chat([
S("You're excellent at extracting personal information", json_schema: person_schema),
U("I'm Dr Nic and I'm almost 50.")
], json: true)
JSON.parse(response["content"])
# => {"name"=>"Dr Nic", "age"=>49}
```

NOTE: `bin/console` already loads the `dry-schema` library and the `json_schema` extension because its handy.

### Tools/Functions

LLMs are increasingly supporting deferring to tools or functions to fetch data, perform calculations, or store structured data. Groq Cloud in turn then supports their tool implementations through its API.
Expand Down
3 changes: 3 additions & 0 deletions bin/console
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@ require "groq"
@client = Groq::Client.new
include Groq::Helpers

require "dry-schema"
Dry::Schema.load_extensions(:json_schema)

require "irb"
IRB.start(__FILE__)
1 change: 1 addition & 0 deletions groq.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ Gem::Specification.new do |spec|

spec.add_development_dependency "vcr", "~> 6.0"
spec.add_development_dependency "webmock", "~> 3.0"
spec.add_development_dependency "dry-schema", "~> 1.13"
end
5 changes: 4 additions & 1 deletion lib/groq/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ def A(content)
end
alias_method :Assistant, :A

def S(content)
def S(content, json_schema: nil)
if json_schema
content += "\nJSON must use schema: #{json_schema}"
end
{role: "system", content: content}
end
alias_method :System, :S
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions test/groq/test_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,30 @@ def test_json_mode
end
end

def test_json_mode_with_dry_schema
require "dry-schema"
Dry::Schema.load_extensions(:json_schema)

person_schema_defn = Dry::Schema.JSON do
required(:name).filled(:string)
optional(:age).filled(:integer)
optional(:email).filled(:string)
end
person_schema = person_schema_defn.json_schema

system_message = S("You're excellent at extracting personal information", json_schema: person_schema)

VCR.use_cassette("llama3-8b-8192/chat_json_mode_with_dry_schema") do
client = Groq::Client.new(model_id: "llama3-8b-8192")
response = client.chat([
system_message,
U("I'm Dr Nic and I'm almost 50.")
], json: true)
data = JSON.parse(response["content"])
assert_equal data, {"name" => "Dr Nic", "age" => 49}
end
end

def test_tools_weather_report
VCR.use_cassette("mixtral-8x7b-32768/chat_tools_weather_report") do
client = Groq::Client.new(model_id: "mixtral-8x7b-32768")
Expand Down

0 comments on commit 5a83fe3

Please sign in to comment.