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

Commit 110a162

Browse files
keegangeorgexfalcoxpmusaraj
authored
DEV: Update rate limits for image captioning (#816)
This PR updates the rate limits for AI helper so that image caption follows a specific rate limit of 20 requests per minute. This should help when uploading multiple files that need to be captioned. This PR also updates the UI so that it shows toast message with the extracted error message instead of having a blocking `popupAjaxError` error dialog. --------- Co-authored-by: Rafael dos Santos Silva <[email protected]> Co-authored-by: Penar Musaraj <[email protected]>
1 parent 7ae6c17 commit 110a162

File tree

3 files changed

+64
-4
lines changed

3 files changed

+64
-4
lines changed

app/controllers/discourse_ai/ai_helper/assistant_controller.rb

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,21 @@ class AssistantController < ::ApplicationController
66
requires_plugin ::DiscourseAi::PLUGIN_NAME
77
requires_login
88
before_action :ensure_can_request_suggestions
9-
before_action :rate_limiter_performed!, except: %i[prompts]
9+
before_action :rate_limiter_performed!
1010

1111
include SecureUploadEndpointHelpers
1212

13+
RATE_LIMITS = {
14+
"default" => {
15+
amount: 6,
16+
interval: 3.minutes,
17+
},
18+
"caption_image" => {
19+
amount: 20,
20+
interval: 1.minute,
21+
},
22+
}.freeze
23+
1324
def suggest
1425
input = get_text_param!
1526
force_default_locale = params[:force_default_locale] || false
@@ -161,7 +172,13 @@ def get_post_param!
161172
end
162173

163174
def rate_limiter_performed!
164-
RateLimiter.new(current_user, "ai_assistant", 6, 3.minutes).performed!
175+
action_rate_limit = RATE_LIMITS[action_name] || RATE_LIMITS["default"]
176+
RateLimiter.new(
177+
current_user,
178+
"ai_assistant",
179+
action_rate_limit[:amount],
180+
action_rate_limit[:interval],
181+
).performed!
165182
end
166183

167184
def ensure_can_request_suggestions

assets/javascripts/initializers/ai-image-caption.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ajax } from "discourse/lib/ajax";
2-
import { popupAjaxError } from "discourse/lib/ajax-error";
2+
import { extractError, popupAjaxError } from "discourse/lib/ajax-error";
33
import { apiInitializer } from "discourse/lib/api";
44
import { getUploadMarkdown, isImage } from "discourse/lib/uploads";
55
import I18n from "discourse-i18n";
@@ -111,7 +111,13 @@ export default apiInitializer("1.25.0", (api) => {
111111
});
112112
return response.caption;
113113
} catch (error) {
114-
popupAjaxError(error);
114+
toasts.error({
115+
class: "ai-image-caption-error-toast",
116+
duration: 3000,
117+
data: {
118+
message: extractError(error),
119+
},
120+
});
115121
}
116122
}
117123

@@ -129,6 +135,7 @@ export default apiInitializer("1.25.0", (api) => {
129135
return;
130136
}
131137

138+
const toasts = api.container.lookup("service:toasts");
132139
// Automatically caption uploaded images
133140
api.addComposerUploadMarkdownResolver(async (upload) => {
134141
const autoCaptionEnabled = currentUser.get(

spec/requests/ai_helper/assistant_controller_spec.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,23 @@
100100
expect(response.parsed_body["diff"]).to eq(expected_diff)
101101
end
102102
end
103+
104+
context "when performing numerous requests" do
105+
it "rate limits" do
106+
RateLimiter.enable
107+
rate_limit = described_class::RATE_LIMITS["default"]
108+
amount = rate_limit[:amount]
109+
110+
amount.times do
111+
post "/discourse-ai/ai-helper/suggest", params: { mode: mode, text: text_to_proofread }
112+
expect(response.status).to eq(200)
113+
end
114+
DiscourseAi::Completions::Llm.with_prepared_responses([proofread_text]) do
115+
post "/discourse-ai/ai-helper/suggest", params: { mode: mode, text: text_to_proofread }
116+
expect(response.status).to eq(429)
117+
end
118+
end
119+
end
103120
end
104121
end
105122

@@ -258,6 +275,25 @@ def request_caption(params)
258275
end
259276
end
260277
end
278+
279+
context "when performing numerous requests" do
280+
it "rate limits" do
281+
RateLimiter.enable
282+
283+
rate_limit = described_class::RATE_LIMITS["caption_image"]
284+
amount = rate_limit[:amount]
285+
286+
amount.times do
287+
request_caption({ image_url: image_url, image_url_type: "long_url" }) do |r|
288+
expect(r.status).to eq(200)
289+
end
290+
end
291+
292+
request_caption({ image_url: image_url, image_url_type: "long_url" }) do |r|
293+
expect(r.status).to eq(429)
294+
end
295+
end
296+
end
261297
end
262298
end
263299
end

0 commit comments

Comments
 (0)