mirror of
https://github.com/discourse/discourse-ai.git
synced 2025-02-09 21:14:43 +00:00
a3c827efcc
* FEATURE: allow personas to supply top_p and temperature params Code assistance generally are more focused at a lower temperature This amends it so SQL Helper runs at 0.2 temperature vs the more common default across LLMs of 1.0. Reduced temperature leads to more focused, concise and predictable answers for the SQL Helper * fix tests * This is not perfect, but far better than what we do today Instead of fishing for 1. Draft sequence 2. Draft body We skip (2), this means the composer "only" needs 1 http request to open, we also want to eliminate (1) but it is a bit of a trickier core change, may figure out how to pull it off (defer it to first draft save) Value of bot drafts < value of opening bot conversations really fast
87 lines
2.7 KiB
Ruby
87 lines
2.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe DiscourseAi::AiBot::Bot do
|
|
subject(:bot) { described_class.as(bot_user) }
|
|
|
|
fab!(:admin) { Fabricate(:admin) }
|
|
|
|
before do
|
|
SiteSetting.ai_bot_enabled_chat_bots = "gpt-4"
|
|
SiteSetting.ai_bot_enabled = true
|
|
end
|
|
|
|
let(:bot_user) { User.find(DiscourseAi::AiBot::EntryPoint::GPT4_ID) }
|
|
|
|
let!(:user) { Fabricate(:user) }
|
|
|
|
let(:function_call) { <<~TEXT }
|
|
Let me try using a function to get more info:<function_calls>
|
|
<invoke>
|
|
<tool_name>categories</tool_name>
|
|
</invoke>
|
|
</function_calls>
|
|
TEXT
|
|
|
|
let(:response) { "As expected, your forum has multiple tags" }
|
|
|
|
let(:llm_responses) { [function_call, response] }
|
|
|
|
describe "#reply" do
|
|
it "sets top_p and temperature params" do
|
|
# full integration test so we have certainty it is passed through
|
|
|
|
DiscourseAi::Completions::Endpoints::Fake.delays = []
|
|
DiscourseAi::Completions::Endpoints::Fake.last_call = nil
|
|
|
|
SiteSetting.ai_bot_enabled_chat_bots = "fake"
|
|
SiteSetting.ai_bot_enabled = true
|
|
Group.refresh_automatic_groups!
|
|
|
|
bot_user = User.find(DiscourseAi::AiBot::EntryPoint::FAKE_ID)
|
|
AiPersona.create!(
|
|
name: "TestPersona",
|
|
top_p: 0.5,
|
|
temperature: 0.4,
|
|
system_prompt: "test",
|
|
description: "test",
|
|
allowed_group_ids: [Group::AUTO_GROUPS[:trust_level_0]],
|
|
)
|
|
|
|
personaClass = DiscourseAi::AiBot::Personas::Persona.find_by(user: admin, name: "TestPersona")
|
|
|
|
bot = DiscourseAi::AiBot::Bot.as(bot_user, persona: personaClass.new)
|
|
bot.reply(
|
|
{ conversation_context: [{ type: :user, content: "test" }] },
|
|
) do |_partial, _cancel, _placeholder|
|
|
# we just need the block so bot has something to call with results
|
|
end
|
|
|
|
last_call = DiscourseAi::Completions::Endpoints::Fake.last_call
|
|
expect(last_call[:model_params][:top_p]).to eq(0.5)
|
|
expect(last_call[:model_params][:temperature]).to eq(0.4)
|
|
end
|
|
|
|
context "when using function chaining" do
|
|
it "yields a loading placeholder while proceeds to invoke the command" do
|
|
tool = DiscourseAi::AiBot::Tools::ListCategories.new({})
|
|
partial_placeholder = +(<<~HTML)
|
|
<details>
|
|
<summary>#{tool.summary}</summary>
|
|
<p></p>
|
|
</details>
|
|
<span></span>
|
|
|
|
HTML
|
|
|
|
context = { conversation_context: [{ type: :user, content: "Does my site has tags?" }] }
|
|
|
|
DiscourseAi::Completions::Llm.with_prepared_responses(llm_responses) do
|
|
bot.reply(context) do |_bot_reply_post, cancel, placeholder|
|
|
expect(placeholder).to eq(partial_placeholder) if placeholder
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|