geminize 1.2.0 → 1.3.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 900c19e9cf075e32779e3ee2f4f4530fdced2c027e8bc393d05250c1b20e5dac
4
- data.tar.gz: 7d1a9a2f365eff24d2625492916d578f661fd881263c1cd4101352d7b16780ce
3
+ metadata.gz: 86fb5e9a612c451c27419e3c7d17f707ed337b9f38283493a521123b515e0e03
4
+ data.tar.gz: 9743507bf4df70ea1292757b01bc5e7d4f4c32cf7ef899b3bd9ef63acfb7966a
5
5
  SHA512:
6
- metadata.gz: b1e3a5235a330b9bba4690a2452992f331bf4b76294109e2d4a8beb3fbc357c3f06be8b9728d607aff8653367458827bf17b166a1c89c6d243062272e747b154
7
- data.tar.gz: a9c73fc3264fccaa26ba6b525d89807a9a99052232c12387281844d1cca821609c795fe199ed222c601962e8f144fc73854b73eccc75994fc3ab6ac70e4f7b2d
6
+ metadata.gz: f279410c3e5b848ba9ac652b15cc78a4112da3d5ea5aab425a2257525aa16fdf42bd68e03329f91e98ebef9bfda3a72eb2dfd18db489eed10def917e2ba6dfb5
7
+ data.tar.gz: 608c8b726d586e66ed8ae8b81174509fa4b5ff9d3fae299efde0013afc6d7b91d7c25f6840b7f7d94d0a3a4a645657843c4a4d1d0bf61723761e771050e93c85
@@ -12,6 +12,7 @@
12
12
  - Function calling capabilities
13
13
  - JSON mode for structured responses
14
14
  - Safety settings for content moderation
15
+ - Code execution capabilities
15
16
 
16
17
  ### Key Implementation Details
17
18
 
@@ -32,6 +33,15 @@
32
33
  - Function result processing
33
34
  - String-based function call detection
34
35
 
36
+ #### Code Execution
37
+
38
+ - Python code generation and execution support
39
+ - Code execution result handling
40
+ - Support for code libraries like matplotlib, numpy, etc.
41
+ - Tool-based code execution integration
42
+ - Executable code response parsing
43
+ - Code output result parsing
44
+
35
45
  #### JSON Mode
36
46
 
37
47
  - Structured data response handling
@@ -91,10 +101,10 @@
91
101
  - Error handling refinements
92
102
  - Models API integration
93
103
  - Function calling support
104
+ - Code execution capabilities
94
105
 
95
106
  ### Upcoming Features
96
107
 
97
- - Code execution support
98
108
  - Additional content types (audio, PDF)
99
109
  - Caching support
100
110
  - Advanced parameter tuning
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Current Status
4
4
 
5
- Geminize is a functional Ruby gem providing a complete interface to the Google Gemini API. The current implementation includes all core features with a focus on stability, documentation, and ease of use. The gem now also includes function calling, JSON mode, and safety settings features.
5
+ Geminize is a functional Ruby gem providing a complete interface to the Google Gemini API. The current implementation includes all core features with a focus on stability, documentation, and ease of use. The gem now also includes function calling, JSON mode, safety settings, and code execution features.
6
6
 
7
7
  ## Development Progress
8
8
 
@@ -19,6 +19,7 @@ Geminize is a functional Ruby gem providing a complete interface to the Google G
19
19
  - **Function Calling**: ✅ Complete
20
20
  - **JSON Mode**: ✅ Complete
21
21
  - **Safety Settings**: ✅ Complete
22
+ - **Code Execution**: ✅ Complete
22
23
 
23
24
  ### Documentation
24
25
 
@@ -79,7 +80,7 @@ Geminize is a functional Ruby gem providing a complete interface to the Google G
79
80
 
80
81
  ### v1.3.0 (Planned)
81
82
 
82
- - Code execution support
83
+ - Added code execution support
83
84
  - Additional content types (audio, PDF)
84
85
  - Caching mechanisms
85
86
  - Improved conversation persistence
@@ -29,10 +29,12 @@
29
29
  - [x] Add safety configuration to requests
30
30
  - [x] Implement module-level safety methods
31
31
  - [x] Add tests for safety settings
32
- - [ ] **Code Execution Support**
33
- - [ ] Create code execution model classes
34
- - [ ] Implement code execution tools in requests
35
- - [ ] Update response handling for code execution
32
+ - [x] **Code Execution Support**
33
+ - [x] Create code execution model classes
34
+ - [x] Implement code execution tools in requests
35
+ - [x] Update response handling for code execution
36
+ - [x] Add module-level code execution methods
37
+ - [x] Create example script for code execution
36
38
  - [ ] **Additional Content Types**
37
39
  - [ ] Audio content support
38
40
  - [ ] Document/PDF content support
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## [1.3.1] - 2025-05-17
2
+
3
+ ### Changed
4
+
5
+ - Refactored `Geminize::ModuleExtensions` and `Geminize::ModuleSafety` into the main `Geminize` module for a flatter internal structure. This change is internal and does not affect the public API.
6
+
7
+ ## [1.3.0] - 2024-05-02
8
+
9
+ ### Added
10
+
11
+ - Code execution capabilities for generating and running Python code
12
+ - Added `generate_with_code_execution` method to create and execute Python code
13
+ - Implemented `ExecutableCode` model for representing generated code
14
+ - Added `CodeExecutionResult` model for capturing execution output and status
15
+ - Added support for visualizations and data analysis with matplotlib and other libraries
16
+ - Extended tool system to support code execution tools
17
+ - Updated content request/response handling for code execution
18
+ - Added comprehensive test suite with VCR tests for code execution
19
+ - Added examples demonstrating code execution functionality
20
+
1
21
  ## [1.2.0] - 2025-05-02
2
22
 
3
23
  ### Added
data/README.md CHANGED
@@ -311,7 +311,7 @@ weather_functions = [
311
311
  response = Geminize.generate_with_functions(
312
312
  "What's the weather in San Francisco?",
313
313
  weather_functions,
314
- "gemini-1.5-pro", # Make sure you use a model that supports function calling
314
+ "gemini-2.0-flash", # Make sure you use a model that supports function calling
315
315
  {
316
316
  temperature: 0.2,
317
317
  system_instruction: "Use the provided function to get weather information."
@@ -382,7 +382,7 @@ require 'geminize'
382
382
  # Request JSON-formatted data
383
383
  response = Geminize.generate_json(
384
384
  "List the three largest planets in our solar system with their diameters in km",
385
- "gemini-1.5-pro", # Use a model that supports JSON mode
385
+ "gemini-2.0-flash", # Use a model that supports JSON mode
386
386
  { temperature: 0.2 }
387
387
  )
388
388
 
@@ -417,7 +417,7 @@ safety_settings = [
417
417
  response = Geminize.generate_with_safety_settings(
418
418
  "Explain the concept of nuclear fission",
419
419
  safety_settings,
420
- "gemini-1.5-pro",
420
+ "gemini-2.0-flash",
421
421
  { temperature: 0.7 }
422
422
  )
423
423
 
@@ -426,7 +426,7 @@ puts response.text
426
426
  # For maximum safety (blocks most potentially harmful content)
427
427
  safe_response = Geminize.generate_text_safe(
428
428
  "Tell me about controversial political topics",
429
- "gemini-1.5-pro"
429
+ "gemini-2.0-flash"
430
430
  )
431
431
 
432
432
  puts "Safe response: #{safe_response.text}"
@@ -434,7 +434,7 @@ puts "Safe response: #{safe_response.text}"
434
434
  # For minimum filtering (blocks only the most harmful content)
435
435
  permissive_response = Geminize.generate_text_permissive(
436
436
  "Describe a controversial historical event",
437
- "gemini-1.5-pro"
437
+ "gemini-2.0-flash"
438
438
  )
439
439
 
440
440
  puts "Permissive response: #{permissive_response.text}"
@@ -454,6 +454,48 @@ Available threshold levels (from most to least restrictive):
454
454
  - `BLOCK_ONLY_HIGH`
455
455
  - `BLOCK_NONE`
456
456
 
457
+ ## Code Execution
458
+
459
+ Generate and run Python code to solve problems or analyze data:
460
+
461
+ ```ruby
462
+ require 'geminize'
463
+ # Assumes API key is configured via .env
464
+
465
+ # Ask Gemini to solve a problem with code
466
+ response = Geminize.generate_with_code_execution(
467
+ "Calculate the sum of the first 10 prime numbers",
468
+ "gemini-2.0-flash", # Use a model that supports code execution
469
+ { temperature: 0.2 }
470
+ )
471
+
472
+ # Display the response text
473
+ puts "Gemini's explanation:"
474
+ puts response.text
475
+
476
+ # Access the generated code
477
+ if response.has_executable_code?
478
+ puts "\nGenerated Python code:"
479
+ puts response.executable_code.code
480
+ end
481
+
482
+ # Access the code execution result
483
+ if response.has_code_execution_result?
484
+ puts "\nExecution result:"
485
+ puts "Outcome: #{response.code_execution_result.outcome}"
486
+ puts "Output: #{response.code_execution_result.output}"
487
+ end
488
+ ```
489
+
490
+ Code execution is perfect for:
491
+
492
+ - Solving mathematical problems
493
+ - Data analysis and visualization
494
+ - Algorithm implementation
495
+ - Demonstrating programming concepts
496
+
497
+ The model generates Python code, executes it in a secure environment, and returns both the code and its execution results.
498
+
457
499
  ## Streaming Responses
458
500
 
459
501
  Get real-time, token-by-token responses:
@@ -496,6 +538,8 @@ Check out these example applications to see Geminize in action:
496
538
  - [Multimodal Example](examples/multimodal.rb)
497
539
  - [System Instructions Example](examples/system_instructions.rb)
498
540
  - [Models API Example](examples/models_api.rb)
541
+ - [Function Calling Example](examples/function_calling.rb)
542
+ - [Code Execution Example](examples/code_execution.rb)
499
543
 
500
544
  ## Working with Models
501
545
 
@@ -510,7 +554,7 @@ models = Geminize.list_models
510
554
  puts "Available models: #{models.size}"
511
555
 
512
556
  # Get details about a specific model
513
- model = Geminize.get_model("gemini-1.5-pro")
557
+ model = Geminize.get_model("gemini-2.0-flash")
514
558
  puts "Model: #{model.display_name}"
515
559
  puts "Token limits: #{model.input_token_limit} input, #{model.output_token_limit} output"
516
560
 
@@ -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 "==========================================="
@@ -8,7 +8,7 @@ require "json"
8
8
  # Configure the API key
9
9
  Geminize.configure do |config|
10
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
11
+ config.default_model = "gemini-2.0-flash" # Use the latest model that supports function calling
12
12
  end
13
13
 
14
14
  # Define a weather function that can handle a location and unit
@@ -63,7 +63,7 @@ begin
63
63
  {source_type: "file", data: File.join(File.dirname(__FILE__), "ruby.png")}, # Use relative path from script
64
64
  {source_type: "file", data: File.join(File.dirname(__FILE__), "ruby.png")} # Use relative path from script
65
65
  ],
66
- "gemini-1.5-pro-latest", # Explicitly specify model
66
+ "gemini-2.0-flash", # Explicitly specify model
67
67
  max_tokens: 500
68
68
  )
69
69
 
@@ -106,7 +106,7 @@ begin
106
106
  # Create a content request
107
107
  request = Geminize::Models::ContentRequest.new(
108
108
  "Tell me about these images:",
109
- "gemini-1.5-pro-latest",
109
+ "gemini-2.0-flash",
110
110
  temperature: 0.3,
111
111
  max_tokens: 800
112
112
  )
@@ -7,7 +7,7 @@ require "geminize"
7
7
  # Configure the API key
8
8
  Geminize.configure do |config|
9
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
10
+ config.default_model = "gemini-2.0-flash" # Use the latest model
11
11
  end
12
12
 
13
13
  # A prompt that might trigger safety filters
@@ -104,7 +104,7 @@ module Geminize
104
104
  # @return [Geminize::Models::Model] The model information
105
105
  # @raise [Geminize::GeminizeError] If the request fails or model is not found
106
106
  def get_model(model_name, force_refresh: false)
107
- # Handle both formats: "models/gemini-1.5-pro" or just "gemini-1.5-pro"
107
+ # Handle both formats: "models/gemini-2.0-flash" or just "gemini-2.0-flash"
108
108
  unless model_name.start_with?("models/")
109
109
  model_name = "models/#{model_name}"
110
110
  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
@@ -31,6 +31,14 @@ module Geminize
31
31
  self
32
32
  end
33
33
 
34
+ # Enable code execution for the request
35
+ # @return [self] The request object for chaining
36
+ def enable_code_execution
37
+ @tools ||= []
38
+ @tools << Tool.new(nil, true)
39
+ self
40
+ end
41
+
34
42
  # Set the tool config for function execution
35
43
  # @param execution_mode [String] The execution mode for functions ("AUTO", "MANUAL", or "NONE")
36
44
  # @return [self] The request object for chaining