open_ai_bot 0.3.0 → 0.3.2
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/.rubocop.yml +1 -1
- data/.ruby-version +1 -0
- data/Gemfile.lock +28 -23
- data/README.md +2 -2
- data/lib/open_ai/chat_gpt.rb +25 -18
- data/lib/open_ai/chat_thread.rb +10 -2
- data/lib/open_ai/image.rb +38 -0
- data/lib/open_ai/message.rb +19 -8
- data/lib/open_ai/model.rb +65 -0
- data/lib/open_ai/utils.rb +2 -0
- data/lib/open_ai_bot.rb +2 -1
- data/main.rb +1 -0
- data/open_ai_bot.gemspec +1 -1
- metadata +10 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e31ed7bc34cf94ba2d339a1efa6b57a0d9fd972aec39961a98253cb5b9dcc4df
|
|
4
|
+
data.tar.gz: 2f92b54b9788efacd9bf50b66004c777a8eeb3bd934ffc65a2ea93a4a12c39e6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 38ff4646a9493b2771d62cce25d8a2ff0ab589bc2d300041fec4536e6e75065e33c79fe452994dd5d9a628be6646e4ed97bb97a7c28503811b3a3db1b8fefa9f
|
|
7
|
+
data.tar.gz: 872adfdeb95db9ccbdd8073ee736136a40d4517b1b4eddee9ddf5885638dfe286c705554dd708c654dd1e9b83c62682626fd63cf3d2e878fea536a4d79c08d67
|
data/.rubocop.yml
CHANGED
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.3.2
|
data/Gemfile.lock
CHANGED
|
@@ -3,17 +3,17 @@ GEM
|
|
|
3
3
|
specs:
|
|
4
4
|
addressable (2.8.6)
|
|
5
5
|
public_suffix (>= 2.0.2, < 6.0)
|
|
6
|
-
async (2.
|
|
7
|
-
console (~> 1.
|
|
6
|
+
async (2.12.0)
|
|
7
|
+
console (~> 1.25, >= 1.25.2)
|
|
8
8
|
fiber-annotation
|
|
9
|
-
io-event (~> 1.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
console (1.23.3)
|
|
9
|
+
io-event (~> 1.6)
|
|
10
|
+
bigdecimal (3.1.8)
|
|
11
|
+
concurrent-ruby (1.3.2)
|
|
12
|
+
console (1.25.2)
|
|
14
13
|
fiber-annotation
|
|
15
|
-
fiber-local
|
|
16
|
-
|
|
14
|
+
fiber-local (~> 1.1)
|
|
15
|
+
json
|
|
16
|
+
down (5.4.2)
|
|
17
17
|
addressable (~> 2.8)
|
|
18
18
|
dry-core (1.0.1)
|
|
19
19
|
concurrent-ruby (~> 1.0)
|
|
@@ -28,31 +28,35 @@ GEM
|
|
|
28
28
|
dry-types (>= 1.7, < 2)
|
|
29
29
|
ice_nine (~> 0.11)
|
|
30
30
|
zeitwerk (~> 2.6)
|
|
31
|
-
dry-types (1.7.
|
|
31
|
+
dry-types (1.7.2)
|
|
32
|
+
bigdecimal (~> 3.0)
|
|
32
33
|
concurrent-ruby (~> 1.0)
|
|
33
34
|
dry-core (~> 1.0)
|
|
34
35
|
dry-inflector (~> 1.0)
|
|
35
36
|
dry-logic (~> 1.4)
|
|
36
37
|
zeitwerk (~> 2.6)
|
|
37
38
|
event_stream_parser (0.3.0)
|
|
38
|
-
faraday (2.
|
|
39
|
-
|
|
40
|
-
faraday-net_http (>= 2.0, < 3.1)
|
|
41
|
-
ruby2_keywords (>= 0.0.4)
|
|
39
|
+
faraday (2.9.1)
|
|
40
|
+
faraday-net_http (>= 2.0, < 3.2)
|
|
42
41
|
faraday-multipart (1.0.4)
|
|
43
42
|
multipart-post (~> 2)
|
|
44
|
-
faraday-net_http (3.0
|
|
43
|
+
faraday-net_http (3.1.0)
|
|
44
|
+
net-http
|
|
45
45
|
fiber-annotation (0.2.0)
|
|
46
|
-
fiber-local (1.
|
|
46
|
+
fiber-local (1.1.0)
|
|
47
|
+
fiber-storage
|
|
48
|
+
fiber-storage (0.1.1)
|
|
47
49
|
ice_nine (0.11.2)
|
|
48
|
-
io-event (1.
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
io-event (1.6.0)
|
|
51
|
+
json (2.7.2)
|
|
52
|
+
multipart-post (2.4.1)
|
|
53
|
+
net-http (0.4.1)
|
|
54
|
+
uri
|
|
55
|
+
public_suffix (5.0.5)
|
|
51
56
|
ruby-openai (5.2.0)
|
|
52
57
|
event_stream_parser (>= 0.3.0, < 1.0.0)
|
|
53
58
|
faraday (>= 1)
|
|
54
59
|
faraday-multipart (>= 1)
|
|
55
|
-
ruby2_keywords (0.0.5)
|
|
56
60
|
rubydium (0.4.1)
|
|
57
61
|
async (~> 2.3)
|
|
58
62
|
telegram-bot-ruby (~> 1.0.0)
|
|
@@ -61,10 +65,11 @@ GEM
|
|
|
61
65
|
faraday (~> 2.0)
|
|
62
66
|
faraday-multipart (~> 1.0)
|
|
63
67
|
zeitwerk (~> 2.6)
|
|
64
|
-
|
|
65
|
-
zeitwerk (2.6.
|
|
68
|
+
uri (0.13.0)
|
|
69
|
+
zeitwerk (2.6.15)
|
|
66
70
|
|
|
67
71
|
PLATFORMS
|
|
72
|
+
ruby
|
|
68
73
|
x86_64-linux
|
|
69
74
|
|
|
70
75
|
DEPENDENCIES
|
|
@@ -73,4 +78,4 @@ DEPENDENCIES
|
|
|
73
78
|
rubydium (>= 0.2.5)
|
|
74
79
|
|
|
75
80
|
BUNDLED WITH
|
|
76
|
-
2.
|
|
81
|
+
2.5.9
|
data/README.md
CHANGED
|
@@ -16,8 +16,8 @@ sudo apt install autoconf patch build-essential rustc libssl-dev libyaml-dev lib
|
|
|
16
16
|
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.13.1
|
|
17
17
|
echo '. "$HOME/.asdf/asdf.sh"' >> ~/.bashrc
|
|
18
18
|
asdf plugin add ruby https://github.com/asdf-vm/asdf-ruby.git
|
|
19
|
-
asdf install ruby 3.
|
|
20
|
-
echo 'ruby 3.
|
|
19
|
+
asdf install ruby 3.3.2
|
|
20
|
+
echo 'ruby 3.3.2' >> ~/.tool-versions
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
2. `ffmpeg`
|
data/lib/open_ai/chat_gpt.rb
CHANGED
|
@@ -8,6 +8,7 @@ module OpenAI
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def new_thread(chat_id, model = nil)
|
|
11
|
+
model ||= config.open_ai["chat_gpt_model"].to_sym
|
|
11
12
|
msgs = config.open_ai["whitelist"].include?(chat_id) ? initial_messages : []
|
|
12
13
|
new_thread = ChatThread.new(msgs, model)
|
|
13
14
|
threads[chat_id] = new_thread
|
|
@@ -72,16 +73,6 @@ module OpenAI
|
|
|
72
73
|
"NULL"
|
|
73
74
|
end
|
|
74
75
|
|
|
75
|
-
def base64(file)
|
|
76
|
-
return unless config.open_ai["chat_gpt_model"] == "gpt-4-vision-preview"
|
|
77
|
-
return unless file
|
|
78
|
-
|
|
79
|
-
f = download_file(file)
|
|
80
|
-
res = Base64.encode64(f.read)
|
|
81
|
-
FileUtils.rm_rf("./#{f.original_filename}")
|
|
82
|
-
res
|
|
83
|
-
end
|
|
84
|
-
|
|
85
76
|
def handle_gpt_command
|
|
86
77
|
return unless bot_mentioned? || bot_replied_to? || private_chat?
|
|
87
78
|
return if self.class.registered_commands.keys.any? { @text.include? _1 }
|
|
@@ -97,7 +88,8 @@ module OpenAI
|
|
|
97
88
|
from: username(@user),
|
|
98
89
|
body: @text_without_bot_mentions,
|
|
99
90
|
chat_id: @chat.id,
|
|
100
|
-
|
|
91
|
+
chat_thread: current_thread,
|
|
92
|
+
image: Image.from_tg_photo(download_file(@msg.photo&.last), model: current_thread.model)
|
|
101
93
|
)
|
|
102
94
|
|
|
103
95
|
return unless current_message.valid?
|
|
@@ -110,7 +102,8 @@ module OpenAI
|
|
|
110
102
|
from: username(@target),
|
|
111
103
|
body: @replies_to.text.to_s.gsub(/@#{config.bot_username}\b/, ""),
|
|
112
104
|
chat_id: @chat.id,
|
|
113
|
-
|
|
105
|
+
chat_thread: current_thread,
|
|
106
|
+
image: Image.from_tg_photo(download_file(@replies_to.photo&.last), model: current_thread.model)
|
|
114
107
|
)
|
|
115
108
|
else
|
|
116
109
|
nil
|
|
@@ -127,7 +120,7 @@ module OpenAI
|
|
|
127
120
|
|
|
128
121
|
response = open_ai.chat(
|
|
129
122
|
parameters: {
|
|
130
|
-
model: current_thread.model
|
|
123
|
+
model: current_thread.model.to_s,
|
|
131
124
|
messages: current_thread.as_json
|
|
132
125
|
}
|
|
133
126
|
)
|
|
@@ -138,9 +131,10 @@ module OpenAI
|
|
|
138
131
|
send_chat_gpt_error(error_text.strip)
|
|
139
132
|
else
|
|
140
133
|
text = response.dig("choices", 0, "message", "content")
|
|
141
|
-
tokens = response.dig("usage", "total_tokens")
|
|
142
134
|
|
|
143
|
-
|
|
135
|
+
tokens_info = get_tokens_info!(response)
|
|
136
|
+
|
|
137
|
+
send_chat_gpt_response(text, tokens_info)
|
|
144
138
|
end
|
|
145
139
|
end
|
|
146
140
|
|
|
@@ -148,15 +142,28 @@ module OpenAI
|
|
|
148
142
|
reply(text, parse_mode: "Markdown")
|
|
149
143
|
end
|
|
150
144
|
|
|
151
|
-
def
|
|
152
|
-
|
|
145
|
+
def get_tokens_info!(response)
|
|
146
|
+
completion_tokens = response.dig("usage", "completion_tokens")
|
|
147
|
+
prompt_tokens = response.dig("usage", "prompt_tokens")
|
|
148
|
+
vision_tokens = current_thread.claim_vision_tokens!
|
|
149
|
+
|
|
150
|
+
result = current_thread.model.request_cost(completion_tokens:, prompt_tokens:, vision_tokens:, current_thread:)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def send_chat_gpt_response(text, tokens_info)
|
|
154
|
+
tokens_text = tokens_info[:info]
|
|
155
|
+
|
|
156
|
+
id = reply(text + tokens_text).dig("result", "message_id")
|
|
157
|
+
|
|
153
158
|
bot_message = BotMessage.new(
|
|
154
159
|
id: id,
|
|
155
160
|
replies_to: @message_id,
|
|
156
161
|
body: text,
|
|
157
162
|
chat_id: @chat.id,
|
|
158
|
-
|
|
163
|
+
chat_thread: current_thread,
|
|
164
|
+
cost: tokens_info[:total]
|
|
159
165
|
)
|
|
166
|
+
|
|
160
167
|
current_thread.add(bot_message)
|
|
161
168
|
end
|
|
162
169
|
end
|
data/lib/open_ai/chat_thread.rb
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module OpenAI
|
|
4
4
|
class ChatThread
|
|
5
|
-
def initialize(defaults = [], model
|
|
5
|
+
def initialize(defaults = [], model)
|
|
6
6
|
@history ||= defaults
|
|
7
|
-
@model = model
|
|
7
|
+
@model = model.is_a?(Model) ? model : Model.new(model)
|
|
8
8
|
puts @history
|
|
9
9
|
end
|
|
10
10
|
|
|
@@ -20,6 +20,14 @@ module OpenAI
|
|
|
20
20
|
true
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
def total_cost
|
|
24
|
+
@history.map(&:cost).compact.sum
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def claim_vision_tokens!
|
|
28
|
+
@history.reject(&:vision_tokens_claimed?).map(&:claim_vision_tokens!).compact.sum
|
|
29
|
+
end
|
|
30
|
+
|
|
23
31
|
def add(message)
|
|
24
32
|
return false unless message&.valid?
|
|
25
33
|
return false if @history.any? { message.id == _1.id}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module OpenAI
|
|
2
|
+
class Image
|
|
3
|
+
BASE_TOKENS = 85
|
|
4
|
+
TILE_TOKENS = 170
|
|
5
|
+
TILE_SIZE = 512
|
|
6
|
+
|
|
7
|
+
def self.from_tg_photo(file, model:)
|
|
8
|
+
return unless file
|
|
9
|
+
return unless model.has_vision?
|
|
10
|
+
|
|
11
|
+
base64 = Base64.encode64(file.read)
|
|
12
|
+
size = `identify -format "%w %h" ./#{file.original_filename}`
|
|
13
|
+
width, height = size.split(" ")
|
|
14
|
+
FileUtils.rm_rf("./#{file.original_filename}")
|
|
15
|
+
|
|
16
|
+
new(width, height, base64)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
attr_accessor :width, :height, :base64
|
|
20
|
+
|
|
21
|
+
def initialize(width, height, base64)
|
|
22
|
+
@width = width
|
|
23
|
+
@height = height
|
|
24
|
+
@base64 = base64
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def tokens
|
|
28
|
+
@tokens ||= begin
|
|
29
|
+
tiles = tiles(width) * tiles(height)
|
|
30
|
+
(tiles * TILE_TOKENS) + BASE_TOKENS
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def tiles(pixels)
|
|
35
|
+
(pixels.to_f / TILE_SIZE).ceil
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
data/lib/open_ai/message.rb
CHANGED
|
@@ -3,29 +3,40 @@ module OpenAI
|
|
|
3
3
|
# (ChatGPT isn't brilliant at parsing JSON sructures without starting to reply in JSON, so most of it is useless)
|
|
4
4
|
|
|
5
5
|
class Message
|
|
6
|
-
attr_accessor :body, :from, :id, :replies_to, :
|
|
6
|
+
attr_accessor :body, :from, :id, :replies_to, :chat_id, :image, :chat_thread, :cost
|
|
7
7
|
attr_reader :role, :timestamp
|
|
8
8
|
|
|
9
9
|
def initialize(**kwargs)
|
|
10
10
|
kwargs.each_pair { public_send("#{_1}=", _2) }
|
|
11
11
|
@role = :user
|
|
12
12
|
@timestamp = Time.now.to_i
|
|
13
|
+
@vision_tokens_claimed = !image
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def vision_tokens_claimed?
|
|
17
|
+
@vision_tokens_claimed
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def claim_vision_tokens!
|
|
21
|
+
# binding.pry
|
|
22
|
+
@vision_tokens_claimed = true
|
|
23
|
+
image&.tokens
|
|
13
24
|
end
|
|
14
25
|
|
|
15
26
|
def valid?
|
|
16
|
-
[(
|
|
27
|
+
[(image || body), from, id, chat_id, chat_thread].all?(&:present?)
|
|
17
28
|
end
|
|
18
29
|
|
|
19
30
|
# Format for OpenAI API
|
|
20
31
|
def as_json
|
|
21
32
|
msg = [from, body].compact.join("\n")
|
|
22
33
|
|
|
23
|
-
if
|
|
34
|
+
if image
|
|
24
35
|
{
|
|
25
36
|
role: role,
|
|
26
37
|
content: [
|
|
27
38
|
{ type: "text", text: msg },
|
|
28
|
-
{ type: "image_url", image_url: { url: "data:image/jpeg;base64,#{
|
|
39
|
+
{ type: "image_url", image_url: { url: "data:image/jpeg;base64,#{image.base64}" } }
|
|
29
40
|
]
|
|
30
41
|
}
|
|
31
42
|
else
|
|
@@ -46,8 +57,8 @@ module OpenAI
|
|
|
46
57
|
"From" => from,
|
|
47
58
|
"To" => replies_to,
|
|
48
59
|
"Body" => body,
|
|
49
|
-
"Tokens used" => tokens,
|
|
50
|
-
"Image" => (
|
|
60
|
+
# "Tokens used" => tokens,
|
|
61
|
+
"Image" => (image ? "Some image" : "None")
|
|
51
62
|
}.reject { |_k, v|
|
|
52
63
|
v.blank?
|
|
53
64
|
}.map { |k, v|
|
|
@@ -69,7 +80,7 @@ module OpenAI
|
|
|
69
80
|
end
|
|
70
81
|
|
|
71
82
|
def valid?
|
|
72
|
-
body.present?
|
|
83
|
+
[body, chat_thread].all?(&:present?)
|
|
73
84
|
end
|
|
74
85
|
end
|
|
75
86
|
|
|
@@ -80,7 +91,7 @@ module OpenAI
|
|
|
80
91
|
end
|
|
81
92
|
|
|
82
93
|
def valid?
|
|
83
|
-
[body, id, chat_id,
|
|
94
|
+
[body, id, chat_id, chat_thread].all?(&:present?)
|
|
84
95
|
end
|
|
85
96
|
end
|
|
86
97
|
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module OpenAI
|
|
2
|
+
class Model
|
|
3
|
+
# All prices are per 1K tokens
|
|
4
|
+
MODEL_INFO = {
|
|
5
|
+
"gpt-4o": {
|
|
6
|
+
max_context: 128_000,
|
|
7
|
+
prompt_price: 0.005,
|
|
8
|
+
completion_price: 0.015,
|
|
9
|
+
vision_price: 0.005
|
|
10
|
+
},
|
|
11
|
+
"gpt-3.5-turbo": {
|
|
12
|
+
max_context: 16385,
|
|
13
|
+
prompt_price: 0.0005,
|
|
14
|
+
completion_price: 0.0015,
|
|
15
|
+
vision_price: 0
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
attr_accessor :max_context, :prompt_price, :completion_price, :vision_price
|
|
20
|
+
|
|
21
|
+
[:max_context, :prompt_price, :completion_price, :vision_price].each do |attr|
|
|
22
|
+
define_method(attr) do
|
|
23
|
+
MODEL_INFO[@model][attr]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def initialize(model)
|
|
28
|
+
if MODEL_INFO[model].nil?
|
|
29
|
+
raise ArgumentError.new("Unknown model: #{model.inspect}.")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
@model = model
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def to_s
|
|
36
|
+
@model
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def has_vision?
|
|
40
|
+
MODEL_INFO[@model][:vision_price].positive?
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def request_cost(prompt_tokens:, completion_tokens:, vision_tokens:, current_thread:)
|
|
44
|
+
prompt_cost = prompt_tokens * prompt_price / 1000
|
|
45
|
+
completion_cost = completion_tokens * completion_price / 1000
|
|
46
|
+
vision_cost = vision_tokens * vision_price / 1000
|
|
47
|
+
|
|
48
|
+
total = prompt_cost + completion_cost + vision_cost
|
|
49
|
+
thread_total = current_thread.total_cost
|
|
50
|
+
|
|
51
|
+
info = "\n\n" + {
|
|
52
|
+
prompt: "#{prompt_tokens} tokens (#{prompt_cost.round(5)}$)",
|
|
53
|
+
completion: "#{completion_tokens} tokens (#{completion_cost.round(5)}$)",
|
|
54
|
+
vision: "#{vision_tokens} tokens (#{vision_cost.round(5)}$)",
|
|
55
|
+
total: "#{total.round(5)}$",
|
|
56
|
+
total_for_this_conversation: "#{(thread_total + total).round(5)}$",
|
|
57
|
+
max_context: max_context
|
|
58
|
+
}.map { |k, v|
|
|
59
|
+
"#{k}: #{v}"
|
|
60
|
+
}.join("\n")
|
|
61
|
+
|
|
62
|
+
{ info:, total: }
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
data/lib/open_ai/utils.rb
CHANGED
data/lib/open_ai_bot.rb
CHANGED
|
@@ -6,11 +6,12 @@ require_relative "open_ai/message"
|
|
|
6
6
|
require_relative "open_ai/dalle"
|
|
7
7
|
require_relative "open_ai/utils"
|
|
8
8
|
require_relative "open_ai/whisper"
|
|
9
|
+
require_relative "open_ai/model"
|
|
10
|
+
require_relative "open_ai/image"
|
|
9
11
|
|
|
10
12
|
require_relative "ext/blank"
|
|
11
13
|
require_relative "ext/in"
|
|
12
14
|
|
|
13
|
-
|
|
14
15
|
class OpenAIBot < Rubydium::Bot
|
|
15
16
|
include OpenAI::ChatGPT
|
|
16
17
|
include OpenAI::Dalle
|
data/main.rb
CHANGED
data/open_ai_bot.gemspec
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: open_ai_bot
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- bulgakke
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-06-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: down
|
|
@@ -80,7 +80,7 @@ dependencies:
|
|
|
80
80
|
- - "~>"
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
82
|
version: '5.1'
|
|
83
|
-
description:
|
|
83
|
+
description:
|
|
84
84
|
email:
|
|
85
85
|
- vvp835@yandex.ru
|
|
86
86
|
executables: []
|
|
@@ -89,6 +89,7 @@ extra_rdoc_files: []
|
|
|
89
89
|
files:
|
|
90
90
|
- ".gitignore"
|
|
91
91
|
- ".rubocop.yml"
|
|
92
|
+
- ".ruby-version"
|
|
92
93
|
- Gemfile
|
|
93
94
|
- Gemfile.lock
|
|
94
95
|
- README.md
|
|
@@ -100,7 +101,9 @@ files:
|
|
|
100
101
|
- lib/open_ai/chat_gpt.rb
|
|
101
102
|
- lib/open_ai/chat_thread.rb
|
|
102
103
|
- lib/open_ai/dalle.rb
|
|
104
|
+
- lib/open_ai/image.rb
|
|
103
105
|
- lib/open_ai/message.rb
|
|
106
|
+
- lib/open_ai/model.rb
|
|
104
107
|
- lib/open_ai/utils.rb
|
|
105
108
|
- lib/open_ai/whisper.rb
|
|
106
109
|
- lib/open_ai_bot.rb
|
|
@@ -113,7 +116,7 @@ metadata:
|
|
|
113
116
|
homepage_uri: https://github.com/bulgakke/open_ai_bot
|
|
114
117
|
source_code_uri: https://github.com/bulgakke/open_ai_bot
|
|
115
118
|
rubygems_mfa_required: 'true'
|
|
116
|
-
post_install_message:
|
|
119
|
+
post_install_message:
|
|
117
120
|
rdoc_options: []
|
|
118
121
|
require_paths:
|
|
119
122
|
- lib
|
|
@@ -128,8 +131,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
128
131
|
- !ruby/object:Gem::Version
|
|
129
132
|
version: '0'
|
|
130
133
|
requirements: []
|
|
131
|
-
rubygems_version: 3.
|
|
132
|
-
signing_key:
|
|
134
|
+
rubygems_version: 3.5.9
|
|
135
|
+
signing_key:
|
|
133
136
|
specification_version: 4
|
|
134
137
|
summary: Telegram bot for using ChatGPT, DALL-E and Whisper
|
|
135
138
|
test_files: []
|