Skip to content

Commit d75e3ca

Browse files
authored
FEATURE: include tag and category context in search (#217)
Previous to this we just included title/body.. tags and category structure can be very critical for decision making.
1 parent b0310f9 commit d75e3ca

File tree

3 files changed

+63
-15
lines changed

3 files changed

+63
-15
lines changed

lib/modules/ai_bot/commands/search_command.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,17 +154,33 @@ def process(**search_args)
154154
end
155155

156156
@last_num_results = posts.length
157+
# this is the general pattern from core
158+
# if there are millions of hidden tags it may fail
159+
hidden_tags = nil
157160

158161
if posts.blank?
159162
{ args: search_args, rows: [], instruction: "nothing was found, expand your search" }
160163
else
161164
format_results(posts, args: search_args) do |post|
162-
{
165+
category_names = [
166+
post.topic.category&.parent_category&.name,
167+
post.topic.category&.name,
168+
].compact.join(" > ")
169+
row = {
163170
title: post.topic.title,
164171
url: Discourse.base_path + post.url,
165172
excerpt: post.excerpt,
166173
created: post.created_at,
174+
category: category_names,
167175
}
176+
177+
if SiteSetting.tagging_enabled
178+
hidden_tags ||= DiscourseTagging.hidden_tag_names
179+
# using map over pluck to avoid n+1 (assuming caller preloading)
180+
tags = post.topic.tags.map(&:name) - hidden_tags
181+
row[:tags] = tags.join(", ") if tags.present?
182+
end
183+
row
168184
end
169185
end
170186
end

spec/lib/modules/ai_bot/commands/read_command_spec.rb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@
99
fab!(:tag_funny) { Fabricate(:tag, name: "funny") }
1010
fab!(:tag_sad) { Fabricate(:tag, name: "sad") }
1111
fab!(:tag_hidden) { Fabricate(:tag, name: "hidden") }
12-
fab!(:staff_tag_group) { Fabricate(:tag_group, name: "Staff only", tag_names: ["hidden"]) }
12+
fab!(:staff_tag_group) do
13+
tag_group = Fabricate.build(:tag_group, name: "Staff only", tag_names: ["hidden"])
14+
15+
tag_group.permissions = [
16+
[Group::AUTO_GROUPS[:staff], TagGroupPermission.permission_types[:full]],
17+
]
18+
tag_group.save!
19+
tag_group
20+
end
1321
fab!(:topic_with_tags) do
1422
Fabricate(:topic, category: category, tags: [tag_funny, tag_sad, tag_hidden])
1523
end
1624

17-
let(:staff) { Group::AUTO_GROUPS[:staff] }
18-
let(:full) { TagGroupPermission.permission_types[:full] }
19-
20-
before do
21-
staff_tag_group.permissions = [[staff, full]]
22-
staff_tag_group.save!
23-
end
24-
2525
describe "#process" do
2626
it "can read a topic" do
2727
topic_id = topic_with_tags.id

spec/lib/modules/ai_bot/commands/search_command_spec.rb

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,28 @@
99
before { SearchIndexer.enable }
1010
after { SearchIndexer.disable }
1111

12+
fab!(:parent_category) { Fabricate(:category, name: "animals") }
13+
fab!(:category) { Fabricate(:category, parent_category: parent_category, name: "amazing-cat") }
14+
15+
fab!(:tag_funny) { Fabricate(:tag, name: "funny") }
16+
fab!(:tag_sad) { Fabricate(:tag, name: "sad") }
17+
fab!(:tag_hidden) { Fabricate(:tag, name: "hidden") }
18+
fab!(:staff_tag_group) do
19+
tag_group = Fabricate.build(:tag_group, name: "Staff only", tag_names: ["hidden"])
20+
21+
tag_group.permissions = [
22+
[Group::AUTO_GROUPS[:staff], TagGroupPermission.permission_types[:full]],
23+
]
24+
tag_group.save!
25+
tag_group
26+
end
27+
fab!(:topic_with_tags) do
28+
Fabricate(:topic, category: category, tags: [tag_funny, tag_sad, tag_hidden])
29+
end
30+
1231
describe "#process" do
1332
it "can handle no results" do
14-
post1 = Fabricate(:post)
33+
post1 = Fabricate(:post, topic: topic_with_tags)
1534
search = described_class.new(bot_user: bot_user, post: post1, args: nil)
1635

1736
results = search.process(query: "order:fake ABDDCDCEDGDG")
@@ -42,7 +61,7 @@
4261
hyde_embedding,
4362
)
4463

45-
post1 = Fabricate(:post)
64+
post1 = Fabricate(:post, topic: topic_with_tags)
4665
search = described_class.new(bot_user: bot_user, post: post1, args: nil)
4766

4867
DiscourseAi::Embeddings::VectorRepresentations::AllMpnetBaseV2
@@ -60,16 +79,30 @@
6079
it "supports subfolder properly" do
6180
Discourse.stubs(:base_path).returns("/subfolder")
6281

63-
post1 = Fabricate(:post)
82+
post1 = Fabricate(:post, topic: topic_with_tags)
6483

6584
search = described_class.new(bot_user: bot_user, post: post1, args: nil)
6685

6786
results = search.process(limit: 1, user: post1.user.username)
6887
expect(results[:rows].to_s).to include("/subfolder" + post1.url)
6988
end
7089

90+
it "returns category and tags" do
91+
post1 = Fabricate(:post, topic: topic_with_tags)
92+
search = described_class.new(bot_user: bot_user, post: post1, args: nil)
93+
results = search.process(user: post1.user.username)
94+
95+
row = results[:rows].first
96+
category = row[results[:column_names].index("category")]
97+
98+
expect(category).to eq("animals > amazing-cat")
99+
100+
tags = row[results[:column_names].index("tags")]
101+
expect(tags).to eq("funny, sad")
102+
end
103+
71104
it "can handle limits" do
72-
post1 = Fabricate(:post)
105+
post1 = Fabricate(:post, topic: topic_with_tags)
73106
_post2 = Fabricate(:post, user: post1.user)
74107
_post3 = Fabricate(:post, user: post1.user)
75108

@@ -78,7 +111,6 @@
78111

79112
results = search.process(limit: 2, user: post1.user.username)
80113

81-
expect(results[:column_names].length).to eq(4)
82114
expect(results[:rows].length).to eq(2)
83115

84116
# just searching for everything

0 commit comments

Comments
 (0)