Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 5ae8064

Browse files
authored
Merge branch 'main' into default-llm-model
2 parents b675c4c + ad6a8cb commit 5ae8064

31 files changed

+340
-221
lines changed

app/models/embedding_definition.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def presets
8484
dimensions: 2000,
8585
max_sequence_length: 8191,
8686
pg_function: "<=>",
87-
tokenizer_class: "DiscourseAi::Tokenizer::OpenAiTokenizer",
87+
tokenizer_class: "DiscourseAi::Tokenizer::OpenAiCl100kTokenizer",
8888
url: "https://api.openai.com/v1/embeddings",
8989
provider: OPEN_AI,
9090
matryoshka_dimensions: true,
@@ -98,7 +98,7 @@ def presets
9898
dimensions: 1536,
9999
max_sequence_length: 8191,
100100
pg_function: "<=>",
101-
tokenizer_class: "DiscourseAi::Tokenizer::OpenAiTokenizer",
101+
tokenizer_class: "DiscourseAi::Tokenizer::OpenAiCl100kTokenizer",
102102
url: "https://api.openai.com/v1/embeddings",
103103
provider: OPEN_AI,
104104
matryoshka_dimensions: true,
@@ -112,7 +112,7 @@ def presets
112112
dimensions: 1536,
113113
max_sequence_length: 8191,
114114
pg_function: "<=>",
115-
tokenizer_class: "DiscourseAi::Tokenizer::OpenAiTokenizer",
115+
tokenizer_class: "DiscourseAi::Tokenizer::OpenAiCl100kTokenizer",
116116
url: "https://api.openai.com/v1/embeddings",
117117
provider: OPEN_AI,
118118
provider_params: {

assets/javascripts/discourse/components/ai-bot-conversations.gjs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,10 +260,11 @@ export default class AiBotConversations extends Component {
260260

261261
@action
262262
async prepareAndSubmitToBot() {
263-
// Pass uploads to the service before submitting
264-
this.aiBotConversationsHiddenSubmit.uploads = this.uploads;
265263
try {
266-
await this.aiBotConversationsHiddenSubmit.submitToBot();
264+
await this.aiBotConversationsHiddenSubmit.submitToBot({
265+
uploads: this.uploads,
266+
inProgressUploadsCount: this.inProgressUploads.length,
267+
});
267268
this.uploads = new TrackedArray();
268269
} catch (error) {
269270
popupAjaxError(error);

assets/javascripts/discourse/components/ai-features-list.gjs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,9 @@ class ExpandableList extends Component {
6666

6767
export default class AiFeaturesList extends Component {
6868
get sortedModules() {
69-
if (!this.args.modules || !this.args.modules.length) {
70-
return [];
71-
}
72-
73-
return this.args.modules.toSorted((a, b) =>
74-
a.module_name.localeCompare(b.module_name)
69+
const modules = this.args.modules?.toArray() || this.args.modules;
70+
return [...(modules || [])].toSorted((a, b) =>
71+
(a.module_name || "").localeCompare(b.module_name || "")
7572
);
7673
}
7774

assets/javascripts/discourse/services/ai-bot-conversations-hidden-submit.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ export default class AiBotConversationsHiddenSubmit extends Service {
1818

1919
personaId;
2020
targetUsername;
21-
uploads = [];
2221

2322
inputValue = "";
2423

@@ -32,7 +31,7 @@ export default class AiBotConversationsHiddenSubmit extends Service {
3231
}
3332

3433
@action
35-
async submitToBot() {
34+
async submitToBot(uploadData) {
3635
if (
3736
this.inputValue.length <
3837
this.siteSettings.min_personal_message_post_length
@@ -48,7 +47,7 @@ export default class AiBotConversationsHiddenSubmit extends Service {
4847
}
4948

5049
// Don't submit if there are still uploads in progress
51-
if (document.querySelector(".ai-bot-upload--in-progress")) {
50+
if (uploadData.inProgressUploadsCount > 0) {
5251
return this.dialog.alert({
5352
message: i18n("discourse_ai.ai_bot.conversations.uploads_in_progress"),
5453
});
@@ -61,10 +60,10 @@ export default class AiBotConversationsHiddenSubmit extends Service {
6160
let rawContent = this.inputValue;
6261

6362
// Append upload markdown if we have uploads
64-
if (this.uploads && this.uploads.length > 0) {
63+
if (uploadData.uploads && uploadData.uploads.length > 0) {
6564
rawContent += "\n\n";
6665

67-
this.uploads.forEach((upload) => {
66+
uploadData.uploads.forEach((upload) => {
6867
const uploadMarkdown = getUploadMarkdown(upload);
6968
rawContent += uploadMarkdown + "\n";
7069
});
@@ -83,7 +82,6 @@ export default class AiBotConversationsHiddenSubmit extends Service {
8382
});
8483

8584
// Reset uploads after successful submission
86-
this.uploads = [];
8785
this.inputValue = "";
8886

8987
this.appEvents.trigger("discourse-ai:bot-pm-created", {

config/locales/client.de.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,9 @@ de:
233233
inference:
234234
name: "Abgeleitete Konzepte"
235235
description: "Ordnet Themen und Beiträge in Interessensgebiete / Labels."
236+
generate_concepts: "Konzepterkennung"
236237
match_concepts: "Passende Konzepte"
238+
deduplicate_concepts: "Deduplizierung von Konzepten"
237239
ai_helper:
238240
name: "Helfer"
239241
description: "Unterstützt Benutzer bei der Interaktion in der Community, z. B. beim Erstellen von Themen, Verfassen von Beiträgen und Lesen von Inhalten"
@@ -773,6 +775,7 @@ de:
773775
shortcut_title: "Starte eine PN mit einem KI-Bot"
774776
share: "KI-Unterhaltung kopieren"
775777
conversation_shared: "Unterhaltung kopiert"
778+
embed_copied: "Einbettung in die Zwischenablage kopiert"
776779
debug_ai: "Rohdaten der KI-Anfrage und -Antwort anzeigen"
777780
sidebar_empty: "Der Verlauf der Bot-Konversation wird hier angezeigt."
778781
debug_ai_modal:

config/locales/client.en.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ en:
106106
top_p:
107107
label: "Top P"
108108
description: "Top P to use for the LLM, increase to increase randomness (leave empty to use model default)"
109+
persona_id:
110+
label: "Persona"
111+
description: "AI Persona to use for report generation"
109112

110113
llm_tool_triage:
111114
fields:
@@ -876,6 +879,7 @@ en:
876879
last_7_days: "Last 7 days"
877880
last_30_days: "Last 30 days"
878881
upload_files: "Upload files"
882+
uploads_in_progress: "Cannot submit while uploads are in progress"
879883
sentiments:
880884
dashboard:
881885
title: "Sentiment"

config/locales/server.de.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ de:
116116
ai_translation_model: "Das Modell, das für die Übersetzung verwendet werden soll. Dieses Modell muss die Übersetzung unterstützen. Personas können diese Einstellung überschreiben."
117117
ai_translation_backfill_limit_to_public_content: "Wenn diese Option aktiviert ist, werden nur Inhalte in öffentlichen Kategorien übersetzt. Wenn sie deaktiviert ist, werden auch Inhalte in Gruppen-PMs und privaten Kategorien zur Übersetzung gesendet."
118118
ai_translation_max_post_length: "Die maximale Länge eines zu übersetzenden Beitrags. Längere Beiträge werden nicht übersetzt."
119-
ai_translation_backfill_max_age_days: "Das maximale Alter eines zu übersetzenden Beitrags und Themas. Ältere Beiträge und Themen werden nicht übersetzt."
119+
ai_translation_backfill_max_age_days: "Das maximale Alter eines Beitrags oder Themas, das übersetzt werden soll. Beiträge und Themen, die älter sind, werden nicht übersetzt. 0 deaktiviert die rückwirkende Übersetzung, aber nicht die Übersetzung von neuen Beiträgen."
120120
reviewables:
121121
reasons:
122122
flagged_by_toxicity: Das KI-Plug-in meldete dies nach der Klassifizierung als toxisch.
@@ -221,6 +221,7 @@ de:
221221
one: "Du kannst nur %{count} Schlüssel im Artefakt haben."
222222
other: "Du kannst nur %{count} Schlüssel im Artefakt haben."
223223
link: "In neuem Tab anzeigen"
224+
copy_embed: "Einbettung kopieren"
224225
view_source: "Quelle anzeigen"
225226
view_changes: "Änderungen anzeigen"
226227
change_description: "Beschreibung ändern"
@@ -590,6 +591,7 @@ de:
590591
bedrock_invalid_url: "Bitte fülle alle Felder aus, um dieses Modell zu verwenden."
591592
ai_staff_action_logger:
592593
updated: "aktualisiert"
594+
set: "gesetzt"
593595
removed: "entfernt"
594596
errors:
595597
quota_exceeded: "Du hast das Kontingent für dieses Modell überschritten. Bitte versuche es erneut in %{relative_time}."

config/locales/server.en.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,9 @@ en:
398398
content_creator:
399399
name: "Content creator"
400400
description: "Default persona powering HyDE search"
401+
report_runner:
402+
name: "Report runner"
403+
description: "Default persona used in the report automation script"
401404

402405
topic_not_found: "Summary unavailable, topic not found!"
403406
summarizing: "Summarizing topic"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# frozen_string_literal: true
2+
class UpdateOpenAiEmbeddingsTokenizer < ActiveRecord::Migration[7.2]
3+
def up
4+
execute <<~SQL
5+
UPDATE embedding_definitions
6+
SET tokenizer_class = 'DiscourseAi::Tokenizer::OpenAiCl100kTokenizer'
7+
WHERE url LIKE '%https://api.openai.com/%' AND tokenizer_class <> 'DiscourseAi::Tokenizer::OpenAiCl100kTokenizer'
8+
SQL
9+
end
10+
11+
def down
12+
raise ActiveRecord::IrreversibleMigration
13+
end
14+
end

discourse_automation/llm_report.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ module DiscourseAutomation::LlmReport
2121
field :sample_size, component: :text, required: true, default_value: 100
2222
field :tokens_per_post, component: :text, required: true, default_value: 150
2323

24+
field :persona_id,
25+
component: :choices,
26+
required: true,
27+
default_value:
28+
DiscourseAi::Personas::Persona.system_personas[DiscourseAi::Personas::ReportRunner],
29+
extra: {
30+
content:
31+
DiscourseAi::Automation.available_persona_choices(
32+
require_user: false,
33+
require_default_llm: false,
34+
),
35+
}
2436
field :model,
2537
component: :choices,
2638
required: true,
@@ -60,6 +72,7 @@ module DiscourseAutomation::LlmReport
6072
offset = fields.dig("offset", "value").to_i
6173
priority_group = fields.dig("priority_group", "value")
6274
tokens_per_post = fields.dig("tokens_per_post", "value")
75+
persona_id = fields.dig("persona_id", "value")
6376

6477
exclude_category_ids = fields.dig("exclude_categories", "value")
6578
exclude_tags = fields.dig("exclude_tags", "value")
@@ -78,12 +91,19 @@ module DiscourseAutomation::LlmReport
7891
temperature = temperature.to_f
7992
end
8093

94+
# Backwards-compat for scripts created before this field was added.
95+
if persona_id == "" || persona_id.nil?
96+
persona_id =
97+
DiscourseAi::Personas::Persona.system_personas[DiscourseAi::Personas::ReportRunner]
98+
end
99+
81100
suppress_notifications = !!fields.dig("suppress_notifications", "value")
82101
DiscourseAi::Automation::ReportRunner.run!(
83102
sender_username: sender,
84103
receivers: receivers,
85104
topic_id: topic_id,
86105
title: title,
106+
persona_id: persona_id,
87107
model: model,
88108
category_ids: category_ids,
89109
tags: tags,

0 commit comments

Comments
 (0)