Class: GeminiAI::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/core/client.rb

Overview

Core client class for Gemini AI API communication

Constant Summary collapse

BASE_URL =
'https://generativelanguage.googleapis.com/v1/models'
MODELS =
{
  # Gemini 2.5 models (latest)
  pro: 'gemini-2.5-pro',
  flash: 'gemini-2.5-flash',
  
  # Gemini 2.0 models
  flash_2_0: 'gemini-2.0-flash',
  flash_lite: 'gemini-2.0-flash-lite',
  
  # Legacy aliases for backward compatibility
  pro_2_0: 'gemini-2.0-flash',
  
  # Gemini 1.5 models (for specific use cases)
  pro_1_5: 'gemini-1.5-pro',
  flash_1_5: 'gemini-1.5-flash',
  flash_8b: 'gemini-1.5-flash-8b'
}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_key = nil, model: :pro) ⇒ Client

Returns a new instance of Client.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/core/client.rb', line 42

def initialize(api_key = nil, model: :pro)
  # Prioritize passed API key, then environment variable
  @api_key = api_key || ENV['GEMINI_API_KEY']
  
  # Rate limiting - track last request time
  @last_request_time = nil
  # More conservative rate limiting in CI environments
  @min_request_interval = (ENV['CI'] == 'true' || ENV['GITHUB_ACTIONS'] == 'true') ? 3.0 : 1.0
  
  # Extensive logging for debugging
  self.class.logger.debug("Initializing Client")
  self.class.logger.debug("API Key present: #{!@api_key.nil?}")
  self.class.logger.debug("API Key length: #{@api_key&.length}")
  
  # Validate API key
  validate_api_key!
  
  @model = MODELS.fetch(model) { 
    self.class.logger.warn("Invalid model: #{model}, defaulting to pro")
    MODELS[:pro] 
  }
  
  self.class.logger.debug("Selected model: #{@model}")
end

Class Method Details

.loggerObject

Configure logging



31
32
33
34
35
36
37
38
39
40
# File 'lib/core/client.rb', line 31

def self.logger
  @logger ||= Logger.new(STDOUT).tap do |log|
    log.level = Logger::DEBUG
    log.formatter = proc do |severity, datetime, progname, msg|
      # Mask any potential API key in logs
      masked_msg = msg.to_s.gsub(/AIza[a-zA-Z0-9_-]{35,}/, '[REDACTED]')
      "#{datetime}: #{severity} -- #{masked_msg}\n"
    end
  end
end

Instance Method Details

#chat(messages, options = {}) ⇒ Object



94
95
96
97
98
99
100
101
# File 'lib/core/client.rb', line 94

def chat(messages, options = {})
  request_body = {
    contents: messages.map { |msg| { role: msg[:role], parts: [{ text: msg[:content] }] } },
    generationConfig: build_generation_config(options)
  }

  send_request(request_body)
end

#generate_image_text(image_base64, prompt, options = {}) ⇒ Object

Raises:



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/core/client.rb', line 78

def generate_image_text(image_base64, prompt, options = {})
  raise Error, "Image is required" if image_base64.nil? || image_base64.empty?
  
  request_body = {
    contents: [
      { parts: [
        { inline_data: { mime_type: 'image/jpeg', data: image_base64 } },
        { text: prompt }
      ]}
    ],
    generationConfig: build_generation_config(options)
  }

  send_request(request_body, model: :pro_vision)
end

#generate_text(prompt, options = {}) ⇒ Object



67
68
69
70
71
72
73
74
75
76
# File 'lib/core/client.rb', line 67

def generate_text(prompt, options = {})
  validate_prompt!(prompt)

  request_body = {
    contents: [{ parts: [{ text: prompt }] }],
    generationConfig: build_generation_config(options)
  }

  send_request(request_body)
end