From 441cc065ae414781ddf14be9a45134a33c5643e7 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 29 Jul 2025 08:14:50 +0400 Subject: [PATCH] feat: add config for OpenAI endpoint (#12051) Co-authored-by: Muhsin Keloth --- config/installation_config.yml | 4 ++ .../super_admin/app_configs_controller.rb | 2 +- .../app/services/llm/base_open_ai_service.rb | 5 +++ .../captain/copilot/chat_service_spec.rb | 43 +++++++++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/config/installation_config.yml b/config/installation_config.yml index fcf4ade2f..53251fc3c 100644 --- a/config/installation_config.yml +++ b/config/installation_config.yml @@ -170,6 +170,10 @@ display_title: 'OpenAI Model' description: 'The OpenAI model configured for use in Captain AI. Default: gpt-4o-mini' locked: false +- name: CAPTAIN_OPEN_AI_ENDPOINT + display_title: 'OpenAI API Endpoint (optional)' + description: 'The OpenAI endpoint configured for use in Captain AI. Default: https://api.openai.com/' + locked: false - name: CAPTAIN_FIRECRAWL_API_KEY display_title: 'FireCrawl API Key (optional)' description: 'The FireCrawl API key for the Captain AI service' diff --git a/enterprise/app/controllers/enterprise/super_admin/app_configs_controller.rb b/enterprise/app/controllers/enterprise/super_admin/app_configs_controller.rb index 41c8411b1..5466c86a4 100644 --- a/enterprise/app/controllers/enterprise/super_admin/app_configs_controller.rb +++ b/enterprise/app/controllers/enterprise/super_admin/app_configs_controller.rb @@ -10,7 +10,7 @@ module Enterprise::SuperAdmin::AppConfigsController when 'internal' @allowed_configs = internal_config_options when 'captain' - @allowed_configs = %w[CAPTAIN_OPEN_AI_API_KEY CAPTAIN_OPEN_AI_MODEL CAPTAIN_FIRECRAWL_API_KEY] + @allowed_configs = %w[CAPTAIN_OPEN_AI_API_KEY CAPTAIN_OPEN_AI_MODEL CAPTAIN_OPEN_AI_ENDPOINT CAPTAIN_FIRECRAWL_API_KEY] else super end diff --git a/enterprise/app/services/llm/base_open_ai_service.rb b/enterprise/app/services/llm/base_open_ai_service.rb index 1f229f182..04909cbf4 100644 --- a/enterprise/app/services/llm/base_open_ai_service.rb +++ b/enterprise/app/services/llm/base_open_ai_service.rb @@ -4,6 +4,7 @@ class Llm::BaseOpenAiService def initialize @client = OpenAI::Client.new( access_token: InstallationConfig.find_by!(name: 'CAPTAIN_OPEN_AI_API_KEY').value, + uri_base: uri_base, log_errors: Rails.env.development? ) setup_model @@ -13,6 +14,10 @@ class Llm::BaseOpenAiService private + def uri_base + InstallationConfig.find_by(name: 'CAPTAIN_OPEN_AI_ENDPOINT')&.value || 'https://api.openai.com/' + end + def setup_model config_value = InstallationConfig.find_by(name: 'CAPTAIN_OPEN_AI_MODEL')&.value @model = (config_value.presence || DEFAULT_MODEL) diff --git a/spec/enterprise/services/captain/copilot/chat_service_spec.rb b/spec/enterprise/services/captain/copilot/chat_service_spec.rb index a4274ec4e..a02063b5e 100644 --- a/spec/enterprise/services/captain/copilot/chat_service_spec.rb +++ b/spec/enterprise/services/captain/copilot/chat_service_spec.rb @@ -22,6 +22,7 @@ RSpec.describe Captain::Copilot::ChatService do before do create(:installation_config, name: 'CAPTAIN_OPEN_AI_API_KEY', value: 'test-key') + create(:installation_config, name: 'CAPTAIN_OPEN_AI_ENDPOINT', value: 'https://api.openai.com/') allow(OpenAI::Client).to receive(:new).and_return(mock_openai_client) allow(mock_openai_client).to receive(:chat).and_return({ choices: [{ message: { content: '{ "content": "Hey" }' } }] @@ -47,6 +48,48 @@ RSpec.describe Captain::Copilot::ChatService do expect(messages.second[:role]).to eq('system') expect(messages.second[:content]).to include(account.id.to_s) end + + it 'initializes OpenAI client with configured endpoint' do + expect(OpenAI::Client).to receive(:new).with( + access_token: 'test-key', + uri_base: 'https://api.openai.com/', + log_errors: Rails.env.development? + ) + + described_class.new(assistant, config) + end + + context 'when CAPTAIN_OPEN_AI_ENDPOINT is not configured' do + before do + InstallationConfig.find_by(name: 'CAPTAIN_OPEN_AI_ENDPOINT')&.destroy + end + + it 'uses default OpenAI endpoint' do + expect(OpenAI::Client).to receive(:new).with( + access_token: 'test-key', + uri_base: 'https://api.openai.com/', + log_errors: Rails.env.development? + ) + + described_class.new(assistant, config) + end + end + + context 'when custom endpoint is configured' do + before do + InstallationConfig.find_by(name: 'CAPTAIN_OPEN_AI_ENDPOINT').update!(value: 'https://custom.azure.com/') + end + + it 'uses custom endpoint for OpenAI client' do + expect(OpenAI::Client).to receive(:new).with( + access_token: 'test-key', + uri_base: 'https://custom.azure.com/', + log_errors: Rails.env.development? + ) + + described_class.new(assistant, config) + end + end end describe '#generate_response' do