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

Commit 00f4de9

Browse files
committed
WIP: allow triage using persona from triage
1 parent e255c7a commit 00f4de9

File tree

3 files changed

+57
-14
lines changed

3 files changed

+57
-14
lines changed

config/locales/client.en.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ en:
146146
include_personal_messages:
147147
label: "Include personal messages"
148148
description: "Also scan and triage personal messages"
149+
whisper:
150+
label: "Reply as Whisper"
151+
description: "Whether the AI's response should be a whisper"
152+
reply_persona:
153+
label: "Reply Persona"
154+
description: "AI Persona to use for replies (must have default LLM), will be prioritized over canned reply"
149155
model:
150156
label: "Model"
151157
description: "Language model used for triage"

discourse_automation/llm_triage.rb

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,58 @@
99

1010
triggerables %i[post_created_edited]
1111

12-
field :system_prompt, component: :message, required: false
13-
field :search_for_text, component: :text, required: true
14-
field :max_post_tokens, component: :text
15-
field :stop_sequences, component: :text_list, required: false
12+
# TODO move to triggerables
13+
field :include_personal_messages, component: :boolean
14+
15+
# Inputs
1616
field :model,
1717
component: :choices,
1818
required: true,
1919
extra: {
2020
content: DiscourseAi::Automation.available_models,
2121
}
22+
field :system_prompt, component: :message, required: false
23+
field :search_for_text, component: :text, required: true
24+
field :max_post_tokens, component: :text
25+
field :stop_sequences, component: :text_list, required: false
26+
field :temperature, component: :text
27+
28+
# Actions
2229
field :category, component: :category
2330
field :tags, component: :tags
2431
field :hide_topic, component: :boolean
2532
field :flag_post, component: :boolean
26-
field :include_personal_messages, component: :boolean
27-
field :temperature, component: :text
2833
field :flag_type,
2934
component: :choices,
3035
required: false,
3136
extra: {
3237
content: DiscourseAi::Automation.flag_types,
3338
},
3439
default: "review"
35-
field :canned_reply, component: :message
3640
field :canned_reply_user, component: :user
41+
field :canned_reply, component: :message
42+
field :reply_persona,
43+
component: :choices,
44+
extra: {
45+
content: DiscourseAi::Automation.available_persona_choices,
46+
}
47+
field :whisper, component: :boolean
3748

3849
script do |context, fields|
3950
post = context["post"]
51+
52+
post = context["post"]
53+
next if post&.user&.bot?
54+
55+
if post.topic.private_message?
56+
include_personal_messages = fields.dig("include_personal_messages", "value")
57+
next if !include_personal_messages
58+
end
59+
4060
canned_reply = fields.dig("canned_reply", "value")
4161
canned_reply_user = fields.dig("canned_reply_user", "value")
62+
reply_persona_id = fields["reply_persona"]["value"]
63+
whisper = fields["whisper"]["value"]
4264

4365
# nothing to do if we already replied
4466
next if post.user.username == canned_reply_user
@@ -65,11 +87,6 @@
6587

6688
stop_sequences = fields.dig("stop_sequences", "value")
6789

68-
if post.topic.private_message?
69-
include_personal_messages = fields.dig("include_personal_messages", "value")
70-
next if !include_personal_messages
71-
end
72-
7390
begin
7491
RateLimiter.new(
7592
Discourse.system_user,
@@ -94,6 +111,8 @@
94111
tags: tags,
95112
canned_reply: canned_reply,
96113
canned_reply_user: canned_reply_user,
114+
reply_persona_id: reply_persona_id,
115+
whisper: whisper,
97116
hide_topic: hide_topic,
98117
flag_post: flag_post,
99118
flag_type: flag_type.to_s.to_sym,

lib/automation/llm_triage.rb

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ def self.handle(
1818
automation: nil,
1919
max_post_tokens: nil,
2020
stop_sequences: nil,
21-
temperature: nil
21+
temperature: nil,
22+
whisper: nil,
23+
reply_persona_id: nil
2224
)
2325
if category_id.blank? && tags.blank? && canned_reply.blank? && hide_topic.blank? &&
2426
flag_post.blank?
@@ -55,13 +57,29 @@ def self.handle(
5557
if result.present? && result.downcase.include?(search_for_text.downcase)
5658
user = User.find_by_username(canned_reply_user) if canned_reply_user.present?
5759
user = user || Discourse.system_user
58-
if canned_reply.present?
60+
if reply_persona_id.present?
61+
ai_persona = AiPersona.find_by(id: persona_id)
62+
if ai_persona.present?
63+
persona_class = ai_persona.class_instance
64+
persona = persona_class.new
65+
66+
bot_user = ai_persona.user
67+
if bot_user.nil?
68+
bot = DiscourseAi::AiBot::Bot.as(bot_user, persona: persona)
69+
playground = DiscourseAi::AiBot::Playground.new(bot)
70+
71+
playground.reply_to(post, whisper: whisper, context_style: :topic)
72+
end
73+
end
74+
elsif canned_reply.present?
75+
post_type = whisper ? Post.types[:whisper] : Post.types[:regular]
5976
PostCreator.create!(
6077
user,
6178
topic_id: post.topic_id,
6279
raw: canned_reply,
6380
reply_to_post_number: post.post_number,
6481
skip_validations: true,
82+
post_type: post_type,
6583
)
6684
end
6785

0 commit comments

Comments
 (0)