ai-chat 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +35 -2
- data/lib/ai/chat/version.rb +1 -1
- data/lib/ai/chat.rb +29 -1
- data/test_program/test_ai_chat.rb +42 -0
- metadata +1 -2
- data/ai_chat.gemspec +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80aebb03e5962c921d6f5e47ee1521b760ffabe223869141eaa0b1d6b53514c0
|
4
|
+
data.tar.gz: 53fb9565b1e41a7bf5b93bd85cabe09af0be5028a163612bc440298aef4a01df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1216d345bb460a00a9baf6555fc60d1337ee2ac73590fb6ec8d5a0af839a7eca664dfc83f94f5b7f1898217ad67d8ecd314c911874d4affbbcc3d5f1d8ab3f75
|
7
|
+
data.tar.gz: a8bcf3c0f3edadfc6ba9398220214fd9c90c0bfa2ec9a4ad5c3f54c957b0a30a5c5d6df4beb36cfd8df86e2defd4117acd827c52387710e9246e6e8649e1ccfa
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.0.7] - 2025-04-25
|
4
|
+
|
5
|
+
- Added support for reasoning effort parameter (`reasoning_effort`) with the OpenAI Responses API
|
6
|
+
- Support for reasoning models like o3, o4-mini
|
7
|
+
- Updated documentation with examples
|
8
|
+
|
9
|
+
## [0.0.6] - 2025-04-25
|
10
|
+
|
11
|
+
- Fixed minor bugs
|
12
|
+
- Improved error handling
|
13
|
+
|
3
14
|
## [0.0.5] - 2025-04-25
|
4
15
|
|
5
16
|
- Updated to use OpenAI's Responses API instead of Chat Completions API
|
data/README.md
CHANGED
@@ -154,12 +154,45 @@ Useful if you are reconstructing a chat that has already happened.
|
|
154
154
|
- You can call `.messages` to get an array containing the conversation so far.
|
155
155
|
- TODO: Setting `.messages` will replace the conversation with the provided array.
|
156
156
|
|
157
|
+
## Testing with Real API Calls
|
158
|
+
|
159
|
+
While this gem includes specs, they use mocked API responses. To test with real API calls:
|
160
|
+
|
161
|
+
1. Navigate to the test program directory: `cd test_program`
|
162
|
+
2. Create a `.env` file in the test_program directory with your API credentials:
|
163
|
+
```
|
164
|
+
# Your OpenAI API key
|
165
|
+
OPENAI_API_KEY=your_openai_api_key_here
|
166
|
+
```
|
167
|
+
3. Install dependencies: `bundle install`
|
168
|
+
4. Run the test program: `ruby test_ai_chat.rb`
|
169
|
+
|
170
|
+
This test program runs through all the major features of the gem, making real API calls to OpenAI.
|
171
|
+
|
172
|
+
## Reasoning Effort
|
173
|
+
|
174
|
+
When using reasoning models like `o3` or `o4-mini`, you can specify a reasoning effort level to control how much reasoning the model does before producing its final response:
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
x = AI::Chat.new
|
178
|
+
x.model = "o4-mini"
|
179
|
+
x.reasoning_effort = "medium" # Can be "low", "medium", or "high"
|
180
|
+
|
181
|
+
x.user("Write a bash script that transposes a matrix represented as '[1,2],[3,4],[5,6]'")
|
182
|
+
x.assistant!
|
183
|
+
```
|
184
|
+
|
185
|
+
The `reasoning_effort` parameter guides the model on how many reasoning tokens to generate before creating a response to the prompt. Options are:
|
186
|
+
- `"low"`: Favors speed and economical token usage
|
187
|
+
- `"medium"`: (Default) Balances speed and reasoning accuracy
|
188
|
+
- `"high"`: Favors more complete reasoning
|
189
|
+
|
190
|
+
Setting to `nil` disables the reasoning parameter.
|
191
|
+
|
157
192
|
## TODOs
|
158
193
|
|
159
|
-
- Add a `reasoning_effort` parameter.
|
160
194
|
- Add the ability to set all messages at once, ideally with an ActiveRecord Relation.
|
161
195
|
- Add a way to access the whole API response body (rather than just the message content).
|
162
|
-
- Add specs.
|
163
196
|
|
164
197
|
## Contributing
|
165
198
|
|
data/lib/ai/chat/version.rb
CHANGED
data/lib/ai/chat.rb
CHANGED
@@ -5,11 +5,31 @@
|
|
5
5
|
module AI
|
6
6
|
class Chat
|
7
7
|
attr_accessor :messages, :schema, :model
|
8
|
+
attr_reader :reasoning_effort
|
9
|
+
|
10
|
+
VALID_REASONING_EFFORTS = [:low, :medium, :high].freeze
|
8
11
|
|
9
12
|
def initialize(api_key: nil)
|
10
13
|
@api_key = api_key || ENV.fetch("OPENAI_API_KEY")
|
11
14
|
@messages = []
|
12
15
|
@model = "gpt-4.1-mini"
|
16
|
+
@reasoning_effort = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def reasoning_effort=(value)
|
20
|
+
if value.nil?
|
21
|
+
@reasoning_effort = nil
|
22
|
+
else
|
23
|
+
# Convert string to symbol if needed
|
24
|
+
symbol_value = value.is_a?(String) ? value.to_sym : value
|
25
|
+
|
26
|
+
if VALID_REASONING_EFFORTS.include?(symbol_value)
|
27
|
+
@reasoning_effort = symbol_value
|
28
|
+
else
|
29
|
+
valid_values = VALID_REASONING_EFFORTS.map { |v| ":#{v} or \"#{v}\"" }.join(", ")
|
30
|
+
raise ArgumentError, "Invalid reasoning_effort value: '#{value}'. Must be one of: #{valid_values}"
|
31
|
+
end
|
32
|
+
end
|
13
33
|
end
|
14
34
|
|
15
35
|
def system(content)
|
@@ -99,6 +119,14 @@ module AI
|
|
99
119
|
"input" => messages
|
100
120
|
}
|
101
121
|
|
122
|
+
# Add reasoning parameter if specified
|
123
|
+
if !@reasoning_effort.nil?
|
124
|
+
# Convert symbol back to string for the API request
|
125
|
+
request_body_hash["reasoning"] = {
|
126
|
+
"effort" => @reasoning_effort.to_s
|
127
|
+
}
|
128
|
+
end
|
129
|
+
|
102
130
|
# Handle structured output (JSON schema)
|
103
131
|
if !schema.nil?
|
104
132
|
# Parse the schema and use it with Structured Output (json_schema)
|
@@ -172,7 +200,7 @@ module AI
|
|
172
200
|
end
|
173
201
|
|
174
202
|
def inspect
|
175
|
-
"#<#{self.class.name} @messages=#{messages.inspect} @model=#{@model.inspect} @schema=#{@schema.inspect}>"
|
203
|
+
"#<#{self.class.name} @messages=#{messages.inspect} @model=#{@model.inspect} @schema=#{@schema.inspect} @reasoning_effort=#{@reasoning_effort.inspect}>"
|
176
204
|
end
|
177
205
|
|
178
206
|
private
|
@@ -112,4 +112,46 @@ a.user("Tell me a joke.")
|
|
112
112
|
response = a.assistant!
|
113
113
|
puts "Assistant response after manual message: #{response}"
|
114
114
|
|
115
|
+
# Reasoning Effort Test
|
116
|
+
puts "\nReasoning Effort Test:"
|
117
|
+
puts "---------------------"
|
118
|
+
begin
|
119
|
+
r = AI::Chat.new
|
120
|
+
r.model = "o4-mini" # Use a reasoning model
|
121
|
+
r.reasoning_effort = "medium"
|
122
|
+
r.user("Write a short bash script that counts the number of unique words in a text file.")
|
123
|
+
response = r.assistant!
|
124
|
+
puts "Response with reasoning effort 'medium': #{response}"
|
125
|
+
rescue => e
|
126
|
+
puts "Reasoning effort test error: #{e.message}"
|
127
|
+
end
|
128
|
+
|
129
|
+
# Reasoning Effort Validation Test
|
130
|
+
puts "\nReasoning Effort Validation Test:"
|
131
|
+
puts "-------------------------------"
|
132
|
+
begin
|
133
|
+
r = AI::Chat.new
|
134
|
+
puts "Setting valid reasoning effort string 'low'..."
|
135
|
+
r.reasoning_effort = "low"
|
136
|
+
puts "Success: reasoning_effort = #{r.reasoning_effort}"
|
137
|
+
|
138
|
+
puts "Setting valid reasoning effort symbol :medium..."
|
139
|
+
r.reasoning_effort = :medium
|
140
|
+
puts "Success: reasoning_effort = #{r.reasoning_effort}"
|
141
|
+
|
142
|
+
puts "Setting valid reasoning effort string 'high'..."
|
143
|
+
r.reasoning_effort = "high"
|
144
|
+
puts "Success: reasoning_effort = #{r.reasoning_effort}"
|
145
|
+
|
146
|
+
puts "Setting nil reasoning effort..."
|
147
|
+
r.reasoning_effort = nil
|
148
|
+
puts "Success: reasoning_effort = #{r.reasoning_effort}"
|
149
|
+
|
150
|
+
puts "Setting invalid reasoning effort 'extreme'..."
|
151
|
+
r.reasoning_effort = "extreme"
|
152
|
+
puts "This line should not be reached"
|
153
|
+
rescue ArgumentError => e
|
154
|
+
puts "Expected error caught: #{e.message}"
|
155
|
+
end
|
156
|
+
|
115
157
|
puts "\nTests completed!"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ai-chat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Raghu Betina
|
@@ -141,7 +141,6 @@ files:
|
|
141
141
|
- LICENSE.txt
|
142
142
|
- README.md
|
143
143
|
- Rakefile
|
144
|
-
- ai_chat.gemspec
|
145
144
|
- lib/ai-chat.rb
|
146
145
|
- lib/ai/chat.rb
|
147
146
|
- lib/ai/chat/version.rb
|
data/ai_chat.gemspec
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "lib/ai/chat/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |spec|
|
6
|
-
spec.name = "ai-chat"
|
7
|
-
spec.version = AI::Chat::VERSION
|
8
|
-
spec.authors = ["Raghu Betina", "Jelani Woods"]
|
9
|
-
spec.email = ["raghu@firstdraft.com", "jelani@firstdraft.com"]
|
10
|
-
|
11
|
-
spec.summary = "This gem provides a class called `AI::Chat` that is intended to make it as easy as possible to use OpenAI's Responses API."
|
12
|
-
spec.description = "This gem provides a class called `AI::Chat` that is intended to make it as easy as possible to use OpenAI's Responses API. Supports Structured Output and Image Processing."
|
13
|
-
spec.homepage = "https://github.com/firstdraft/ai-chat"
|
14
|
-
spec.license = "MIT"
|
15
|
-
spec.required_ruby_version = ">= 2.0.0"
|
16
|
-
|
17
|
-
# spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
18
|
-
|
19
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
20
|
-
spec.metadata["source_code_uri"] = "https://github.com/firstdraft/ai-chat"
|
21
|
-
spec.metadata["changelog_uri"] = "https://github.com/firstdraft/ai-chat/blob/main/CHANGELOG.md"
|
22
|
-
|
23
|
-
# Specify which files should be added to the gem when it is released.
|
24
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
-
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
|
-
`git ls-files -z`.split("\x0").reject do |f|
|
27
|
-
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(git|travis|circleci)|appveyor)})
|
28
|
-
end
|
29
|
-
end
|
30
|
-
spec.bindir = "exe"
|
31
|
-
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
32
|
-
spec.require_paths = ["lib"]
|
33
|
-
|
34
|
-
# Register dependencies of the gem
|
35
|
-
spec.add_runtime_dependency "mime-types", "~> 3.0"
|
36
|
-
spec.add_runtime_dependency "base64" # Works for all Ruby versions
|
37
|
-
|
38
|
-
# Development dependencies
|
39
|
-
spec.add_development_dependency "rake", "~> 13.0"
|
40
|
-
spec.add_development_dependency "rspec", "~> 3.12"
|
41
|
-
spec.add_development_dependency "factory_bot", "~> 6.2"
|
42
|
-
spec.add_development_dependency "webmock", "~> 3.18"
|
43
|
-
spec.add_development_dependency "vcr", "~> 6.1"
|
44
|
-
spec.add_development_dependency "standard", "~> 1.32"
|
45
|
-
|
46
|
-
# For more information and examples about making a new gem, check out our
|
47
|
-
# guide at: https://bundler.io/guides/creating_gem.html
|
48
|
-
end
|