Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 85717bc

Browse files
committed
open ai and claude are now working
1 parent 2c63ae3 commit 85717bc

File tree

5 files changed

+111
-48
lines changed

5 files changed

+111
-48
lines changed

lib/completions/dialects/chat_gpt.rb

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -102,35 +102,46 @@ def tool_msg(msg)
102102
end
103103

104104
def user_msg(msg)
105-
user_message = { role: "user", content: msg[:content] }
105+
content_array = []
106+
107+
user_message = { role: "user" }
106108

107109
if msg[:id]
108110
if @embed_user_ids
109-
user_message[:content] = "#{msg[:id]}: #{msg[:content]}"
111+
content_array << "#{msg[:id]}: "
110112
else
111113
user_message[:name] = msg[:id]
112114
end
113115
end
114116

115-
user_message[:content] = inline_images(user_message[:content], msg) if vision_support?
117+
content_array << msg[:content]
118+
119+
content_array =
120+
to_encoded_content_array(
121+
content: content_array.flatten,
122+
image_encoder: ->(details) { image_node(details) },
123+
text_encoder: ->(text) { { type: "text", text: text } },
124+
allow_vision: vision_support?,
125+
)
126+
127+
user_message[:content] = no_array_if_only_text(content_array)
116128
user_message
117129
end
118130

119-
def inline_images(content, message)
120-
encoded_uploads = prompt.encoded_uploads(message)
121-
return content if encoded_uploads.blank?
122-
123-
content_w_imgs =
124-
encoded_uploads.reduce([]) do |memo, details|
125-
memo << {
126-
type: "image_url",
127-
image_url: {
128-
url: "data:#{details[:mime_type]};base64,#{details[:base64]}",
129-
},
130-
}
131-
end
131+
def no_array_if_only_text(content_array)
132+
if content_array.size == 1 && content_array.first[:type] == "text"
133+
return content_array.first[:text]
134+
end
135+
content_array
136+
end
132137

133-
content_w_imgs << { type: "text", text: message[:content] }
138+
def image_node(details)
139+
{
140+
type: "image_url",
141+
image_url: {
142+
url: "data:#{details[:mime_type]};base64,#{details[:base64]}",
143+
},
144+
}
134145
end
135146

136147
def per_message_overhead

lib/completions/dialects/claude.rb

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ def tool_msg(msg)
8787
end
8888

8989
def model_msg(msg)
90-
if msg[:thinking] || msg[:redacted_thinking_signature]
91-
content_array = []
90+
content_array = []
9291

92+
if msg[:thinking] || msg[:redacted_thinking_signature]
9393
if msg[:thinking]
9494
content_array << {
9595
type: "thinking",
@@ -104,13 +104,17 @@ def model_msg(msg)
104104
data: msg[:redacted_thinking_signature],
105105
}
106106
end
107+
end
107108

108-
content_array << { type: "text", text: msg[:content] }
109+
content_array =
110+
to_encoded_content_array(
111+
content: [content_array, msg[:content]].flatten,
112+
image_encoder: ->(details) { image_node(details) },
113+
text_encoder: ->(text) { { type: "text", text: text } },
114+
allow_vision: vision_support?,
115+
)
109116

110-
{ role: "assistant", content: content_array }
111-
else
112-
{ role: "assistant", content: msg[:content] }
113-
end
117+
{ role: "assistant", content: no_array_if_only_text(content_array) }
114118
end
115119

116120
def system_msg(msg)
@@ -124,32 +128,31 @@ def system_msg(msg)
124128
end
125129

126130
def user_msg(msg)
127-
content = +""
128-
content << "#{msg[:id]}: " if msg[:id]
129-
message_content = msg[:content]
130-
message_content = [message_content] if !message_content.is_a?(Array)
131-
132131
content_array = []
132+
content_array << "#{msg[:id]}: " if msg[:id]
133+
content_array.concat([msg[:content]].flatten)
134+
135+
content_array =
136+
to_encoded_content_array(
137+
content: content_array,
138+
image_encoder: ->(details) { image_node(details) },
139+
text_encoder: ->(text) { { type: "text", text: text } },
140+
allow_vision: vision_support?,
141+
)
142+
143+
{ role: "user", content: no_array_if_only_text(content_array) }
144+
end
133145

134-
message_content.each do |content_part|
135-
if content_part.is_a?(String)
136-
content << content_part
137-
elsif content_part.is_a?(Hash) && vision_support?
138-
content_array << { type: "text", text: content } if content.present?
139-
image = image_node(content_part[:upload_id])
140-
content_array << image if image
141-
content = +""
142-
end
146+
# keeping our payload as backward compatible as possible
147+
def no_array_if_only_text(content_array)
148+
if content_array.length == 1 && content_array.first[:type] == "text"
149+
content_array.first[:text]
150+
else
151+
content_array
143152
end
144-
145-
content_array << { type: "text", text: content } if content.present?
146-
147-
{ role: "user", content: content_array }
148153
end
149154

150-
def image_node(upload_id)
151-
details = prompt.encode_upload(upload_id)
152-
return nil if details.blank?
155+
def image_node(details)
153156
{
154157
source: {
155158
type: "base64",

lib/completions/dialects/dialect.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,29 @@ def tool_msg(msg)
227227
msg = msg.merge(content: new_content)
228228
user_msg(msg)
229229
end
230+
231+
def to_encoded_content_array(content:, image_encoder:, text_encoder:, allow_vision:)
232+
content = [content] if !content.is_a?(Array)
233+
234+
current_string = +""
235+
result = []
236+
237+
content.each do |c|
238+
if c.is_a?(String)
239+
current_string << c
240+
elsif c.is_a?(Hash) && c.key?(:upload_id) && allow_vision
241+
if !current_string.empty?
242+
result << text_encoder.call(current_string)
243+
current_string = +""
244+
end
245+
encoded = prompt.encode_upload(c[:upload_id])
246+
result << image_encoder.call(encoded) if encoded
247+
end
248+
end
249+
250+
result << text_encoder.call(current_string) if !current_string.empty?
251+
result
252+
end
230253
end
231254
end
232255
end

lib/completions/prompt_messages_builder.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,19 @@ def to_a(limit: nil, style: nil)
216216

217217
if message[:type] == :user
218218
old_name = last_message.delete(:name)
219-
last_message[:content] = "#{old_name}: #{last_message[:content]}" if old_name
219+
last_message[:content] = ["#{old_name}: ", last_message[:content]].flatten if old_name
220220

221221
new_content = message[:content]
222-
new_content = "#{message[:name]}: #{new_content}" if message[:name]
222+
new_content = ["#{message[:name]}: ", new_content].flatten if message[:name]
223223

224-
last_message[:content] += "\n#{new_content}"
224+
if !last_message[:content].is_a?(Array)
225+
last_message[:content] = [last_message[:content]]
226+
end
227+
last_message[:content].concat(["\n", new_content].flatten)
228+
229+
compressed =
230+
compress_messages_buffer(last_message[:content], max_uploads: MAX_TOPIC_UPLOADS)
231+
last_message[:content] = compressed
225232
else
226233
last_message[:content] = message[:content]
227234
end

spec/lib/completions/prompt_messages_builder_spec.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,25 @@
1414
Fabricate(:upload, user: user, original_filename: "image.png", extension: "png")
1515
end
1616

17+
it "correctly merges user messages with uploads" do
18+
builder.push(type: :user, content: "Hello", name: "Alice", upload_ids: [1])
19+
builder.push(type: :user, content: "World", name: "Bob", upload_ids: [2])
20+
21+
messages = builder.to_a
22+
23+
# Check the structure of the merged message
24+
expect(messages.length).to eq(1)
25+
expect(messages[0][:type]).to eq(:user)
26+
27+
# The content should contain the text and both uploads
28+
content = messages[0][:content]
29+
expect(content).to be_an(Array)
30+
expect(content[0]).to eq("Alice: Hello")
31+
expect(content[1]).to eq({ upload_id: 1 })
32+
expect(content[2]).to eq("\nBob: World")
33+
expect(content[3]).to eq({ upload_id: 2 })
34+
end
35+
1736
it "should allow merging user messages" do
1837
builder.push(type: :user, content: "Hello", name: "Alice")
1938
builder.push(type: :user, content: "World", name: "Bob")

0 commit comments

Comments
 (0)