Skip to content

Commit 8db93ce

Browse files
committed
Support verbosity
1 parent d307cb5 commit 8db93ce

4 files changed

Lines changed: 129 additions & 1 deletion

File tree

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,15 @@ The `reasoning_effort` parameter guides the model on how many reasoning tokens t
671671

672672
By default, `reasoning_effort` is `nil`, which means no reasoning parameter is sent to the API. For `gpt-5.2` (the default model), this is equivalent to `"none"` reasoning.
673673

674+
## Verbosity
675+
676+
Verbosity determines how many output tokens are generated. Lowering the number of tokens reduces overall latency. While the model's reasoning approach stays mostly the same, the model finds ways to answer more concisely—which can either improve or diminish answer quality, depending on your use case. Here are some scenarios for both ends of the verbosity spectrum:
677+
678+
- High verbosity: Use when you need the model to provide thorough explanations of documents or perform extensive code refactoring.
679+
- Low verbosity: Best for situations where you want concise answers or simple code generation, such as SQL queries.
680+
681+
The supported values are `:high`, `:medium`, or `:low`. The default value is `:medium` for `gpt-5.2`. **Older models (like `gpt-4.1-nano`) only support `:medium`**.
682+
674683
## Advanced: Response Details
675684

676685
When you call `generate!` (or later call `get_response` in background mode), the gem stores additional information about the API response:

examples/17_verbosity.rb

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env ruby
2+
3+
require_relative "../lib/ai-chat"
4+
require "dotenv"
5+
Dotenv.load(File.expand_path("../.env", __dir__))
6+
require "amazing_print"
7+
8+
puts "\n=== AI::Chat Verbosity Tests ==="
9+
puts
10+
11+
puts "1. Supports verbosity = :low"
12+
puts "-" * 30
13+
chat1 = AI::Chat.new
14+
chat1.verbosity = :low
15+
chat1.user("How high do planes typically fly?")
16+
response = chat1.generate![:content]
17+
puts response
18+
puts
19+
puts "Total characters: #{response.length}"
20+
puts
21+
22+
puts "2. Supports verbosity = :medium"
23+
puts "-" * 30
24+
chat2 = AI::Chat.new
25+
chat2.verbosity = :medium
26+
chat2.user("How high do planes typically fly?")
27+
response = chat2.generate![:content]
28+
puts response
29+
puts
30+
puts "Total characters: #{response.length}"
31+
puts
32+
33+
puts "3. Supports verbosity = :high"
34+
puts "-" * 30
35+
chat3 = AI::Chat.new
36+
chat3.verbosity = :medium
37+
chat3.user("How high do planes typically fly?")
38+
response = chat3.generate![:content]
39+
puts response
40+
puts
41+
puts "Total characters: #{response.length}"
42+
puts
43+
44+
puts "4. Raises error for unsupported verbosity values"
45+
puts "-" * 30
46+
chat4 = AI::Chat.new
47+
chat4.user("How high do planes typically fly?")
48+
begin
49+
chat4.verbosity = :extreme
50+
puts "✗ Failed to raise ArgumentError for invalid verbosity: #{chat4.verbosity}"
51+
rescue ArgumentError => e
52+
puts "✓ Raises Argument error correctly: #{e.message}"
53+
end
54+
puts
55+
56+
puts
57+
puts "5. Supports verbosity with Structured Outputs"
58+
puts "-" * 30
59+
path = "my_schemas/test.json"
60+
File.delete(path) if File.exist?(path)
61+
AI::Chat.generate_schema!("A user with full name (required), first_name (required), last_name (required), coolness_level (score between 0-10 representing how cool the user sounds), coolness_reasoning (the explanation of the coolness_leve)", location: path, api_key: ENV["OPENAI_API_KEY"])
62+
63+
chat5 = AI::Chat.new
64+
chat5.verbosity = :low
65+
chat5.schema_file = path
66+
chat5.system("Extract the profile information from the user message. Describe it like a 90's robot.")
67+
chat5.user("My name is Bryan. I like to skateboard and be cool. I'm seventeen and a quarter. You can reach me at bryan@example.com.")
68+
puts chat5.last[:content]
69+
puts
70+
begin
71+
response = chat5.generate![:content]
72+
puts "✓ Generates structured output response with verbosity"
73+
rescue => e
74+
puts "✗ Failed to generate structured output response with verbosity: #{e.message}"
75+
end
76+
puts
77+
78+
puts "6. Supports verbosity = :medium for gpt-4.1-nano"
79+
puts "-" * 30
80+
chat6 = AI::Chat.new
81+
chat6.model = "gpt-4.1-nano"
82+
chat6.verbosity = :medium
83+
chat6.user("How high do planes typically fly?")
84+
response = chat6.generate![:content]
85+
puts response
86+
puts
87+
puts "Total characters: #{response.length}"
88+
puts
89+
90+
puts "7. Fails verbosity = :low for gpt-4.1-nano"
91+
puts "-" * 30
92+
chat7 = AI::Chat.new
93+
chat7.model = "gpt-4.1-nano"
94+
chat7.verbosity = :low
95+
chat7.user("How high do planes typically fly?")
96+
begin
97+
response = chat7.generate![:content]
98+
puts "✗ Failed to raise error when setting :low verbosity on unsupported model."
99+
rescue OpenAI::Errors::BadRequestError => e
100+
puts "✓ Successfully raises error on for unsupported verbosity for older model: #{e.message}"
101+
end
102+
puts

examples/all.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,9 @@
5353

5454
# Proxy
5555
require_relative "15_proxy"
56+
57+
# Get items
58+
require_relative "16_get_items"
59+
60+
# Verbosity
61+
require_relative "17_verbosity"

lib/ai/chat.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module AI
1919
class Chat
2020
# :reek:Attribute
2121
attr_accessor :background, :code_interpreter, :conversation_id, :image_generation, :image_folder, :messages, :model, :reasoning_effort, :web_search
22-
attr_reader :client, :last_response_id, :proxy, :schema, :schema_file
22+
attr_reader :client, :last_response_id, :proxy, :schema, :schema_file, :verbosity
2323

2424
BASE_PROXY_URL = "https://prepend.me/api.openai.com/v1"
2525

@@ -34,6 +34,7 @@ def initialize(api_key: nil, api_key_env_var: "OPENAI_API_KEY")
3434
@image_generation = false
3535
@image_folder = "./images"
3636
@api_key_validated = false
37+
@verbosity = "medium"
3738
end
3839

3940
def self.generate_schema!(description, location: "schema.json", api_key: nil, api_key_env_var: "OPENAI_API_KEY", proxy: false)
@@ -183,6 +184,14 @@ def schema_file=(path)
183184
self.schema = content
184185
end
185186

187+
def verbosity=(value)
188+
if ["low", "medium", "high"].include?(value.to_s)
189+
@verbosity = value.to_sym
190+
else
191+
raise ArgumentError, "Invalid verbosity value:'#{value}'. Must be one of :low, :medium, :high."
192+
end
193+
end
194+
186195
def last
187196
messages.last
188197
end
@@ -221,6 +230,7 @@ def inspectable_attributes
221230
attrs << [:@web_search, @web_search] if @web_search
222231
attrs << [:@schema, @schema] if @schema
223232
attrs << [:@schema_file, @schema_file] if @schema_file
233+
attrs << [:@verbosity, verbosity] if verbosity
224234

225235
attrs
226236
end
@@ -274,6 +284,7 @@ def create_response
274284

275285
create_conversation unless conversation_id
276286
parameters[:conversation] = conversation_id
287+
parameters[:text] = (parameters[:text] || {}).merge(verbosity: verbosity) if verbosity
277288

278289
messages_to_send = prepare_messages_for_api
279290
parameters[:input] = strip_responses(messages_to_send) unless messages_to_send.empty?

0 commit comments

Comments
 (0)