Compare commits
19
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
415c1156e0 | ||
|
|
c312b3184a | ||
|
|
f231aad8b5 | ||
|
|
cc77e73cfd | ||
|
|
1d88ca44f0 | ||
|
|
6059b6e111 | ||
|
|
5d80a34589 | ||
|
|
8630bc145e | ||
|
|
ad6a8cb812 | ||
|
|
06743d1939 | ||
|
|
67664029e5 | ||
|
|
1b16fc876c | ||
|
|
8c069490f0 | ||
|
|
6a4dbd8126 | ||
|
|
89bcf9b1f0 | ||
|
|
6b5ea38644 | ||
|
|
d54cd1f602 | ||
|
|
cf7288e1bf | ||
|
|
027d7f1199 |
@@ -1,3 +1,4 @@
|
||||
< 3.5.0.beta8-dev: 5d80a34589d63e381d80273828072badc18955b1
|
||||
< 3.5.0.beta7-dev: cd14b0c0bee0cf63c59b64b6f7213e31a37f11a7
|
||||
< 3.5.0.beta6-dev: 3e74eea1e5e3143888d67a8d8a11206df214dc24
|
||||
< 3.5.0.beta3-dev: 09a68414804a1447f52e5d60691ba59742cda9ec
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ GEM
|
||||
racc
|
||||
prettier_print (1.2.1)
|
||||
racc (1.8.1)
|
||||
rack (3.1.16)
|
||||
rack (3.1.18)
|
||||
rainbow (3.1.1)
|
||||
regexp_parser (2.10.0)
|
||||
rubocop (1.74.0)
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
# **Discourse AI** Plugin
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This plugin has now been bundled into Discourse core. See: https://meta.discourse.org/t/bundling-more-popular-plugins-with-discourse-core/373574
|
||||
|
||||
**Plugin Summary**
|
||||
|
||||
For more information, please see: https://meta.discourse.org/t/discourse-ai/259214?u=falco
|
||||
|
||||
### Evals
|
||||
|
||||
The directory `evals` contains AI evals for the Discourse AI plugin.
|
||||
The directory `evals` contains AI evals for the Discourse AI plugin.
|
||||
You may create a local config by copying `config/eval-llms.yml` to `config/eval-llms.local.yml` and modifying the values.
|
||||
|
||||
To run them use:
|
||||
To run them use:
|
||||
|
||||
cd evals
|
||||
./run --help
|
||||
|
||||
@@ -6,8 +6,7 @@ module Jobs
|
||||
sidekiq_options retry: false
|
||||
|
||||
def execute(args)
|
||||
return if !SiteSetting.discourse_ai_enabled
|
||||
return if !SiteSetting.ai_translation_enabled
|
||||
return if !DiscourseAi::Translation.enabled?
|
||||
return if args[:post_id].blank?
|
||||
|
||||
post = Post.find_by(id: args[:post_id])
|
||||
@@ -36,12 +35,14 @@ module Jobs
|
||||
end
|
||||
end
|
||||
|
||||
return if detected_locale.blank?
|
||||
locales = SiteSetting.content_localization_supported_locales.split("|")
|
||||
return if locales.blank?
|
||||
|
||||
locales.each do |locale|
|
||||
next if locale == detected_locale
|
||||
next if post.post_localizations.exists?(locale:)
|
||||
next if LocaleNormalizer.is_same?(locale, detected_locale)
|
||||
regionless_locale = locale.split("_").first
|
||||
next if post.post_localizations.where("locale LIKE ?", "#{regionless_locale}%").exists?
|
||||
|
||||
begin
|
||||
DiscourseAi::Translation::PostLocalizer.localize(post, locale)
|
||||
|
||||
@@ -6,8 +6,7 @@ module Jobs
|
||||
sidekiq_options retry: false
|
||||
|
||||
def execute(args)
|
||||
return if !SiteSetting.discourse_ai_enabled
|
||||
return if !SiteSetting.ai_translation_enabled
|
||||
return if !DiscourseAi::Translation.enabled?
|
||||
return if args[:topic_id].blank?
|
||||
|
||||
topic = Topic.find_by(id: args[:topic_id])
|
||||
@@ -34,12 +33,14 @@ module Jobs
|
||||
end
|
||||
end
|
||||
|
||||
return if detected_locale.blank?
|
||||
locales = SiteSetting.content_localization_supported_locales.split("|")
|
||||
return if locales.blank?
|
||||
|
||||
locales.each do |locale|
|
||||
next if locale == detected_locale
|
||||
next if topic.topic_localizations.exists?(locale:)
|
||||
next if LocaleNormalizer.is_same?(locale, detected_locale)
|
||||
regionless_locale = locale.split("_").first
|
||||
next if topic.topic_localizations.where("locale LIKE ?", "#{regionless_locale}%").exists?
|
||||
|
||||
begin
|
||||
DiscourseAi::Translation::TopicLocalizer.localize(topic, locale)
|
||||
|
||||
@@ -6,21 +6,17 @@ module Jobs
|
||||
sidekiq_options retry: false
|
||||
|
||||
def execute(args)
|
||||
return if !DiscourseAi::Translation.enabled?
|
||||
|
||||
limit = args[:limit]
|
||||
raise Discourse::InvalidParameters.new(:limit) if limit.nil?
|
||||
return if limit <= 0
|
||||
|
||||
return if !SiteSetting.discourse_ai_enabled
|
||||
return if !SiteSetting.ai_translation_enabled
|
||||
locales = SiteSetting.content_localization_supported_locales.split("|")
|
||||
return if locales.blank?
|
||||
|
||||
categories = Category.where("locale IS NOT NULL")
|
||||
|
||||
if SiteSetting.ai_translation_backfill_limit_to_public_content
|
||||
categories = categories.where(read_restricted: false)
|
||||
end
|
||||
|
||||
categories = categories.order(:id).limit(limit)
|
||||
return if categories.empty?
|
||||
|
||||
@@ -33,6 +29,7 @@ module Jobs
|
||||
missing_locales = locales - existing_locales - [category.locale]
|
||||
missing_locales.each do |locale|
|
||||
break if remaining_limit <= 0
|
||||
next if LocaleNormalizer.is_same?(locale, category.locale)
|
||||
|
||||
begin
|
||||
DiscourseAi::Translation::CategoryLocalizer.localize(category, locale)
|
||||
|
||||
@@ -9,23 +9,25 @@ module Jobs
|
||||
limit = args[:limit]
|
||||
raise Discourse::InvalidParameters.new(:limit) if limit.blank? || limit <= 0
|
||||
|
||||
return if !SiteSetting.discourse_ai_enabled
|
||||
return if !SiteSetting.ai_translation_enabled
|
||||
return if !DiscourseAi::Translation.backfill_enabled?
|
||||
|
||||
locales = SiteSetting.content_localization_supported_locales.split("|")
|
||||
return if locales.blank?
|
||||
|
||||
locales.each do |locale|
|
||||
base_locale = locale.split("_").first
|
||||
posts =
|
||||
Post
|
||||
.joins(
|
||||
"LEFT JOIN post_localizations pl ON pl.post_id = posts.id AND pl.locale = #{ActiveRecord::Base.connection.quote(locale)}",
|
||||
"LEFT JOIN post_localizations pl ON pl.post_id = posts.id AND pl.locale LIKE '#{base_locale}%'",
|
||||
)
|
||||
.where(
|
||||
"posts.created_at > ?",
|
||||
SiteSetting.ai_translation_backfill_max_age_days.days.ago,
|
||||
)
|
||||
.where(deleted_at: nil)
|
||||
.where("posts.user_id > 0")
|
||||
.where.not(raw: [nil, ""])
|
||||
.where.not(locale: nil)
|
||||
.where.not(locale: locale)
|
||||
.where("posts.locale NOT LIKE '#{base_locale}%'")
|
||||
.where("pl.id IS NULL")
|
||||
|
||||
posts = posts.joins(:topic)
|
||||
@@ -46,14 +48,6 @@ module Jobs
|
||||
)
|
||||
end
|
||||
|
||||
if SiteSetting.ai_translation_backfill_max_age_days > 0
|
||||
posts =
|
||||
posts.where(
|
||||
"posts.created_at > ?",
|
||||
SiteSetting.ai_translation_backfill_max_age_days.days.ago,
|
||||
)
|
||||
end
|
||||
|
||||
posts = posts.order(updated_at: :desc).limit(limit)
|
||||
|
||||
next if posts.empty?
|
||||
|
||||
@@ -9,22 +9,24 @@ module Jobs
|
||||
limit = args[:limit]
|
||||
raise Discourse::InvalidParameters.new(:limit) if limit.blank? || limit <= 0
|
||||
|
||||
return if !SiteSetting.discourse_ai_enabled
|
||||
return if !SiteSetting.ai_translation_enabled
|
||||
return if !DiscourseAi::Translation.backfill_enabled?
|
||||
|
||||
locales = SiteSetting.content_localization_supported_locales.split("|")
|
||||
return if locales.blank?
|
||||
|
||||
locales.each do |locale|
|
||||
base_locale = locale.split("_").first
|
||||
topics =
|
||||
Topic
|
||||
.joins(
|
||||
"LEFT JOIN topic_localizations tl ON tl.topic_id = topics.id AND tl.locale = #{ActiveRecord::Base.connection.quote(locale)}",
|
||||
"LEFT JOIN topic_localizations tl ON tl.topic_id = topics.id AND tl.locale LIKE '#{base_locale}%'",
|
||||
)
|
||||
.where(
|
||||
"topics.created_at > ?",
|
||||
SiteSetting.ai_translation_backfill_max_age_days.days.ago,
|
||||
)
|
||||
.where(deleted_at: nil)
|
||||
.where("topics.user_id > 0")
|
||||
.where.not(locale: nil)
|
||||
.where.not(locale: locale)
|
||||
.where("topics.locale NOT LIKE '#{base_locale}%'")
|
||||
.where("tl.id IS NULL")
|
||||
|
||||
if SiteSetting.ai_translation_backfill_limit_to_public_content
|
||||
@@ -43,14 +45,6 @@ module Jobs
|
||||
)
|
||||
end
|
||||
|
||||
if SiteSetting.ai_translation_backfill_max_age_days > 0
|
||||
topics =
|
||||
topics.where(
|
||||
"topics.created_at > ?",
|
||||
SiteSetting.ai_translation_backfill_max_age_days.days.ago,
|
||||
)
|
||||
end
|
||||
|
||||
topics = topics.order(updated_at: :desc).limit(limit)
|
||||
|
||||
next if topics.empty?
|
||||
|
||||
@@ -7,10 +7,7 @@ module Jobs
|
||||
cluster_concurrency 1
|
||||
|
||||
def execute(args)
|
||||
return if !SiteSetting.discourse_ai_enabled
|
||||
return if !SiteSetting.ai_translation_enabled
|
||||
limit = SiteSetting.ai_translation_backfill_hourly_rate
|
||||
return if limit == 0
|
||||
return if !DiscourseAi::Translation.backfill_enabled?
|
||||
|
||||
categories = Category.where(locale: nil)
|
||||
|
||||
@@ -18,6 +15,7 @@ module Jobs
|
||||
categories = categories.where(read_restricted: false)
|
||||
end
|
||||
|
||||
limit = SiteSetting.ai_translation_backfill_hourly_rate
|
||||
categories = categories.limit(limit)
|
||||
return if categories.empty?
|
||||
|
||||
|
||||
@@ -6,11 +6,8 @@ module Jobs
|
||||
cluster_concurrency 1
|
||||
|
||||
def execute(args)
|
||||
return if !SiteSetting.discourse_ai_enabled
|
||||
return if !SiteSetting.ai_translation_enabled
|
||||
return if SiteSetting.content_localization_supported_locales.blank?
|
||||
return if !DiscourseAi::Translation.backfill_enabled?
|
||||
limit = SiteSetting.ai_translation_backfill_hourly_rate
|
||||
return if limit == 0
|
||||
|
||||
Jobs.enqueue(:localize_categories, limit:)
|
||||
end
|
||||
|
||||
@@ -6,10 +6,8 @@ module Jobs
|
||||
cluster_concurrency 1
|
||||
|
||||
def execute(args)
|
||||
return if !SiteSetting.discourse_ai_enabled
|
||||
return if !SiteSetting.ai_translation_enabled
|
||||
return if !DiscourseAi::Translation.backfill_enabled?
|
||||
|
||||
return if SiteSetting.content_localization_supported_locales.blank?
|
||||
limit = SiteSetting.ai_translation_backfill_hourly_rate / (60 / 5) # this job runs in 5-minute intervals
|
||||
return if limit == 0
|
||||
|
||||
|
||||
@@ -7,16 +7,16 @@ module Jobs
|
||||
cluster_concurrency 1
|
||||
|
||||
def execute(args)
|
||||
return if !SiteSetting.discourse_ai_enabled
|
||||
return if !SiteSetting.ai_translation_enabled
|
||||
return if !DiscourseAi::Translation.backfill_enabled?
|
||||
|
||||
limit = SiteSetting.ai_translation_backfill_hourly_rate / (60 / 5) # this job runs in 5-minute intervals
|
||||
return if limit == 0
|
||||
|
||||
posts =
|
||||
Post
|
||||
.where(locale: nil)
|
||||
.where(deleted_at: nil)
|
||||
.where("posts.user_id > 0")
|
||||
.where("posts.created_at > ?", SiteSetting.ai_translation_backfill_max_age_days.days.ago)
|
||||
.where.not(raw: [nil, ""])
|
||||
|
||||
if SiteSetting.ai_translation_backfill_limit_to_public_content
|
||||
@@ -33,14 +33,6 @@ module Jobs
|
||||
)
|
||||
end
|
||||
|
||||
if SiteSetting.ai_translation_backfill_max_age_days > 0
|
||||
posts =
|
||||
posts.where(
|
||||
"posts.created_at > ?",
|
||||
SiteSetting.ai_translation_backfill_max_age_days.days.ago,
|
||||
)
|
||||
end
|
||||
|
||||
posts = posts.order(updated_at: :desc).limit(limit)
|
||||
return if posts.empty?
|
||||
|
||||
|
||||
@@ -36,7 +36,12 @@ module ::Jobs
|
||||
existing_summary = strategy.existing_summary
|
||||
|
||||
if existing_summary.blank? || existing_summary.outdated
|
||||
strategy.summarize(user)
|
||||
begin
|
||||
strategy.summarize(user)
|
||||
rescue => e
|
||||
Rails.logger.error("Error summarizing topic #{topic.id}: #{e.class.name} - #{e.message}")
|
||||
raise e
|
||||
end
|
||||
else
|
||||
# Hiding or deleting a post, and creating a small action alters the Topic#highest_post_number.
|
||||
# We use this as a quick way to select potential backfill candidates without relying on original_content_sha.
|
||||
|
||||
@@ -6,13 +6,9 @@ module Jobs
|
||||
cluster_concurrency 1
|
||||
|
||||
def execute(args)
|
||||
return if !SiteSetting.discourse_ai_enabled
|
||||
return if !SiteSetting.ai_translation_enabled
|
||||
return if !DiscourseAi::Translation.backfill_enabled?
|
||||
|
||||
return if SiteSetting.content_localization_supported_locales.blank?
|
||||
limit = SiteSetting.ai_translation_backfill_hourly_rate / (60 / 5) # this job runs in 5-minute intervals
|
||||
return if limit == 0
|
||||
|
||||
Jobs.enqueue(:localize_topics, limit:)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,12 +7,15 @@ module Jobs
|
||||
cluster_concurrency 1
|
||||
|
||||
def execute(args)
|
||||
return if !SiteSetting.discourse_ai_enabled
|
||||
return if !SiteSetting.ai_translation_enabled
|
||||
limit = SiteSetting.ai_translation_backfill_hourly_rate / (60 / 5) # this job runs in 5-minute intervals
|
||||
return if limit == 0
|
||||
return if !DiscourseAi::Translation.backfill_enabled?
|
||||
|
||||
topics = Topic.where(locale: nil, deleted_at: nil).where("topics.user_id > 0")
|
||||
limit = SiteSetting.ai_translation_backfill_hourly_rate / (60 / 5) # this job runs in 5-minute intervals
|
||||
|
||||
topics =
|
||||
Topic
|
||||
.where(locale: nil, deleted_at: nil)
|
||||
.where("topics.user_id > 0")
|
||||
.where("topics.created_at > ?", SiteSetting.ai_translation_backfill_max_age_days.days.ago)
|
||||
|
||||
if SiteSetting.ai_translation_backfill_limit_to_public_content
|
||||
topics =
|
||||
@@ -28,14 +31,6 @@ module Jobs
|
||||
)
|
||||
end
|
||||
|
||||
if SiteSetting.ai_translation_backfill_max_age_days > 0
|
||||
topics =
|
||||
topics.where(
|
||||
"topics.created_at > ?",
|
||||
SiteSetting.ai_translation_backfill_max_age_days.days.ago,
|
||||
)
|
||||
end
|
||||
|
||||
topics = topics.order(updated_at: :desc).limit(limit)
|
||||
return if topics.empty?
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ class EmbeddingDefinition < ActiveRecord::Base
|
||||
dimensions: 2000,
|
||||
max_sequence_length: 8191,
|
||||
pg_function: "<=>",
|
||||
tokenizer_class: "DiscourseAi::Tokenizer::OpenAiTokenizer",
|
||||
tokenizer_class: "DiscourseAi::Tokenizer::OpenAiCl100kTokenizer",
|
||||
url: "https://api.openai.com/v1/embeddings",
|
||||
provider: OPEN_AI,
|
||||
matryoshka_dimensions: true,
|
||||
@@ -98,7 +98,7 @@ class EmbeddingDefinition < ActiveRecord::Base
|
||||
dimensions: 1536,
|
||||
max_sequence_length: 8191,
|
||||
pg_function: "<=>",
|
||||
tokenizer_class: "DiscourseAi::Tokenizer::OpenAiTokenizer",
|
||||
tokenizer_class: "DiscourseAi::Tokenizer::OpenAiCl100kTokenizer",
|
||||
url: "https://api.openai.com/v1/embeddings",
|
||||
provider: OPEN_AI,
|
||||
matryoshka_dimensions: true,
|
||||
@@ -112,7 +112,7 @@ class EmbeddingDefinition < ActiveRecord::Base
|
||||
dimensions: 1536,
|
||||
max_sequence_length: 8191,
|
||||
pg_function: "<=>",
|
||||
tokenizer_class: "DiscourseAi::Tokenizer::OpenAiTokenizer",
|
||||
tokenizer_class: "DiscourseAi::Tokenizer::OpenAiCl100kTokenizer",
|
||||
url: "https://api.openai.com/v1/embeddings",
|
||||
provider: OPEN_AI,
|
||||
provider_params: {
|
||||
|
||||
@@ -260,10 +260,11 @@ export default class AiBotConversations extends Component {
|
||||
|
||||
@action
|
||||
async prepareAndSubmitToBot() {
|
||||
// Pass uploads to the service before submitting
|
||||
this.aiBotConversationsHiddenSubmit.uploads = this.uploads;
|
||||
try {
|
||||
await this.aiBotConversationsHiddenSubmit.submitToBot();
|
||||
await this.aiBotConversationsHiddenSubmit.submitToBot({
|
||||
uploads: this.uploads,
|
||||
inProgressUploadsCount: this.inProgressUploads.length,
|
||||
});
|
||||
this.uploads = new TrackedArray();
|
||||
} catch (error) {
|
||||
popupAjaxError(error);
|
||||
|
||||
@@ -66,12 +66,9 @@ class ExpandableList extends Component {
|
||||
|
||||
export default class AiFeaturesList extends Component {
|
||||
get sortedModules() {
|
||||
if (!this.args.modules || !this.args.modules.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.args.modules.toSorted((a, b) =>
|
||||
a.module_name.localeCompare(b.module_name)
|
||||
const modules = this.args.modules?.toArray() || this.args.modules;
|
||||
return [...(modules || [])].toSorted((a, b) =>
|
||||
(a.module_name || "").localeCompare(b.module_name || "")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ export default class AiBotConversationsHiddenSubmit extends Service {
|
||||
|
||||
personaId;
|
||||
targetUsername;
|
||||
uploads = [];
|
||||
|
||||
inputValue = "";
|
||||
|
||||
@@ -32,7 +31,7 @@ export default class AiBotConversationsHiddenSubmit extends Service {
|
||||
}
|
||||
|
||||
@action
|
||||
async submitToBot() {
|
||||
async submitToBot(uploadData) {
|
||||
if (
|
||||
this.inputValue.length <
|
||||
this.siteSettings.min_personal_message_post_length
|
||||
@@ -48,7 +47,7 @@ export default class AiBotConversationsHiddenSubmit extends Service {
|
||||
}
|
||||
|
||||
// Don't submit if there are still uploads in progress
|
||||
if (document.querySelector(".ai-bot-upload--in-progress")) {
|
||||
if (uploadData.inProgressUploadsCount > 0) {
|
||||
return this.dialog.alert({
|
||||
message: i18n("discourse_ai.ai_bot.conversations.uploads_in_progress"),
|
||||
});
|
||||
@@ -61,10 +60,10 @@ export default class AiBotConversationsHiddenSubmit extends Service {
|
||||
let rawContent = this.inputValue;
|
||||
|
||||
// Append upload markdown if we have uploads
|
||||
if (this.uploads && this.uploads.length > 0) {
|
||||
if (uploadData.uploads && uploadData.uploads.length > 0) {
|
||||
rawContent += "\n\n";
|
||||
|
||||
this.uploads.forEach((upload) => {
|
||||
uploadData.uploads.forEach((upload) => {
|
||||
const uploadMarkdown = getUploadMarkdown(upload);
|
||||
rawContent += uploadMarkdown + "\n";
|
||||
});
|
||||
@@ -83,7 +82,6 @@ export default class AiBotConversationsHiddenSubmit extends Service {
|
||||
});
|
||||
|
||||
// Reset uploads after successful submission
|
||||
this.uploads = [];
|
||||
this.inputValue = "";
|
||||
|
||||
this.appEvents.trigger("discourse-ai:bot-pm-created", {
|
||||
|
||||
@@ -158,6 +158,8 @@ ar:
|
||||
reset: "إعادة التعيين"
|
||||
search:
|
||||
name: "البحث"
|
||||
embeddings:
|
||||
name: "التضمينات"
|
||||
ai_helper:
|
||||
name: "المساعد"
|
||||
proofread: تدقيق النص لغويًا
|
||||
|
||||
@@ -29,6 +29,22 @@ de:
|
||||
label: "Sortieren nach"
|
||||
tag:
|
||||
label: "Schlagwort"
|
||||
logs:
|
||||
staff_actions:
|
||||
actions:
|
||||
create_ai_llm_model: "LLM-Modell erstellen"
|
||||
update_ai_llm_model: "LLM-Modell aktualisieren"
|
||||
delete_ai_llm_model: "LLM-Modell löschen"
|
||||
create_ai_persona: "KI-Persona erstellen"
|
||||
update_ai_persona: "KI-Persona aktualisieren"
|
||||
delete_ai_persona: "KI-Persona löschen"
|
||||
create_ai_tool: "KI-Tool erstellen"
|
||||
update_ai_tool: "KI-Tool aktualisieren"
|
||||
delete_ai_tool: "KI-Tool löschen"
|
||||
create_ai_embedding: "KI-Einbettung erstellen"
|
||||
update_ai_embedding: "KI-Einbettung aktualisieren"
|
||||
delete_ai_embedding: "KI-Einbettung löschen"
|
||||
update_ai_spam_settings: "KI-Spam-Einstellungen aktualisieren"
|
||||
js:
|
||||
discourse_automation:
|
||||
scriptables:
|
||||
@@ -98,21 +114,21 @@ de:
|
||||
fields:
|
||||
model:
|
||||
label: "Modell"
|
||||
description: "Das für die Triage verwendete Standard-Sprachmodell"
|
||||
description: "Das für die Sichtung verwendete Standard-Sprachmodell"
|
||||
tool:
|
||||
label: "Werkzeug"
|
||||
description: "Werkzeug für die Triage (das Werkzeug darf keine Parameter definiert haben)"
|
||||
label: "Tool"
|
||||
description: "Tool für die Sichtung (das Tool darf keine Parameter definiert haben)"
|
||||
llm_persona_triage:
|
||||
fields:
|
||||
persona:
|
||||
label: "Persona"
|
||||
description: "KI-Persona, die für die Triage verwendet werden soll (Standard-LLM und -Benutzer müssen eingestellt sein)"
|
||||
description: "KI-Persona, die für die Sichtung verwendet werden soll (Standard-LLM und -Benutzer müssen eingestellt sein)"
|
||||
whisper:
|
||||
label: "Als Flüstern antworten"
|
||||
description: "Ob die Antwort der Persona ein Flüstern sein soll"
|
||||
silent_mode:
|
||||
label: "Stiller Modus"
|
||||
description: "Im stillen Modus empfängt die Persona den Inhalt, schreibt aber nichts in das Forum - nützlich bei der Triage mit Tools"
|
||||
description: "Im stillen Modus empfängt die Persona den Inhalt, schreibt aber nichts in das Forum - nützlich bei der Sichtung mit Tools"
|
||||
llm_triage:
|
||||
fields:
|
||||
system_prompt:
|
||||
@@ -177,6 +193,7 @@ de:
|
||||
llm:
|
||||
one: "LLM:"
|
||||
other: "LLM:"
|
||||
no_llm: "Kein LLM ausgewählt"
|
||||
no_persona: "Nicht festgelegt"
|
||||
no_groups: "Keiner"
|
||||
edit: "Bearbeiten"
|
||||
@@ -184,35 +201,75 @@ de:
|
||||
one: "(%{count} weitere)"
|
||||
other: "(%{count} weitere)"
|
||||
collapse_list: "(weniger anzeigen)"
|
||||
bot:
|
||||
bot: "Chatbot"
|
||||
name: "Bot"
|
||||
description: "Ein Chatbot, der Fragen beantworten und Benutzern in persönlichen Nachrichten, im Forum und im Chat helfen kann"
|
||||
nav:
|
||||
configured: "Konfiguriert"
|
||||
unconfigured: "Nicht konfiguriert"
|
||||
filters:
|
||||
all: "Gesamt"
|
||||
text: "Suche nach Funktionen, Personas, LLMs oder Gruppen..."
|
||||
no_results: "Es wurden keine Funktionen gefunden, die deinen Filtern entsprechen."
|
||||
reset: "Zurücksetzen"
|
||||
summarization:
|
||||
name: "Zusammenfassungen"
|
||||
description: "Stellt eine Schaltfläche für Zusammenfassungen zur Verfügung, mit der Besucher Themen zusammenfassen können"
|
||||
topic_summaries: "Themenzusammenfassungen"
|
||||
gists: "Kurze Zusammenfassungen der in Themenliste"
|
||||
search:
|
||||
name: "Suche"
|
||||
description: "Verbessert das Sucherlebnis durch KI-generierte Antworten auf Suchanfragen"
|
||||
discoveries: "Entdeckungen"
|
||||
embeddings:
|
||||
name: "Einbettungen"
|
||||
description: "Ermöglicht Funktionen wie „Verwandte Themen“ und „KI-Suche“ durch die Erstellung semantischer Textdarstellungen"
|
||||
hyde: "HyDE"
|
||||
discord:
|
||||
name: "Discord-Integration"
|
||||
description: "Fügt die Möglichkeit hinzu, Discord-Kanäle zu durchsuchen"
|
||||
search: "Discord-Suche"
|
||||
inference:
|
||||
name: "Abgeleitete Konzepte"
|
||||
description: "Ordnet Themen und Beiträge in Interessensgebiete / Labels."
|
||||
generate_concepts: "Konzepterkennung"
|
||||
match_concepts: "Passende Konzepte"
|
||||
deduplicate_concepts: "Deduplizierung von Konzepten"
|
||||
ai_helper:
|
||||
name: "Helfer"
|
||||
description: "Unterstützt Benutzer bei der Interaktion in der Community, z. B. beim Erstellen von Themen, Verfassen von Beiträgen und Lesen von Inhalten"
|
||||
proofread: Text korrekturlesen
|
||||
title_suggestions: "Titel vorschlagen"
|
||||
explain: "Erklären"
|
||||
illustrate_post: "Beitrag illustrieren"
|
||||
smart_dates: "Intelligente Termine"
|
||||
translate: "Übersetzen"
|
||||
markdown_tables: "Markdown-Tabelle generieren"
|
||||
custom_prompt: "Benutzerdefinierte Eingabeaufforderung"
|
||||
image_caption: "Bildbeschriftungen"
|
||||
translator: "Übersetzer"
|
||||
translation:
|
||||
name: "Übersetzen"
|
||||
description: "Übersetzt Inhalte in unterstützte Sprachen"
|
||||
locale_detector: "Sprachdetektor"
|
||||
post_raw_translator: "Übersetzer für die Roheingabe des Beitrags"
|
||||
topic_title_translator: "Thementitel-Übersetzer"
|
||||
short_text_translator: "Kurztext-Übersetzer"
|
||||
spam:
|
||||
name: "Spam"
|
||||
description: "Identifiziert potenziellen Spam mithilfe des ausgewählten LLMs und meldet ihn den Moderatoren der Website in der Warteschlange zur Überprüfung."
|
||||
inspect_posts: "Beiträge prüfen"
|
||||
modals:
|
||||
select_option: "Wähle eine Option aus..."
|
||||
layout:
|
||||
table: "Tabelle"
|
||||
card: "Karte"
|
||||
spam:
|
||||
short_title: "Spam"
|
||||
title: "Spam-Behandlung konfigurieren"
|
||||
select_llm: "LLM auswählen"
|
||||
select_persona: "Persona auswählen"
|
||||
custom_instructions: "Benutzerdefinierte Anweisungen"
|
||||
custom_instructions_help: "Benutzerdefinierte Anweisungen speziell für deine Website, die der KI beim Identifizieren von Spam helfen, z. B. „Gehe beim Scannen von Posts, die nicht in englischer Sprache sind, aggressiver vor.“"
|
||||
last_seven_days: "Letzte 7 Tage"
|
||||
@@ -293,6 +350,9 @@ de:
|
||||
name: "Name"
|
||||
edit: "Bearbeiten"
|
||||
export: "Exportieren"
|
||||
import: "Importieren"
|
||||
import_error_conflict: "Beim Importieren von %{name} wurde ein Konflikt erkannt. Möchtest du die vorhandene Persona aktualisieren?"
|
||||
overwrite: "Überschreiben"
|
||||
description: "Beschreibung"
|
||||
no_llm_selected: "Kein Sprachmodell ausgewählt"
|
||||
use_parent_llm: "Verwende das Personas Sprachmodell"
|
||||
@@ -370,7 +430,10 @@ de:
|
||||
title: "KI-Bot-Optionen"
|
||||
save_first: "Weitere KI-Bot-Optionen werden verfügbar, sobald du die Persona gespeichert hast."
|
||||
filters:
|
||||
text: "Finde eine Persona"
|
||||
reset: "Zurücksetzen"
|
||||
no_results: "Es wurden keine Personas gefunden, die deinen Filtern entsprechen."
|
||||
all_features: "Jede Funktion"
|
||||
features_list:
|
||||
one: "Funktion:"
|
||||
other: "Funktionen:"
|
||||
@@ -401,11 +464,14 @@ de:
|
||||
back: "Zurück"
|
||||
short_title: "Tools"
|
||||
export: "Exportieren"
|
||||
import: "Importieren"
|
||||
import_error_conflict: "Tool existiert bereits, möchtest du es aktualisieren?"
|
||||
overwrite: "Überschreiben"
|
||||
no_tools: "Du hast noch keine Tools erstellt"
|
||||
name: "Name"
|
||||
name_help: "Der Name wird in der Discourse-Benutzeroberfläche angezeigt und ist die Kurzkennung, die Du verwendest, um das Werkzeug in verschiedenen Einstellungen zu finden. Er sollte eindeutig sein (er ist erforderlich)."
|
||||
name_help: "Der Name wird in der Discourse-Benutzeroberfläche angezeigt und ist die Kurzkennung, die du verwendest, um das Tool in verschiedenen Einstellungen zu finden. Er sollte eindeutig sein (er ist erforderlich)."
|
||||
new: "Neues Tool"
|
||||
tool_name: "Werkzeugname"
|
||||
tool_name: "Name des Tools"
|
||||
tool_name_help: "Der Werkzeugname wird dem großen Sprachmodell präsentiert. Es ist nicht eindeutig, aber es ist von Person zu Person unterschiedlich. (Persona wird beim Speichern validiert)"
|
||||
description: "Beschreibung"
|
||||
description_help: "Eine klare Beschreibung des Zwecks des Tools für das Sprachmodell"
|
||||
@@ -486,14 +552,18 @@ de:
|
||||
ai_summarization: "Zusammenfassen"
|
||||
ai_embeddings_semantic_search: "KI-Suche"
|
||||
ai_spam: "Spam"
|
||||
automation: "Automatisierung (%{name})"
|
||||
automation: "Automatisierung (%{persona})"
|
||||
in_use_warning:
|
||||
one: "Dieses Modell wird derzeit von %{settings} verwendet. Wenn es falsch konfiguriert ist, wird die Funktion nicht wie erwartet funktionieren."
|
||||
other: "Dieses Modell wird derzeit verwendet von: %{settings}. Wenn es falsch konfiguriert ist, werden die Funktionen nicht wie erwartet funktionieren. "
|
||||
model_description:
|
||||
none: "Allgemeine Einstellungen, die für die meisten Sprachmodelle funktionieren"
|
||||
anthropic-claude-opus-4-0: "Das intelligenteste Modell von Anthropic"
|
||||
anthropic-claude-sonnet-4-0: "Optimales Gleichgewicht zwischen Geschwindigkeit und Kosten"
|
||||
anthropic-claude-3-7-sonnet-latest: "Optimales Gleichgewicht zwischen Geschwindigkeit und Kosten (vorherige Generation)"
|
||||
anthropic-claude-3-5-haiku-latest: "Schnell und kosteneffizient"
|
||||
google-gemini-2-5-pro: "Großes multimodales Modell, das eine Vielzahl von Aufgaben bewältigen kann"
|
||||
google-gemini-2-0-flash: "Leicht, schnell und kosteneffizient mit multimodaler Argumentation (vorherige Generation)"
|
||||
google-gemini-2-5-flash: "Leicht, schnell und kosteneffizient mit multimodaler Argumentation"
|
||||
google-gemini-2-0-flash-lite: "Kosteneffizientes Modell mit niedriger Latenz"
|
||||
open_ai-o3: "Das leistungsfähigste Argumentationsmodell von Open AI"
|
||||
@@ -505,6 +575,9 @@ de:
|
||||
samba_nova-Meta-Llama-3-3-70B-Instruct": "Leistungsstarkes Mehrzweckmodell"
|
||||
mistral-mistral-large-latest: "Das leistungsstärkste Modell von Mistral"
|
||||
mistral-pixtral-large-latest: "Das leistungsstärkste Modell von Mistral mit Sichtfunktion"
|
||||
open_router-x-ai-grok-3-beta: "Das neueste Modell von xAI"
|
||||
open_router-deepseek-deepseek-r1-0528-free: "DeepSeeks neuestes Argumentationsmodell"
|
||||
open_router-meta-llama-3-3-70b-instruct: "Leistungsstarkes mehrsprachiges Modell"
|
||||
preseeded_model_description: "Vorkonfiguriertes Open-Source-Modell unter Verwendung von %{model}"
|
||||
configured:
|
||||
title: "Konfigurierte LLMs"
|
||||
@@ -565,6 +638,7 @@ de:
|
||||
reasoning_tokens: "Anzahl der für die Argumentation verwendeten Token"
|
||||
disable_temperature: "Temperatur deaktivieren (einige Denkmodelle unterstützen keine Temperatur)"
|
||||
disable_top_p: "Top P deaktivieren (einige Denkmodelle unterstützen Top P nicht)"
|
||||
enable_responses_api: "Aktiviere die Antwort-API (bei bestimmten OpenAI-Modellen erforderlich)"
|
||||
related_topics:
|
||||
title: "Verwandte Themen"
|
||||
pill: "Verwandt"
|
||||
@@ -583,6 +657,7 @@ de:
|
||||
trigger: "KI fragen"
|
||||
loading: "KI generiert"
|
||||
cancel: "Abbrechen"
|
||||
regen: "Erneut versuchen"
|
||||
confirm: "Bestätigen"
|
||||
discard: "Verwerfen"
|
||||
changes: "Empfohlene Änderungen"
|
||||
@@ -700,6 +775,7 @@ de:
|
||||
shortcut_title: "Starte eine PN mit einem KI-Bot"
|
||||
share: "KI-Unterhaltung kopieren"
|
||||
conversation_shared: "Unterhaltung kopiert"
|
||||
embed_copied: "Einbettung in die Zwischenablage kopiert"
|
||||
debug_ai: "Rohdaten der KI-Anfrage und -Antwort anzeigen"
|
||||
sidebar_empty: "Der Verlauf der Bot-Konversation wird hier angezeigt."
|
||||
debug_ai_modal:
|
||||
@@ -759,6 +835,7 @@ de:
|
||||
today: "Heute"
|
||||
last_7_days: "Letzte 7 Tage"
|
||||
last_30_days: "Letzte 30 Tage"
|
||||
upload_files: "Dateien hochladen"
|
||||
sentiments:
|
||||
dashboard:
|
||||
title: "Stimmung"
|
||||
|
||||
@@ -106,6 +106,9 @@ en:
|
||||
top_p:
|
||||
label: "Top P"
|
||||
description: "Top P to use for the LLM, increase to increase randomness (leave empty to use model default)"
|
||||
persona_id:
|
||||
label: "Persona"
|
||||
description: "AI Persona to use for report generation"
|
||||
|
||||
llm_tool_triage:
|
||||
fields:
|
||||
@@ -177,6 +180,9 @@ en:
|
||||
temperature:
|
||||
label: "Temperature"
|
||||
description: "Temperature to use for the LLM. Increase to increase randomness (leave empty to use model default)"
|
||||
max_output_tokens:
|
||||
label: "Max output tokens"
|
||||
description: "When specified, sets an upper bound to the maximum number of tokens the model can generate. Respects LLM's max output tokens limit"
|
||||
|
||||
discourse_ai:
|
||||
title: "AI"
|
||||
@@ -872,6 +878,7 @@ en:
|
||||
last_7_days: "Last 7 days"
|
||||
last_30_days: "Last 30 days"
|
||||
upload_files: "Upload files"
|
||||
uploads_in_progress: "Cannot submit while uploads are in progress"
|
||||
sentiments:
|
||||
dashboard:
|
||||
title: "Sentiment"
|
||||
|
||||
@@ -154,6 +154,8 @@ es:
|
||||
reset: "Restablecer"
|
||||
search:
|
||||
name: "Buscar"
|
||||
embeddings:
|
||||
name: "Incrustaciones"
|
||||
ai_helper:
|
||||
name: "Ayudante"
|
||||
proofread: Corregir el texto
|
||||
|
||||
@@ -154,6 +154,8 @@ fi:
|
||||
reset: "Palauta"
|
||||
search:
|
||||
name: "Hae"
|
||||
embeddings:
|
||||
name: "Upotukset"
|
||||
ai_helper:
|
||||
name: "Apuri"
|
||||
proofread: Oikolue teksti
|
||||
|
||||
@@ -154,6 +154,8 @@ fr:
|
||||
reset: "Réinitialiser"
|
||||
search:
|
||||
name: "Recherche"
|
||||
embeddings:
|
||||
name: "Intégrations"
|
||||
ai_helper:
|
||||
name: "Assistant"
|
||||
proofread: Relisez le texte
|
||||
|
||||
@@ -185,6 +185,7 @@ he:
|
||||
two: "LLMים:"
|
||||
many: "LLMים:"
|
||||
other: "LLMים:"
|
||||
no_llm: "לא נבחר מש״ג/LLM"
|
||||
no_persona: "לא מוגדר"
|
||||
no_groups: "ללא"
|
||||
edit: "עריכה"
|
||||
@@ -196,24 +197,44 @@ he:
|
||||
collapse_list: "(להציג פחות)"
|
||||
bot:
|
||||
name: "בוט"
|
||||
description: "צ׳אט בוט שיכול לענות על שאלות ולסייע למשתמשים בהודעות אישיות, בפורום ובצ׳אט"
|
||||
filters:
|
||||
all: "הכול"
|
||||
text: "חיפוש יכולות, דמויות, LLMים/מש״גים או קבוצות…"
|
||||
reset: "איפוס"
|
||||
summarization:
|
||||
name: "סיכומים"
|
||||
description: "להנגיש את כפתור הסיכום שמאפשר למבקרים לסכם נושאים"
|
||||
topic_summaries: "תקצירי נושאים."
|
||||
search:
|
||||
name: "חיפוש"
|
||||
description: "שיפור חוויית החיפוש על ידי אספקת תשובות שנוצרו על ידי בינה מלאכותית לשאילתות"
|
||||
discoveries: "תגליות"
|
||||
embeddings:
|
||||
name: "הטמעות"
|
||||
discord:
|
||||
name: "שילוב מול Discord"
|
||||
description: "הוספת היכולת לחפש בערוצי Discord"
|
||||
search: "חיפוש ב־Discord"
|
||||
inference:
|
||||
generate_concepts: "הסקת תפיסות"
|
||||
ai_helper:
|
||||
name: "מסייע"
|
||||
proofread: הגהת הטקסט
|
||||
title_suggestions: "הצעת כותרות"
|
||||
explain: "הסבר"
|
||||
illustrate_post: "איור פוסט"
|
||||
smart_dates: "תאריכים חכמים"
|
||||
translate: "תרגום"
|
||||
markdown_tables: "יצירת טבלה ב־Markdown"
|
||||
custom_prompt: "בקשה מותאמת אישית"
|
||||
image_caption: "הוספת כותרות לתמונות"
|
||||
translation:
|
||||
description: "תרגום תוכן לשפות נתמכות"
|
||||
locale_detector: "מזהה שפה ומקום"
|
||||
post_raw_translator: "מתרגם פוסטים גולמי"
|
||||
topic_title_translator: "מתרגם כותרות נושאים"
|
||||
short_text_translator: "מתרגם טקסטים קצרים"
|
||||
spam:
|
||||
name: "ספאם"
|
||||
modals:
|
||||
@@ -491,7 +512,7 @@ he:
|
||||
ai_summarization: "סיכום"
|
||||
ai_embeddings_semantic_search: "חיפוש בינה מלאכותית"
|
||||
ai_spam: "ספאם"
|
||||
automation: "אוטומציה (%{name})"
|
||||
automation: "אוטומציה (%{persona})"
|
||||
in_use_warning:
|
||||
one: "המודל הזה משמש את %{settings}. אם לא מוגדר כראוי, היכולת לא תעבוד כמצופה."
|
||||
two: "המודל הזה משמש את: %{settings}. אם ההגדרות שגויות היכולת לא תעבודנה כמצופה."
|
||||
|
||||
@@ -154,6 +154,8 @@ it:
|
||||
reset: "Annulla"
|
||||
search:
|
||||
name: "Cerca"
|
||||
embeddings:
|
||||
name: "Integrazioni"
|
||||
ai_helper:
|
||||
name: "Assistente"
|
||||
proofread: Testo corretto
|
||||
|
||||
@@ -157,6 +157,8 @@ ja:
|
||||
reset: "リセット"
|
||||
search:
|
||||
name: "検索"
|
||||
embeddings:
|
||||
name: "埋め込み"
|
||||
ai_helper:
|
||||
name: "ヘルパー"
|
||||
proofread: テキストを構成
|
||||
|
||||
@@ -154,6 +154,8 @@ nl:
|
||||
reset: "Resetten"
|
||||
search:
|
||||
name: "Zoeken"
|
||||
embeddings:
|
||||
name: "Insluitingen"
|
||||
ai_helper:
|
||||
name: "Helper"
|
||||
proofread: Tekst proeflezen
|
||||
|
||||
@@ -154,6 +154,8 @@ pt_BR:
|
||||
reset: "Redefinir"
|
||||
search:
|
||||
name: "Pesquisar"
|
||||
embeddings:
|
||||
name: "Incorporações"
|
||||
ai_helper:
|
||||
name: "Ajudante"
|
||||
proofread: Revisar texto
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user