DEV: Clearly separate post/composer helper settings (#747)

This commit is contained in:
Keegan George 2024-08-12 15:40:23 -07:00 committed by GitHub
parent a1eb1ba180
commit f72ab12761
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 77 additions and 56 deletions

View File

@ -165,9 +165,13 @@ module DiscourseAi
end end
def ensure_can_request_suggestions def ensure_can_request_suggestions
if !current_user.in_any_groups?(SiteSetting.ai_helper_allowed_groups_map) allowed_groups =
raise Discourse::InvalidAccess (
end SiteSetting.composer_ai_helper_allowed_groups_map |
SiteSetting.post_ai_helper_allowed_groups_map
)
raise Discourse::InvalidAccess if !current_user.in_any_groups?(allowed_groups)
end end
end end
end end

View File

@ -20,7 +20,5 @@ export function showPostAIHelper(outletArgs, helper) {
} }
function _helperEnabled(siteSettings) { function _helperEnabled(siteSettings) {
return ( return siteSettings.discourse_ai_enabled && siteSettings.ai_helper_enabled;
siteSettings.discourse_ai_enabled && siteSettings.composer_ai_helper_enabled
);
} }

View File

@ -46,8 +46,8 @@ en:
ai_hugging_face_tei_endpoint: URL where the API is running for the Hugging Face text embeddings inference ai_hugging_face_tei_endpoint: URL where the API is running for the Hugging Face text embeddings inference
ai_hugging_face_tei_api_key: API key for Hugging Face text embeddings inference ai_hugging_face_tei_api_key: API key for Hugging Face text embeddings inference
composer_ai_helper_enabled: "Enable the Composer's AI helper." ai_helper_enabled: "Enable the AI helper."
ai_helper_allowed_groups: "Users on these groups will see the AI helper button in the composer." composer_ai_helper_allowed_groups: "Users on these groups will see the AI helper button in the composer."
ai_helper_allowed_in_pm: "Enable the composer's AI helper in PMs." ai_helper_allowed_in_pm: "Enable the composer's AI helper in PMs."
ai_helper_model: "Model to use for the AI helper." ai_helper_model: "Model to use for the AI helper."
ai_helper_custom_prompts_allowed_groups: "Users on these groups will see the custom prompt option in the AI helper." ai_helper_custom_prompts_allowed_groups: "Users on these groups will see the custom prompt option in the AI helper."

View File

@ -96,10 +96,10 @@ discourse_ai:
- opennsfw2 - opennsfw2
- nsfw_detector - nsfw_detector
ai_openai_gpt35_url: ai_openai_gpt35_url:
default: "https://api.openai.com/v1/chat/completions" default: "https://api.openai.com/v1/chat/completions"
hidden: true hidden: true
ai_openai_gpt35_16k_url: ai_openai_gpt35_16k_url:
default: "https://api.openai.com/v1/chat/completions" default: "https://api.openai.com/v1/chat/completions"
hidden: true hidden: true
ai_openai_gpt4o_url: ai_openai_gpt4o_url:
@ -108,15 +108,15 @@ discourse_ai:
ai_openai_gpt4_url: ai_openai_gpt4_url:
default: "https://api.openai.com/v1/chat/completions" default: "https://api.openai.com/v1/chat/completions"
hidden: true hidden: true
ai_openai_gpt4_32k_url: ai_openai_gpt4_32k_url:
default: "https://api.openai.com/v1/chat/completions" default: "https://api.openai.com/v1/chat/completions"
hidden: true hidden: true
ai_openai_gpt4_turbo_url: ai_openai_gpt4_turbo_url:
default: "https://api.openai.com/v1/chat/completions" default: "https://api.openai.com/v1/chat/completions"
hidden: true hidden: true
ai_openai_dall_e_3_url: "https://api.openai.com/v1/images/generations" ai_openai_dall_e_3_url: "https://api.openai.com/v1/images/generations"
ai_openai_embeddings_url: "https://api.openai.com/v1/embeddings" ai_openai_embeddings_url: "https://api.openai.com/v1/embeddings"
ai_openai_organization: ai_openai_organization:
default: "" default: ""
hidden: true hidden: true
ai_openai_api_key: ai_openai_api_key:
@ -206,7 +206,7 @@ discourse_ai:
ai_vllm_endpoint_srv: ai_vllm_endpoint_srv:
default: "" default: ""
hidden: true hidden: true
ai_vllm_api_key: ai_vllm_api_key:
default: "" default: ""
hidden: true hidden: true
ai_llava_endpoint: ai_llava_endpoint:
@ -215,7 +215,7 @@ discourse_ai:
ai_llava_endpoint_srv: ai_llava_endpoint_srv:
default: "" default: ""
hidden: true hidden: true
ai_llava_api_key: ai_llava_api_key:
default: "" default: ""
hidden: true hidden: true
ai_strict_token_counting: ai_strict_token_counting:
@ -225,11 +225,11 @@ discourse_ai:
hidden: true hidden: true
default: "" default: ""
composer_ai_helper_enabled: ai_helper_enabled:
default: false default: false
client: true client: true
validator: "DiscourseAi::Configuration::LlmDependencyValidator" validator: "DiscourseAi::Configuration::LlmDependencyValidator"
ai_helper_allowed_groups: composer_ai_helper_allowed_groups:
type: group_list type: group_list
list_type: compact list_type: compact
default: "3|14" # 3: @staff, 14: @trust_level_4 default: "3|14" # 3: @staff, 14: @trust_level_4

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class RenameAiHelperEnabledSetting < ActiveRecord::Migration[7.1]
def up
execute "UPDATE site_settings SET name = 'ai_helper_enabled' WHERE name = 'composer_ai_helper_enabled'"
end
def down
execute "UPDATE site_settings SET name = 'composer_ai_helper_enabled' WHERE name = 'ai_helper_enabled'"
end
end

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class RenameAiHelperAllowedGroupsSetting < ActiveRecord::Migration[7.1]
def up
execute "UPDATE site_settings SET name = 'composer_ai_helper_allowed_groups' WHERE name = 'ai_helper_allowed_groups'"
end
def down
execute "UPDATE site_settings SET name = 'ai_helper_allowed_groups' WHERE name = 'composer_ai_helper_allowed_groups'"
end
end

View File

@ -151,18 +151,6 @@ module DiscourseAi
bots_map bots_map
end end
plugin.add_to_serializer(:current_user, :can_use_assistant) do
scope.user.in_any_groups?(SiteSetting.ai_helper_allowed_groups_map)
end
plugin.add_to_serializer(:current_user, :can_use_assistant_in_post) do
scope.user.in_any_groups?(SiteSetting.post_ai_helper_allowed_groups_map)
end
plugin.add_to_serializer(:current_user, :can_use_custom_prompts) do
scope.user.in_any_groups?(SiteSetting.ai_helper_custom_prompts_allowed_groups_map)
end
plugin.add_to_serializer(:current_user, :can_share_ai_bot_conversations) do plugin.add_to_serializer(:current_user, :can_share_ai_bot_conversations) do
scope.user.in_any_groups?(SiteSetting.ai_bot_public_sharing_allowed_groups_map) scope.user.in_any_groups?(SiteSetting.ai_bot_public_sharing_allowed_groups_map)
end end

View File

@ -10,8 +10,20 @@ module DiscourseAi
additional_icons = %w[spell-check language images] additional_icons = %w[spell-check language images]
additional_icons.each { |icon| plugin.register_svg_icon(icon) } additional_icons.each { |icon| plugin.register_svg_icon(icon) }
plugin.add_to_serializer(:current_user, :can_use_assistant) do
scope.user.in_any_groups?(SiteSetting.composer_ai_helper_allowed_groups_map)
end
plugin.add_to_serializer(:current_user, :can_use_assistant_in_post) do
scope.user.in_any_groups?(SiteSetting.post_ai_helper_allowed_groups_map)
end
plugin.add_to_serializer(:current_user, :can_use_custom_prompts) do
scope.user.in_any_groups?(SiteSetting.ai_helper_custom_prompts_allowed_groups_map)
end
plugin.on(:chat_message_created) do |message, channel, user, extra| plugin.on(:chat_message_created) do |message, channel, user, extra|
next unless SiteSetting.composer_ai_helper_enabled next unless SiteSetting.ai_helper_enabled
next unless SiteSetting.ai_helper_automatic_chat_thread_title next unless SiteSetting.ai_helper_automatic_chat_thread_title
next if extra[:thread].blank? next if extra[:thread].blank?
next if extra[:thread].title.present? next if extra[:thread].title.present?
@ -32,10 +44,7 @@ module DiscourseAi
plugin.add_to_serializer( plugin.add_to_serializer(
:current_user, :current_user,
:ai_helper_prompts, :ai_helper_prompts,
include_condition: -> do include_condition: -> { SiteSetting.ai_helper_enabled && scope.authenticated? },
SiteSetting.composer_ai_helper_enabled && scope.authenticated? &&
scope.user.in_any_groups?(SiteSetting.ai_helper_allowed_groups_map)
end,
) do ) do
ActiveModel::ArraySerializer.new( ActiveModel::ArraySerializer.new(
DiscourseAi::AiHelper::Assistant.new.available_prompts(scope.user), DiscourseAi::AiHelper::Assistant.new.available_prompts(scope.user),
@ -52,7 +61,7 @@ module DiscourseAi
:user_option, :user_option,
:auto_image_caption, :auto_image_caption,
include_condition: -> do include_condition: -> do
SiteSetting.composer_ai_helper_enabled && SiteSetting.ai_helper_enabled &&
SiteSetting.ai_helper_enabled_features.include?("image_caption") && SiteSetting.ai_helper_enabled_features.include?("image_caption") &&
scope.user.in_any_groups?(SiteSetting.ai_auto_image_caption_allowed_groups_map) scope.user.in_any_groups?(SiteSetting.ai_auto_image_caption_allowed_groups_map)
end, end,
@ -62,7 +71,7 @@ module DiscourseAi
:current_user_option, :current_user_option,
:auto_image_caption, :auto_image_caption,
include_condition: -> do include_condition: -> do
SiteSetting.composer_ai_helper_enabled && SiteSetting.ai_helper_enabled &&
SiteSetting.ai_helper_enabled_features.include?("image_caption") && SiteSetting.ai_helper_enabled_features.include?("image_caption") &&
scope.user.in_any_groups?(SiteSetting.ai_auto_image_caption_allowed_groups_map) scope.user.in_any_groups?(SiteSetting.ai_auto_image_caption_allowed_groups_map)
end, end,

View File

@ -57,7 +57,7 @@ module DiscourseAi
def modules_and_choose_llm_settings def modules_and_choose_llm_settings
{ {
ai_embeddings_semantic_search_enabled: :ai_embeddings_semantic_search_hyde_model, ai_embeddings_semantic_search_enabled: :ai_embeddings_semantic_search_hyde_model,
composer_ai_helper_enabled: :ai_helper_model, ai_helper_enabled: :ai_helper_model,
ai_summarization_enabled: :ai_summarization_model, ai_summarization_enabled: :ai_summarization_model,
} }
end end

View File

@ -19,7 +19,7 @@ RSpec.describe Jobs::StreamPostHelper do
before do before do
Group.find(Group::AUTO_GROUPS[:trust_level_3]).add(user) Group.find(Group::AUTO_GROUPS[:trust_level_3]).add(user)
SiteSetting.composer_ai_helper_enabled = true SiteSetting.ai_helper_enabled = true
end end
describe "validates params" do describe "validates params" do

View File

@ -8,8 +8,8 @@ describe DiscourseAi::AiHelper::EntryPoint do
assign_fake_provider_to(:ai_helper_model) assign_fake_provider_to(:ai_helper_model)
SiteSetting.default_locale = "en" SiteSetting.default_locale = "en"
SiteSetting.allow_user_locale = true SiteSetting.allow_user_locale = true
SiteSetting.composer_ai_helper_enabled = true SiteSetting.ai_helper_enabled = true
SiteSetting.ai_helper_allowed_groups = "10" # tl0 SiteSetting.composer_ai_helper_allowed_groups = "10" # tl0
DiscourseAi::AiHelper::Assistant.clear_prompt_cache! DiscourseAi::AiHelper::Assistant.clear_prompt_cache!
Group.refresh_automatic_groups! Group.refresh_automatic_groups!
@ -40,7 +40,7 @@ describe DiscourseAi::AiHelper::EntryPoint do
it "will include auto_image_caption field in the user_option if image caption is enabled" do it "will include auto_image_caption field in the user_option if image caption is enabled" do
assign_fake_provider_to(:ai_helper_model) assign_fake_provider_to(:ai_helper_model)
assign_fake_provider_to(:ai_helper_image_caption_model) assign_fake_provider_to(:ai_helper_image_caption_model)
SiteSetting.composer_ai_helper_enabled = true SiteSetting.ai_helper_enabled = true
SiteSetting.ai_helper_enabled_features = "image_caption" SiteSetting.ai_helper_enabled_features = "image_caption"
SiteSetting.ai_auto_image_caption_allowed_groups = "10" # tl0 SiteSetting.ai_auto_image_caption_allowed_groups = "10" # tl0
serializer = CurrentUserSerializer.new(english_user, scope: Guardian.new(english_user)) serializer = CurrentUserSerializer.new(english_user, scope: Guardian.new(english_user))

View File

@ -4,7 +4,7 @@ RSpec.describe UserOption do
before do before do
assign_fake_provider_to(:ai_helper_model) assign_fake_provider_to(:ai_helper_model)
assign_fake_provider_to(:ai_helper_image_caption_model) assign_fake_provider_to(:ai_helper_image_caption_model)
SiteSetting.composer_ai_helper_enabled = true SiteSetting.ai_helper_enabled = true
SiteSetting.ai_helper_enabled_features = "image_caption" SiteSetting.ai_helper_enabled_features = "image_caption"
SiteSetting.ai_auto_image_caption_allowed_groups = "10" # tl0 SiteSetting.ai_auto_image_caption_allowed_groups = "10" # tl0
end end

View File

@ -29,7 +29,7 @@ describe Plugin::Instance do
before do before do
assign_fake_provider_to(:ai_helper_model) assign_fake_provider_to(:ai_helper_model)
SiteSetting.composer_ai_helper_enabled = true SiteSetting.ai_helper_enabled = true
SiteSetting.ai_helper_illustrate_post_model = "disabled" SiteSetting.ai_helper_illustrate_post_model = "disabled"
Group.find_by(id: Group::AUTO_GROUPS[:admins]).add(user) Group.find_by(id: Group::AUTO_GROUPS[:admins]).add(user)

View File

@ -21,7 +21,7 @@ RSpec.describe DiscourseAi::AiHelper::AssistantController do
before do before do
sign_in(user) sign_in(user)
SiteSetting.ai_helper_allowed_groups = Group::AUTO_GROUPS[:staff] SiteSetting.composer_ai_helper_allowed_groups = Group::AUTO_GROUPS[:staff]
end end
it "returns a 403 response" do it "returns a 403 response" do
@ -37,7 +37,7 @@ RSpec.describe DiscourseAi::AiHelper::AssistantController do
before do before do
sign_in(user) sign_in(user)
user.group_ids = [Group::AUTO_GROUPS[:trust_level_1]] user.group_ids = [Group::AUTO_GROUPS[:trust_level_1]]
SiteSetting.ai_helper_allowed_groups = Group::AUTO_GROUPS[:trust_level_1] SiteSetting.composer_ai_helper_allowed_groups = Group::AUTO_GROUPS[:trust_level_1]
end end
it "returns a 400 if the helper mode is invalid" do it "returns a 400 if the helper mode is invalid" do
@ -128,7 +128,7 @@ RSpec.describe DiscourseAi::AiHelper::AssistantController do
before do before do
sign_in(user) sign_in(user)
SiteSetting.ai_helper_allowed_groups = Group::AUTO_GROUPS[:trust_level_1] SiteSetting.composer_ai_helper_allowed_groups = Group::AUTO_GROUPS[:trust_level_1]
end end
it "returns the suggested caption for the image" do it "returns the suggested caption for the image" do
@ -208,9 +208,9 @@ RSpec.describe DiscourseAi::AiHelper::AssistantController do
stub_s3_store stub_s3_store
assign_fake_provider_to(:ai_helper_image_caption_model) assign_fake_provider_to(:ai_helper_image_caption_model)
SiteSetting.secure_uploads = true SiteSetting.secure_uploads = true
SiteSetting.ai_helper_allowed_groups = Group::AUTO_GROUPS[:trust_level_1] SiteSetting.composer_ai_helper_allowed_groups = Group::AUTO_GROUPS[:trust_level_1]
Group.find(SiteSetting.ai_helper_allowed_groups_map.first).add(user) Group.find(SiteSetting.composer_ai_helper_allowed_groups_map.first).add(user)
user.reload user.reload
stub_request( stub_request(

View File

@ -7,7 +7,7 @@ RSpec.describe "AI Composer helper", type: :system, js: true do
before do before do
Group.find_by(id: Group::AUTO_GROUPS[:admins]).add(user) Group.find_by(id: Group::AUTO_GROUPS[:admins]).add(user)
assign_fake_provider_to(:ai_helper_model) assign_fake_provider_to(:ai_helper_model)
SiteSetting.composer_ai_helper_enabled = true SiteSetting.ai_helper_enabled = true
sign_in(user) sign_in(user)
end end
@ -383,7 +383,7 @@ RSpec.describe "AI Composer helper", type: :system, js: true do
context "when AI helper is disabled" do context "when AI helper is disabled" do
let(:mode) { CompletionPrompt::GENERATE_TITLES } let(:mode) { CompletionPrompt::GENERATE_TITLES }
before { SiteSetting.composer_ai_helper_enabled = false } before { SiteSetting.ai_helper_enabled = false }
it "does not trigger AI context menu" do it "does not trigger AI context menu" do
trigger_context_menu(input) trigger_context_menu(input)
@ -400,7 +400,7 @@ RSpec.describe "AI Composer helper", type: :system, js: true do
context "when user is not a member of AI helper allowed group" do context "when user is not a member of AI helper allowed group" do
let(:mode) { CompletionPrompt::GENERATE_TITLES } let(:mode) { CompletionPrompt::GENERATE_TITLES }
before { SiteSetting.ai_helper_allowed_groups = non_member_group.id.to_s } before { SiteSetting.composer_ai_helper_allowed_groups = non_member_group.id.to_s }
it "does not trigger AI context menu" do it "does not trigger AI context menu" do
trigger_context_menu(input) trigger_context_menu(input)

View File

@ -37,7 +37,7 @@ RSpec.describe "AI image caption", type: :system, js: true do
end end
context "when not a member of ai helper group" do context "when not a member of ai helper group" do
before { SiteSetting.ai_helper_allowed_groups = non_member_group.id.to_s } before { SiteSetting.composer_ai_helper_allowed_groups = non_member_group.id.to_s }
include_examples "shows no image caption button" include_examples "shows no image caption button"
end end

View File

@ -29,7 +29,7 @@ RSpec.describe "AI Post helper", type: :system, js: true do
before do before do
Group.find_by(id: Group::AUTO_GROUPS[:admins]).add(user) Group.find_by(id: Group::AUTO_GROUPS[:admins]).add(user)
assign_fake_provider_to(:ai_helper_model) assign_fake_provider_to(:ai_helper_model)
SiteSetting.composer_ai_helper_enabled = true SiteSetting.ai_helper_enabled = true
sign_in(user) sign_in(user)
end end
@ -170,7 +170,7 @@ RSpec.describe "AI Post helper", type: :system, js: true do
end end
context "when AI helper is disabled" do context "when AI helper is disabled" do
before { SiteSetting.composer_ai_helper_enabled = false } before { SiteSetting.ai_helper_enabled = false }
it "does not show the Ask AI button in the post selection toolbar" do it "does not show the Ask AI button in the post selection toolbar" do
select_post_text(post) select_post_text(post)
@ -181,7 +181,7 @@ RSpec.describe "AI Post helper", type: :system, js: true do
context "when user is not a member of the post AI helper allowed group" do context "when user is not a member of the post AI helper allowed group" do
before do before do
SiteSetting.composer_ai_helper_enabled = true SiteSetting.ai_helper_enabled = true
SiteSetting.post_ai_helper_allowed_groups = non_member_group.id.to_s SiteSetting.post_ai_helper_allowed_groups = non_member_group.id.to_s
end end

View File

@ -39,7 +39,7 @@ RSpec.describe "AI Post helper", type: :system, js: true do
before do before do
Group.find_by(id: Group::AUTO_GROUPS[:admins]).add(user) Group.find_by(id: Group::AUTO_GROUPS[:admins]).add(user)
assign_fake_provider_to(:ai_helper_model) assign_fake_provider_to(:ai_helper_model)
SiteSetting.composer_ai_helper_enabled = true SiteSetting.ai_helper_enabled = true
sign_in(user) sign_in(user)
end end