From 4c960970fae710fc7648920e574b7975cf9a6d05 Mon Sep 17 00:00:00 2001 From: Roman Rizzi Date: Wed, 22 Mar 2023 16:00:28 -0300 Subject: [PATCH] DEV: Log information about errors from the completions OpenAI API (#26) --- .../discourse_ai/ai_helper/assistant_controller.rb | 3 +++ config/locales/server.en.yml | 2 ++ lib/modules/ai_helper/open_ai_prompt.rb | 6 ------ lib/shared/inference/openai_completions.rb | 9 ++++++++- spec/lib/modules/ai_helper/open_ai_prompt_spec.rb | 6 +++--- .../requests/ai_helper/assistant_controller_spec.rb | 10 ++++++++++ spec/support/openai_completions_inference_stubs.rb | 13 ++++++++----- spec/system/ai_helper/ai_composer_helper_spec.rb | 6 +++--- 8 files changed, 37 insertions(+), 18 deletions(-) diff --git a/app/controllers/discourse_ai/ai_helper/assistant_controller.rb b/app/controllers/discourse_ai/ai_helper/assistant_controller.rb index 4b8dbf6e..c657c639 100644 --- a/app/controllers/discourse_ai/ai_helper/assistant_controller.rb +++ b/app/controllers/discourse_ai/ai_helper/assistant_controller.rb @@ -32,6 +32,9 @@ module DiscourseAi ), status: 200 end + rescue DiscourseAi::Inference::OpenAiCompletions::CompletionFailed + render_json_error I18n.t("discourse_ai.ai_helper.errors.completion_request_failed"), + status: 502 end private diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 5e3a4c35..fab5c71e 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -57,6 +57,8 @@ en: discourse_ai: ai_helper: + errors: + completion_request_failed: "Something went wrong while trying to provide suggestions. Please, try again." prompts: translate: Translate to English generate_titles: Suggest topic titles diff --git a/lib/modules/ai_helper/open_ai_prompt.rb b/lib/modules/ai_helper/open_ai_prompt.rb index ebe89505..243adeb9 100644 --- a/lib/modules/ai_helper/open_ai_prompt.rb +++ b/lib/modules/ai_helper/open_ai_prompt.rb @@ -3,12 +3,6 @@ module DiscourseAi module AiHelper class OpenAiPrompt - TRANSLATE = "translate" - GENERATE_TITLES = "generate_titles" - PROOFREAD = "proofread" - MARKDOWN_TABLE = "markdown_table" - VALID_TYPES = [TRANSLATE, GENERATE_TITLES, PROOFREAD, MARKDOWN_TABLE] - def available_prompts CompletionPrompt .where(enabled: true) diff --git a/lib/shared/inference/openai_completions.rb b/lib/shared/inference/openai_completions.rb index 2887d889..22439b6a 100644 --- a/lib/shared/inference/openai_completions.rb +++ b/lib/shared/inference/openai_completions.rb @@ -3,6 +3,8 @@ module ::DiscourseAi module Inference class OpenAiCompletions + CompletionFailed = Class.new(StandardError) + def self.perform!(messages, model = "gpt-3.5-turbo") headers = { "Authorization" => "Bearer #{SiteSetting.ai_openai_api_key}", @@ -18,7 +20,12 @@ module ::DiscourseAi headers, ) - raise Net::HTTPBadResponse unless response.status == 200 + if response.status != 200 + Rails.logger.error( + "OpenAiCompletions: status: #{response.status} - body: #{response.body}", + ) + raise CompletionFailed + end JSON.parse(response.body, symbolize_names: true) end diff --git a/spec/lib/modules/ai_helper/open_ai_prompt_spec.rb b/spec/lib/modules/ai_helper/open_ai_prompt_spec.rb index 944accbc..5d73a8a0 100644 --- a/spec/lib/modules/ai_helper/open_ai_prompt_spec.rb +++ b/spec/lib/modules/ai_helper/open_ai_prompt_spec.rb @@ -7,7 +7,7 @@ RSpec.describe DiscourseAi::AiHelper::OpenAiPrompt do describe "#generate_and_send_prompt" do context "when using the translate mode" do - let(:mode) { "translate" } + let(:mode) { OpenAiCompletionsInferenceStubs::TRANSLATE } before { OpenAiCompletionsInferenceStubs.stub_prompt(mode) } @@ -22,7 +22,7 @@ RSpec.describe DiscourseAi::AiHelper::OpenAiPrompt do end context "when using the proofread mode" do - let(:mode) { "proofread" } + let(:mode) { OpenAiCompletionsInferenceStubs::PROOFREAD } before { OpenAiCompletionsInferenceStubs.stub_prompt(mode) } @@ -40,7 +40,7 @@ RSpec.describe DiscourseAi::AiHelper::OpenAiPrompt do end context "when generating titles" do - let(:mode) { "generate_titles" } + let(:mode) { OpenAiCompletionsInferenceStubs::GENERATE_TITLES } before { OpenAiCompletionsInferenceStubs.stub_prompt(mode) } diff --git a/spec/requests/ai_helper/assistant_controller_spec.rb b/spec/requests/ai_helper/assistant_controller_spec.rb index 2bd11c73..019cc0f3 100644 --- a/spec/requests/ai_helper/assistant_controller_spec.rb +++ b/spec/requests/ai_helper/assistant_controller_spec.rb @@ -53,6 +53,16 @@ RSpec.describe DiscourseAi::AiHelper::AssistantController do expect(response.status).to eq(400) end + it "returns a generic error when the completion call fails" do + WebMock.stub_request(:post, "https://api.openai.com/v1/chat/completions").to_return( + status: 500, + ) + + post "/discourse-ai/ai-helper/suggest", params: { mode: mode, text: text } + + expect(response.status).to eq(502) + end + it "returns a suggestion" do OpenAiCompletionsInferenceStubs.stub_prompt(mode) diff --git a/spec/support/openai_completions_inference_stubs.rb b/spec/support/openai_completions_inference_stubs.rb index c71d8e73..594c2701 100644 --- a/spec/support/openai_completions_inference_stubs.rb +++ b/spec/support/openai_completions_inference_stubs.rb @@ -1,6 +1,10 @@ # frozen_string_literal: true class OpenAiCompletionsInferenceStubs + TRANSLATE = "translate" + PROOFREAD = "proofread" + GENERATE_TITLES = "generate_titles" + class << self def spanish_text <<~STRING @@ -69,19 +73,18 @@ class OpenAiCompletionsInferenceStubs def response_text_for(type) case type - when DiscourseAi::AiHelper::OpenAiPrompt::TRANSLATE + when TRANSLATE translated_response - when DiscourseAi::AiHelper::OpenAiPrompt::PROOFREAD + when PROOFREAD proofread_response - when DiscourseAi::AiHelper::OpenAiPrompt::GENERATE_TITLES + when GENERATE_TITLES generated_titles end end def stub_prompt(type) prompt_builder = DiscourseAi::AiHelper::OpenAiPrompt.new - text = - type == DiscourseAi::AiHelper::OpenAiPrompt::TRANSLATE ? spanish_text : translated_response + text = type == TRANSLATE ? spanish_text : translated_response prompt_messages = CompletionPrompt.find_by(name: type).messages_with_user_input(text) diff --git a/spec/system/ai_helper/ai_composer_helper_spec.rb b/spec/system/ai_helper/ai_composer_helper_spec.rb index ce6b1b94..3c24f8de 100644 --- a/spec/system/ai_helper/ai_composer_helper_spec.rb +++ b/spec/system/ai_helper/ai_composer_helper_spec.rb @@ -15,7 +15,7 @@ RSpec.describe "AI Composer helper", type: :system, js: true do let(:ai_helper_modal) { PageObjects::Modals::AiHelper.new } context "when using the translation mode" do - let(:mode) { DiscourseAi::AiHelper::OpenAiPrompt::TRANSLATE } + let(:mode) { OpenAiCompletionsInferenceStubs::TRANSLATE } before { OpenAiCompletionsInferenceStubs.stub_prompt(mode) } @@ -38,7 +38,7 @@ RSpec.describe "AI Composer helper", type: :system, js: true do end context "when using the proofreading mode" do - let(:mode) { DiscourseAi::AiHelper::OpenAiPrompt::PROOFREAD } + let(:mode) { OpenAiCompletionsInferenceStubs::PROOFREAD } before { OpenAiCompletionsInferenceStubs.stub_prompt(mode) } @@ -61,7 +61,7 @@ RSpec.describe "AI Composer helper", type: :system, js: true do end context "when selecting an AI generated title" do - let(:mode) { DiscourseAi::AiHelper::OpenAiPrompt::GENERATE_TITLES } + let(:mode) { OpenAiCompletionsInferenceStubs::GENERATE_TITLES } before { OpenAiCompletionsInferenceStubs.stub_prompt(mode) }