Class: Commiti::GoogleClient
- Inherits:
-
Object
- Object
- Commiti::GoogleClient
- Includes:
- HTTParty
- Defined in:
- lib/services/google_client.rb
Constant Summary collapse
- DEFAULT_MODEL =
'gemma-4-31b-it'- DEFAULT_TEMPERATURE =
0.2- DEFAULT_TIMEOUT_SECONDS =
180- DEFAULT_OPEN_TIMEOUT_SECONDS =
10
Instance Method Summary collapse
- #extract_content(parsed) ⇒ Object
- #extract_error(body) ⇒ Object
- #extract_generated_content(body) ⇒ Object
- #generate(system:, user:, api_key: nil, model: nil, temperature: nil, timeout_seconds: nil, open_timeout_seconds: nil) ⇒ Object
- #generate_content(system:, user:, settings:) ⇒ Object
-
#initialize(config: Commiti::ConfigLoader.load) ⇒ GoogleClient
constructor
A new instance of GoogleClient.
- #normalize_api_key(value) ⇒ Object
- #normalize_float(value, fallback) ⇒ Object
- #normalize_integer(value, fallback) ⇒ Object
- #normalize_model(model) ⇒ Object
- #request_body(system:, user:, settings:) ⇒ Object
- #request_settings(api_key:, model:, temperature:, timeout_seconds:, open_timeout_seconds:) ⇒ Object
Constructor Details
#initialize(config: Commiti::ConfigLoader.load) ⇒ GoogleClient
Returns a new instance of GoogleClient.
17 18 19 |
# File 'lib/services/google_client.rb', line 17 def initialize(config: Commiti::ConfigLoader.load) @config = config || {} end |
Instance Method Details
#extract_content(parsed) ⇒ Object
79 80 81 82 83 84 |
# File 'lib/services/google_client.rb', line 79 def extract_content(parsed) parts = parsed.dig('candidates', 0, 'content', 'parts') return '' unless parts.is_a?(Array) parts.map { |part| part['text'].to_s }.join.strip end |
#extract_error(body) ⇒ Object
68 69 70 71 72 73 74 75 76 77 |
# File 'lib/services/google_client.rb', line 68 def extract_error(body) parsed = JSON.parse(body.to_s) error = parsed['error'] return error['message'].to_s.strip if error.is_a?(Hash) return error.to_s.strip unless error.nil? '' rescue JSON::ParserError '' end |
#extract_generated_content(body) ⇒ Object
96 97 98 99 100 101 102 103 104 |
# File 'lib/services/google_client.rb', line 96 def extract_generated_content(body) parsed = JSON.parse(body.to_s) content = extract_content(parsed) raise 'Google AI error: response did not include generated text' if content.empty? content rescue JSON::ParserError => e raise "Google AI error: invalid JSON response (#{e.})" end |
#generate(system:, user:, api_key: nil, model: nil, temperature: nil, timeout_seconds: nil, open_timeout_seconds: nil) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/services/google_client.rb', line 21 def generate(system:, user:, api_key: nil, model: nil, temperature: nil, timeout_seconds: nil, open_timeout_seconds: nil) settings = request_settings( api_key: api_key, model: model, temperature: temperature, timeout_seconds: timeout_seconds, open_timeout_seconds: open_timeout_seconds ) response = generate_content(system: system, user: user, settings: settings) unless response.success? detail = extract_error(response.body) = "Google AI error: #{response.code}" = "#{} - #{detail}" unless detail.empty? raise end extract_generated_content(response.body) end |
#generate_content(system:, user:, settings:) ⇒ Object
106 107 108 109 110 111 112 113 114 115 |
# File 'lib/services/google_client.rb', line 106 def generate_content(system:, user:, settings:) self.class.post( "/v1beta/models/#{URI.encode_www_form_component(settings[:model])}:generateContent", query: { key: settings[:api_key] }, headers: { 'Content-Type' => 'application/json' }, timeout: settings[:timeout_seconds], open_timeout: settings[:open_timeout_seconds], body: request_body(system: system, user: user, settings: settings).to_json ) end |
#normalize_api_key(value) ⇒ Object
45 46 47 48 49 50 |
# File 'lib/services/google_client.rb', line 45 def normalize_api_key(value) key = value.to_s.strip return key unless key.empty? raise 'Google API key is missing. Set GOOGLE_API_KEY (or GEMINI_API_KEY) in your environment.' end |
#normalize_float(value, fallback) ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/services/google_client.rb', line 52 def normalize_float(value, fallback) return fallback if value.nil? || value.to_s.strip.empty? Float(value) rescue ArgumentError fallback end |
#normalize_integer(value, fallback) ⇒ Object
60 61 62 63 64 65 66 |
# File 'lib/services/google_client.rb', line 60 def normalize_integer(value, fallback) return fallback if value.nil? || value.to_s.strip.empty? Integer(value) rescue ArgumentError fallback end |
#normalize_model(model) ⇒ Object
39 40 41 42 43 |
# File 'lib/services/google_client.rb', line 39 def normalize_model(model) value = model.to_s.strip normalized = value.sub(%r{\Amodels/}, '') normalized.empty? ? DEFAULT_MODEL : normalized end |
#request_body(system:, user:, settings:) ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/services/google_client.rb', line 117 def request_body(system:, user:, settings:) { systemInstruction: { parts: [{ text: system.to_s }] }, generationConfig: { temperature: settings[:temperature] }, contents: [ { role: 'user', parts: [{ text: user.to_s }] } ] } end |
#request_settings(api_key:, model:, temperature:, timeout_seconds:, open_timeout_seconds:) ⇒ Object
86 87 88 89 90 91 92 93 94 |
# File 'lib/services/google_client.rb', line 86 def request_settings(api_key:, model:, temperature:, timeout_seconds:, open_timeout_seconds:) { api_key: normalize_api_key(api_key || @config[:google_api_key]), model: normalize_model(model || @config[:model]), temperature: normalize_float(temperature || @config[:temperature], DEFAULT_TEMPERATURE), timeout_seconds: normalize_integer(timeout_seconds || @config[:timeout_seconds], DEFAULT_TIMEOUT_SECONDS), open_timeout_seconds: normalize_integer(open_timeout_seconds || @config[:open_timeout_seconds], DEFAULT_OPEN_TIMEOUT_SECONDS) } end |