ai-chat 0.5.8 → 0.6.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 +17 -17
- data/ai-chat.gemspec +1 -1
- data/lib/ai/chat.rb +42 -27
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 50c5c8743e007a3b5dee31d4d56e81073fd28b6bcf92fbb5d0fe0671bbbfac2e
|
|
4
|
+
data.tar.gz: 2cf832e2e5a211612f281e2058590bced4550fae4f60fc0410e7da37058cc010
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 53732280a8dc68de3bb9e90b174b6b3bf092f43e2fdfa997bbe499e253151570c713ee7166235a0c2e0494ae9b743b729ba8a7bea82e0aa26020baed16e14fd0
|
|
7
|
+
data.tar.gz: d0429dd257cc64fa91d31b0aa7543d21faa32aef74249f98d63810f71e63891bb32e878f571e2367e78b0bb098b9eaea79e8404ab1a380c0668124df37aa18e9
|
data/README.md
CHANGED
|
@@ -238,7 +238,7 @@ See [OpenAI's model documentation](https://platform.openai.com/docs/models) for
|
|
|
238
238
|
|
|
239
239
|
### API key
|
|
240
240
|
|
|
241
|
-
|
|
241
|
+
By default, the gem uses `OPENAI_API_KEY`. When proxy mode is enabled (`AICHAT_PROXY=true`), it uses `AICHAT_PROXY_KEY` instead.
|
|
242
242
|
|
|
243
243
|
You can specify a different environment variable name:
|
|
244
244
|
|
|
@@ -404,7 +404,7 @@ AI::Chat.generate_schema!("A user profile with name (required), email (required)
|
|
|
404
404
|
|
|
405
405
|
This method returns a String containing the JSON schema. The JSON schema also writes (or overwrites) to `schema.json` at the root of the project.
|
|
406
406
|
|
|
407
|
-
|
|
407
|
+
This class method uses the same API key and proxy resolution as `AI::Chat.new`. You can also pass the API key directly or choose a different environment variable:
|
|
408
408
|
|
|
409
409
|
```rb
|
|
410
410
|
# Passing the API key directly
|
|
@@ -414,7 +414,7 @@ AI::Chat.generate_schema!("A user with full name (required), first_name (require
|
|
|
414
414
|
AI::Chat.generate_schema!("A user with full name (required), first_name (required), and last_name (required).", api_key_env_var: "CUSTOM_KEY")
|
|
415
415
|
```
|
|
416
416
|
|
|
417
|
-
`generate_schema!` also follows proxy defaults from the `AICHAT_PROXY` environment variable.
|
|
417
|
+
`generate_schema!` also follows proxy defaults from the `AICHAT_PROXY` environment variable.
|
|
418
418
|
|
|
419
419
|
```bash
|
|
420
420
|
export AICHAT_PROXY=true
|
|
@@ -617,28 +617,30 @@ message = chat.get_response(wait: true, timeout: 600)
|
|
|
617
617
|
puts message[:content]
|
|
618
618
|
```
|
|
619
619
|
|
|
620
|
-
## Proxying Through
|
|
620
|
+
## Proxying Through Prepend.me
|
|
621
621
|
|
|
622
|
-
You can proxy API calls through [
|
|
622
|
+
You can proxy API calls through [Prepend.me](https://prepend.me/). When proxy mode is enabled, the gem uses the `AICHAT_PROXY_KEY` environment variable instead of `OPENAI_API_KEY`.
|
|
623
|
+
|
|
624
|
+
You can enable proxy mode at construction time:
|
|
623
625
|
|
|
624
626
|
```rb
|
|
625
|
-
chat = AI::Chat.new
|
|
626
|
-
chat.proxy = true
|
|
627
|
-
chat.user("Tell me a story")
|
|
628
|
-
chat.generate!
|
|
629
|
-
puts chat.last[:content]
|
|
630
|
-
# => "Once upon a time..."
|
|
627
|
+
chat = AI::Chat.new(proxy: true)
|
|
631
628
|
```
|
|
632
629
|
|
|
633
|
-
|
|
630
|
+
Or default it from the environment (case-insensitive):
|
|
634
631
|
|
|
635
632
|
```bash
|
|
636
633
|
export AICHAT_PROXY=true
|
|
637
634
|
```
|
|
638
635
|
|
|
639
|
-
|
|
636
|
+
Or toggle it on an existing instance:
|
|
637
|
+
|
|
638
|
+
```rb
|
|
639
|
+
chat = AI::Chat.new
|
|
640
|
+
chat.proxy = true
|
|
641
|
+
```
|
|
640
642
|
|
|
641
|
-
When proxy is enabled, **you must
|
|
643
|
+
When proxy is enabled, **you must set `AICHAT_PROXY_KEY`** with your API key from Prepend.me.
|
|
642
644
|
|
|
643
645
|
## Building Conversations Without API Calls
|
|
644
646
|
|
|
@@ -748,9 +750,7 @@ This is particularly useful for background mode workflows. If you want to retrie
|
|
|
748
750
|
```ruby
|
|
749
751
|
require "openai"
|
|
750
752
|
|
|
751
|
-
|
|
752
|
-
api_key = ENV.fetch("OPENAI_API_KEY") if api_key.nil? || api_key.empty?
|
|
753
|
-
client = OpenAI::Client.new(api_key: api_key)
|
|
753
|
+
client = OpenAI::Client.new(api_key: ENV.fetch("OPENAI_API_KEY"))
|
|
754
754
|
|
|
755
755
|
response_id = "resp_abc123..." # e.g., load from your database
|
|
756
756
|
response = client.responses.retrieve(response_id)
|
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.6.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"
|
data/lib/ai/chat.rb
CHANGED
|
@@ -22,10 +22,15 @@ module AI
|
|
|
22
22
|
attr_reader :client, :last_response_id, :proxy, :schema, :schema_file, :verbosity
|
|
23
23
|
|
|
24
24
|
BASE_PROXY_URL = "https://prepend.me/api.openai.com/v1"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
PROXY_ENV = "AICHAT_PROXY"
|
|
26
|
+
PROXY_KEY_ENV = "AICHAT_PROXY_KEY"
|
|
27
|
+
OPENAI_KEY_ENV = "OPENAI_API_KEY"
|
|
28
|
+
|
|
29
|
+
def initialize(api_key: nil, api_key_env_var: nil, proxy: nil)
|
|
30
|
+
@api_key_arg = api_key
|
|
31
|
+
@api_key_env_var_arg = api_key_env_var
|
|
32
|
+
@proxy = proxy.nil? ? ENV[PROXY_ENV]&.downcase == "true" : !!proxy
|
|
33
|
+
@api_key = resolve_api_key
|
|
29
34
|
@messages = []
|
|
30
35
|
@reasoning_effort = nil
|
|
31
36
|
@model = "gpt-5.2"
|
|
@@ -40,8 +45,8 @@ module AI
|
|
|
40
45
|
end
|
|
41
46
|
|
|
42
47
|
def self.generate_schema!(description, location: "schema.json", api_key: nil, api_key_env_var: nil, proxy: nil)
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
proxy = proxy.nil? ? ENV[PROXY_ENV]&.downcase == "true" : !!proxy
|
|
49
|
+
api_key = api_key || ENV.fetch(api_key_env_var || (proxy ? PROXY_KEY_ENV : OPENAI_KEY_ENV))
|
|
45
50
|
prompt_path = File.expand_path("../prompts/schema_generator.md", __dir__)
|
|
46
51
|
system_prompt = File.read(prompt_path)
|
|
47
52
|
|
|
@@ -73,16 +78,6 @@ module AI
|
|
|
73
78
|
content
|
|
74
79
|
end
|
|
75
80
|
|
|
76
|
-
def self.resolve_api_key(api_key: nil, api_key_env_var: nil)
|
|
77
|
-
return api_key if api_key
|
|
78
|
-
return ENV.fetch(api_key_env_var) if api_key_env_var
|
|
79
|
-
|
|
80
|
-
aichat_api_key = ENV["AICHAT_API_KEY"]
|
|
81
|
-
return aichat_api_key if aichat_api_key && !aichat_api_key.empty?
|
|
82
|
-
|
|
83
|
-
ENV.fetch("OPENAI_API_KEY")
|
|
84
|
-
end
|
|
85
|
-
|
|
86
81
|
# :reek:TooManyStatements
|
|
87
82
|
# :reek:NilCheck
|
|
88
83
|
def add(content, role: "user", response: nil, status: nil, image: nil, images: nil, file: nil, files: nil)
|
|
@@ -169,15 +164,20 @@ module AI
|
|
|
169
164
|
end
|
|
170
165
|
|
|
171
166
|
def proxy=(value)
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
167
|
+
new_proxy = !!value
|
|
168
|
+
previous_proxy = @proxy
|
|
169
|
+
@proxy = new_proxy
|
|
170
|
+
new_key = resolve_api_key
|
|
171
|
+
client_options = {api_key: new_key}
|
|
172
|
+
client_options[:base_url] = BASE_PROXY_URL if new_proxy
|
|
173
|
+
new_client = OpenAI::Client.new(**client_options)
|
|
174
|
+
|
|
175
|
+
@api_key = new_key
|
|
176
|
+
@api_key_validated = false
|
|
177
|
+
@client = new_client
|
|
178
|
+
rescue => error
|
|
179
|
+
@proxy = previous_proxy
|
|
180
|
+
raise
|
|
181
181
|
end
|
|
182
182
|
|
|
183
183
|
def schema=(value)
|
|
@@ -262,6 +262,21 @@ module AI
|
|
|
262
262
|
|
|
263
263
|
private
|
|
264
264
|
|
|
265
|
+
def resolve_api_key
|
|
266
|
+
env_var = @api_key_env_var_arg || (@proxy ? PROXY_KEY_ENV : OPENAI_KEY_ENV)
|
|
267
|
+
@api_key_arg || ENV.fetch(env_var) {
|
|
268
|
+
if @proxy
|
|
269
|
+
raise KeyError, "Proxy mode is enabled but #{PROXY_KEY_ENV} is not set. " \
|
|
270
|
+
"Create an environment variable called #{PROXY_KEY_ENV} " \
|
|
271
|
+
"with your API key from Prepend.me."
|
|
272
|
+
else
|
|
273
|
+
raise KeyError, "#{OPENAI_KEY_ENV} is not set. " \
|
|
274
|
+
"Create an environment variable called #{OPENAI_KEY_ENV} " \
|
|
275
|
+
"with your API key from https://platform.openai.com/api-keys."
|
|
276
|
+
end
|
|
277
|
+
}
|
|
278
|
+
end
|
|
279
|
+
|
|
265
280
|
class InputClassificationError < StandardError; end
|
|
266
281
|
|
|
267
282
|
class WrongAPITokenUsedError < StandardError; end
|
|
@@ -597,11 +612,11 @@ module AI
|
|
|
597
612
|
rescue OpenAI::Errors::AuthenticationError
|
|
598
613
|
message = if proxy
|
|
599
614
|
<<~STRING
|
|
600
|
-
|
|
615
|
+
Your API key was not accepted by Prepend.me. Since proxy mode is enabled, you need a valid API key from Prepend.me in the #{PROXY_KEY_ENV} environment variable.
|
|
601
616
|
STRING
|
|
602
617
|
else
|
|
603
618
|
<<~STRING
|
|
604
|
-
|
|
619
|
+
Your API key was not accepted by OpenAI. Make sure the #{OPENAI_KEY_ENV} environment variable contains a valid key from https://platform.openai.com/api-keys.
|
|
605
620
|
STRING
|
|
606
621
|
end
|
|
607
622
|
raise WrongAPITokenUsedError, message, cause: nil
|