diff --git a/config/settings.yml b/config/settings.yml index d2e212fb7..86e6a35a4 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -358,3 +358,10 @@ discourse_ai: ai_rag_images_enabled: default: false hidden: true + + ai_summary_persona_id: + default: "" + hidden: true + ai_summary_consolidator_persona_id: + default: "" + hidden: true diff --git a/lib/summarization/strategies/topic_summary.rb b/lib/summarization/strategies/topic_summary.rb index 4dfca68c5..08b7cdaf0 100644 --- a/lib/summarization/strategies/topic_summary.rb +++ b/lib/summarization/strategies/topic_summary.rb @@ -32,27 +32,41 @@ def targets_data end end + def summary_prompt(topic_id:, persona_id:, default_prompt:) + prompt_text = default_prompt + if persona_id + persona = AiPersona.find_by(id: persona_id) + prompt_text = persona.system_prompt if persona + end + DiscourseAi::Completions::Prompt.new(prompt_text, topic_id: topic_id) + end + def summary_extension_prompt(summary, contents) resource_path = "#{Discourse.base_path}/t/-/#{target.id}" content_title = target.title input = contents.map { |item| "(#{item[:id]} #{item[:poster]} said: #{item[:text]})" }.join - prompt = DiscourseAi::Completions::Prompt.new(<<~TEXT, topic_id: target.id) - You are an advanced summarization bot tasked with enhancing an existing summary by incorporating additional posts. - - ### Guidelines: - - Only include the enhanced summary, without any additional commentary. - - Understand and generate Discourse forum Markdown; including links, _italics_, **bold**. - - Maintain the original language of the text being summarized. - - Aim for summaries to be 400 words or less. - - Each new post is formatted as ") " - - Cite specific noteworthy posts using the format [DESCRIPTION](#{resource_path}/POST_NUMBER) - - Example: links to the 3rd and 6th posts by sam: sam ([#3](#{resource_path}/3), [#6](#{resource_path}/6)) - - Example: link to the 6th post by jane: [agreed with](#{resource_path}/6) - - Example: link to the 13th post by joe: [joe](#{resource_path}/13) - - When formatting usernames either use @USERNAME or [USERNAME](#{resource_path}/POST_NUMBER) - TEXT + prompt = + summary_prompt( + topic_id: target.id, + persona_id: SiteSetting.ai_summary_consolidator_persona_id, + default_prompt: <<~TEXT, + You are an advanced summarization bot tasked with enhancing an existing summary by incorporating additional posts. + + ### Guidelines: + - Only include the enhanced summary, without any additional commentary. + - Understand and generate Discourse forum Markdown; including links, _italics_, **bold**. + - Maintain the original language of the text being summarized. + - Aim for summaries to be 400 words or less. + - Each new post is formatted as ") " + - Cite specific noteworthy posts using the format [DESCRIPTION](#{resource_path}/POST_NUMBER) + - Example: links to the 3rd and 6th posts by sam: sam ([#3](#{resource_path}/3), [#6](#{resource_path}/6)) + - Example: link to the 6th post by jane: [agreed with](#{resource_path}/6) + - Example: link to the 13th post by joe: [joe](#{resource_path}/13) + - When formatting usernames either use @USERNAME or [USERNAME](#{resource_path}/POST_NUMBER) + TEXT + ) prompt.push(type: :user, content: <<~TEXT.strip) ### Context: @@ -81,20 +95,25 @@ def first_summary_prompt(contents) input = contents.map { |item| "(#{item[:id]} #{item[:poster]} said: #{item[:text]} " }.join - prompt = DiscourseAi::Completions::Prompt.new(<<~TEXT.strip, topic_id: target.id) - You are an advanced summarization bot that generates concise, coherent summaries of provided text. - - - Only include the summary, without any additional commentary. - - You understand and generate Discourse forum Markdown; including links, _italics_, **bold**. - - Maintain the original language of the text being summarized. - - Aim for summaries to be 400 words or less. - - Each post is formatted as ") " - - Cite specific noteworthy posts using the format [DESCRIPTION](#{resource_path}/POST_NUMBER) - - Example: links to the 3rd and 6th posts by sam: sam ([#3](#{resource_path}/3), [#6](#{resource_path}/6)) - - Example: link to the 6th post by jane: [agreed with](#{resource_path}/6) - - Example: link to the 13th post by joe: [joe](#{resource_path}/13) - - When formatting usernames either use @USERNMAE OR [USERNAME](#{resource_path}/POST_NUMBER) - TEXT + prompt = + summary_prompt( + topic_id: target.id, + persona_id: SiteSetting.ai_summary_persona_id, + default_prompt: <<~TEXT, + You are an advanced summarization bot that generates concise, coherent summaries of provided text. + + - Only include the summary, without any additional commentary. + - You understand and generate Discourse forum Markdown; including links, _italics_, **bold**. + - Maintain the original language of the text being summarized. + - Aim for summaries to be 400 words or less. + - Each post is formatted as ") " + - Cite specific noteworthy posts using the format [DESCRIPTION](#{resource_path}/POST_NUMBER) + - Example: links to the 3rd and 6th posts by sam: sam ([#3](#{resource_path}/3), [#6](#{resource_path}/6)) + - Example: link to the 6th post by jane: [agreed with](#{resource_path}/6) + - Example: link to the 13th post by joe: [joe](#{resource_path}/13) + - When formatting usernames either use @USERNMAE OR [USERNAME](#{resource_path}/POST_NUMBER) + TEXT + ) prompt.push( type: :user, diff --git a/spec/lib/modules/summarization/strategies/topic_summary_spec.rb b/spec/lib/modules/summarization/strategies/topic_summary_spec.rb index 93f2c4c2c..cc41cab82 100644 --- a/spec/lib/modules/summarization/strategies/topic_summary_spec.rb +++ b/spec/lib/modules/summarization/strategies/topic_summary_spec.rb @@ -6,6 +6,7 @@ fab!(:topic) { Fabricate(:topic, highest_post_number: 25) } fab!(:post_1) { Fabricate(:post, topic: topic, post_number: 1) } fab!(:post_2) { Fabricate(:post, topic: topic, post_number: 2) } + fab!(:admin) describe "#targets_data" do shared_examples "includes only public-visible topics" do @@ -62,4 +63,49 @@ end end end + + describe "Summary prompt" do + let!(:ai_persona) do + AiPersona.create!( + name: "TestPersona", + system_prompt: "test prompt", + description: "test", + allowed_group_ids: [Group::AUTO_GROUPS[:trust_level_0]], + ) + end + + let!(:persona_class) do + DiscourseAi::AiBot::Personas::Persona.find_by(user: admin, name: "TestPersona") + end + + context "when ai_summary_consolidator_persona_id siteSetting is set" do + it "returns a summary extension prompt with the correct text" do + SiteSetting.ai_summary_consolidator_persona_id = persona_class.id + + expect( + topic_summary + .summary_extension_prompt(nil, [{ id: 1, poster: "test", text: "hello" }]) + .messages + .first[ + :content + ], + ).to include("test prompt") + end + end + + context "when ai_summary_persona_id siteSetting is set" do + it "returns a first summary prompt with the correct text" do + SiteSetting.ai_summary_persona_id = persona_class.id + + expect( + topic_summary + .first_summary_prompt([{ id: 1, poster: "test", text: "hello" }]) + .messages + .first[ + :content + ], + ).to include("test prompt") + end + end + end end