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

Commit 584420b

Browse files
authored
Merge branch 'main' into ux-filter-feature-styles
2 parents 054ff5f + 57b0052 commit 584420b

File tree

7 files changed

+78
-35
lines changed

7 files changed

+78
-35
lines changed

assets/javascripts/discourse/components/ai-features-list.gjs

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ export default class AiFeaturesList extends Component {
7373
return this.args.modules.sortBy("module_name");
7474
}
7575

76+
@action
77+
isSpamModule(aModule) {
78+
return aModule.module_name === "spam";
79+
}
80+
7681
@action
7782
hasGroups(feature) {
7883
return this.groupList(feature).length > 0;
@@ -106,12 +111,20 @@ export default class AiFeaturesList extends Component {
106111
<h3>{{i18n
107112
(concat "discourse_ai.features." module.module_name ".name")
108113
}}</h3>
109-
<DButton
110-
class="edit"
111-
@label="discourse_ai.features.edit"
112-
@route="adminPlugins.show.discourse-ai-features.edit"
113-
@routeModels={{module.id}}
114-
/>
114+
{{#if (this.isSpamModule module)}}
115+
<DButton
116+
class="edit"
117+
@label="discourse_ai.features.edit"
118+
@route="adminPlugins.show.discourse-ai-spam"
119+
/>
120+
{{else}}
121+
<DButton
122+
class="edit"
123+
@label="discourse_ai.features.edit"
124+
@route="adminPlugins.show.discourse-ai-features.edit"
125+
@routeModels={{module.id}}
126+
/>
127+
{{/if}}
115128
</div>
116129
<div>{{i18n
117130
(concat
@@ -194,24 +207,25 @@ export default class AiFeaturesList extends Component {
194207
</span>
195208
{{/if}}
196209
</div>
197-
{{#if feature.personas}}
198-
<div class="ai-feature-card__groups">
199-
<span class="ai-feature-card__label">
200-
{{i18n "discourse_ai.features.groups"}}
201-
</span>
202-
{{#if (this.hasGroups feature)}}
203-
<ul class="ai-feature-card__item-groups">
204-
{{#each (this.groupList feature) as |group|}}
205-
<li>{{group.name}}</li>
206-
{{/each}}
207-
</ul>
208-
{{else}}
210+
{{#unless (this.isSpamModule module)}}
211+
{{#if feature.personas}}
212+
<div class="ai-feature-card__groups">
209213
<span class="ai-feature-card__label">
210-
{{i18n "discourse_ai.features.no_groups"}}
214+
{{i18n "discourse_ai.features.groups"}}
211215
</span>
216+
{{#if (this.hasGroups feature)}}
217+
<ul class="ai-feature-card__item-groups">
218+
{{#each (this.groupList feature) as |group|}}
219+
<li>{{group.name}}</li>
220+
{{/each}}
221+
</ul>
222+
{{else}}
223+
<span class="ai-feature-card__label">
224+
{{i18n "discourse_ai.features.no_groups"}}
225+
</span>
212226
{{/if}}
213227
</div>
214-
{{/if}}
228+
{{/unless}}
215229
</div>
216230
</div>
217231
{{/each}}

config/locales/client.en.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ en:
235235

236236
ai_helper:
237237
name: "Helper"
238-
description: "Assists users in community interaction, such as creating topics, writing posts, and reading content."
238+
description: "Assists users in community interaction, such as creating topics, writing posts, and reading content"
239239
proofread: Proofread text
240240
title_suggestions: "Suggest titles"
241241
explain: "Explain"
@@ -253,6 +253,11 @@ en:
253253
post_raw_translator: "Post raw translator"
254254
topic_title_translator: "Topic title translator"
255255
short_text_translator: "Short text translator"
256+
257+
spam:
258+
name: "Spam"
259+
description: "Identifies potential spam using the selected LLM and flags it for site moderators to inspect in the review queue"
260+
inspect_posts: "Inspect posts"
256261

257262
modals:
258263
select_option: "Select an option..."

lib/configuration/feature.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,19 @@ def bot_features
131131
]
132132
end
133133

134+
def spam_features
135+
feature_cache[:spam] ||= [
136+
new(
137+
"inspect_posts",
138+
nil,
139+
DiscourseAi::Configuration::Module::SPAM_ID,
140+
DiscourseAi::Configuration::Module::SPAM,
141+
persona_ids_lookup: -> { [AiModerationSetting.spam&.ai_persona_id].compact },
142+
llm_models_lookup: -> { [AiModerationSetting.spam&.llm_model].compact },
143+
),
144+
]
145+
end
146+
134147
def lookup_bot_persona_ids
135148
AiPersona
136149
.where(enabled: true)
@@ -182,6 +195,7 @@ def all
182195
ai_helper_features,
183196
translation_features,
184197
bot_features,
198+
spam_features,
185199
].flatten
186200
end
187201

lib/configuration/module.rb

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ class Module
1010
AI_HELPER = "ai_helper"
1111
TRANSLATION = "translation"
1212
BOT = "bot"
13+
SPAM = "spam"
1314

14-
NAMES = [SUMMARIZATION, SEARCH, DISCORD, INFERENCE, AI_HELPER, TRANSLATION, BOT].freeze
15+
NAMES = [SUMMARIZATION, SEARCH, DISCORD, INFERENCE, AI_HELPER, TRANSLATION, BOT, SPAM].freeze
1516

1617
SUMMARIZATION_ID = 1
1718
SEARCH_ID = 2
@@ -20,53 +21,60 @@ class Module
2021
AI_HELPER_ID = 5
2122
TRANSLATION_ID = 6
2223
BOT_ID = 7
24+
SPAM_ID = 8
2325

2426
class << self
2527
def all
2628
[
2729
new(
2830
SUMMARIZATION_ID,
2931
SUMMARIZATION,
30-
"ai_summarization_enabled",
32+
enabled_by_setting: "ai_summarization_enabled",
3133
features: DiscourseAi::Configuration::Feature.summarization_features,
3234
),
3335
new(
3436
SEARCH_ID,
3537
SEARCH,
36-
"ai_bot_enabled",
38+
enabled_by_setting: "ai_bot_enabled",
3739
features: DiscourseAi::Configuration::Feature.search_features,
3840
extra_check: -> { SiteSetting.ai_bot_discover_persona.present? },
3941
),
4042
new(
4143
DISCORD_ID,
4244
DISCORD,
43-
"ai_discord_search_enabled",
45+
enabled_by_setting: "ai_discord_search_enabled",
4446
features: DiscourseAi::Configuration::Feature.discord_features,
4547
),
4648
new(
4749
INFERENCE_ID,
4850
INFERENCE,
49-
"inferred_concepts_enabled",
51+
enabled_by_setting: "inferred_concepts_enabled",
5052
features: DiscourseAi::Configuration::Feature.inference_features,
5153
),
5254
new(
5355
AI_HELPER_ID,
5456
AI_HELPER,
55-
"ai_helper_enabled",
57+
enabled_by_setting: "ai_helper_enabled",
5658
features: DiscourseAi::Configuration::Feature.ai_helper_features,
5759
),
5860
new(
5961
TRANSLATION_ID,
6062
TRANSLATION,
61-
"ai_translation_enabled",
63+
enabled_by_setting: "ai_translation_enabled",
6264
features: DiscourseAi::Configuration::Feature.translation_features,
6365
),
6466
new(
6567
BOT_ID,
6668
BOT,
67-
"ai_bot_enabled",
69+
enabled_by_setting: "ai_bot_enabled",
6870
features: DiscourseAi::Configuration::Feature.bot_features,
6971
),
72+
new(
73+
SPAM_ID,
74+
SPAM,
75+
enabled_by_setting: "ai_spam_detection_enabled",
76+
features: DiscourseAi::Configuration::Feature.spam_features,
77+
),
7078
]
7179
end
7280

@@ -75,7 +83,7 @@ def find_by(id:)
7583
end
7684
end
7785

78-
def initialize(id, name, enabled_by_setting, features: [], extra_check: nil)
86+
def initialize(id, name, enabled_by_setting: nil, features: [], extra_check: nil)
7987
@id = id
8088
@name = name
8189
@enabled_by_setting = enabled_by_setting
@@ -86,6 +94,8 @@ def initialize(id, name, enabled_by_setting, features: [], extra_check: nil)
8694
attr_reader :id, :name, :enabled_by_setting, :features
8795

8896
def enabled?
97+
return @extra_check.call if enabled_by_setting.blank? && @extra_check.present?
98+
8999
enabled_setting = SiteSetting.get(enabled_by_setting)
90100

91101
if @extra_check

lib/personas/spam_detector.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ def system_prompt
4444
- Site description: {site_description}
4545
- Site top 10 categories: {top_categories}
4646
47-
Format your response as a JSON object with a one key named "spam", which indicates if a post is spam or legitimate.
47+
Format your response as a JSON object with a one key named "spam", which is a boolean that indicates if a post is spam or legitimate.
4848
Your output should be in the following format:
4949
<output>
50-
{"spam": "xx"}
50+
{"spam": xx}
5151
</output>
5252
53-
Where "xx" is true if the post is spam, or false if it's legitimate.
53+
Where xx is true if the post is spam, or false if it's legitimate.
5454
PROMPT
5555
end
5656

spec/requests/admin/ai_features_controller_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
get "/admin/plugins/discourse-ai/ai-features.json"
2020

2121
expect(response.status).to eq(200)
22-
expect(response.parsed_body["ai_features"].count).to eq(7)
22+
expect(response.parsed_body["ai_features"].count).to eq(8)
2323
end
2424
end
2525

spec/system/admin_ai_features_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
ai_features_page.toggle_unconfigured
2929

3030
# this changes as we add more AI features
31-
expect(ai_features_page).to have_listed_modules(6)
31+
expect(ai_features_page).to have_listed_modules(7)
3232
end
3333

3434
it "lists the persona used for the corresponding AI feature" do

0 commit comments

Comments
 (0)