Class: Crystil::Wrappers::GeminiAI

Inherits:
Object
  • Object
show all
Defined in:
lib/crystil/wrappers/geminiai.rb,
sig/crystil/wrappers/geminiai.rbs

Overview

Wrapper for Google GenerativeAI Ruby client (gemini-ai gem version 4.3.0)

Instance Method Summary collapse

Constructor Details

#initialize(config, collector, sentinel = nil) ⇒ GeminiAI

Returns a new instance of GeminiAI.

Parameters:



9
10
11
12
13
# File 'lib/crystil/wrappers/geminiai.rb', line 9

def initialize(config, collector, sentinel = nil)
  @config = config
  @collector = collector
  @sentinel = sentinel
end

Instance Method Details

#register(client) ⇒ Object

Parameters:

  • client (Object)

Returns:

  • (Object)


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/crystil/wrappers/geminiai.rb', line 15

def register(client)
  validate_client!(client)

  # Prevent double registration
  return client if client.instance_variable_defined?(:@crystil_registered)

  # Store references in client instance
  client.instance_variable_set(:@crystil_config, @config)
  client.instance_variable_set(:@crystil_collector, @collector)
  client.instance_variable_set(:@crystil_sentinel, @sentinel)
  client.instance_variable_set(:@crystil_registered, true)

  # Wrap the generate_content and stream_generate_content methods
  wrap_generate_content_method(client)
  wrap_stream_generate_content_method(client)

  client
end

#validate_client!(client) ⇒ void

This method returns an undefined value.

Parameters:

  • client (Object)

Raises:



36
37
38
39
40
41
42
# File 'lib/crystil/wrappers/geminiai.rb', line 36

def validate_client!(client)
  return if client.respond_to?(:generate_content) && client.respond_to?(:stream_generate_content)

  raise RegistrationError,
        "Client does not appear to be a valid Gemini AI client " \
        "(missing generate_content or stream_generate_content method)"
end

#wrap_generate_content_method(client) ⇒ void

This method returns an undefined value.

Parameters:

  • client (Object)


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/crystil/wrappers/geminiai.rb', line 44

def wrap_generate_content_method(client)
  client.singleton_class.class_eval do
    include Base

    alias_method :original_generate_content, :generate_content

    define_method(:generate_content) do |*args, **kwargs, &block|
      # Handle both positional hash and keyword arguments
      parameters = if args.first.is_a?(Hash)
                     args.first
                   elsif kwargs.any?
                     kwargs
                   else
                     {}
                   end

      start_time = Time.now
      version = defined?(::Gemini::GEM) && ::Gemini::GEM.is_a?(Hash) ? ::Gemini::GEM[:version] : nil

      sentinel = instance_variable_get(:@crystil_sentinel)
      sentinel&.raise_if_irrelevant!(
        title: GOOGLE_CLIENT_TITLE,
        request: parameters,
        version: version
      )

      # Call original method
      response = original_generate_content(*args, **kwargs, &block)

      # Submit analytics
      crystil_submit_analytics(
        method: :generate_content,
        args: [],
        kwargs: parameters,
        response: response,
        start_time: start_time,
        end_time: Time.now,
        title: GOOGLE_CLIENT_TITLE,
        version: version
      )

      response
    rescue CrystilRequestInterceptedError => e
      # We don't want to send intercepts to collector
      raise e
    rescue StandardError => e
      crystil_submit_error_analytics(
        method: :generate_content,
        args: [],
        kwargs: parameters,
        error: e,
        start_time: start_time,
        end_time: Time.now,
        title: GOOGLE_CLIENT_TITLE,
        version: version
      )

      raise e
    end
  end
end

#wrap_stream_generate_content_method(client) ⇒ void

This method returns an undefined value.

Handles the stream_generate_content from the client. Note, that the Crystil backend does not expect the payload to be merged like the OpenAI payload is. So, all the results are just sent as an array.

Parameters:

  • client (Object)


110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/crystil/wrappers/geminiai.rb', line 110

def wrap_stream_generate_content_method(client)
  client.singleton_class.class_eval do
    include Base

    alias_method :original_stream_generate_content, :stream_generate_content

    define_method(:stream_generate_content) do |*args, **kwargs, &block|
      # Handle both positional hash and keyword arguments
      parameters = if args.first.is_a?(Hash)
                     args.first
                   elsif kwargs.any?
                     kwargs
                   else
                     {}
                   end

      start_time = Time.now
      version = defined?(::Gemini::GEM) && ::Gemini::GEM.is_a?(Hash) ? ::Gemini::GEM[:version] : nil

      sentinel = instance_variable_get(:@crystil_sentinel)
      sentinel&.raise_if_irrelevant!(
        title: GOOGLE_CLIENT_TITLE,
        request: parameters,
        version: version
      )

      # Call original method with wrapped block
      response = original_stream_generate_content(*args, **kwargs, &block)

      # Submit analytics with accumulated response
      crystil_submit_analytics(
        method: :stream_generate_content,
        args: [],
        kwargs: parameters,
        response: response,
        start_time: start_time,
        end_time: Time.now,
        title: GOOGLE_CLIENT_TITLE,
        version: version
      )

      response
    rescue CrystilRequestInterceptedError => e
      # We don't want to send intercepts to collector
      raise e
    rescue StandardError => e
      crystil_submit_error_analytics(
        method: :stream_generate_content,
        args: [],
        kwargs: parameters,
        error: e,
        start_time: start_time,
        end_time: Time.now,
        title: GOOGLE_CLIENT_TITLE,
        version: version
      )

      raise e
    end
  end
end