114 lines
3.6 KiB
Ruby
114 lines
3.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "rails_helper"
|
|
|
|
RSpec.describe DiscourseAi::Automation::LlmToolTriage do
|
|
fab!(:solver) { Fabricate(:user) }
|
|
fab!(:new_user) { Fabricate(:user, trust_level: TrustLevel[0], created_at: 1.day.ago) }
|
|
fab!(:topic) { Fabricate(:topic, user: new_user) }
|
|
fab!(:post) { Fabricate(:post, topic: topic, user: new_user, raw: "How do I reset my password?") }
|
|
fab!(:llm_model)
|
|
fab!(:ai_persona) do
|
|
persona = Fabricate(:ai_persona, default_llm: llm_model)
|
|
persona.create_user
|
|
persona
|
|
end
|
|
|
|
fab!(:tool) do
|
|
tool_script = <<~JS
|
|
function invoke(params) {
|
|
const postId = context.post_id;
|
|
const post = discourse.getPost(postId);
|
|
const user = discourse.getUser(post.user_id);
|
|
|
|
if (user.trust_level > 0) {
|
|
return {
|
|
processed: false,
|
|
reason: "User is not new"
|
|
};
|
|
}
|
|
|
|
const helper = discourse.getPersona("#{ai_persona.name}");
|
|
const answer = helper.respondTo({ post_id: post.id });
|
|
|
|
return {
|
|
answer: answer,
|
|
processed: true,
|
|
reason: "answered question"
|
|
};
|
|
}
|
|
JS
|
|
|
|
AiTool.create!(
|
|
name: "New User Question Answerer",
|
|
tool_name: "new_user_question_answerer",
|
|
description: "Automatically answers questions from new users when possible",
|
|
parameters: [], # No parameters as required by llm_tool_triage
|
|
script: tool_script,
|
|
created_by_id: Discourse.system_user.id,
|
|
summary: "Answers new user questions",
|
|
enabled: true,
|
|
)
|
|
end
|
|
|
|
before do
|
|
SiteSetting.discourse_ai_enabled = true
|
|
SiteSetting.ai_bot_enabled = true
|
|
end
|
|
|
|
it "It is able to answer new user questions" do
|
|
result = nil
|
|
DiscourseAi::Completions::Llm.with_prepared_responses(
|
|
["this is how you reset your password"],
|
|
) { result = described_class.handle(post: post, tool_id: tool.id) }
|
|
expect(result["processed"]).to eq(true)
|
|
response = post.topic.reload.posts.order(:post_number).last
|
|
expect(response.raw).to eq("this is how you reset your password")
|
|
end
|
|
|
|
it "Is able to respond as a whisper if instructed" do
|
|
# Create a tool with a script that explicitly requests a whisper response
|
|
whisper_tool =
|
|
AiTool.create!(
|
|
name: "Whisper Triage Tool",
|
|
tool_name: "whisper_triage_tool",
|
|
description: "Responds with whispers to moderation issues",
|
|
parameters: [],
|
|
script: <<~JS,
|
|
function invoke(params) {
|
|
const postId = context.post_id;
|
|
const post = discourse.getPost(postId);
|
|
|
|
const helper = discourse.getPersona("#{ai_persona.name}");
|
|
// Pass instructions to make response a whisper
|
|
const answer = helper.respondTo({
|
|
post_id: post.id,
|
|
instructions: "Respond as a whisper for moderators only",
|
|
whisper: true
|
|
});
|
|
|
|
return {
|
|
answer: answer,
|
|
processed: true,
|
|
reason: "responded with whisper"
|
|
};
|
|
}
|
|
JS
|
|
created_by_id: Discourse.system_user.id,
|
|
summary: "Responds with whispers",
|
|
enabled: true,
|
|
)
|
|
|
|
result = nil
|
|
DiscourseAi::Completions::Llm.with_prepared_responses(
|
|
["This moderation note is only visible to staff"],
|
|
) { result = described_class.handle(post: post, tool_id: whisper_tool.id) }
|
|
|
|
expect(result["processed"]).to eq(true)
|
|
response = post.topic.reload.posts.order(:post_number).last
|
|
expect(response.raw).to eq("This moderation note is only visible to staff")
|
|
# Check that the response is indeed a whisper
|
|
expect(response.post_type).to eq(Post.types[:whisper])
|
|
end
|
|
end
|