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

Commit 9196546

Browse files
SamSaffronlis2
andauthored
FIX: better LLM feedback for image generation failures (#1306)
* FIX: handle error conditions when generating images gracefully * FIX: also handle error for edit_image * Update lib/inference/open_ai_image_generator.rb Co-authored-by: Krzysztof Kotlarek <[email protected]> * lint --------- Co-authored-by: Krzysztof Kotlarek <[email protected]>
1 parent 47d3705 commit 9196546

File tree

5 files changed

+86
-23
lines changed

5 files changed

+86
-23
lines changed

lib/inference/open_ai_image_generator.rb

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ def self.create_uploads!(
4040
output_format: output_format,
4141
)
4242

43+
raise api_responses[0] if api_responses.all? { |resp| resp.is_a?(StandardError) }
44+
45+
api_responses = api_responses.filter { |response| !response.is_a?(StandardError) }
46+
4347
create_uploads_from_responses(api_responses, user_id, for_private_message, title)
4448
end
4549

@@ -151,11 +155,16 @@ def self.generate_images_in_threads(
151155
)
152156
rescue => e
153157
attempts += 1
154-
sleep 2
155-
retry if attempts < 3
156-
Discourse.warn_exception(e, message: "Failed to generate image for prompt #{prompt}")
158+
# to keep tests speedy
159+
if !Rails.env.test?
160+
retry if attempts < 3
161+
end
162+
Discourse.warn_exception(
163+
e,
164+
message: "Failed to generate image for prompt #{prompt}\n",
165+
)
157166
puts "Error generating image for prompt: #{prompt} #{e}" if Rails.env.development?
158-
nil
167+
e
159168
end
160169
end
161170
end
@@ -203,14 +212,16 @@ def self.edit_images(
203212
)
204213
rescue => e
205214
attempts += 1
206-
sleep 2
207-
retry if attempts < 3
208-
if Rails.env.development? || Rails.env.test?
215+
if !Rails.env.test?
216+
sleep 2
217+
retry if attempts < 3
218+
end
219+
if Rails.env.development?
209220
puts "Error editing image(s) with prompt: #{prompt} #{e}"
210221
p e
211222
end
212223
Discourse.warn_exception(e, message: "Failed to edit image(s) with prompt #{prompt}")
213-
nil
224+
raise e
214225
end
215226
end
216227

lib/personas/tools/create_image.rb

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def prompts
3030
end
3131

3232
def chain_next_response?
33-
false
33+
!!@error
3434
end
3535

3636
def invoke
@@ -42,14 +42,20 @@ def invoke
4242

4343
results = nil
4444

45-
results =
46-
DiscourseAi::Inference::OpenAiImageGenerator.create_uploads!(
47-
max_prompts,
48-
model: "gpt-image-1",
49-
user_id: bot_user.id,
50-
)
45+
begin
46+
results =
47+
DiscourseAi::Inference::OpenAiImageGenerator.create_uploads!(
48+
max_prompts,
49+
model: "gpt-image-1",
50+
user_id: bot_user.id,
51+
)
52+
rescue => e
53+
@error = e
54+
return { prompts: max_prompts, error: e.message }
55+
end
5156

5257
if results.blank?
58+
@error = true
5359
return { prompts: max_prompts, error: "Something went wrong, could not generate image" }
5460
end
5561

lib/personas/tools/edit_image.rb

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def prompt
3737
end
3838

3939
def chain_next_response?
40-
false
40+
!!@error
4141
end
4242

4343
def image_urls
@@ -50,19 +50,24 @@ def invoke
5050
return { prompt: prompt, error: "No valid images provided" } if image_urls.blank?
5151

5252
sha1s = image_urls.map { |url| Upload.sha1_from_short_url(url) }.compact
53-
5453
uploads = Upload.where(sha1: sha1s).order(created_at: :asc).limit(10).to_a
5554

5655
return { prompt: prompt, error: "No valid images provided" } if uploads.blank?
5756

58-
result =
59-
DiscourseAi::Inference::OpenAiImageGenerator.create_edited_upload!(
60-
uploads,
61-
prompt,
62-
user_id: bot_user.id,
63-
)
57+
begin
58+
result =
59+
DiscourseAi::Inference::OpenAiImageGenerator.create_edited_upload!(
60+
uploads,
61+
prompt,
62+
user_id: bot_user.id,
63+
)
64+
rescue => e
65+
@error = e
66+
return { prompt: prompt, error: e.message }
67+
end
6468

6569
if result.blank?
70+
@error = true
6671
return { prompt: prompt, error: "Something went wrong, could not generate image" }
6772
end
6873

spec/lib/personas/tools/create_image_spec.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,26 @@
2222
end
2323

2424
describe "#process" do
25+
it "can reject generation of images and return a proper error to llm" do
26+
error_message = {
27+
error: {
28+
message:
29+
"Your request was rejected as a result of our safety system. Your request may contain content that is not allowed by our safety system.",
30+
type: "user_error",
31+
param: nil,
32+
code: "moderation_blocked",
33+
},
34+
}
35+
36+
WebMock.stub_request(:post, "https://api.openai.com/v1/images/generations").to_return(
37+
status: 400,
38+
body: error_message.to_json,
39+
)
40+
41+
info = create_image.invoke(&progress_blk).to_json
42+
expect(info).to include("Your request was rejected as a result of our safety system.")
43+
expect(create_image.chain_next_response?).to eq(true)
44+
end
2545
it "can generate images with gpt-image-1 model" do
2646
data = [{ b64_json: base64_image, revised_prompt: "a watercolor painting of flowers" }]
2747

spec/lib/personas/tools/edit_image_spec.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,27 @@
3535
end
3636

3737
describe "#process" do
38+
it "can reject generation of images and return a proper error to llm" do
39+
error_message = {
40+
error: {
41+
message:
42+
"Your request was rejected as a result of our safety system. Your request may contain content that is not allowed by our safety system.",
43+
type: "user_error",
44+
param: nil,
45+
code: "moderation_blocked",
46+
},
47+
}
48+
49+
WebMock.stub_request(:post, "https://api.openai.com/v1/images/edits").to_return(
50+
status: 400,
51+
body: error_message.to_json,
52+
)
53+
54+
info = edit_image.invoke(&progress_blk).to_json
55+
expect(info).to include("Your request was rejected as a result of our safety system.")
56+
expect(edit_image.chain_next_response?).to eq(true)
57+
end
58+
3859
it "can edit an image with the GPT image model" do
3960
data = [{ b64_json: base64_image, revised_prompt: "image with rainbow added in background" }]
4061

0 commit comments

Comments
 (0)