ai-chat 0.6.0 → 0.7.0
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/README.md +306 -672
- data/ai-chat.gemspec +3 -3
- data/lib/ai/chat.rb +42 -8
- metadata +5 -5
data/ai-chat.gemspec
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |spec|
|
|
4
4
|
spec.name = "ai-chat"
|
|
5
|
-
spec.version = "0.
|
|
5
|
+
spec.version = "0.7.0"
|
|
6
6
|
spec.authors = ["Raghu Betina", "Jelani Woods"]
|
|
7
7
|
spec.email = ["raghu@firstdraft.com", "jelani@firstdraft.com"]
|
|
8
8
|
spec.homepage = "https://github.com/firstdraft/ai-chat"
|
|
@@ -18,8 +18,8 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
"source_code_uri" => "https://github.com/firstdraft/ai-chat"
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
spec.required_ruby_version = ">= 3.
|
|
22
|
-
spec.add_runtime_dependency "openai", "~> 0.
|
|
21
|
+
spec.required_ruby_version = ">= 3.3"
|
|
22
|
+
spec.add_runtime_dependency "openai", "~> 0.80"
|
|
23
23
|
spec.add_runtime_dependency "marcel", "~> 1.0"
|
|
24
24
|
spec.add_runtime_dependency "base64", "~> 0.1", "> 0.1.1"
|
|
25
25
|
spec.add_runtime_dependency "json", "~> 2.0"
|
data/lib/ai/chat.rb
CHANGED
|
@@ -18,8 +18,8 @@ module AI
|
|
|
18
18
|
# :reek:IrresponsibleModule
|
|
19
19
|
class Chat
|
|
20
20
|
# :reek:Attribute
|
|
21
|
-
attr_accessor :background, :code_interpreter, :conversation_id, :
|
|
22
|
-
attr_reader :client, :last_response_id, :proxy, :schema, :schema_file, :verbosity
|
|
21
|
+
attr_accessor :background, :code_interpreter, :conversation_id, :image_folder, :messages, :model, :reasoning_effort, :web_search
|
|
22
|
+
attr_reader :client, :image_generation, :last_response_id, :proxy, :schema, :schema_file, :verbosity
|
|
23
23
|
|
|
24
24
|
BASE_PROXY_URL = "https://prepend.me/api.openai.com/v1"
|
|
25
25
|
PROXY_ENV = "AICHAT_PROXY"
|
|
@@ -32,8 +32,8 @@ module AI
|
|
|
32
32
|
@proxy = proxy.nil? ? ENV[PROXY_ENV]&.downcase == "true" : !!proxy
|
|
33
33
|
@api_key = resolve_api_key
|
|
34
34
|
@messages = []
|
|
35
|
-
@reasoning_effort =
|
|
36
|
-
@model = "gpt-5.
|
|
35
|
+
@reasoning_effort = "none"
|
|
36
|
+
@model = "gpt-5.6-terra"
|
|
37
37
|
client_options = {api_key: @api_key}
|
|
38
38
|
client_options[:base_url] = BASE_PROXY_URL if @proxy
|
|
39
39
|
@client = OpenAI::Client.new(**client_options)
|
|
@@ -57,7 +57,7 @@ module AI
|
|
|
57
57
|
|
|
58
58
|
client = OpenAI::Client.new(**options)
|
|
59
59
|
response = client.responses.create(
|
|
60
|
-
model: "gpt-5.
|
|
60
|
+
model: "gpt-5.6-terra",
|
|
61
61
|
input: [
|
|
62
62
|
{role: :system, content: system_prompt},
|
|
63
63
|
{role: :user, content: description}
|
|
@@ -205,6 +205,19 @@ module AI
|
|
|
205
205
|
end
|
|
206
206
|
end
|
|
207
207
|
|
|
208
|
+
def image_generation=(value)
|
|
209
|
+
case value
|
|
210
|
+
when true
|
|
211
|
+
@image_generation = true
|
|
212
|
+
when false, nil
|
|
213
|
+
@image_generation = false
|
|
214
|
+
when Hash
|
|
215
|
+
@image_generation = value.transform_keys(&:to_sym)
|
|
216
|
+
else
|
|
217
|
+
raise ArgumentError, "Invalid image_generation value: #{value.inspect}. Must be true, false, or a Hash of tool options (e.g., { size: \"1536x1024\", quality: \"low\" })."
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
208
221
|
def last
|
|
209
222
|
messages.last
|
|
210
223
|
end
|
|
@@ -294,6 +307,13 @@ module AI
|
|
|
294
307
|
end
|
|
295
308
|
end
|
|
296
309
|
|
|
310
|
+
# Reasoning summaries are only meaningful when the model actually reasons.
|
|
311
|
+
def reasoning_parameters
|
|
312
|
+
params = {effort: reasoning_effort}
|
|
313
|
+
params[:summary] = "auto" unless reasoning_effort.to_s == "none"
|
|
314
|
+
params
|
|
315
|
+
end
|
|
316
|
+
|
|
297
317
|
def create_conversation
|
|
298
318
|
conversation = client.conversations.create
|
|
299
319
|
self.conversation_id = conversation.id
|
|
@@ -308,7 +328,7 @@ module AI
|
|
|
308
328
|
parameters[:background] = background if background
|
|
309
329
|
parameters[:tools] = tools unless tools.empty?
|
|
310
330
|
parameters[:text] = schema if schema
|
|
311
|
-
parameters[:reasoning] =
|
|
331
|
+
parameters[:reasoning] = reasoning_parameters if reasoning_effort
|
|
312
332
|
|
|
313
333
|
create_conversation unless conversation_id
|
|
314
334
|
parameters[:conversation] = conversation_id
|
|
@@ -523,7 +543,8 @@ module AI
|
|
|
523
543
|
tools_list << {type: "web_search"}
|
|
524
544
|
end
|
|
525
545
|
if image_generation
|
|
526
|
-
|
|
546
|
+
options = image_generation.is_a?(Hash) ? image_generation : {}
|
|
547
|
+
tools_list << options.merge(type: "image_generation")
|
|
527
548
|
end
|
|
528
549
|
if code_interpreter
|
|
529
550
|
tools_list << {type: "code_interpreter", container: {type: "auto"}}
|
|
@@ -577,7 +598,8 @@ module AI
|
|
|
577
598
|
result = output.result
|
|
578
599
|
image_data = Base64.strict_decode64(result)
|
|
579
600
|
|
|
580
|
-
|
|
601
|
+
extension = image_extension_for(image_data)
|
|
602
|
+
filename = "#{(index + 1).to_s.rjust(3, "0")}.#{extension}"
|
|
581
603
|
file_path = File.join(subfolder_path, filename)
|
|
582
604
|
|
|
583
605
|
File.binwrite(file_path, image_data)
|
|
@@ -589,6 +611,18 @@ module AI
|
|
|
589
611
|
image_filenames
|
|
590
612
|
end
|
|
591
613
|
|
|
614
|
+
IMAGE_EXTENSIONS_BY_MIME_TYPE = {
|
|
615
|
+
"image/png" => "png",
|
|
616
|
+
"image/jpeg" => "jpg",
|
|
617
|
+
"image/webp" => "webp"
|
|
618
|
+
}.freeze
|
|
619
|
+
|
|
620
|
+
# :reek:UtilityFunction
|
|
621
|
+
def image_extension_for(bytes)
|
|
622
|
+
mime_type = Marcel::MimeType.for(StringIO.new(bytes))
|
|
623
|
+
IMAGE_EXTENSIONS_BY_MIME_TYPE.fetch(mime_type, "png")
|
|
624
|
+
end
|
|
625
|
+
|
|
592
626
|
def create_images_folder(response_id)
|
|
593
627
|
# ISO 8601 basic format with centisecond precision
|
|
594
628
|
timestamp = Time.now.strftime("%Y%m%dT%H%M%S%2N")
|
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.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Raghu Betina
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0.
|
|
19
|
+
version: '0.80'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '0.
|
|
26
|
+
version: '0.80'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: marcel
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -149,14 +149,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
149
149
|
requirements:
|
|
150
150
|
- - ">="
|
|
151
151
|
- !ruby/object:Gem::Version
|
|
152
|
-
version: '3.
|
|
152
|
+
version: '3.3'
|
|
153
153
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
154
|
requirements:
|
|
155
155
|
- - ">="
|
|
156
156
|
- !ruby/object:Gem::Version
|
|
157
157
|
version: '0'
|
|
158
158
|
requirements: []
|
|
159
|
-
rubygems_version:
|
|
159
|
+
rubygems_version: 3.6.9
|
|
160
160
|
specification_version: 4
|
|
161
161
|
summary: A beginner-friendly Ruby interface for OpenAI's API
|
|
162
162
|
test_files: []
|