139 lines
4.7 KiB
Ruby
139 lines
4.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe DiscourseAi::Personas::Tools::CreateImage do
|
|
let(:prompts) { ["a watercolor painting", "an abstract design"] }
|
|
|
|
fab!(:gpt_35_turbo) { Fabricate(:llm_model, name: "gpt-3.5-turbo") }
|
|
|
|
before do
|
|
SiteSetting.ai_bot_enabled = true
|
|
toggle_enabled_bots(bots: [gpt_35_turbo])
|
|
SiteSetting.ai_openai_api_key = "abc"
|
|
end
|
|
|
|
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(gpt_35_turbo.name) }
|
|
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{gpt_35_turbo.id}") }
|
|
let(:progress_blk) { Proc.new {} }
|
|
|
|
let(:create_image) { described_class.new({ prompts: prompts }, llm: llm, bot_user: bot_user) }
|
|
|
|
let(:base64_image) do
|
|
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
|
|
end
|
|
|
|
describe "#process" do
|
|
it "can reject generation of images and return a proper error to llm" do
|
|
error_message = {
|
|
error: {
|
|
message:
|
|
"Your request was rejected as a result of our safety system. Your request may contain content that is not allowed by our safety system.",
|
|
type: "user_error",
|
|
param: nil,
|
|
code: "moderation_blocked",
|
|
},
|
|
}
|
|
|
|
WebMock.stub_request(:post, "https://api.openai.com/v1/images/generations").to_return(
|
|
status: 400,
|
|
body: error_message.to_json,
|
|
)
|
|
|
|
info = create_image.invoke(&progress_blk).to_json
|
|
expect(info).to include("Your request was rejected as a result of our safety system.")
|
|
expect(create_image.chain_next_response?).to eq(true)
|
|
end
|
|
it "can generate images with gpt-image-1 model" do
|
|
data = [{ b64_json: base64_image, revised_prompt: "a watercolor painting of flowers" }]
|
|
|
|
WebMock
|
|
.stub_request(:post, "https://api.openai.com/v1/images/generations")
|
|
.with do |request|
|
|
json = JSON.parse(request.body, symbolize_names: true)
|
|
|
|
expect(prompts).to include(json[:prompt])
|
|
expect(json[:model]).to eq("gpt-image-1")
|
|
expect(json[:size]).to eq("auto")
|
|
true
|
|
end
|
|
.to_return(status: 200, body: { data: data }.to_json)
|
|
|
|
info = create_image.invoke(&progress_blk).to_json
|
|
|
|
expect(JSON.parse(info)).to eq(
|
|
{
|
|
"prompts" => [
|
|
{
|
|
"prompt" => "a watercolor painting of flowers",
|
|
"url" => "upload://pv9zsrM93Jz3U8xELTJCPYU2DD0.png",
|
|
},
|
|
{
|
|
"prompt" => "a watercolor painting of flowers",
|
|
"url" => "upload://pv9zsrM93Jz3U8xELTJCPYU2DD0.png",
|
|
},
|
|
],
|
|
},
|
|
)
|
|
expect(create_image.custom_raw).to include("upload://")
|
|
expect(create_image.custom_raw).to include("[grid]")
|
|
expect(create_image.custom_raw).to include("a watercolor painting of flowers")
|
|
end
|
|
|
|
it "can defaults to auto size" do
|
|
create_image_with_size =
|
|
described_class.new({ prompts: ["a landscape"] }, llm: llm, bot_user: bot_user)
|
|
|
|
data = [{ b64_json: base64_image, revised_prompt: "a detailed landscape" }]
|
|
|
|
WebMock
|
|
.stub_request(:post, "https://api.openai.com/v1/images/generations")
|
|
.with do |request|
|
|
json = JSON.parse(request.body, symbolize_names: true)
|
|
|
|
expect(json[:prompt]).to eq("a landscape")
|
|
expect(json[:size]).to eq("auto")
|
|
true
|
|
end
|
|
.to_return(status: 200, body: { data: data }.to_json)
|
|
|
|
info = create_image_with_size.invoke(&progress_blk).to_json
|
|
expect(JSON.parse(info)).to eq(
|
|
"prompts" => [
|
|
{
|
|
"prompt" => "a detailed landscape",
|
|
"url" => "upload://pv9zsrM93Jz3U8xELTJCPYU2DD0.png",
|
|
},
|
|
],
|
|
)
|
|
end
|
|
|
|
it "handles custom API endpoint" do
|
|
SiteSetting.ai_openai_image_generation_url = "https://custom-api.example.com/images/generate"
|
|
|
|
data = [{ b64_json: base64_image, revised_prompt: "a watercolor painting" }]
|
|
|
|
WebMock
|
|
.stub_request(:post, SiteSetting.ai_openai_image_generation_url)
|
|
.with do |request|
|
|
json = JSON.parse(request.body, symbolize_names: true)
|
|
expect(prompts).to include(json[:prompt])
|
|
true
|
|
end
|
|
.to_return(status: 200, body: { data: data }.to_json)
|
|
|
|
info = create_image.invoke(&progress_blk).to_json
|
|
expect(JSON.parse(info)).to eq(
|
|
"prompts" => [
|
|
{
|
|
"prompt" => "a watercolor painting",
|
|
"url" => "upload://pv9zsrM93Jz3U8xELTJCPYU2DD0.png",
|
|
},
|
|
{
|
|
"prompt" => "a watercolor painting",
|
|
"url" => "upload://pv9zsrM93Jz3U8xELTJCPYU2DD0.png",
|
|
},
|
|
],
|
|
)
|
|
end
|
|
end
|
|
end
|