From 2a6c0468c075890004b67ffea68add30a9421237 Mon Sep 17 00:00:00 2001 From: papayalabs Date: Mon, 18 Nov 2024 15:29:22 +0100 Subject: [PATCH] Add tests --- .../settings/api_services_controller_test.rb | 2 +- .../language_models_controller_test.rb | 2 +- test/fixtures/api_services.yml | 7 +++ test/fixtures/assistants.yml | 8 +++ test/fixtures/conversations.yml | 6 ++ test/fixtures/language_models.yml | 11 ++++ test/fixtures/messages.yml | 11 ++++ .../get_next_ai_message_job_gemini_test.rb | 56 +++++++++++++++++++ test/support/test_client/gemini.rb | 31 ++++++++++ 9 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 test/jobs/get_next_ai_message_job_gemini_test.rb create mode 100644 test/support/test_client/gemini.rb diff --git a/test/controllers/settings/api_services_controller_test.rb b/test/controllers/settings/api_services_controller_test.rb index 33b1baf28..366b66674 100644 --- a/test/controllers/settings/api_services_controller_test.rb +++ b/test/controllers/settings/api_services_controller_test.rb @@ -10,7 +10,7 @@ class Settings::APIServicesControllerTest < ActionDispatch::IntegrationTest test "should get index" do get settings_api_services_url assert_response :success - assert_select "table#api-services tbody tr", count: 4 + assert_select "table#api-services tbody tr", count: 5 assert_select "p a", "Add New" assert_select "p#no-api-services", false end diff --git a/test/controllers/settings/language_models_controller_test.rb b/test/controllers/settings/language_models_controller_test.rb index 184cfdb3c..30f0a6fd4 100644 --- a/test/controllers/settings/language_models_controller_test.rb +++ b/test/controllers/settings/language_models_controller_test.rb @@ -10,7 +10,7 @@ class Settings::LanguageModelsControllerTest < ActionDispatch::IntegrationTest test "should get index for user" do get settings_language_models_url assert_response :success - assert_select "table#language-models tbody tr", count: 18 + assert_select "table#language-models tbody tr", count: 19 assert_select "p a", "Add New" end diff --git a/test/fixtures/api_services.yml b/test/fixtures/api_services.yml index cd9094939..fcfa2eaba 100644 --- a/test/fixtures/api_services.yml +++ b/test/fixtures/api_services.yml @@ -34,6 +34,13 @@ rob_openai_service: token: rob-secret driver: openai +keith_gemini_service: + name: Gemini + user: keith + url: https://api.gemini.com/v1/ + token: keith-secret + driver: gemini + rob_anthropic_service: name: Anthropic user: rob diff --git a/test/fixtures/assistants.yml b/test/fixtures/assistants.yml index 4892f1639..2410e42c2 100644 --- a/test/fixtures/assistants.yml +++ b/test/fixtures/assistants.yml @@ -74,3 +74,11 @@ pacos_asst: instructions: Point out flower-related local items, also historical events involving flowers tools: [] external_id: + +keith_gemini: + user: keith + language_model: gemini_flash_1_5 + name: Gemini Flash 1.5 + description: Gemini Flash 1.5 + instructions: + tools: [] \ No newline at end of file diff --git a/test/fixtures/conversations.yml b/test/fixtures/conversations.yml index 5631c0eca..a14817481 100644 --- a/test/fixtures/conversations.yml +++ b/test/fixtures/conversations.yml @@ -34,6 +34,12 @@ hello_claude: title: Meeting Claude last_assistant_message: claude_age_replying +gemini_conversation: + user: keith + assistant: keith_gemini + title: Meeting Gemini + last_assistant_message: hello_gemini + debugging: user: rob assistant: rob_gpt4 diff --git a/test/fixtures/language_models.yml b/test/fixtures/language_models.yml index 7ebfa15fb..1b679aaa9 100644 --- a/test/fixtures/language_models.yml +++ b/test/fixtures/language_models.yml @@ -331,3 +331,14 @@ guanaco: supports_tools: false input_token_cost_cents: 0.0001 output_token_cost_cents: 0.0001 + +gemini_flash_1_5: + position: 23 + user: keith + name: Gemini Flash 1.5 + api_name: gemini-1.5-flash + api_service: keith_gemini_service + supports_images: true + supports_tools: false + input_token_cost_cents: 0.0001 + output_token_cost_cents: 0.0001 \ No newline at end of file diff --git a/test/fixtures/messages.yml b/test/fixtures/messages.yml index 274504320..dcf55f404 100644 --- a/test/fixtures/messages.yml +++ b/test/fixtures/messages.yml @@ -327,6 +327,17 @@ hello_claude: index: 0 version: 1 +hello_gemini: + assistant: keith_gemini + conversation: gemini_conversation + role: user + content_text: Hi Gemini, can you hear me? + content_document: + run: + created_at: 2023-12-30 1:00:00 + index: 0 + version: 1 + claude_replying: assistant: keith_claude3 conversation: hello_claude diff --git a/test/jobs/get_next_ai_message_job_gemini_test.rb b/test/jobs/get_next_ai_message_job_gemini_test.rb new file mode 100644 index 000000000..1681a01b1 --- /dev/null +++ b/test/jobs/get_next_ai_message_job_gemini_test.rb @@ -0,0 +1,56 @@ +require "test_helper" + +class GetNextAIMessageJobGeminiTest < ActiveJob::TestCase + setup do + @conversation = conversations(:gemini_conversation) + @user = @conversation.user + @assistant = @conversation.assistant + @conversation.messages.create! role: :user, content_text: "Still there?", assistant: @assistant + @assistant.language_model.update!(supports_tools: false) # this will change the TestClient response so we want to be selective about this + @message = @conversation.latest_message_for_version(:latest) + @test_client = TestClient::Gemini.new(access_token: "abc") + end + + test "populates the latest message from the assistant" do + assert_no_difference "@conversation.messages.reload.length" do + TestClient::Gemini.stub :text, "Hello" do + assert GetNextAIMessageJob.perform_now(@user.id, @message.id, @assistant.id) + end + end + + assert_equal "Hello", @conversation.latest_message_for_version(:latest).content_text + end + + test "returns early if the message id was invalid" do + refute GetNextAIMessageJob.perform_now(@user.id, 0, @assistant.id) + end + + test "returns early if the assistant id was invalid" do + refute GetNextAIMessageJob.perform_now(@user.id, @message.id, 0) + end + + test "returns early if the message was already generated" do + @message.update!(content_text: "Hello") + refute GetNextAIMessageJob.perform_now(@user.id, @message.id, @assistant.id) + end + + test "returns early if the user has replied after this" do + @conversation.messages.create! role: :user, content_text: "Ignore that, new question:", assistant: @assistant + refute GetNextAIMessageJob.perform_now(@user.id, @message.id, @assistant.id) + end + + test "when Gemini key is blank, a nice error message is displayed" do + api_service = @assistant.language_model.api_service + api_service.update!(token: "") + + assert GetNextAIMessageJob.perform_now(@user.id, @message.id, @assistant.id) + assert_includes @conversation.latest_message_for_version(:latest).content_text, "need to enter a valid API key for Gemini" + end + + test "when API response key is missing, a nice error message is displayed" do + TestClient::Gemini.stub :text, "" do + assert GetNextAIMessageJob.perform_now(@user.id, @message.id, @assistant.id) + assert_includes @conversation.latest_message_for_version(:latest).content_text, "a blank response" + end + end +end diff --git a/test/support/test_client/gemini.rb b/test/support/test_client/gemini.rb new file mode 100644 index 000000000..91029af93 --- /dev/null +++ b/test/support/test_client/gemini.rb @@ -0,0 +1,31 @@ +module TestClient + class Gemini + def initialize(args) + end + + def self.text + nil + end + + # This response is a valid example response from the API. + # + # Stub this method to respond with something more specific if needed. + def stream_generate_content(args) + contents = args.dig(:contents) + system_message = args.dig(:system_instruction) + return [{"candidates"=> + [{"content"=> + {"role"=>"model", + "parts"=> + [{"text"=> self.class.text || "Hello this is a model with instruction #{system_message.to_s.inspect}! How can I assist you today?"}]}, + "safetyRatings"=> + [{"category"=>"HARM_CATEGORY_HARASSMENT", "probability"=>"NEGLIGIBLE"}, + {"category"=>"HARM_CATEGORY_HATE_SPEECH", "probability"=>"NEGLIGIBLE"}, + {"category"=>"HARM_CATEGORY_SEXUALLY_EXPLICIT", "probability"=>"NEGLIGIBLE"}, + {"category"=>"HARM_CATEGORY_DANGEROUS_CONTENT", "probability"=>"NEGLIGIBLE"}]}], + "usageMetadata"=>{"promptTokenCount"=>1037, "candidatesTokenCount"=>31, "totalTokenCount"=>1068} + }] + + end + end +end