mirror of
https://ghfast.top/https://github.com/discourse/discourse-ai.git
synced 2026-07-16 11:36:23 +08:00
* DEV: refactor bot internals This introduces a proper object for bot context, this makes it simpler to improve context management as we go cause we have a nice object to work with Starts refactoring allowing for a single message to have multiple uploads throughout * transplant method to message builder * chipping away at inline uploads * image support is improved but not fully fixed yet partially working in anthropic, still got quite a few dialects to go * open ai and claude are now working * Gemini is now working as well * fix nova * more dialects... * fix ollama * fix specs * update artifact fixed * more tests * spam scanner * pass more specs * bunch of specs improved * more bug fixes. * all the rest of the tests are working * improve tests coverage and ensure custom tools are aware of new context object * tests are working, but we need more tests * resolve merge conflict * new preamble and expanded specs on ai tool * remove concept of "standalone tools" This is no longer needed, we can set custom raw, tool details are injected into tool calls
95 lines
3 KiB
Ruby
95 lines
3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe DiscourseAi::Completions::Dialects::OpenAiCompatible do
|
|
context "when system prompts are disabled" do
|
|
fab!(:model) do
|
|
Fabricate(:vllm_model, vision_enabled: true, provider_params: { disable_system_prompt: true })
|
|
end
|
|
|
|
it "merges the system prompt into the first message" do
|
|
system_msg = "This is a system message"
|
|
user_msg = "user message"
|
|
prompt =
|
|
DiscourseAi::Completions::Prompt.new(
|
|
system_msg,
|
|
messages: [{ type: :user, content: user_msg }],
|
|
)
|
|
|
|
translated_messages = described_class.new(prompt, model).translate
|
|
|
|
expect(translated_messages.length).to eq(1)
|
|
expect(translated_messages).to contain_exactly(
|
|
{ role: "user", content: [system_msg, user_msg].join("\n") },
|
|
)
|
|
end
|
|
|
|
context "when the prompt has inline images" do
|
|
let(:image100x100) { plugin_file_from_fixtures("100x100.jpg") }
|
|
|
|
it "produces a valid message" do
|
|
upload = UploadCreator.new(image100x100, "image.jpg").create_for(Discourse.system_user.id)
|
|
prompt =
|
|
DiscourseAi::Completions::Prompt.new(
|
|
"You are a bot specializing in image captioning.",
|
|
messages: [
|
|
{
|
|
type: :user,
|
|
content: ["Describe this image in a single sentence.", { upload_id: upload.id }],
|
|
},
|
|
],
|
|
)
|
|
encoded_upload =
|
|
DiscourseAi::Completions::UploadEncoder.encode(
|
|
upload_ids: [upload.id],
|
|
max_pixels: prompt.max_pixels,
|
|
).first
|
|
|
|
translated_messages = described_class.new(prompt, model).translate
|
|
|
|
expect(translated_messages.length).to eq(1)
|
|
|
|
# no system message support here
|
|
expected_user_message = {
|
|
role: "user",
|
|
content: [
|
|
{
|
|
type: "text",
|
|
text:
|
|
"You are a bot specializing in image captioning.\nDescribe this image in a single sentence.",
|
|
},
|
|
{
|
|
type: "image_url",
|
|
image_url: {
|
|
url: "data:#{encoded_upload[:mime_type]};base64,#{encoded_upload[:base64]}",
|
|
},
|
|
},
|
|
],
|
|
}
|
|
|
|
expect(translated_messages).to contain_exactly(expected_user_message)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when system prompts are enabled" do
|
|
it "includes system and user messages separately" do
|
|
system_msg = "This is a system message"
|
|
user_msg = "user message"
|
|
prompt =
|
|
DiscourseAi::Completions::Prompt.new(
|
|
system_msg,
|
|
messages: [{ type: :user, content: user_msg }],
|
|
)
|
|
|
|
model = Fabricate(:vllm_model, provider_params: { disable_system_prompt: false })
|
|
|
|
translated_messages = described_class.new(prompt, model).translate
|
|
|
|
expect(translated_messages.length).to eq(2)
|
|
expect(translated_messages).to contain_exactly(
|
|
{ role: "system", content: system_msg },
|
|
{ role: "user", content: user_msg },
|
|
)
|
|
end
|
|
end
|
|
end
|