FEATURE: optional warning attached to all AI bot conversations (#137)
* FEATURE: optional warning attached to all AI bot conversations This commit introduces `ai_bot_enable_chat_warning` which can be used to warn people prior to starting a chat with the bot. In particular this is useful if moderators are regularly reading chat transcripts as it sets expectations early. By default this is disabled. Also: - Stops making ajax call prior to opening composer - Hides PM title when starting a bot PM Co-authored-by: Rafael dos Santos Silva <xfalcox@gmail.com>
This commit is contained in:
parent
49f2453c2d
commit
01f833f86e
|
@ -10,7 +10,7 @@ export default class AiBotHeaderPanel extends Component {
|
||||||
@service composer;
|
@service composer;
|
||||||
|
|
||||||
@action
|
@action
|
||||||
async composeMessageWithTargetBot(target) {
|
composeMessageWithTargetBot(target) {
|
||||||
this.#composeAiBotMessage(target);
|
this.#composeAiBotMessage(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ export default class AiBotHeaderPanel extends Component {
|
||||||
return this.siteSettings.ai_bot_enabled_chat_bots.split("|");
|
return this.siteSettings.ai_bot_enabled_chat_bots.split("|");
|
||||||
}
|
}
|
||||||
|
|
||||||
async #composeAiBotMessage(targetBot) {
|
#composeAiBotMessage(targetBot) {
|
||||||
this.args.closePanel();
|
this.args.closePanel();
|
||||||
composeAiBotMessage(targetBot, this.composer);
|
composeAiBotMessage(targetBot, this.composer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
{{#if this.isAiBotChat}}
|
||||||
|
<DSection @bodyClass="ai-bot-chat" />
|
||||||
|
{{#if this.renderChatWarning}}
|
||||||
|
<div class="ai-bot-chat-warning">{{i18n
|
||||||
|
"discourse_ai.ai_bot.pm_warning"
|
||||||
|
}}</div>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
|
@ -0,0 +1,32 @@
|
||||||
|
import Component from "@glimmer/component";
|
||||||
|
import { inject as service } from "@ember/service";
|
||||||
|
import { computed } from "@ember/object";
|
||||||
|
|
||||||
|
export default class extends Component {
|
||||||
|
static shouldRender() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@service currentUser;
|
||||||
|
@service siteSettings;
|
||||||
|
|
||||||
|
get composerModel() {
|
||||||
|
return this.args.outletArgs.model;
|
||||||
|
}
|
||||||
|
|
||||||
|
get renderChatWarning() {
|
||||||
|
return this.siteSettings.ai_bot_enable_chat_warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed("composerModel.targetRecipients")
|
||||||
|
get isAiBotChat() {
|
||||||
|
if (this.composerModel.targetRecipients) {
|
||||||
|
let reciepients = this.composerModel.targetRecipients.split(",");
|
||||||
|
|
||||||
|
return this.currentUser.ai_enabled_chat_bots.any((bot) =>
|
||||||
|
reciepients.any((username) => username === bot.username)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,12 @@
|
||||||
import { ajax } from "discourse/lib/ajax";
|
|
||||||
import Composer from "discourse/models/composer";
|
import Composer from "discourse/models/composer";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
|
|
||||||
export async function composeAiBotMessage(targetBot, composer) {
|
export function composeAiBotMessage(targetBot, composer) {
|
||||||
let botUsername = await ajax("/discourse-ai/ai-bot/bot-username", {
|
const currentUser = composer.currentUser;
|
||||||
data: { username: targetBot },
|
|
||||||
}).then((data) => {
|
let botUsername = currentUser.ai_enabled_chat_bots.find(
|
||||||
return data.bot_username;
|
(bot) => bot.model_name === targetBot
|
||||||
});
|
).username;
|
||||||
|
|
||||||
composer.focusComposer({
|
composer.focusComposer({
|
||||||
fallbackToNewTopic: true,
|
fallbackToNewTopic: true,
|
||||||
|
|
|
@ -2,6 +2,25 @@ nav.post-controls .actions button.cancel-streaming {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ai-bot-chat #reply-control {
|
||||||
|
.title-input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bot-chat-warning {
|
||||||
|
color: var(--tertiary);
|
||||||
|
background-color: var(--tertiary-low);
|
||||||
|
box-shadow: 0px 0px 0px 2px var(--tertiary-medium);
|
||||||
|
opacity: 0.75;
|
||||||
|
.d-icon {
|
||||||
|
color: var(--tertiary);
|
||||||
|
}
|
||||||
|
margin: 10px 2px 0;
|
||||||
|
padding: 4px 10px;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
article.streaming nav.post-controls .actions button.cancel-streaming {
|
article.streaming nav.post-controls .actions button.cancel-streaming {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ en:
|
||||||
semantic_search: "Topics (Semantic)"
|
semantic_search: "Topics (Semantic)"
|
||||||
|
|
||||||
ai_bot:
|
ai_bot:
|
||||||
|
pm_warning: "AI chatbot messages are monitored regularly by moderators."
|
||||||
cancel_streaming: "Stop reply"
|
cancel_streaming: "Stop reply"
|
||||||
default_pm_prefix: "[Untitled AI bot PM]"
|
default_pm_prefix: "[Untitled AI bot PM]"
|
||||||
shortcut_title: "Start a PM with an AI bot"
|
shortcut_title: "Start a PM with an AI bot"
|
||||||
|
|
|
@ -58,6 +58,7 @@ en:
|
||||||
ai_summarization_discourse_service_api_key: "API key for the Discourse summarization API."
|
ai_summarization_discourse_service_api_key: "API key for the Discourse summarization API."
|
||||||
|
|
||||||
ai_bot_enabled: "Enable the AI Bot module."
|
ai_bot_enabled: "Enable the AI Bot module."
|
||||||
|
ai_bot_enable_chat_warning: "Display a warning when PM chat is initiated. Can be overriden by editing the translation string: discourse_ai.ai_bot.pm_warning"
|
||||||
ai_bot_allowed_groups: "When the GPT Bot has access to the PM, it will reply to members of these groups."
|
ai_bot_allowed_groups: "When the GPT Bot has access to the PM, it will reply to members of these groups."
|
||||||
ai_bot_enabled_chat_bots: "Available models to act as an AI Bot"
|
ai_bot_enabled_chat_bots: "Available models to act as an AI Bot"
|
||||||
ai_bot_enabled_chat_commands: "Available GPT integrations used to provide external functionality to the model. Only works with GPT-4 and GPT-3.5"
|
ai_bot_enabled_chat_commands: "Available GPT integrations used to provide external functionality to the model. Only works with GPT-4 and GPT-3.5"
|
||||||
|
|
|
@ -179,6 +179,9 @@ plugins:
|
||||||
ai_bot_enabled:
|
ai_bot_enabled:
|
||||||
default: false
|
default: false
|
||||||
client: true
|
client: true
|
||||||
|
ai_bot_enable_chat_warning:
|
||||||
|
default: false
|
||||||
|
client: true
|
||||||
ai_bot_allowed_groups:
|
ai_bot_allowed_groups:
|
||||||
client: true
|
client: true
|
||||||
type: group_list
|
type: group_list
|
||||||
|
|
|
@ -43,6 +43,33 @@ module DiscourseAi
|
||||||
Rails.root.join("plugins", "discourse-ai", "db", "fixtures", "ai_bot"),
|
Rails.root.join("plugins", "discourse-ai", "db", "fixtures", "ai_bot"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
plugin.add_to_serializer(
|
||||||
|
:current_user,
|
||||||
|
:ai_enabled_chat_bots,
|
||||||
|
include_condition: -> do
|
||||||
|
SiteSetting.ai_bot_enabled && scope.authenticated? &&
|
||||||
|
scope.user.in_any_groups?(SiteSetting.ai_bot_allowed_groups_map)
|
||||||
|
end,
|
||||||
|
) do
|
||||||
|
model_map = {}
|
||||||
|
SiteSetting
|
||||||
|
.ai_bot_enabled_chat_bots
|
||||||
|
.split("|")
|
||||||
|
.each do |bot_name|
|
||||||
|
model_map[
|
||||||
|
::DiscourseAi::AiBot::EntryPoint.map_bot_model_to_user_id(bot_name)
|
||||||
|
] = bot_name
|
||||||
|
end
|
||||||
|
|
||||||
|
# not 100% ideal, cause it is one extra query, but we need it
|
||||||
|
bots = DB.query_hash(<<~SQL, user_ids: model_map.keys)
|
||||||
|
SELECT username, id FROM users WHERE id IN (:user_ids)
|
||||||
|
SQL
|
||||||
|
|
||||||
|
bots.each { |hash| hash["model_name"] = model_map[hash["id"]] }
|
||||||
|
bots
|
||||||
|
end
|
||||||
|
|
||||||
plugin.register_svg_icon("robot")
|
plugin.register_svg_icon("robot")
|
||||||
|
|
||||||
plugin.on(:post_created) do |post|
|
plugin.on(:post_created) do |post|
|
||||||
|
|
Loading…
Reference in New Issue