DEV: add API to get topic info from a custom tool (#1197)

Previously we could only get post info
This commit is contained in:
Sam 2025-03-17 18:47:23 +11:00 committed by GitHub
parent 7d7c169afa
commit 269f169abf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 77 additions and 15 deletions

View File

@ -77,6 +77,7 @@ module DiscourseAi
return _discourse_search(params);
},
getPost: _discourse_get_post,
getTopic: _discourse_get_topic,
getUser: _discourse_get_user,
getPersona: function(name) {
return {
@ -276,7 +277,28 @@ module DiscourseAi
post = Post.find_by(id: post_id)
return nil if post.nil?
guardian = Guardian.new(Discourse.system_user)
recursive_as_json(PostSerializer.new(post, scope: guardian, root: false))
obj =
recursive_as_json(
PostSerializer.new(post, scope: guardian, root: false, add_raw: true),
)
topic_obj =
recursive_as_json(
ListableTopicSerializer.new(post.topic, scope: guardian, root: false),
)
obj["topic"] = topic_obj
obj
end
end,
)
mini_racer_context.attach(
"_discourse_get_topic",
->(topic_id) do
in_attached_function do
topic = Topic.find_by(id: topic_id)
return nil if topic.nil?
guardian = Guardian.new(Discourse.system_user)
recursive_as_json(ListableTopicSerializer.new(topic, scope: guardian, root: false))
end
end,
)

View File

@ -3,6 +3,8 @@
RSpec.describe AiTool do
fab!(:llm_model) { Fabricate(:llm_model, name: "claude-2") }
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
fab!(:topic)
fab!(:post) { Fabricate(:post, topic: topic, raw: "bananas are a tasty fruit") }
def create_tool(
parameters: nil,
@ -329,36 +331,74 @@ RSpec.describe AiTool do
end
end
context "when using the topic API" do
it "can fetch topic details" do
script = <<~JS
function invoke(params) {
return discourse.getTopic(params.topic_id);
}
JS
tool = create_tool(script: script)
runner = tool.runner({ "topic_id" => topic.id }, llm: nil, bot_user: nil, context: {})
result = runner.invoke
expect(result["id"]).to eq(topic.id)
expect(result["title"]).to eq(topic.title)
expect(result["archetype"]).to eq("regular")
expect(result["posts_count"]).to eq(1)
end
end
context "when using the post API" do
it "can fetch post details" do
script = <<~JS
function invoke(params) {
const post = discourse.getPost(params.post_id);
return {
post: post,
topic: post.topic
}
}
JS
tool = create_tool(script: script)
runner = tool.runner({ "post_id" => post.id }, llm: nil, bot_user: nil, context: {})
result = runner.invoke
post_hash = result["post"]
topic_hash = result["topic"]
expect(post_hash["id"]).to eq(post.id)
expect(post_hash["topic_id"]).to eq(topic.id)
expect(post_hash["raw"]).to eq(post.raw)
expect(topic_hash["id"]).to eq(topic.id)
end
end
context "when using the search API" do
before { SearchIndexer.enable }
after { SearchIndexer.disable }
it "can perform a discourse search" do
# Create a new topic
topic = Fabricate(:topic, title: "Test Search Topic", category: Fabricate(:category))
post = Fabricate(:post, topic: topic, raw: "This is a test post content, banana")
# Ensure the topic is indexed
SearchIndexer.index(topic, force: true)
SearchIndexer.index(post, force: true)
# Define the tool script
script = <<~JS
function invoke(params) {
return discourse.search({ search_query: params.query });
}
JS
function invoke(params) {
return discourse.search({ search_query: params.query });
}
JS
# Create the tool and runner
tool = create_tool(script: script)
runner = tool.runner({ "query" => "banana" }, llm: nil, bot_user: nil, context: {})
# Invoke the tool and get the results
result = runner.invoke
# Verify the topic is found
expect(result["rows"].length).to be > 0
expect(result["rows"].first["title"]).to eq("Test Search Topic")
expect(result["rows"].first["title"]).to eq(topic.title)
end
end
end