diff --git a/docs/_getting_started/configuration.md b/docs/_getting_started/configuration.md index fb48ce66d..8c98a9f8d 100644 --- a/docs/_getting_started/configuration.md +++ b/docs/_getting_started/configuration.md @@ -55,6 +55,7 @@ RubyLLM.configure do |config| config.gemini_api_key = ENV['GEMINI_API_KEY'] config.vertexai_project_id = ENV['GOOGLE_CLOUD_PROJECT'] # Available in v1.7.0+ config.vertexai_location = ENV['GOOGLE_CLOUD_LOCATION'] + config.vertexai_service_account_key = ENV['VERTEXAI_SERVICE_ACCOUNT_KEY'] # JSON Key as String from GCP config.deepseek_api_key = ENV['DEEPSEEK_API_KEY'] config.mistral_api_key = ENV['MISTRAL_API_KEY'] config.perplexity_api_key = ENV['PERPLEXITY_API_KEY'] @@ -96,6 +97,12 @@ end These headers are optional and only needed for organization-specific billing or project tracking. +### Vertex AI Authentication Configuration + +Google Cloud disallows the creation of Vertex AI API keys for Service Accounts, by default. The recommended way to connect is by using a Service Account's JSON key with appropriate IAM roles or by using Application Default Credentials. + +RubyLLM supports both methods of authenticating to Vertex AI and will only use a Service Account key if the key is provided in the `config.vertexai_service_account_key` configuration field. Otherwise, it will fallback to ADC. + ## Custom Endpoints ### OpenAI-Compatible APIs @@ -389,6 +396,7 @@ RubyLLM.configure do |config| config.gemini_api_key = String config.vertexai_project_id = String # GCP project ID config.vertexai_location = String # e.g., 'us-central1' + config.vertexai_service_account_key = String # The JSON key as available for GCP Service Accountss config.deepseek_api_key = String config.mistral_api_key = String config.perplexity_api_key = String diff --git a/lib/ruby_llm/configuration.rb b/lib/ruby_llm/configuration.rb index 4b0c46d64..7240fd10f 100644 --- a/lib/ruby_llm/configuration.rb +++ b/lib/ruby_llm/configuration.rb @@ -16,6 +16,7 @@ class Configuration :gemini_api_base, :vertexai_project_id, :vertexai_location, + :vertexai_service_account_key, :deepseek_api_key, :perplexity_api_key, :bedrock_api_key, diff --git a/lib/ruby_llm/providers/vertexai.rb b/lib/ruby_llm/providers/vertexai.rb index 742121eec..05fdedfcd 100644 --- a/lib/ruby_llm/providers/vertexai.rb +++ b/lib/ruby_llm/providers/vertexai.rb @@ -10,6 +10,11 @@ class VertexAI < Gemini include VertexAI::Models include VertexAI::Transcription + SCOPES = [ + 'https://www.googleapis.com/auth/cloud-platform', + 'https://www.googleapis.com/auth/generative-language.retriever' + ] + def initialize(config) super @authorizer = nil @@ -36,7 +41,7 @@ def headers class << self def configuration_requirements - %i[vertexai_project_id vertexai_location] + %i[vertexai_project_id vertexai_location vertexai_service_account_key] end end @@ -44,12 +49,14 @@ def configuration_requirements def initialize_authorizer require 'googleauth' - @authorizer = ::Google::Auth.get_application_default( - scope: [ - 'https://www.googleapis.com/auth/cloud-platform', - 'https://www.googleapis.com/auth/generative-language.retriever' - ] - ) + @authorizer = if @config.vertexai_service_account_key + ::Google::Auth::ServiceAccountCredentials.make_creds( + json_key_io: StringIO.new(@config.vertexai_service_account_key), + scope: SCOPES + ) + else + ::Google::Auth.get_application_default(scope: SCOPES) + end rescue LoadError raise Error, 'The googleauth gem ~> 1.15 is required for Vertex AI. Please add it to your Gemfile: gem "googleauth"' diff --git a/spec/support/rubyllm_configuration.rb b/spec/support/rubyllm_configuration.rb index f5f2958c6..ade6d8288 100644 --- a/spec/support/rubyllm_configuration.rb +++ b/spec/support/rubyllm_configuration.rb @@ -14,6 +14,9 @@ config.bedrock_region = 'us-west-2' config.bedrock_secret_key = ENV.fetch('AWS_SECRET_ACCESS_KEY', 'test') config.bedrock_session_token = ENV.fetch('AWS_SESSION_TOKEN', nil) + config.vertexai_project_id = ENV.fetch('GOOGLE_CLOUD_PROJECT', 'test-project') + config.vertexai_location = ENV.fetch('GOOGLE_CLOUD_LOCATION', 'us-central1') + config.vertexai_service_account_key = ENV.fetch('VERTEXAI_SERVICE_ACCOUNT_KEY', "{ secret_key: 'test' }") config.deepseek_api_key = ENV.fetch('DEEPSEEK_API_KEY', 'test') config.gemini_api_key = ENV.fetch('GEMINI_API_KEY', 'test') config.gpustack_api_base = ENV.fetch('GPUSTACK_API_BASE', 'http://localhost:11444/v1')