191 lines
5.7 KiB
Ruby
191 lines
5.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe DiscourseAi::Admin::AiEmbeddingsController do
|
|
fab!(:admin)
|
|
|
|
before { sign_in(admin) }
|
|
|
|
let(:valid_attrs) do
|
|
{
|
|
display_name: "Embedding config test",
|
|
dimensions: 1001,
|
|
max_sequence_length: 234,
|
|
pg_function: "<#>",
|
|
provider: "hugging_face",
|
|
url: "https://test.com/api/v1/embeddings",
|
|
api_key: "test",
|
|
tokenizer_class: "DiscourseAi::Tokenizer::BgeM3Tokenizer",
|
|
embed_prompt: "I come first:",
|
|
search_prompt: "prefix for search",
|
|
matryoshka_dimensions: true,
|
|
}
|
|
end
|
|
|
|
describe "POST #create" do
|
|
context "with valid attrs" do
|
|
it "creates a new embedding definition" do
|
|
post "/admin/plugins/discourse-ai/ai-embeddings.json", params: { ai_embedding: valid_attrs }
|
|
|
|
created_def = EmbeddingDefinition.last
|
|
|
|
expect(response.status).to eq(201)
|
|
expect(created_def.display_name).to eq(valid_attrs[:display_name])
|
|
expect(created_def.embed_prompt).to eq(valid_attrs[:embed_prompt])
|
|
expect(created_def.search_prompt).to eq(valid_attrs[:search_prompt])
|
|
expect(created_def.matryoshka_dimensions).to eq(true)
|
|
end
|
|
|
|
it "stores provider-specific config params" do
|
|
post "/admin/plugins/discourse-ai/ai-embeddings.json",
|
|
params: {
|
|
ai_embedding:
|
|
valid_attrs.merge(
|
|
provider: "open_ai",
|
|
provider_params: {
|
|
model_name: "embeddings-v1",
|
|
},
|
|
),
|
|
}
|
|
|
|
created_def = EmbeddingDefinition.last
|
|
|
|
expect(response.status).to eq(201)
|
|
expect(created_def.provider_params["model_name"]).to eq("embeddings-v1")
|
|
end
|
|
|
|
it "ignores parameters not associated with that provider" do
|
|
post "/admin/plugins/discourse-ai/ai-embeddings.json",
|
|
params: {
|
|
ai_embedding: valid_attrs.merge(provider_params: { custom: "custom" }),
|
|
}
|
|
|
|
created_def = EmbeddingDefinition.last
|
|
|
|
expect(response.status).to eq(201)
|
|
expect(created_def.lookup_custom_param("custom")).to be_nil
|
|
end
|
|
end
|
|
|
|
context "with invalid attrs" do
|
|
it "doesn't create a new embedding defitinion" do
|
|
post "/admin/plugins/discourse-ai/ai-embeddings.json",
|
|
params: {
|
|
ai_embedding: valid_attrs.except(:provider),
|
|
}
|
|
|
|
created_def = EmbeddingDefinition.last
|
|
|
|
expect(created_def).to be_nil
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "PUT #update" do
|
|
fab!(:embedding_definition)
|
|
|
|
context "with valid update params" do
|
|
let(:update_attrs) { { provider: "open_ai" } }
|
|
|
|
it "updates the model" do
|
|
put "/admin/plugins/discourse-ai/ai-embeddings/#{embedding_definition.id}.json",
|
|
params: {
|
|
ai_embedding: update_attrs,
|
|
}
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(embedding_definition.reload.provider).to eq(update_attrs[:provider])
|
|
end
|
|
|
|
it "returns a 404 if there is no model with the given Id" do
|
|
put "/admin/plugins/discourse-ai/ai-embeddings/9999999.json"
|
|
|
|
expect(response.status).to eq(404)
|
|
end
|
|
|
|
it "doesn't allow dimenstions to be updated" do
|
|
new_dimensions = 200
|
|
|
|
put "/admin/plugins/discourse-ai/ai-embeddings/#{embedding_definition.id}.json",
|
|
params: {
|
|
ai_embedding: {
|
|
dimensions: new_dimensions,
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(embedding_definition.reload.dimensions).not_to eq(new_dimensions)
|
|
end
|
|
end
|
|
|
|
context "with invalid update params" do
|
|
it "doesn't update the model" do
|
|
put "/admin/plugins/discourse-ai/ai-embeddings/#{embedding_definition.id}.json",
|
|
params: {
|
|
ai_embedding: {
|
|
url: "",
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(422)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "DELETE #destroy" do
|
|
fab!(:embedding_definition)
|
|
|
|
it "destroys the embedding defitinion" do
|
|
expect {
|
|
delete "/admin/plugins/discourse-ai/ai-embeddings/#{embedding_definition.id}.json"
|
|
|
|
expect(response).to have_http_status(:no_content)
|
|
}.to change(EmbeddingDefinition, :count).by(-1)
|
|
end
|
|
|
|
it "validates the model is not in use" do
|
|
SiteSetting.ai_embeddings_selected_model = embedding_definition.id
|
|
|
|
delete "/admin/plugins/discourse-ai/ai-embeddings/#{embedding_definition.id}.json"
|
|
|
|
expect(response.status).to eq(409)
|
|
expect(embedding_definition.reload).to eq(embedding_definition)
|
|
end
|
|
end
|
|
|
|
describe "GET #test" do
|
|
context "when we can generate an embedding" do
|
|
it "returns a success true flag" do
|
|
WebMock.stub_request(:post, valid_attrs[:url]).to_return(status: 200, body: [[1]].to_json)
|
|
|
|
get "/admin/plugins/discourse-ai/ai-embeddings/test.json",
|
|
params: {
|
|
ai_embedding: valid_attrs,
|
|
}
|
|
|
|
expect(response).to be_successful
|
|
expect(response.parsed_body["success"]).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "when we cannot generate an embedding" do
|
|
it "returns a success false flag and the error message" do
|
|
error_message = { error: "Embedding generation failed." }
|
|
|
|
WebMock.stub_request(:post, valid_attrs[:url]).to_return(
|
|
status: 422,
|
|
body: error_message.to_json,
|
|
)
|
|
|
|
get "/admin/plugins/discourse-ai/ai-embeddings/test.json",
|
|
params: {
|
|
ai_embedding: valid_attrs,
|
|
}
|
|
|
|
expect(response).to be_successful
|
|
expect(response.parsed_body["success"]).to eq(false)
|
|
expect(response.parsed_body["error"]).to eq(error_message.to_json)
|
|
end
|
|
end
|
|
end
|
|
end
|