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;
|
||||
|
||||
@action
|
||||
async composeMessageWithTargetBot(target) {
|
||||
composeMessageWithTargetBot(target) {
|
||||
this.#composeAiBotMessage(target);
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ export default class AiBotHeaderPanel extends Component {
|
|||
return this.siteSettings.ai_bot_enabled_chat_bots.split("|");
|
||||
}
|
||||
|
||||
async #composeAiBotMessage(targetBot) {
|
||||
#composeAiBotMessage(targetBot) {
|
||||
this.args.closePanel();
|
||||
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 I18n from "I18n";
|
||||
|
||||
export async function composeAiBotMessage(targetBot, composer) {
|
||||
let botUsername = await ajax("/discourse-ai/ai-bot/bot-username", {
|
||||
data: { username: targetBot },
|
||||
}).then((data) => {
|
||||
return data.bot_username;
|
||||
});
|
||||
export function composeAiBotMessage(targetBot, composer) {
|
||||
const currentUser = composer.currentUser;
|
||||
|
||||
let botUsername = currentUser.ai_enabled_chat_bots.find(
|
||||
(bot) => bot.model_name === targetBot
|
||||
).username;
|
||||
|
||||
composer.focusComposer({
|
||||
fallbackToNewTopic: true,
|
||||
|
|
|
@ -2,6 +2,25 @@ nav.post-controls .actions button.cancel-streaming {
|
|||
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 {
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ en:
|
|||
semantic_search: "Topics (Semantic)"
|
||||
|
||||
ai_bot:
|
||||
pm_warning: "AI chatbot messages are monitored regularly by moderators."
|
||||
cancel_streaming: "Stop reply"
|
||||
default_pm_prefix: "[Untitled AI bot PM]"
|
||||
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_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_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"
|
||||
|
|
|
@ -179,6 +179,9 @@ plugins:
|
|||
ai_bot_enabled:
|
||||
default: false
|
||||
client: true
|
||||
ai_bot_enable_chat_warning:
|
||||
default: false
|
||||
client: true
|
||||
ai_bot_allowed_groups:
|
||||
client: true
|
||||
type: group_list
|
||||
|
|
|
@ -43,6 +43,33 @@ module DiscourseAi
|
|||
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.on(:post_created) do |post|
|
||||
|
|
Loading…
Reference in New Issue