geminize 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "geminize"
6
+
7
+ # Configure the API key
8
+ Geminize.configure do |config|
9
+ config.api_key = ENV["GEMINI_API_KEY"] # Make sure to set your API key in the environment
10
+ config.default_model = "gemini-2.0-flash" # Use a model that supports code execution
11
+ end
12
+
13
+ puts "==========================================="
14
+ puts "= GEMINIZE CODE EXECUTION EXAMPLES ="
15
+ puts "==========================================="
16
+
17
+ puts "\n=== BASIC CODE EXECUTION EXAMPLE ==="
18
+ puts "Asking Gemini to calculate the sum of the first 50 prime numbers..."
19
+
20
+ begin
21
+ # Generate a response with code execution enabled
22
+ response = Geminize.generate_with_code_execution(
23
+ "What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.",
24
+ nil,
25
+ {temperature: 0.2}
26
+ )
27
+
28
+ # Display the generated text
29
+ puts "\nGemini's response:"
30
+ puts response.text
31
+
32
+ # Display the executable code if present
33
+ if response.has_executable_code?
34
+ puts "\nGenerated code:"
35
+ puts "```#{response.executable_code.language.downcase}"
36
+ puts response.executable_code.code
37
+ puts "```"
38
+ end
39
+
40
+ # Display the code execution result if present
41
+ if response.has_code_execution_result?
42
+ puts "\nCode execution result:"
43
+ puts "Outcome: #{response.code_execution_result.outcome}"
44
+ puts "Output: #{response.code_execution_result.output}"
45
+ end
46
+ rescue => e
47
+ puts "Error during code execution: #{e.message}"
48
+ end
49
+
50
+ puts "\n\n=== PRACTICAL CODE EXECUTION EXAMPLE ==="
51
+ puts "Asking Gemini to analyze some text data..."
52
+
53
+ begin
54
+ # Generate a response with code execution for data analysis
55
+ response = Geminize.generate_with_code_execution(
56
+ "I have a list of temperatures: 32, 25, 30, 22, 28, 27, 35, 31, 29, 26. " \
57
+ "Please write code to calculate the mean, median, and standard deviation. " \
58
+ "Also, create a simple histogram visualization using matplotlib.",
59
+ nil,
60
+ {temperature: 0.2}
61
+ )
62
+
63
+ # Display the generated text
64
+ puts "\nGemini's response:"
65
+ puts response.text
66
+
67
+ # Display the executable code if present
68
+ if response.has_executable_code?
69
+ puts "\nGenerated code:"
70
+ puts "```#{response.executable_code.language.downcase}"
71
+ puts response.executable_code.code
72
+ puts "```"
73
+ end
74
+
75
+ # Display the code execution result if present
76
+ if response.has_code_execution_result?
77
+ puts "\nCode execution result:"
78
+ puts "Outcome: #{response.code_execution_result.outcome}"
79
+ puts "Output: #{response.code_execution_result.output}"
80
+ end
81
+ rescue => e
82
+ puts "Error during code execution: #{e.message}"
83
+ end
84
+
85
+ puts "\n\n=== ITERATIVE PROBLEM SOLVING EXAMPLE ==="
86
+ puts "Asking Gemini to solve a complex problem using code execution..."
87
+
88
+ begin
89
+ # Generate a response for a more complex problem
90
+ response = Geminize.generate_with_code_execution(
91
+ "Write a Python function to find the nth Fibonacci number where n is a positive integer. " \
92
+ "Then use this function to calculate the 50th Fibonacci number. " \
93
+ "Implement it efficiently using memoization to avoid redundant calculations.",
94
+ nil,
95
+ {temperature: 0.2}
96
+ )
97
+
98
+ # Display the generated text
99
+ puts "\nGemini's response:"
100
+ puts response.text
101
+
102
+ # Display the executable code if present
103
+ if response.has_executable_code?
104
+ puts "\nGenerated code:"
105
+ puts "```#{response.executable_code.language.downcase}"
106
+ puts response.executable_code.code
107
+ puts "```"
108
+ end
109
+
110
+ # Display the code execution result if present
111
+ if response.has_code_execution_result?
112
+ puts "\nCode execution result:"
113
+ puts "Outcome: #{response.code_execution_result.outcome}"
114
+ puts "Output: #{response.code_execution_result.output}"
115
+ end
116
+ rescue => e
117
+ puts "Error during code execution: #{e.message}"
118
+ puts "\nNOTE: If you hit a quota limit, try:"
119
+ puts "1. Using a paid API key with higher quotas"
120
+ puts "2. Reducing the number of examples you run"
121
+ puts "3. Adding delays between API calls"
122
+ end
123
+
124
+ puts "\n==========================================="
125
+ puts "= END OF EXAMPLES ="
126
+ puts "==========================================="
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "geminize"
6
+ require "json"
7
+
8
+ # Configure the API key
9
+ Geminize.configure do |config|
10
+ config.api_key = ENV["GEMINI_API_KEY"] # Make sure to set your API key in the environment
11
+ config.default_model = "gemini-1.5-pro-latest" # Use the latest model that supports function calling
12
+ end
13
+
14
+ # Define a weather function that can handle a location and unit
15
+ def get_weather(location, unit = "celsius")
16
+ puts "Getting weather for #{location} in #{unit}..."
17
+
18
+ # In a real implementation, this would call a weather API
19
+ # For this example, we'll return mock data
20
+ case location.downcase
21
+ when /new york/
22
+ {temperature: (unit == "celsius") ? 22 : 72, conditions: "Sunny", humidity: 45}
23
+ when /london/
24
+ {temperature: (unit == "celsius") ? 15 : 59, conditions: "Rainy", humidity: 80}
25
+ when /tokyo/
26
+ {temperature: (unit == "celsius") ? 26 : 79, conditions: "Partly Cloudy", humidity: 65}
27
+ else
28
+ {temperature: (unit == "celsius") ? 20 : 68, conditions: "Unknown", humidity: 50}
29
+ end
30
+ end
31
+
32
+ # Enhanced weather function that can handle a batch of locations
33
+ def get_weather_batch(locations, unit = "celsius")
34
+ if locations.is_a?(Array)
35
+ results = {}
36
+ locations.each do |location|
37
+ results[location] = get_weather(location, unit)
38
+ end
39
+ results
40
+ else
41
+ {locations => get_weather(locations, unit)}
42
+ end
43
+ end
44
+
45
+ # Define a function schema for get_weather
46
+ weather_function = {
47
+ name: "get_weather",
48
+ description: "Get the current weather in a location",
49
+ parameters: {
50
+ type: "object",
51
+ properties: {
52
+ location: {
53
+ type: "string",
54
+ description: "The city and state or country, e.g., 'New York, NY' or 'London, UK'"
55
+ },
56
+ unit: {
57
+ type: "string",
58
+ enum: ["celsius", "fahrenheit"],
59
+ description: "The unit of temperature"
60
+ }
61
+ },
62
+ required: ["location"]
63
+ }
64
+ }
65
+
66
+ # Define a batch weather function schema that can handle multiple locations
67
+ batch_weather_function = {
68
+ name: "get_weather_batch",
69
+ description: "Get the current weather for multiple locations at once",
70
+ parameters: {
71
+ type: "object",
72
+ properties: {
73
+ locations: {
74
+ type: "array",
75
+ items: {
76
+ type: "string"
77
+ },
78
+ description: "List of cities, e.g., ['New York, NY', 'London, UK', 'Tokyo, Japan']"
79
+ },
80
+ unit: {
81
+ type: "string",
82
+ enum: ["celsius", "fahrenheit"],
83
+ description: "The unit of temperature"
84
+ }
85
+ },
86
+ required: ["locations"]
87
+ }
88
+ }
89
+
90
+ puts "==========================================="
91
+ puts "= GEMINIZE FUNCTION CALLING & JSON EXAMPLES ="
92
+ puts "==========================================="
93
+
94
+ puts "\n=== FUNCTION CALLING EXAMPLE ==="
95
+ puts "Asking Gemini about the weather in New York..."
96
+
97
+ begin
98
+ # Generate a response with the function definition
99
+ response = Geminize.generate_with_functions(
100
+ "What's the weather like in New York?",
101
+ [weather_function],
102
+ nil,
103
+ {temperature: 0.2}
104
+ )
105
+
106
+ # Check if the model wants to call a function
107
+ if response.has_function_call?
108
+ function_call = response.function_call
109
+ puts "Model wants to call function: #{function_call.name}"
110
+ puts "With arguments: #{function_call.response.inspect}"
111
+
112
+ function_name = function_call.name
113
+ args = function_call.response
114
+
115
+ if function_name == "get_weather"
116
+ location = args["location"]
117
+ unit = args["unit"] || "celsius"
118
+
119
+ # Call our weather function
120
+ weather_data = get_weather(location, unit)
121
+ puts "Weather data for #{location}: #{weather_data.inspect}"
122
+
123
+ # Process the function result
124
+ final_response = Geminize.process_function_call(response) do |name, arguments|
125
+ get_weather(arguments["location"], arguments["unit"])
126
+ end
127
+
128
+ puts "\nFinal response from Gemini:"
129
+ puts final_response.text
130
+ else
131
+ puts "Unexpected function call: #{function_name}"
132
+ end
133
+ else
134
+ puts "Model did not request to call a function."
135
+ puts "Response: #{response.text}"
136
+ end
137
+ rescue => e
138
+ puts "Error during function calling: #{e.message}"
139
+ end
140
+
141
+ # Example of using JSON mode
142
+ puts "\n\n=== JSON MODE EXAMPLE ==="
143
+ puts "Using JSON mode to get weather data in structured format..."
144
+
145
+ begin
146
+ json_response = Geminize.generate_json(
147
+ "Get the current temperature and weather conditions for New York.",
148
+ nil,
149
+ {
150
+ system_instruction: "Return a JSON object with temperature in celsius and conditions."
151
+ }
152
+ )
153
+
154
+ if json_response.has_json_response?
155
+ puts "Structured JSON response:"
156
+ puts JSON.pretty_generate(json_response.json_response)
157
+ else
158
+ puts "Raw text response (not valid JSON):"
159
+ puts json_response.text
160
+ end
161
+ rescue => e
162
+ puts "Error during JSON mode: #{e.message}"
163
+ end
164
+
165
+ puts "\n\n=== BATCH FUNCTION CALL EXAMPLE ==="
166
+ puts "Using batch function to efficiently get weather for multiple cities at once..."
167
+
168
+ begin
169
+ # Use a batch function to get all cities at once (more efficient)
170
+ response = Geminize.generate_with_functions(
171
+ "I need weather information for New York, Tokyo, and London. Please get all this information in a single function call.",
172
+ [batch_weather_function],
173
+ nil,
174
+ {temperature: 0.2}
175
+ )
176
+
177
+ # Check if the model wants to call the batch function
178
+ if response.has_function_call?
179
+ function_call = response.function_call
180
+ puts "Model wants to call function: #{function_call.name}"
181
+ puts "With arguments: #{function_call.response.inspect}"
182
+
183
+ function_name = function_call.name
184
+ args = function_call.response
185
+
186
+ if function_name == "get_weather_batch"
187
+ locations = args["locations"]
188
+ unit = args["unit"] || "celsius"
189
+
190
+ # Get weather for all locations at once
191
+ weather_data = get_weather_batch(locations, unit)
192
+ puts "Weather data for multiple locations: #{weather_data.inspect}"
193
+
194
+ # Process the function result with a single API call
195
+ final_response = Geminize.process_function_call(response) do |name, arguments|
196
+ get_weather_batch(arguments["locations"], arguments["unit"])
197
+ end
198
+
199
+ puts "\nFinal response from Gemini:"
200
+ puts final_response.text
201
+ else
202
+ puts "Unexpected function call: #{function_name}"
203
+ end
204
+ else
205
+ puts "Model did not request to call a function."
206
+ puts "Response: #{response.text}"
207
+ end
208
+ rescue => e
209
+ puts "Error during batch function calling: #{e.message}"
210
+ puts "\nNOTE: If you hit a quota limit, try:"
211
+ puts "1. Using a paid API key with higher quotas"
212
+ puts "2. Reducing the number of examples you run"
213
+ puts "3. Adding delays between API calls"
214
+ end
215
+
216
+ puts "\n==========================================="
217
+ puts "= END OF EXAMPLES ="
218
+ puts "==========================================="
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "geminize"
6
+
7
+ # Configure the API key
8
+ Geminize.configure do |config|
9
+ config.api_key = ENV["GEMINI_API_KEY"] # Make sure to set your API key in the environment
10
+ config.default_model = "gemini-1.5-pro-latest" # Use the latest model
11
+ end
12
+
13
+ # A prompt that might trigger safety filters
14
+ POTENTIALLY_SENSITIVE_PROMPT = "Describe a violent conflict scene from a movie"
15
+
16
+ puts "1. Generating with default safety settings:"
17
+ begin
18
+ response = Geminize.generate_text(POTENTIALLY_SENSITIVE_PROMPT, nil, temperature: 0.2)
19
+ puts "Default response:\n#{response.text}\n\n"
20
+ rescue Geminize::GeminizeError => e
21
+ puts "Error with default settings: #{e.message}\n\n"
22
+ end
23
+
24
+ puts "2. Generating with maximum safety (blocking most potentially harmful content):"
25
+ begin
26
+ response = Geminize.generate_text_safe(POTENTIALLY_SENSITIVE_PROMPT, nil, temperature: 0.2)
27
+ puts "Maximum safety response:\n#{response.text}\n\n"
28
+ rescue Geminize::GeminizeError => e
29
+ puts "Error with maximum safety: #{e.message}\n\n"
30
+ end
31
+
32
+ puts "3. Generating with minimum safety (blocking only high-risk content):"
33
+ begin
34
+ response = Geminize.generate_text_permissive(POTENTIALLY_SENSITIVE_PROMPT, nil, temperature: 0.2)
35
+ puts "Minimum safety response:\n#{response.text}\n\n"
36
+ rescue Geminize::GeminizeError => e
37
+ puts "Error with minimum safety: #{e.message}\n\n"
38
+ end
39
+
40
+ puts "4. Generating with custom safety settings:"
41
+ begin
42
+ # Custom safety settings:
43
+ # - Block medium and above for dangerous content
44
+ # - Block low and above for hate speech
45
+ # - Block only high for sexually explicit content
46
+ # - No blocks for harassment
47
+ custom_safety_settings = [
48
+ {category: "HARM_CATEGORY_DANGEROUS_CONTENT", threshold: "BLOCK_MEDIUM_AND_ABOVE"},
49
+ {category: "HARM_CATEGORY_HATE_SPEECH", threshold: "BLOCK_LOW_AND_ABOVE"},
50
+ {category: "HARM_CATEGORY_SEXUALLY_EXPLICIT", threshold: "BLOCK_ONLY_HIGH"},
51
+ {category: "HARM_CATEGORY_HARASSMENT", threshold: "BLOCK_NONE"}
52
+ ]
53
+
54
+ response = Geminize.generate_with_safety_settings(
55
+ POTENTIALLY_SENSITIVE_PROMPT,
56
+ custom_safety_settings,
57
+ nil,
58
+ temperature: 0.2
59
+ )
60
+ puts "Custom safety response:\n#{response.text}\n\n"
61
+ rescue Geminize::GeminizeError => e
62
+ puts "Error with custom safety: #{e.message}\n\n"
63
+ end
64
+
65
+ # Demonstrate direct usage of safety settings in a ContentRequest
66
+ puts "5. Using safety settings directly in a ContentRequest:"
67
+ begin
68
+ generator = Geminize::TextGeneration.new
69
+ content_request = Geminize::Models::ContentRequest.new(
70
+ POTENTIALLY_SENSITIVE_PROMPT,
71
+ nil,
72
+ temperature: 0.2
73
+ )
74
+
75
+ # Add specific safety settings
76
+ content_request.add_safety_setting("HARM_CATEGORY_DANGEROUS_CONTENT", "BLOCK_MEDIUM_AND_ABOVE")
77
+
78
+ response = generator.generate(content_request)
79
+ puts "ContentRequest safety response:\n#{response.text}\n\n"
80
+ rescue Geminize::GeminizeError => e
81
+ puts "Error with ContentRequest safety: #{e.message}\n\n"
82
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Geminize
4
+ module Models
5
+ module CodeExecution
6
+ # Represents the result of executed code
7
+ class CodeExecutionResult
8
+ # Valid outcome values for code execution
9
+ VALID_OUTCOMES = ["OUTCOME_OK", "OUTCOME_ERROR"].freeze
10
+
11
+ # @return [String] The outcome of the code execution (e.g., "OUTCOME_OK", "OUTCOME_ERROR")
12
+ attr_reader :outcome
13
+
14
+ # @return [String] The output from the code execution
15
+ attr_reader :output
16
+
17
+ # Initialize a new code execution result
18
+ # @param outcome [String] The outcome of the code execution
19
+ # @param output [String] The output from the code execution
20
+ # @raise [Geminize::ValidationError] If the code execution result is invalid
21
+ def initialize(outcome, output)
22
+ @outcome = outcome
23
+ @output = output
24
+ validate!
25
+ end
26
+
27
+ # Validate the code execution result
28
+ # @raise [Geminize::ValidationError] If the code execution result is invalid
29
+ # @return [Boolean] true if validation passes
30
+ def validate!
31
+ unless @outcome.is_a?(String)
32
+ raise Geminize::ValidationError.new(
33
+ "Outcome must be a string, got #{@outcome.class}",
34
+ "INVALID_ARGUMENT"
35
+ )
36
+ end
37
+
38
+ unless VALID_OUTCOMES.include?(@outcome)
39
+ raise Geminize::ValidationError.new(
40
+ "Invalid outcome: #{@outcome}. Must be one of: #{VALID_OUTCOMES.join(", ")}",
41
+ "INVALID_ARGUMENT"
42
+ )
43
+ end
44
+
45
+ unless @output.is_a?(String)
46
+ raise Geminize::ValidationError.new(
47
+ "Output must be a string, got #{@output.class}",
48
+ "INVALID_ARGUMENT"
49
+ )
50
+ end
51
+
52
+ true
53
+ end
54
+
55
+ # Convert the code execution result to a hash
56
+ # @return [Hash] The code execution result as a hash
57
+ def to_hash
58
+ {
59
+ outcome: @outcome,
60
+ output: @output
61
+ }
62
+ end
63
+
64
+ # Alias for to_hash
65
+ # @return [Hash] The code execution result as a hash
66
+ def to_h
67
+ to_hash
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Geminize
4
+ module Models
5
+ module CodeExecution
6
+ # Represents executable code generated by the model
7
+ class ExecutableCode
8
+ # Valid language options for executable code
9
+ VALID_LANGUAGES = ["PYTHON"].freeze
10
+
11
+ # @return [String] The language of the code (e.g., "PYTHON")
12
+ attr_reader :language
13
+
14
+ # @return [String] The code content
15
+ attr_reader :code
16
+
17
+ # Initialize a new executable code object
18
+ # @param language [String] The programming language of the code (e.g., "PYTHON")
19
+ # @param code [String] The code content
20
+ # @raise [Geminize::ValidationError] If the executable code is invalid
21
+ def initialize(language, code)
22
+ @language = language
23
+ @code = code
24
+ validate!
25
+ end
26
+
27
+ # Validate the executable code
28
+ # @raise [Geminize::ValidationError] If the executable code is invalid
29
+ # @return [Boolean] true if validation passes
30
+ def validate!
31
+ unless @language.is_a?(String)
32
+ raise Geminize::ValidationError.new(
33
+ "Language must be a string, got #{@language.class}",
34
+ "INVALID_ARGUMENT"
35
+ )
36
+ end
37
+
38
+ unless VALID_LANGUAGES.include?(@language)
39
+ raise Geminize::ValidationError.new(
40
+ "Invalid language: #{@language}. Must be one of: #{VALID_LANGUAGES.join(", ")}",
41
+ "INVALID_ARGUMENT"
42
+ )
43
+ end
44
+
45
+ unless @code.is_a?(String)
46
+ raise Geminize::ValidationError.new(
47
+ "Code must be a string, got #{@code.class}",
48
+ "INVALID_ARGUMENT"
49
+ )
50
+ end
51
+
52
+ true
53
+ end
54
+
55
+ # Convert the executable code to a hash
56
+ # @return [Hash] The executable code as a hash
57
+ def to_hash
58
+ {
59
+ language: @language,
60
+ code: @code
61
+ }
62
+ end
63
+
64
+ # Alias for to_hash
65
+ # @return [Hash] The executable code as a hash
66
+ def to_h
67
+ to_hash
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end