diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index e4354129..88214c5f 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -540,7 +540,7 @@ en: provider_quantizations: "Order of provider quantizations (comma delimited list eg: fp16,fp8)" disable_streaming: "Disable streaming completions (convert streaming to non streaming requests)" reasoning_effort: "Reasoning effort (only applicable to reasoning models)" - enable_reasoning: "Enable reasoning (only applicable to Sonnet 3.7)" + enable_reasoning: "Enable reasoning (only applicable to reasoning models)" enable_thinking: "Enable thinking (only on applicable models eg: flash 2.5)" thinking_tokens: "Number of tokens used for thinking" reasoning_tokens: "Number of tokens used for reasoning" diff --git a/lib/personas/tools/researcher.rb b/lib/personas/tools/researcher.rb index 0c0921e6..d8221a5e 100644 --- a/lib/personas/tools/researcher.rb +++ b/lib/personas/tools/researcher.rb @@ -85,6 +85,16 @@ module DiscourseAi limit: max_results, guardian: guardian, ) + + if filter.invalid_filters.present? + return( + { + error: + "Invalid filter fragment: #{filter.invalid_filters.join(" ")}\n\n#{self.class.filter_description}", + } + ) + end + @result_count = filter.search.count blk.call details diff --git a/lib/utils/research/filter.rb b/lib/utils/research/filter.rb index 630ba7f3..fe0e8033 100644 --- a/lib/utils/research/filter.rb +++ b/lib/utils/research/filter.rb @@ -17,7 +17,7 @@ module DiscourseAi ::Search.word_to_date(str) end - attr_reader :term, :filters, :order, :guardian, :limit, :offset + attr_reader :term, :filters, :order, :guardian, :limit, :offset, :invalid_filters # Define all filters at class level register_filter(/\Astatus:open\z/i) do |relation, _, _| @@ -206,7 +206,6 @@ module DiscourseAi end def initialize(term, guardian: nil, limit: nil, offset: nil) - @term = term.to_s @guardian = guardian || Guardian.new @limit = limit @offset = offset @@ -214,8 +213,10 @@ module DiscourseAi @valid = true @order = :latest_post @topic_ids = nil + @invalid_filters = [] + @term = term.to_s.strip - @term = process_filters(@term) + process_filters(@term) end def set_order!(order) @@ -248,12 +249,16 @@ module DiscourseAi end if @topic_ids.present? - filtered = - original_filtered.where( - "posts.topic_id IN (?) OR posts.id IN (?)", - @topic_ids, - filtered.select("posts.id"), - ) + if original_filtered == filtered + filtered = original_filtered.where("posts.topic_id IN (?)", @topic_ids) + else + filtered = + original_filtered.where( + "posts.topic_id IN (?) OR posts.id IN (?)", + @topic_ids, + filtered.select("posts.id"), + ) + end end filtered = filtered.limit(@limit) if @limit.to_i > 0 @@ -275,7 +280,7 @@ module DiscourseAi private def process_filters(term) - return "" if term.blank? + return if term.blank? term .to_s @@ -293,10 +298,8 @@ module DiscourseAi end end - found ? nil : word + invalid_filters << word if !found end - .compact - .join(" ") end end end diff --git a/spec/lib/personas/tools/researcher_spec.rb b/spec/lib/personas/tools/researcher_spec.rb index b3784cac..23ed98a7 100644 --- a/spec/lib/personas/tools/researcher_spec.rb +++ b/spec/lib/personas/tools/researcher_spec.rb @@ -17,10 +17,23 @@ RSpec.describe DiscourseAi::Personas::Tools::Researcher do fab!(:topic_with_tags) { Fabricate(:topic, category: category, tags: [tag_research, tag_data]) } fab!(:post) { Fabricate(:post, topic: topic_with_tags) } + fab!(:another_post) { Fabricate(:post) } before { SiteSetting.ai_bot_enabled = true } describe "#invoke" do + it "can correctly filter to a topic id" do + researcher = + described_class.new( + { dry_run: true, filter: "topic:#{topic_with_tags.id}", goals: "analyze topic content" }, + bot_user: bot_user, + llm: llm, + context: DiscourseAi::Personas::BotContext.new(user: user, post: post), + ) + results = researcher.invoke(&progress_blk) + expect(results[:number_of_posts]).to eq(1) + end + it "returns filter information and result count" do researcher = described_class.new( @@ -63,6 +76,20 @@ RSpec.describe DiscourseAi::Personas::Tools::Researcher do expect(researcher.options[:max_results]).to eq(50) end + it "returns error for invalid filter fragments" do + researcher = + described_class.new( + { filter: "invalidfilter tag:research", goals: "analyze content" }, + bot_user: bot_user, + llm: llm, + context: DiscourseAi::Personas::BotContext.new(user: user, post: post), + ) + + results = researcher.invoke(&progress_blk) + + expect(results[:error]).to include("Invalid filter fragment") + end + it "returns correct results for non-dry-run with filtered posts" do # Stage 2 topics, each with 2 posts topics = Array.new(2) { Fabricate(:topic, category: category, tags: [tag_research]) }