Skip to content

Commit 460f5c4

Browse files
authored
FIX: display search correctly, bug when stripping XML (#668)
- Display filtered search correctly, so it is not confusing - When XML stripping, if a chunk was `<` it would crash - SQL Helper improved to be better aware of Data Explorer
1 parent f642a27 commit 460f5c4

File tree

5 files changed

+65
-20
lines changed

5 files changed

+65
-20
lines changed

lib/ai_bot/personas/sql_helper.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,18 @@ def system_prompt
5858
- When generating SQL always use ```sql Markdown code blocks.
5959
- When generating SQL NEVER end SQL samples with a semicolon (;).
6060
61-
Eg:
61+
- You also understand the special formatting rules for Data Explorer in Discourse.
62+
- The columns named (user_id, group_id, topic_id, post_id, badge_id) are rendered as links when a report is run, prefer them where possible.
63+
- You can define custom params to create flexible queries, example:
64+
-- [params]
65+
-- int :num = 1
66+
-- text :name
67+
68+
SELECT :num, :name
69+
- You support the types (integer, text, boolean, date)
70+
71+
72+
- When generating SQL use markdown formatting for code blocks, example:
6273
6374
```sql
6475
select 1 from table

lib/ai_bot/tools/search.rb

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ module DiscourseAi
44
module AiBot
55
module Tools
66
class Search < Tool
7+
attr_reader :last_query
8+
79
MIN_SEMANTIC_RESULTS = 5
810

911
class << self
@@ -95,40 +97,38 @@ def search_args
9597
parameters.slice(:category, :user, :order, :max_posts, :tags, :before, :after, :status)
9698
end
9799

98-
def invoke
99-
search_string =
100-
search_args.reduce(+parameters[:search_query].to_s) do |memo, (key, value)|
101-
return memo if value.blank?
102-
memo << " " << "#{key}:#{value}"
103-
end
104-
105-
@last_query = search_string
100+
def search_query
101+
parameters[:search_query]
102+
end
106103

107-
yield(I18n.t("discourse_ai.ai_bot.searching", query: search_string))
104+
def invoke
105+
search_terms = []
108106

109-
if options[:base_query].present?
110-
search_string = "#{search_string} #{options[:base_query]}"
111-
end
107+
search_terms << options[:base_query] if options[:base_query].present?
108+
search_terms << search_query.strip if search_query.present?
109+
search_args.each { |key, value| search_terms << "#{key}:#{value}" if value.present? }
112110

113-
safe_search_string = search_string.to_s
114111
guardian = nil
115-
116112
if options[:search_private] && context[:user]
117113
guardian = Guardian.new(context[:user])
118114
else
119115
guardian = Guardian.new
120-
safe_search_string += " status:public"
116+
search_terms << "status:public"
121117
end
122118

123-
results =
124-
::Search.execute(safe_search_string, search_type: :full_page, guardian: guardian)
119+
search_string = search_terms.join(" ").to_s
120+
@last_query = search_string
121+
122+
yield(I18n.t("discourse_ai.ai_bot.searching", query: search_string))
123+
124+
results = ::Search.execute(search_string, search_type: :full_page, guardian: guardian)
125125

126126
max_results = calculate_max_results(llm)
127127
results_limit = parameters[:limit] || max_results
128128
results_limit = max_results if parameters[:limit].to_i > max_results
129129

130130
should_try_semantic_search =
131-
SiteSetting.ai_embeddings_semantic_search_enabled && parameters[:search_query].present?
131+
SiteSetting.ai_embeddings_semantic_search_enabled && search_query.present?
132132

133133
max_semantic_results = max_results / 4
134134
results_limit = results_limit - max_semantic_results if should_try_semantic_search

lib/completions/xml_tag_stripper.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def <<(text)
1717
end
1818
end
1919
@parsed.concat(parse_tags(text))
20+
2021
@parsed, result = process_parsed(@parsed)
2122
result
2223
end
@@ -69,10 +70,15 @@ def parse_tags(text)
6970
while true
7071
before, after = text.split("<", 2)
7172

72-
parsed << { type: :text, content: before }
73+
parsed << { type: :text, content: before } if before && !before.empty?
7374

7475
break if after.nil?
7576

77+
if before.empty? && after.empty?
78+
parsed << { type: :maybe_tag, content: "<" }
79+
break
80+
end
81+
7682
tag, after = after.split(">", 2)
7783

7884
is_end_tag = tag[0] == "/"

spec/lib/completions/xml_tag_stripper_spec.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,32 @@
2929
expect(result).to eq("\nhello\n")
3030
end
3131

32+
it "does not crash when we send a <" do
33+
result = +""
34+
result << (tag_stripper << "based:\n")
35+
result << (tag_stripper << "<").to_s
36+
result << (tag_stripper << " href")
37+
result << (tag_stripper << ">")
38+
result << (tag_stripper << "test ")
39+
40+
expect(result).to eq("based:\n< href>test ")
41+
end
42+
43+
it "strips thinking correctly in a stream" do
44+
result = +""
45+
result << (tag_stripper << "hello")
46+
result << (tag_stripper << "<").to_s
47+
result << (tag_stripper << "thinking").to_s
48+
result << (tag_stripper << ">").to_s
49+
result << (tag_stripper << "test").to_s
50+
result << (tag_stripper << "<").to_s
51+
result << (tag_stripper << "/").to_s
52+
result << (tag_stripper << "thinking").to_s
53+
result << (tag_stripper << "> world")
54+
55+
expect(result).to eq("hello world")
56+
end
57+
3258
it "works when nesting unrelated tags it strips correctly" do
3359
text = <<~TEXT
3460
<thinking>

spec/lib/modules/ai_bot/tools/search_spec.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@
7373
results = search.invoke(&progress_blk)
7474
expect(results[:rows].length).to eq(1)
7575

76+
expect(search.last_query).to eq("#funny order:latest")
77+
7678
GroupUser.create!(group: group, user: user)
7779

7880
results = search.invoke(&progress_blk)

0 commit comments

Comments
 (0)