Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47fdb1acbf |
@@ -1,12 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module DiscourseAi
|
||||
module Admin
|
||||
class DashboardController < ::Admin::StaffController
|
||||
requires_plugin DiscourseAi::PLUGIN_NAME
|
||||
|
||||
def sentiment
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,121 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AiPersona < ActiveRecord::Base
|
||||
# places a hard limit, so per site we cache a maximum of 500 classes
|
||||
MAX_PERSONAS_PER_SITE = 500
|
||||
|
||||
class MultisiteHash
|
||||
def initialize(id)
|
||||
@hash = Hash.new { |h, k| h[k] = {} }
|
||||
@id = id
|
||||
|
||||
MessageBus.subscribe(channel_name) { |message| @hash[message.data] = {} }
|
||||
end
|
||||
|
||||
def channel_name
|
||||
"/multisite-hash-#{@id}"
|
||||
end
|
||||
|
||||
def current_db
|
||||
RailsMultisite::ConnectionManagement.current_db
|
||||
end
|
||||
|
||||
def [](key)
|
||||
@hash.dig(current_db, key)
|
||||
end
|
||||
|
||||
def []=(key, val)
|
||||
@hash[current_db][key] = val
|
||||
end
|
||||
|
||||
def flush!
|
||||
@hash[current_db] = {}
|
||||
MessageBus.publish(channel_name, current_db)
|
||||
end
|
||||
end
|
||||
|
||||
def self.persona_cache
|
||||
@persona_cache ||= MultisiteHash.new("persona_cache")
|
||||
end
|
||||
|
||||
def self.all_personas
|
||||
persona_cache[:value] ||= AiPersona
|
||||
.order(:name)
|
||||
.where(enabled: true)
|
||||
.all
|
||||
.limit(MAX_PERSONAS_PER_SITE)
|
||||
.map do |ai_persona|
|
||||
name = ai_persona.name
|
||||
description = ai_persona.description
|
||||
ai_persona_id = ai_persona.id
|
||||
allowed_group_ids = ai_persona.allowed_group_ids
|
||||
commands =
|
||||
ai_persona.commands.filter_map do |inner_name|
|
||||
begin
|
||||
("DiscourseAi::AiBot::Commands::#{inner_name}").constantize
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
Class.new(DiscourseAi::AiBot::Personas::Persona) do
|
||||
define_singleton_method :name do
|
||||
name
|
||||
end
|
||||
|
||||
define_singleton_method :description do
|
||||
description
|
||||
end
|
||||
|
||||
define_singleton_method :allowed_group_ids do
|
||||
allowed_group_ids
|
||||
end
|
||||
|
||||
define_singleton_method :to_s do
|
||||
"#<DiscourseAi::AiBot::Personas::Persona::Custom @name=#{self.name} @allowed_group_ids=#{self.allowed_group_ids.join(",")}>"
|
||||
end
|
||||
|
||||
define_singleton_method :inspect do
|
||||
"#<DiscourseAi::AiBot::Personas::Persona::Custom @name=#{self.name} @allowed_group_ids=#{self.allowed_group_ids.join(",")}>"
|
||||
end
|
||||
|
||||
define_method :initialize do |*args, **kwargs|
|
||||
@ai_persona = AiPersona.find_by(id: ai_persona_id)
|
||||
super(*args, **kwargs)
|
||||
end
|
||||
|
||||
define_method :commands do
|
||||
commands
|
||||
end
|
||||
|
||||
define_method :system_prompt do
|
||||
@ai_persona&.system_prompt || "You are a helpful bot."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
after_commit :bump_cache
|
||||
|
||||
def bump_cache
|
||||
self.class.persona_cache.flush!
|
||||
end
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: ai_personas
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# name :string(100) not null
|
||||
# description :string(2000) not null
|
||||
# commands :string default([]), not null, is an Array
|
||||
# system_prompt :string not null
|
||||
# allowed_group_ids :integer default([]), not null, is an Array
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_ai_personas_on_name (name) UNIQUE
|
||||
#
|
||||
@@ -1,10 +0,0 @@
|
||||
export default {
|
||||
resource: "admin.dashboard",
|
||||
path: "/dashboard",
|
||||
map() {
|
||||
this.route("admin.dashboardSentiment", {
|
||||
path: "/dashboard/sentiment",
|
||||
resetNamespace: true,
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -1,8 +1,13 @@
|
||||
import Component from "@glimmer/component";
|
||||
import ChatChannel from "discourse/plugins/chat/discourse/models/chat-channel";
|
||||
import { inject as service } from "@ember/service";
|
||||
|
||||
export default class ReviewableAiChatMessage extends Component {
|
||||
@service store;
|
||||
|
||||
get chatChannel() {
|
||||
return ChatChannel.create(this.args.reviewable.chat_channel);
|
||||
return this.store.createRecord(
|
||||
"chat-channel",
|
||||
this.args.reviewable.chat_channel
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { LinkTo } from "@ember/routing";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
const i18n = I18n.t.bind(I18n);
|
||||
|
||||
export default class AISentimentDashboard extends Component {
|
||||
<template>
|
||||
<li class="navigation-item sentiment">
|
||||
<LinkTo @route="admin.dashboardSentiment" class="navigation-link">
|
||||
{{i18n "discourse_ai.sentiments.dashboard.title"}}
|
||||
</LinkTo>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
static shouldRender(_outletArgs, helper) {
|
||||
return helper.siteSettings.ai_sentiment_enabled;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
import Controller from "@ember/controller";
|
||||
import { action } from "@ember/object";
|
||||
import { inject as service } from "@ember/service";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import CustomDateRangeModal from "admin/components/modal/custom-date-range";
|
||||
import PeriodComputationMixin from "admin/mixins/period-computation";
|
||||
|
||||
export default class AdminDashboardSentiment extends Controller.extend(
|
||||
PeriodComputationMixin
|
||||
) {
|
||||
@service modal;
|
||||
|
||||
@discourseComputed("startDate", "endDate")
|
||||
filters(startDate, endDate) {
|
||||
return { startDate, endDate };
|
||||
}
|
||||
|
||||
_reportsForPeriodURL(period) {
|
||||
return getURL(`/admin/dashboard/sentiment?period=${period}`);
|
||||
}
|
||||
|
||||
@action
|
||||
setCustomDateRange(startDate, endDate) {
|
||||
this.setProperties({ startDate, endDate });
|
||||
}
|
||||
|
||||
@action
|
||||
openCustomDateRangeModal() {
|
||||
this.modal.show(CustomDateRangeModal, {
|
||||
model: {
|
||||
startDate: this.startDate,
|
||||
endDate: this.endDate,
|
||||
setCustomDateRange: this.setCustomDateRange,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<div class="sentiment section">
|
||||
<div class="period-section">
|
||||
<div class="section-title">
|
||||
<h2>
|
||||
{{i18n "discourse_ai.sentiments.dashboard.title"}}
|
||||
</h2>
|
||||
<span>
|
||||
<PeriodChooser
|
||||
@period={{this.period}}
|
||||
@action={{action "changePeriod"}}
|
||||
@content={{this.availablePeriods}}
|
||||
@fullDay={{false}}
|
||||
/>
|
||||
<DButton
|
||||
@icon="cog"
|
||||
class="custom-date-range-button"
|
||||
@action={{this.openCustomDateRangeModal}}
|
||||
@title="admin.dashboard.custom_date_range"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-body">
|
||||
<div class="charts">
|
||||
<AdminReport
|
||||
@dataSourceName="overall_sentiment"
|
||||
@filters={{this.filters}}
|
||||
@showHeader={{true}}
|
||||
/>
|
||||
|
||||
<AdminReport
|
||||
@dataSourceName="post_emotion"
|
||||
@filters={{this.filters}}
|
||||
@showHeader={{true}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -262,6 +262,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
#reply-control .showing-ai-suggestions .category-chooser {
|
||||
max-width: calc(100% - 41px); // width of AI button
|
||||
}
|
||||
|
||||
.suggest-tags-button,
|
||||
.suggest-category-button {
|
||||
display: block;
|
||||
@@ -292,13 +296,17 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// Prevent suggestion button from wrapping
|
||||
#reply-control {
|
||||
.with-category .showing-ai-suggestions .category-input,
|
||||
.with-tags .showing-ai-suggestions .mini-tag-chooser {
|
||||
flex-wrap: nowrap;
|
||||
.select-kit {
|
||||
max-width: calc(100% - 34px);
|
||||
// Prevent suggestion button from wrapping on smaller screens
|
||||
@media screen and (max-width: 768px) {
|
||||
#reply-control .composer-fields.showing-ai-suggestions {
|
||||
.category-input {
|
||||
.category-chooser {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
+ .mini-tag-chooser {
|
||||
width: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
.dashboard.dashboard-sentiment {
|
||||
.sentiment {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.navigation-item.sentiment {
|
||||
border-bottom: 0.4em solid var(--tertiary);
|
||||
}
|
||||
|
||||
.charts {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(12, 1fr);
|
||||
grid-column-gap: 1em;
|
||||
grid-row-gap: 1em;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
.dashboard.dashboard-sentiment .charts {
|
||||
.overall-sentiment {
|
||||
grid-column: span 8;
|
||||
}
|
||||
.post-emotion {
|
||||
grid-column: span 4;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
.dashboard.dashboard-sentiment {
|
||||
.charts {
|
||||
.overall-sentiment {
|
||||
grid-column: span 12;
|
||||
}
|
||||
.post-emotion {
|
||||
grid-column: span 12;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,9 +93,6 @@ de:
|
||||
gpt-3:
|
||||
5-turbo: "GPT-3.5"
|
||||
claude-2: "Claude 2"
|
||||
sentiments:
|
||||
dashboard:
|
||||
title: "Stimmung"
|
||||
review:
|
||||
types:
|
||||
reviewable_ai_post:
|
||||
|
||||
@@ -92,9 +92,6 @@ en:
|
||||
gpt-3:
|
||||
5-turbo: "GPT-3.5"
|
||||
claude-2: "Claude 2"
|
||||
sentiments:
|
||||
dashboard:
|
||||
title: "Sentiment"
|
||||
|
||||
review:
|
||||
types:
|
||||
|
||||
@@ -93,9 +93,6 @@ he:
|
||||
gpt-3:
|
||||
5-turbo: "GPT-3.5"
|
||||
claude-2: "Claude 2"
|
||||
sentiments:
|
||||
dashboard:
|
||||
title: "רגש"
|
||||
review:
|
||||
types:
|
||||
reviewable_ai_post:
|
||||
|
||||
@@ -70,9 +70,6 @@ ar:
|
||||
errors:
|
||||
prompt_message_length: تتجاوز الرسالة الحد الأقصى لعدد الحروف، والبالغ 1000 حرف، بمقدار %{idx}.
|
||||
invalid_prompt_role: تنطوي الرسالة %{idx} على دور غير صالح.
|
||||
reports:
|
||||
overall_sentiment:
|
||||
yaxis: "التاريخ"
|
||||
discourse_ai:
|
||||
ai_helper:
|
||||
errors:
|
||||
@@ -132,7 +129,3 @@ ar:
|
||||
few: "قم بتكوين هذه الإعدادات أولًا: %{settings}"
|
||||
many: "قم بتكوين هذه الإعدادات أولًا: %{settings}"
|
||||
other: "قم بتكوين هذه الإعدادات أولًا: %{settings}"
|
||||
sentiment:
|
||||
reports:
|
||||
post_emotion:
|
||||
neutral: "محايد"
|
||||
|
||||
@@ -5,8 +5,3 @@
|
||||
# https://translate.discourse.org/
|
||||
|
||||
be:
|
||||
discourse_ai:
|
||||
sentiment:
|
||||
reports:
|
||||
post_emotion:
|
||||
neutral: "нейтральны"
|
||||
|
||||
@@ -5,6 +5,3 @@
|
||||
# https://translate.discourse.org/
|
||||
|
||||
bg:
|
||||
reports:
|
||||
overall_sentiment:
|
||||
yaxis: "Дата"
|
||||
|
||||
@@ -5,6 +5,3 @@
|
||||
# https://translate.discourse.org/
|
||||
|
||||
bs_BA:
|
||||
reports:
|
||||
overall_sentiment:
|
||||
yaxis: "Datum"
|
||||
|
||||
@@ -5,11 +5,3 @@
|
||||
# https://translate.discourse.org/
|
||||
|
||||
ca:
|
||||
reports:
|
||||
overall_sentiment:
|
||||
yaxis: "Data"
|
||||
discourse_ai:
|
||||
sentiment:
|
||||
reports:
|
||||
post_emotion:
|
||||
neutral: "Neutre"
|
||||
|
||||
@@ -5,6 +5,3 @@
|
||||
# https://translate.discourse.org/
|
||||
|
||||
cs:
|
||||
reports:
|
||||
overall_sentiment:
|
||||
yaxis: "Datum"
|
||||
|
||||
@@ -5,11 +5,3 @@
|
||||
# https://translate.discourse.org/
|
||||
|
||||
da:
|
||||
reports:
|
||||
overall_sentiment:
|
||||
yaxis: "Dato"
|
||||
discourse_ai:
|
||||
sentiment:
|
||||
reports:
|
||||
post_emotion:
|
||||
neutral: "Neutral"
|
||||
|
||||
@@ -92,15 +92,6 @@ de:
|
||||
errors:
|
||||
prompt_message_length: Die Nachricht %{idx} hat die 1000-Zeichen-Grenze überschritten.
|
||||
invalid_prompt_role: Die Nachricht %{idx} hat eine ungültige Rolle.
|
||||
reports:
|
||||
overall_sentiment:
|
||||
title: "Allgemeine Stimmung"
|
||||
description: "Diese Grafik vergleicht die Anzahl der Beiträge, die als positiv oder negativ eingestuft werden."
|
||||
xaxis: "Positiv(%)"
|
||||
yaxis: "Datum"
|
||||
post_emotion:
|
||||
title: "Emotionen posten"
|
||||
description: "Anzahl der Beiträge, die mit einer der folgenden Emotionen klassifiziert wurden, gruppiert nach dem Vertrauenslevel des Posters."
|
||||
discourse_ai:
|
||||
ai_helper:
|
||||
errors:
|
||||
@@ -172,18 +163,3 @@ de:
|
||||
configuration_hint:
|
||||
one: "Konfiguriere zunächst die Einstellung `%{setting}`."
|
||||
other: "Konfiguriere zunächst diese Einstellungen: %{settings}"
|
||||
sentiment:
|
||||
reports:
|
||||
overall_sentiment:
|
||||
positive: "Positiv"
|
||||
negative: "Negativ"
|
||||
post_emotion:
|
||||
tl_01: "Vertrauensstufen 0-1"
|
||||
tl_234: "Vertrauensstufen 2+"
|
||||
sadness: "Traurigkeit"
|
||||
surprise: "Überraschung"
|
||||
neutral: "Neutral"
|
||||
fear: "Furcht"
|
||||
anger: "Wut"
|
||||
joy: "Freude"
|
||||
disgust: "Ekel"
|
||||
|
||||
@@ -5,6 +5,3 @@
|
||||
# https://translate.discourse.org/
|
||||
|
||||
el:
|
||||
reports:
|
||||
overall_sentiment:
|
||||
yaxis: "Ημερομηνία"
|
||||
|
||||
@@ -99,18 +99,6 @@ en:
|
||||
prompt_message_length: The message %{idx} is over the 1000 character limit.
|
||||
invalid_prompt_role: The message %{idx} has an invalid role.
|
||||
|
||||
reports:
|
||||
overall_sentiment:
|
||||
title: "Overall sentiment"
|
||||
description: "This chart compares the number of posts classified either positive or negative."
|
||||
xaxis: "Positive(%)"
|
||||
yaxis: "Date"
|
||||
post_emotion:
|
||||
title: "Post emotion"
|
||||
description: "Number of posts classified with one of the following emotions, grouped by poster's trust level."
|
||||
xaxis:
|
||||
yaxis:
|
||||
|
||||
discourse_ai:
|
||||
ai_helper:
|
||||
errors:
|
||||
@@ -184,19 +172,3 @@ en:
|
||||
configuration_hint:
|
||||
one: "Configure the `%{setting}` setting first."
|
||||
other: "Configure these settings first: %{settings}"
|
||||
|
||||
sentiment:
|
||||
reports:
|
||||
overall_sentiment:
|
||||
positive: "Positive"
|
||||
negative: "Negative"
|
||||
post_emotion:
|
||||
tl_01: "Trust levels 0-1"
|
||||
tl_234: "Trust levels 2+"
|
||||
sadness: "Sadness"
|
||||
surprise: "Surprise"
|
||||
neutral: "Neutral"
|
||||
fear: "Fear"
|
||||
anger: "Anger"
|
||||
joy: "Joy"
|
||||
disgust: "Disgust"
|
||||
|
||||
@@ -70,9 +70,6 @@ es:
|
||||
errors:
|
||||
prompt_message_length: El mensaje %{idx} supera el límite de 1000 caracteres.
|
||||
invalid_prompt_role: El mensaje %{idx} tiene un rol no válido.
|
||||
reports:
|
||||
overall_sentiment:
|
||||
yaxis: "Fecha"
|
||||
discourse_ai:
|
||||
ai_helper:
|
||||
errors:
|
||||
@@ -112,7 +109,3 @@ es:
|
||||
configuration_hint:
|
||||
one: "Configura primero el ajuste `%{setting}`."
|
||||
other: "Configura primero estos ajustes: %{settings}"
|
||||
sentiment:
|
||||
reports:
|
||||
post_emotion:
|
||||
neutral: "Neutro"
|
||||
|
||||
@@ -5,11 +5,3 @@
|
||||
# https://translate.discourse.org/
|
||||
|
||||
et:
|
||||
reports:
|
||||
overall_sentiment:
|
||||
yaxis: "Date"
|
||||
discourse_ai:
|
||||
sentiment:
|
||||
reports:
|
||||
post_emotion:
|
||||
neutral: "Neutraalne"
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
fa_IR:
|
||||
site_settings:
|
||||
discourse_ai_enabled: "افزونه discourse AI را فعال کنید."
|
||||
reports:
|
||||
overall_sentiment:
|
||||
yaxis: "تاریخ"
|
||||
discourse_ai:
|
||||
ai_bot:
|
||||
command_summary:
|
||||
|
||||
@@ -70,9 +70,6 @@ fi:
|
||||
errors:
|
||||
prompt_message_length: Viesti %{idx} ylittää 1 000 merkin rajan.
|
||||
invalid_prompt_role: Viestillä %{idx} on virheellinen rooli.
|
||||
reports:
|
||||
overall_sentiment:
|
||||
yaxis: "Päivämäärä"
|
||||
discourse_ai:
|
||||
ai_helper:
|
||||
errors:
|
||||
@@ -112,7 +109,3 @@ fi:
|
||||
configuration_hint:
|
||||
one: "Määritä ensin %{setting}-asetus."
|
||||
other: "Määritä ensin nämä asetukset: %{settings}"
|
||||
sentiment:
|
||||
reports:
|
||||
post_emotion:
|
||||
neutral: "Neutraali"
|
||||
|
||||
@@ -70,9 +70,6 @@ fr:
|
||||
errors:
|
||||
prompt_message_length: Le message %{idx} dépasse la limite de 1 000 caractères.
|
||||
invalid_prompt_role: Le message %{idx} a un rôle invalide.
|
||||
reports:
|
||||
overall_sentiment:
|
||||
yaxis: "Date"
|
||||
discourse_ai:
|
||||
ai_helper:
|
||||
errors:
|
||||
@@ -112,7 +109,3 @@ fr:
|
||||
configuration_hint:
|
||||
one: "Configurez d'abord le paramètre « %{setting} »."
|
||||
other: "Configurez d'abord ces paramètres : %{settings}"
|
||||
sentiment:
|
||||
reports:
|
||||
post_emotion:
|
||||
neutral: "Neutre"
|
||||
|
||||
@@ -5,11 +5,3 @@
|
||||
# https://translate.discourse.org/
|
||||
|
||||
gl:
|
||||
reports:
|
||||
overall_sentiment:
|
||||
yaxis: "Data"
|
||||
discourse_ai:
|
||||
sentiment:
|
||||
reports:
|
||||
post_emotion:
|
||||
neutral: "Neutro"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user