FEATURE: Display spam module on features list. (#1469)

This commit is contained in:
Roman Rizzi 2025-06-27 14:18:01 -03:00 committed by GitHub
parent b35f9bcc7c
commit 8d943fa29d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 76 additions and 32 deletions

View File

@ -68,6 +68,11 @@ export default class AiFeaturesList extends Component {
}); });
} }
@action
isSpamModule(aModule) {
return aModule.module_name === "spam";
}
@action @action
hasGroups(feature) { hasGroups(feature) {
return this.groupList(feature).length > 0; return this.groupList(feature).length > 0;
@ -101,12 +106,20 @@ export default class AiFeaturesList extends Component {
<h3>{{i18n <h3>{{i18n
(concat "discourse_ai.features." module.module_name ".name") (concat "discourse_ai.features." module.module_name ".name")
}}</h3> }}</h3>
<DButton {{#if (this.isSpamModule module)}}
class="edit" <DButton
@label="discourse_ai.features.edit" class="edit"
@route="adminPlugins.show.discourse-ai-features.edit" @label="discourse_ai.features.edit"
@routeModels={{module.id}} @route="adminPlugins.show.discourse-ai-spam"
/> />
{{else}}
<DButton
class="edit"
@label="discourse_ai.features.edit"
@route="adminPlugins.show.discourse-ai-features.edit"
@routeModels={{module.id}}
/>
{{/if}}
</div> </div>
<div>{{i18n <div>{{i18n
(concat (concat
@ -181,20 +194,22 @@ export default class AiFeaturesList extends Component {
{{i18n "discourse_ai.features.no_llm"}} {{i18n "discourse_ai.features.no_llm"}}
{{/if}} {{/if}}
</div> </div>
{{#if feature.personas}} {{#unless (this.isSpamModule module)}}
<div class="ai-feature-card__groups"> {{#if feature.personas}}
<span>{{i18n "discourse_ai.features.groups"}}</span> <div class="ai-feature-card__groups">
{{#if (this.hasGroups feature)}} <span>{{i18n "discourse_ai.features.groups"}}</span>
<ul class="ai-feature-card__item-groups"> {{#if (this.hasGroups feature)}}
{{#each (this.groupList feature) as |group|}} <ul class="ai-feature-card__item-groups">
<li>{{group.name}}</li> {{#each (this.groupList feature) as |group|}}
{{/each}} <li>{{group.name}}</li>
</ul> {{/each}}
{{else}} </ul>
{{i18n "discourse_ai.features.no_groups"}} {{else}}
{{/if}} {{i18n "discourse_ai.features.no_groups"}}
</div> {{/if}}
{{/if}} </div>
{{/if}}
{{/unless}}
</div> </div>
</div> </div>
{{/each}} {{/each}}

View File

@ -230,7 +230,7 @@ en:
ai_helper: ai_helper:
name: "Helper" name: "Helper"
description: "Assists users in community interaction, such as creating topics, writing posts, and reading content." description: "Assists users in community interaction, such as creating topics, writing posts, and reading content"
proofread: Proofread text proofread: Proofread text
title_suggestions: "Suggest titles" title_suggestions: "Suggest titles"
explain: "Explain" explain: "Explain"
@ -248,6 +248,11 @@ en:
post_raw_translator: "Post raw translator" post_raw_translator: "Post raw translator"
topic_title_translator: "Topic title translator" topic_title_translator: "Topic title translator"
short_text_translator: "Short text translator" short_text_translator: "Short text translator"
spam:
name: "Spam"
description: "Identifies potential spam using the selected LLM and flags it for site moderators to inspect in the review queue"
inspect_posts: "Inspect posts"
modals: modals:
select_option: "Select an option..." select_option: "Select an option..."

View File

@ -131,6 +131,19 @@ module DiscourseAi
] ]
end end
def spam_features
feature_cache[:spam] ||= [
new(
"inspect_posts",
nil,
DiscourseAi::Configuration::Module::SPAM_ID,
DiscourseAi::Configuration::Module::SPAM,
persona_ids_lookup: -> { [AiModerationSetting.spam&.ai_persona_id].compact },
llm_models_lookup: -> { [AiModerationSetting.spam&.llm_model].compact },
),
]
end
def lookup_bot_persona_ids def lookup_bot_persona_ids
AiPersona AiPersona
.where(enabled: true) .where(enabled: true)
@ -182,6 +195,7 @@ module DiscourseAi
ai_helper_features, ai_helper_features,
translation_features, translation_features,
bot_features, bot_features,
spam_features,
].flatten ].flatten
end end

View File

@ -10,8 +10,9 @@ module DiscourseAi
AI_HELPER = "ai_helper" AI_HELPER = "ai_helper"
TRANSLATION = "translation" TRANSLATION = "translation"
BOT = "bot" BOT = "bot"
SPAM = "spam"
NAMES = [SUMMARIZATION, SEARCH, DISCORD, INFERENCE, AI_HELPER, TRANSLATION, BOT].freeze NAMES = [SUMMARIZATION, SEARCH, DISCORD, INFERENCE, AI_HELPER, TRANSLATION, BOT, SPAM].freeze
SUMMARIZATION_ID = 1 SUMMARIZATION_ID = 1
SEARCH_ID = 2 SEARCH_ID = 2
@ -20,6 +21,7 @@ module DiscourseAi
AI_HELPER_ID = 5 AI_HELPER_ID = 5
TRANSLATION_ID = 6 TRANSLATION_ID = 6
BOT_ID = 7 BOT_ID = 7
SPAM_ID = 8
class << self class << self
def all def all
@ -27,46 +29,52 @@ module DiscourseAi
new( new(
SUMMARIZATION_ID, SUMMARIZATION_ID,
SUMMARIZATION, SUMMARIZATION,
"ai_summarization_enabled", enabled_by_setting: "ai_summarization_enabled",
features: DiscourseAi::Configuration::Feature.summarization_features, features: DiscourseAi::Configuration::Feature.summarization_features,
), ),
new( new(
SEARCH_ID, SEARCH_ID,
SEARCH, SEARCH,
"ai_bot_enabled", enabled_by_setting: "ai_bot_enabled",
features: DiscourseAi::Configuration::Feature.search_features, features: DiscourseAi::Configuration::Feature.search_features,
extra_check: -> { SiteSetting.ai_bot_discover_persona.present? }, extra_check: -> { SiteSetting.ai_bot_discover_persona.present? },
), ),
new( new(
DISCORD_ID, DISCORD_ID,
DISCORD, DISCORD,
"ai_discord_search_enabled", enabled_by_setting: "ai_discord_search_enabled",
features: DiscourseAi::Configuration::Feature.discord_features, features: DiscourseAi::Configuration::Feature.discord_features,
), ),
new( new(
INFERENCE_ID, INFERENCE_ID,
INFERENCE, INFERENCE,
"inferred_concepts_enabled", enabled_by_setting: "inferred_concepts_enabled",
features: DiscourseAi::Configuration::Feature.inference_features, features: DiscourseAi::Configuration::Feature.inference_features,
), ),
new( new(
AI_HELPER_ID, AI_HELPER_ID,
AI_HELPER, AI_HELPER,
"ai_helper_enabled", enabled_by_setting: "ai_helper_enabled",
features: DiscourseAi::Configuration::Feature.ai_helper_features, features: DiscourseAi::Configuration::Feature.ai_helper_features,
), ),
new( new(
TRANSLATION_ID, TRANSLATION_ID,
TRANSLATION, TRANSLATION,
"ai_translation_enabled", enabled_by_setting: "ai_translation_enabled",
features: DiscourseAi::Configuration::Feature.translation_features, features: DiscourseAi::Configuration::Feature.translation_features,
), ),
new( new(
BOT_ID, BOT_ID,
BOT, BOT,
"ai_bot_enabled", enabled_by_setting: "ai_bot_enabled",
features: DiscourseAi::Configuration::Feature.bot_features, features: DiscourseAi::Configuration::Feature.bot_features,
), ),
new(
SPAM_ID,
SPAM,
enabled_by_setting: "ai_spam_detection_enabled",
features: DiscourseAi::Configuration::Feature.spam_features,
),
] ]
end end
@ -75,7 +83,7 @@ module DiscourseAi
end end
end end
def initialize(id, name, enabled_by_setting, features: [], extra_check: nil) def initialize(id, name, enabled_by_setting: nil, features: [], extra_check: nil)
@id = id @id = id
@name = name @name = name
@enabled_by_setting = enabled_by_setting @enabled_by_setting = enabled_by_setting
@ -86,6 +94,8 @@ module DiscourseAi
attr_reader :id, :name, :enabled_by_setting, :features attr_reader :id, :name, :enabled_by_setting, :features
def enabled? def enabled?
return @extra_check.call if enabled_by_setting.blank? && @extra_check.present?
enabled_setting = SiteSetting.get(enabled_by_setting) enabled_setting = SiteSetting.get(enabled_by_setting)
if @extra_check if @extra_check

View File

@ -19,7 +19,7 @@ RSpec.describe DiscourseAi::Admin::AiFeaturesController do
get "/admin/plugins/discourse-ai/ai-features.json" get "/admin/plugins/discourse-ai/ai-features.json"
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(response.parsed_body["ai_features"].count).to eq(7) expect(response.parsed_body["ai_features"].count).to eq(8)
end end
end end

View File

@ -28,7 +28,7 @@ RSpec.describe "Admin AI features configuration", type: :system, js: true do
ai_features_page.toggle_unconfigured ai_features_page.toggle_unconfigured
# this changes as we add more AI features # this changes as we add more AI features
expect(ai_features_page).to have_listed_modules(6) expect(ai_features_page).to have_listed_modules(7)
end end
it "lists the persona used for the corresponding AI feature" do it "lists the persona used for the corresponding AI feature" do