FEATURE: allow sending AI based report to a topic (#377)
This makes the reporting far more flexible cause it can target a far wider audience by pointing it at a topic in a secure category or an existing PM
This commit is contained in:
parent
37dd98c937
commit
a5d240991f
|
@ -20,7 +20,10 @@ en:
|
||||||
description: "The user that will send the report"
|
description: "The user that will send the report"
|
||||||
receivers:
|
receivers:
|
||||||
label: "Receivers"
|
label: "Receivers"
|
||||||
description: "The users that will receive the report (can be email or usernames)"
|
description: "The users that will receive the report (emails will be sent direct emails, usernames will be sent a PM)"
|
||||||
|
topic_id:
|
||||||
|
label: "Topic ID"
|
||||||
|
description: "The topic id to post the report to"
|
||||||
title:
|
title:
|
||||||
label: "Title"
|
label: "Title"
|
||||||
description: "The title of the report"
|
description: "The title of the report"
|
||||||
|
|
|
@ -11,8 +11,9 @@ if defined?(DiscourseAutomation)
|
||||||
triggerables %i[recurring]
|
triggerables %i[recurring]
|
||||||
|
|
||||||
field :sender, component: :user, required: true
|
field :sender, component: :user, required: true
|
||||||
field :receivers, component: :users, required: true
|
field :receivers, component: :users
|
||||||
field :title, component: :text, required: true
|
field :topic_id, component: :text
|
||||||
|
field :title, component: :text
|
||||||
field :days, component: :text, required: true, default_value: 7
|
field :days, component: :text, required: true, default_value: 7
|
||||||
field :offset, component: :text, required: true, default_value: 0
|
field :offset, component: :text, required: true, default_value: 0
|
||||||
field :instructions,
|
field :instructions,
|
||||||
|
@ -40,6 +41,7 @@ if defined?(DiscourseAutomation)
|
||||||
begin
|
begin
|
||||||
sender = fields.dig("sender", "value")
|
sender = fields.dig("sender", "value")
|
||||||
receivers = fields.dig("receivers", "value")
|
receivers = fields.dig("receivers", "value")
|
||||||
|
topic_id = fields.dig("topic_id", "value")
|
||||||
title = fields.dig("title", "value")
|
title = fields.dig("title", "value")
|
||||||
model = fields.dig("model", "value")
|
model = fields.dig("model", "value")
|
||||||
category_ids = fields.dig("categories", "value")
|
category_ids = fields.dig("categories", "value")
|
||||||
|
@ -56,6 +58,7 @@ if defined?(DiscourseAutomation)
|
||||||
DiscourseAi::Automation::ReportRunner.run!(
|
DiscourseAi::Automation::ReportRunner.run!(
|
||||||
sender_username: sender,
|
sender_username: sender,
|
||||||
receivers: receivers,
|
receivers: receivers,
|
||||||
|
topic_id: topic_id,
|
||||||
title: title,
|
title: title,
|
||||||
model: model,
|
model: model,
|
||||||
category_ids: category_ids,
|
category_ids: category_ids,
|
||||||
|
|
|
@ -35,25 +35,30 @@ module DiscourseAi
|
||||||
|
|
||||||
def initialize(
|
def initialize(
|
||||||
sender_username:,
|
sender_username:,
|
||||||
receivers:,
|
|
||||||
title:,
|
|
||||||
model:,
|
model:,
|
||||||
category_ids:,
|
|
||||||
tags:,
|
|
||||||
allow_secure_categories:,
|
|
||||||
debug_mode:,
|
|
||||||
sample_size:,
|
sample_size:,
|
||||||
instructions:,
|
instructions:,
|
||||||
|
tokens_per_post:,
|
||||||
days:,
|
days:,
|
||||||
offset:,
|
offset:,
|
||||||
priority_group_id:,
|
receivers: nil,
|
||||||
tokens_per_post:
|
topic_id: nil,
|
||||||
|
title: nil,
|
||||||
|
category_ids: nil,
|
||||||
|
tags: nil,
|
||||||
|
priority_group_id: nil,
|
||||||
|
allow_secure_categories: false,
|
||||||
|
debug_mode: false
|
||||||
)
|
)
|
||||||
@sender = User.find_by(username: sender_username)
|
@sender = User.find_by(username: sender_username)
|
||||||
@receivers = User.where(username: receivers)
|
@receivers = User.where(username: receivers)
|
||||||
@email_receivers = receivers.filter { |r| r.include? "@" }
|
@email_receivers = receivers&.filter { |r| r.include? "@" }
|
||||||
@title = title
|
@title =
|
||||||
|
if title.present?
|
||||||
|
title
|
||||||
|
else
|
||||||
|
I18n.t("discourse_automation.llm_report.title")
|
||||||
|
end
|
||||||
@model = model
|
@model = model
|
||||||
@llm = DiscourseAi::Completions::Llm.proxy(model)
|
@llm = DiscourseAi::Completions::Llm.proxy(model)
|
||||||
@category_ids = category_ids
|
@category_ids = category_ids
|
||||||
|
@ -66,13 +71,18 @@ module DiscourseAi
|
||||||
@offset = offset.to_i
|
@offset = offset.to_i
|
||||||
@priority_group_id = priority_group_id
|
@priority_group_id = priority_group_id
|
||||||
@tokens_per_post = tokens_per_post.to_i
|
@tokens_per_post = tokens_per_post.to_i
|
||||||
|
@topic_id = topic_id.presence&.to_i
|
||||||
|
|
||||||
|
if !@topic_id && !@receivers.present? && !@email_receivers.present?
|
||||||
|
raise ArgumentError, "Must specify topic_id or receivers"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def run!
|
def run!
|
||||||
start_date = (@offset + @days).days.ago
|
start_date = (@offset + @days).days.ago
|
||||||
end_date = start_date + @days.days
|
end_date = start_date + @days.days
|
||||||
|
|
||||||
@title =
|
title =
|
||||||
@title.gsub(
|
@title.gsub(
|
||||||
"%DATE%",
|
"%DATE%",
|
||||||
start_date.strftime("%Y-%m-%d") + " - " + end_date.strftime("%Y-%m-%d"),
|
start_date.strftime("%Y-%m-%d") + " - " + end_date.strftime("%Y-%m-%d"),
|
||||||
|
@ -102,7 +112,7 @@ module DiscourseAi
|
||||||
INPUT
|
INPUT
|
||||||
|
|
||||||
prompt = {
|
prompt = {
|
||||||
insts: "You are a helpful bot specializing in summarizing activity Discourse sites",
|
insts: "You are a helpful bot specializing in summarizing activity on Discourse sites",
|
||||||
input: input,
|
input: input,
|
||||||
final_insts: "Here is the report I generated for you",
|
final_insts: "Here is the report I generated for you",
|
||||||
params: {
|
params: {
|
||||||
|
@ -123,12 +133,17 @@ module DiscourseAi
|
||||||
|
|
||||||
receiver_usernames = @receivers.map(&:username).join(",")
|
receiver_usernames = @receivers.map(&:username).join(",")
|
||||||
|
|
||||||
|
if @topic_id
|
||||||
|
PostCreator.create!(@sender, raw: result, topic_id: @topic_id, skip_validations: true)
|
||||||
|
# no debug mode for topics, it is too noisy
|
||||||
|
end
|
||||||
|
|
||||||
if receiver_usernames.present?
|
if receiver_usernames.present?
|
||||||
post =
|
post =
|
||||||
PostCreator.create!(
|
PostCreator.create!(
|
||||||
@sender,
|
@sender,
|
||||||
raw: result,
|
raw: result,
|
||||||
title: @title,
|
title: title,
|
||||||
archetype: Archetype.private_message,
|
archetype: Archetype.private_message,
|
||||||
target_usernames: receiver_usernames,
|
target_usernames: receiver_usernames,
|
||||||
skip_validations: true,
|
skip_validations: true,
|
||||||
|
@ -157,7 +172,7 @@ module DiscourseAi
|
||||||
if @email_receivers.present?
|
if @email_receivers.present?
|
||||||
@email_receivers.each do |to_address|
|
@email_receivers.each do |to_address|
|
||||||
Email::Sender.new(
|
Email::Sender.new(
|
||||||
::AiReportMailer.send_report(to_address, subject: @title, body: result),
|
::AiReportMailer.send_report(to_address, subject: title, body: result),
|
||||||
:ai_report,
|
:ai_report,
|
||||||
).send
|
).send
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,9 @@ return if !defined?(DiscourseAutomation)
|
||||||
describe DiscourseAutomation do
|
describe DiscourseAutomation do
|
||||||
let(:automation) { Fabricate(:automation, script: "llm_report", enabled: true) }
|
let(:automation) { Fabricate(:automation, script: "llm_report", enabled: true) }
|
||||||
|
|
||||||
|
fab!(:user)
|
||||||
|
fab!(:post)
|
||||||
|
|
||||||
def add_automation_field(name, value, type: "text")
|
def add_automation_field(name, value, type: "text")
|
||||||
automation.fields.create!(
|
automation.fields.create!(
|
||||||
component: type,
|
component: type,
|
||||||
|
@ -17,8 +20,6 @@ describe DiscourseAutomation do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "can trigger via automation" do
|
it "can trigger via automation" do
|
||||||
user = Fabricate(:user)
|
|
||||||
|
|
||||||
add_automation_field("sender", user.username, type: "user")
|
add_automation_field("sender", user.username, type: "user")
|
||||||
add_automation_field("receivers", [user.username], type: "users")
|
add_automation_field("receivers", [user.username], type: "users")
|
||||||
add_automation_field("model", "gpt-4-turbo")
|
add_automation_field("model", "gpt-4-turbo")
|
||||||
|
@ -31,4 +32,16 @@ describe DiscourseAutomation do
|
||||||
pm = Topic.where(title: "Weekly report").first
|
pm = Topic.where(title: "Weekly report").first
|
||||||
expect(pm.posts.first.raw).to eq("An Amazing Report!!!")
|
expect(pm.posts.first.raw).to eq("An Amazing Report!!!")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "can target a topic" do
|
||||||
|
add_automation_field("sender", user.username, type: "user")
|
||||||
|
add_automation_field("topic_id", "#{post.topic_id}")
|
||||||
|
add_automation_field("model", "gpt-4-turbo")
|
||||||
|
|
||||||
|
DiscourseAi::Completions::Llm.with_prepared_responses(["An Amazing Report!!!"]) do
|
||||||
|
automation.trigger!
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(post.topic.reload.ordered_posts.last.raw).to eq("An Amazing Report!!!")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue