2023-05-05 14:28:31 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
RSpec.describe DiscourseAi::AiBot::EntryPoint do
|
|
|
|
describe "#inject_into" do
|
|
|
|
describe "subscribes to the post_created event" do
|
2024-03-05 10:48:28 -05:00
|
|
|
fab!(:admin)
|
2023-05-05 14:28:31 -04:00
|
|
|
fab!(:bot_allowed_group) { Fabricate(:group) }
|
|
|
|
|
2024-06-18 13:32:14 -04:00
|
|
|
fab!(:gpt_4) { Fabricate(:llm_model, name: "gpt-4") }
|
|
|
|
let(:gpt_bot) { gpt_4.reload.user }
|
|
|
|
|
|
|
|
fab!(:claude_2) { Fabricate(:llm_model, name: "claude-2") }
|
|
|
|
|
2023-05-05 14:28:31 -04:00
|
|
|
let(:post_args) do
|
|
|
|
{
|
|
|
|
title: "Dear AI, I want to ask a question",
|
|
|
|
raw: "Hello, Can you please tell me a story?",
|
|
|
|
archetype: Archetype.private_message,
|
|
|
|
target_usernames: [gpt_bot.username].join(","),
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
2024-06-18 13:32:14 -04:00
|
|
|
toggle_enabled_bots(bots: [gpt_4, claude_2])
|
2023-10-23 02:00:58 -04:00
|
|
|
SiteSetting.ai_bot_enabled = true
|
2023-05-05 14:28:31 -04:00
|
|
|
SiteSetting.ai_bot_allowed_groups = bot_allowed_group.id
|
|
|
|
bot_allowed_group.add(admin)
|
|
|
|
end
|
|
|
|
|
2024-04-15 09:22:06 -04:00
|
|
|
it "adds a can_debug_ai_bot_conversations method to current user" do
|
|
|
|
SiteSetting.ai_bot_debugging_allowed_groups = bot_allowed_group.id.to_s
|
|
|
|
serializer = CurrentUserSerializer.new(admin, scope: Guardian.new(admin))
|
|
|
|
serializer = serializer.as_json
|
|
|
|
|
|
|
|
expect(serializer[:current_user][:can_debug_ai_bot_conversations]).to eq(true)
|
|
|
|
end
|
|
|
|
|
2024-10-15 16:20:31 -04:00
|
|
|
it "adds information about forcing default llm to current_user_serializer" do
|
2024-02-29 15:53:42 -05:00
|
|
|
Group.refresh_automatic_groups!
|
|
|
|
|
|
|
|
persona =
|
|
|
|
Fabricate(
|
|
|
|
:ai_persona,
|
|
|
|
enabled: true,
|
|
|
|
allowed_group_ids: [bot_allowed_group.id],
|
2024-10-15 16:20:31 -04:00
|
|
|
default_llm: "claude-2",
|
|
|
|
force_default_llm: true,
|
2024-02-29 15:53:42 -05:00
|
|
|
)
|
|
|
|
persona.create_user!
|
|
|
|
|
|
|
|
serializer = CurrentUserSerializer.new(admin, scope: Guardian.new(admin))
|
|
|
|
serializer = serializer.as_json
|
|
|
|
bots = serializer[:current_user][:ai_enabled_chat_bots]
|
|
|
|
|
|
|
|
persona_bot = bots.find { |bot| bot["id"] == persona.user_id }
|
|
|
|
|
|
|
|
expect(persona_bot["username"]).to eq(persona.user.username)
|
2024-10-15 16:20:31 -04:00
|
|
|
expect(persona_bot["force_default_llm"]).to eq(true)
|
2024-04-15 09:22:06 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "includes user ids for all personas in the serializer" do
|
|
|
|
Group.refresh_automatic_groups!
|
|
|
|
|
|
|
|
persona = Fabricate(:ai_persona, enabled: true, allowed_group_ids: [bot_allowed_group.id])
|
|
|
|
persona.create_user!
|
|
|
|
|
|
|
|
serializer = CurrentUserSerializer.new(admin, scope: Guardian.new(admin))
|
|
|
|
serializer = serializer.as_json
|
|
|
|
bots = serializer[:current_user][:ai_enabled_chat_bots]
|
|
|
|
|
|
|
|
persona_bot = bots.find { |bot| bot["id"] == persona.user_id }
|
|
|
|
expect(persona_bot["username"]).to eq(persona.user.username)
|
2024-10-15 16:20:31 -04:00
|
|
|
expect(persona_bot["force_default_llm"]).to eq(false)
|
2024-02-29 15:53:42 -05:00
|
|
|
end
|
|
|
|
|
2023-05-05 14:28:31 -04:00
|
|
|
it "queues a job to generate a reply by the AI" do
|
|
|
|
expect { PostCreator.create!(admin, post_args) }.to change(
|
|
|
|
Jobs::CreateAiReply.jobs,
|
|
|
|
:size,
|
|
|
|
).by(1)
|
|
|
|
end
|
|
|
|
|
2023-05-20 03:45:54 -04:00
|
|
|
it "does not queue a job for small actions" do
|
|
|
|
post = PostCreator.create!(admin, post_args)
|
|
|
|
|
|
|
|
expect {
|
|
|
|
post.topic.add_moderator_post(
|
|
|
|
admin,
|
|
|
|
"this is a small action",
|
|
|
|
post_type: Post.types[:small_action],
|
|
|
|
)
|
|
|
|
}.not_to change(Jobs::CreateAiReply.jobs, :size)
|
|
|
|
|
|
|
|
expect {
|
|
|
|
post.topic.add_moderator_post(
|
|
|
|
admin,
|
|
|
|
"this is a small action",
|
|
|
|
post_type: Post.types[:moderator_action],
|
|
|
|
)
|
|
|
|
}.not_to change(Jobs::CreateAiReply.jobs, :size)
|
|
|
|
|
|
|
|
expect {
|
|
|
|
post.topic.add_moderator_post(
|
|
|
|
admin,
|
|
|
|
"this is a small action",
|
|
|
|
post_type: Post.types[:whisper],
|
|
|
|
)
|
|
|
|
}.not_to change(Jobs::CreateAiReply.jobs, :size)
|
|
|
|
end
|
|
|
|
|
2023-05-11 09:03:03 -04:00
|
|
|
it "includes the bot's user_id" do
|
2024-06-18 13:32:14 -04:00
|
|
|
claude_bot = DiscourseAi::AiBot::EntryPoint.find_user_from_model("claude-2")
|
2023-05-11 09:03:03 -04:00
|
|
|
claude_post_attrs = post_args.merge(target_usernames: [claude_bot.username].join(","))
|
|
|
|
|
|
|
|
expect { PostCreator.create!(admin, claude_post_attrs) }.to change(
|
|
|
|
Jobs::CreateAiReply.jobs,
|
|
|
|
:size,
|
|
|
|
).by(1)
|
|
|
|
|
|
|
|
job_args = Jobs::CreateAiReply.jobs.last["args"].first
|
|
|
|
expect(job_args["bot_user_id"]).to eq(claude_bot.id)
|
|
|
|
end
|
|
|
|
|
2023-05-05 14:28:31 -04:00
|
|
|
context "when the post is not from a PM" do
|
|
|
|
it "does nothing" do
|
|
|
|
expect {
|
|
|
|
PostCreator.create!(admin, post_args.merge(archetype: Archetype.default))
|
|
|
|
}.not_to change(Jobs::CreateAiReply.jobs, :size)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when the bot doesn't have access to the PM" do
|
|
|
|
it "does nothing" do
|
|
|
|
user_2 = Fabricate(:user)
|
|
|
|
expect {
|
|
|
|
PostCreator.create!(admin, post_args.merge(target_usernames: [user_2.username]))
|
|
|
|
}.not_to change(Jobs::CreateAiReply.jobs, :size)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when the user is not allowed to interact with the bot" do
|
|
|
|
it "does nothing" do
|
|
|
|
bot_allowed_group.remove(admin)
|
|
|
|
expect { PostCreator.create!(admin, post_args) }.not_to change(
|
|
|
|
Jobs::CreateAiReply.jobs,
|
|
|
|
:size,
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when the post was created by the bot" do
|
|
|
|
it "does nothing" do
|
|
|
|
gpt_topic_id = PostCreator.create!(admin, post_args).topic_id
|
|
|
|
reply_args =
|
|
|
|
post_args.except(:archetype, :target_usernames, :title).merge(topic_id: gpt_topic_id)
|
|
|
|
|
|
|
|
expect { PostCreator.create!(gpt_bot, reply_args) }.not_to change(
|
|
|
|
Jobs::CreateAiReply.jobs,
|
|
|
|
:size,
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|