diff --git a/lib/ai_helper/chat_thread_titler.rb b/lib/ai_helper/chat_thread_titler.rb index b60a97bc..755a8426 100644 --- a/lib/ai_helper/chat_thread_titler.rb +++ b/lib/ai_helper/chat_thread_titler.rb @@ -8,26 +8,38 @@ module DiscourseAi end def suggested_title - return nil if thread_content.blank? - - prompt = CompletionPrompt.enabled_by_name("generate_titles") - raise Discourse::InvalidParameters.new(:mode) if !prompt - - response = - DiscourseAi::AiHelper::Assistant.new.generate_and_send_prompt( - prompt, - thread_content, - thread.original_message_user, - ) - response.dig(:suggestions)&.first + @thread.then { thread_content(_1) }.then { call_llm(_1) }.then { cleanup(_1) } end - private + def call_llm(thread_content) + return nil if thread_content.blank? - attr_reader :thread + chat = "\n#{thread_content}\n" - def thread_content - # Replace me by a proper API call + prompt = + DiscourseAi::Completions::Prompt.new( + <<~TEXT.strip, + I want you to act as a title generator for chat between users. I will provide you with the chat transcription, + and you will generate a single attention-grabbing title. Please keep the title concise and under 15 words + and ensure that the meaning is maintained. The title will utilize the same language type of the chat. + I want you to only reply the suggested title and nothing else, do not write explanations. + You will find the chat between XML tags. + TEXT + messages: [{ type: :user, content: chat, id: "User" }], + ) + + DiscourseAi::Completions::Llm.proxy(SiteSetting.ai_helper_model).generate( + prompt, + user: Discourse.system_user, + ) + end + + def cleanup(title) + title.split("\n").first.then { _1.match?(/^("|')(.*)("|')$/) ? title[1..-2] : _1 } + end + + def thread_content(thread) + # TODO: Replace me by a proper API call thread .chat_messages .joins(:user) @@ -35,6 +47,8 @@ module DiscourseAi .map { |username, message| "#{username}: #{message}" } .join("\n") end + + attr_reader :thread end end end diff --git a/spec/lib/modules/ai_helper/chat_thread_titler_spec.rb b/spec/lib/modules/ai_helper/chat_thread_titler_spec.rb index 3dc07252..89ad6674 100644 --- a/spec/lib/modules/ai_helper/chat_thread_titler_spec.rb +++ b/spec/lib/modules/ai_helper/chat_thread_titler_spec.rb @@ -6,17 +6,51 @@ RSpec.describe DiscourseAi::AiHelper::ChatThreadTitler do before { SiteSetting.ai_helper_model = "fake:fake" } fab!(:thread) { Fabricate(:chat_thread) } + fab!(:chat_message) { Fabricate(:chat_message, thread: thread) } fab!(:user) { Fabricate(:user) } - describe "#suggested_title" do - it "suggest the first option from the generate_titles prompt" do - titles = - "The solitary horseThe horse etched in goldA horse's infinite journeyA horse lost in timeA horse's last ride" + describe "#cleanup" do + it "picks the first when there are multiple" do + titles = "The solitary horse\nThe horse etched in gold" expected_title = "The solitary horse" - result = - DiscourseAi::Completions::Llm.with_prepared_responses([titles]) { titler.suggested_title } + + result = titler.cleanup(titles) + + expect(result).to eq(expected_title) + end + + it "cleans up double quotes enclosing the whole title" do + titles = '"The solitary horse"' + expected_title = "The solitary horse" + + result = titler.cleanup(titles) + + expect(result).to eq(expected_title) + end + + it "cleans up single quotes enclosing the whole title" do + titles = "'The solitary horse'" + expected_title = "The solitary horse" + + result = titler.cleanup(titles) + + expect(result).to eq(expected_title) + end + + it "leaves quotes in the middle of title" do + titles = "The 'solitary' horse" + expected_title = "The 'solitary' horse" + + result = titler.cleanup(titles) expect(result).to eq(expected_title) end end + + describe "#thread_content" do + it "returns the chat message and user" do + expect(titler.thread_content(thread)).to include(chat_message.message) + expect(titler.thread_content(thread)).to include(chat_message.user.username) + end + end end