geminize 0.1.0 → 1.0.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.
@@ -8,7 +8,8 @@ Geminize.configure do |config|
8
8
  config.api_key = ENV["GEMINI_API_KEY"] || "your-api-key-here"
9
9
 
10
10
  # Specify the model to use (optional)
11
- config.default_model = "gemini-2.0-flash" # This model supports multimodal inputs
11
+ # Use a model that supports multimodal input, like gemini-1.5-flash-latest
12
+ config.default_model = "gemini-1.5-flash-latest"
12
13
  end
13
14
 
14
15
  puts "============================================================"
@@ -19,7 +20,7 @@ begin
19
20
  # Generate content with an image from a file
20
21
  response = Geminize.generate_text_multimodal(
21
22
  "Describe this image in detail:",
22
- [{source_type: "file", data: "path/to/image.jpg"}]
23
+ [{source_type: "file", data: File.join(File.dirname(__FILE__), "ruby.png")}] # Use relative path from script
23
24
  )
24
25
 
25
26
  puts "Response:"
@@ -27,7 +28,7 @@ begin
27
28
  puts "\nFinish reason: #{response.finish_reason}"
28
29
  rescue => e
29
30
  puts "Error: #{e.message}"
30
- puts "Make sure to update the image path to a real image on your system."
31
+ puts "Make sure the path './ruby.png' is correct relative to the project root."
31
32
  end
32
33
 
33
34
  puts "\n============================================================"
@@ -38,7 +39,7 @@ begin
38
39
  # Generate content with an image from a URL
39
40
  response = Geminize.generate_text_multimodal(
40
41
  "What's in this image?",
41
- [{source_type: "url", data: "https://example.com/sample-image.jpg"}],
42
+ [{source_type: "url", data: "https://miro.medium.com/v2/resize:fit:720/format:webp/1*zkA1cWgJDlMUxI5TRcIHdQ.jpeg"}], # Updated URL
42
43
  nil, # Use default model
43
44
  temperature: 0.7
44
45
  )
@@ -47,7 +48,7 @@ begin
47
48
  puts response.text
48
49
  rescue => e
49
50
  puts "Error: #{e.message}"
50
- puts "Make sure to use a valid image URL."
51
+ puts "Make sure the URL is valid and accessible."
51
52
  end
52
53
 
53
54
  puts "\n============================================================"
@@ -55,12 +56,12 @@ puts "Example 3: Multiple images comparison"
55
56
  puts "============================================================"
56
57
 
57
58
  begin
58
- # Generate content comparing multiple images
59
+ # Generate content comparing multiple images (using the same image twice here for simplicity)
59
60
  response = Geminize.generate_text_multimodal(
60
- "Compare these two images and describe the differences:",
61
+ "Compare these two images and describe the differences (they might be the same):",
61
62
  [
62
- {source_type: "file", data: "path/to/image1.jpg"},
63
- {source_type: "file", data: "path/to/image2.jpg"}
63
+ {source_type: "file", data: File.join(File.dirname(__FILE__), "ruby.png")}, # Use relative path from script
64
+ {source_type: "file", data: File.join(File.dirname(__FILE__), "ruby.png")} # Use relative path from script
64
65
  ],
65
66
  "gemini-1.5-pro-latest", # Explicitly specify model
66
67
  max_tokens: 500
@@ -70,7 +71,7 @@ begin
70
71
  puts response.text
71
72
  rescue => e
72
73
  puts "Error: #{e.message}"
73
- puts "Make sure to update the image paths to real images on your system."
74
+ puts "Make sure the path './ruby.png' is correct."
74
75
  end
75
76
 
76
77
  puts "\n============================================================"
@@ -79,19 +80,19 @@ puts "============================================================"
79
80
 
80
81
  begin
81
82
  # Read image directly into bytes
82
- image_bytes = File.binread("path/to/image.jpg")
83
+ image_bytes = File.binread(File.join(File.dirname(__FILE__), "ruby.png")) # Use relative path from script
83
84
 
84
85
  # Generate content with raw image bytes
85
86
  response = Geminize.generate_text_multimodal(
86
87
  "Analyze this image:",
87
- [{source_type: "bytes", data: image_bytes, mime_type: "image/jpeg"}]
88
+ [{source_type: "bytes", data: image_bytes, mime_type: "image/png"}] # Updated MIME type
88
89
  )
89
90
 
90
91
  puts "Response for raw bytes input:"
91
92
  puts response.text
92
93
  rescue => e
93
94
  puts "Error: #{e.message}"
94
- puts "Make sure to update the image path to a real image on your system."
95
+ puts "Make sure the path './ruby.png' is correct."
95
96
  end
96
97
 
97
98
  puts "\n============================================================"
@@ -111,16 +112,22 @@ begin
111
112
  )
112
113
 
113
114
  # Add multiple images using different methods
114
- request.add_image_from_file("path/to/image1.jpg")
115
- request.add_image_from_url("https://example.com/image2.jpg")
115
+ request.add_image_from_file(File.join(File.dirname(__FILE__), "ruby.png")) # Use relative path from script
116
+ request.add_image_from_url("https://miro.medium.com/v2/resize:fit:720/format:webp/1*zkA1cWgJDlMUxI5TRcIHdQ.jpeg") # Updated URL
116
117
 
117
118
  # Generate the response
118
119
  response = generator.generate(request)
119
120
 
120
121
  puts "Response using ContentRequest directly:"
121
122
  puts response.text
122
- puts "\nUsed #{response.usage.total_tokens} tokens total"
123
+
124
+ # Check if usage data is available before accessing it
125
+ if response.usage&.total_tokens
126
+ puts "\nUsed #{response.usage.total_tokens} tokens total"
127
+ else
128
+ puts "\nUsage data not available in the response."
129
+ end
123
130
  rescue => e
124
131
  puts "Error: #{e.message}"
125
- puts "Make sure to update the paths to real images."
132
+ puts "Make sure paths and URLs are valid."
126
133
  end
data/examples/ruby.png ADDED
Binary file
@@ -211,30 +211,31 @@ module Geminize
211
211
  # Convert the request to a hash suitable for the API
212
212
  # @return [Hash] The request as a hash
213
213
  def to_hash
214
- request = if multimodal?
215
- {
216
- contents: [
217
- {
218
- parts: @content_parts
219
- }
220
- ],
221
- generationConfig: generation_config
222
- }.compact
223
- else
224
- # Keep backward compatibility for text-only requests
225
- {
226
- contents: [
227
- {
228
- parts: [
229
- {
230
- text: @prompt
231
- }
232
- ]
214
+ # Map content_parts to the structure the API expects
215
+ api_parts = @content_parts.map do |part|
216
+ if part[:type] == "text"
217
+ {text: part[:text]}
218
+ elsif part[:type] == "image"
219
+ {
220
+ inlineData: {
221
+ mimeType: part[:mime_type],
222
+ data: part[:data]
233
223
  }
234
- ],
235
- generationConfig: generation_config
236
- }.compact
237
- end
224
+ }
225
+ else
226
+ # Handle potential future types or raise error
227
+ nil # Or raise an error for unknown part types
228
+ end
229
+ end.compact # Remove any nil parts from unknown types
230
+
231
+ request = {
232
+ contents: [
233
+ {
234
+ parts: api_parts # Use the correctly formatted parts
235
+ }
236
+ ],
237
+ generationConfig: generation_config
238
+ }.compact
238
239
 
239
240
  # Add system_instruction if provided
240
241
  if @system_instruction
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Geminize
4
- VERSION = "0.1.0"
4
+ VERSION = "1.0.0"
5
5
  end
data/lib/geminize.rb CHANGED
@@ -37,9 +37,6 @@ require_relative "geminize/conversation_repository"
37
37
  require_relative "geminize/conversation_service"
38
38
  require_relative "geminize/model_info"
39
39
 
40
- # Conditionally load Rails integration if Rails is defined
41
- require_relative "geminize/rails" if defined?(::Rails)
42
-
43
40
  # Main module for the Geminize gem
44
41
  module Geminize
45
42
  class Error < StandardError; end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geminize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nhat Long Nguyen
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-05-01 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: faraday
@@ -123,8 +123,7 @@ dependencies:
123
123
  version: '2.8'
124
124
  description: A convenient and robust Ruby interface for the Google Gemini API, enabling
125
125
  easy integration of powerful generative AI models into your applications. Includes
126
- support for text generation, chat conversations, embeddings, multimodal content,
127
- and Rails integration.
126
+ support for text generation, chat conversations, embeddings, multimodal content.
128
127
  email:
129
128
  - nhatlongnguyen1992@gmail.com
130
129
  executables: []
@@ -144,11 +143,7 @@ files:
144
143
  - examples/configuration.rb
145
144
  - examples/embeddings.rb
146
145
  - examples/multimodal.rb
147
- - examples/rails_chat/README.md
148
- - examples/rails_chat/app/controllers/chat_controller.rb
149
- - examples/rails_chat/app/views/chat/index.html.erb
150
- - examples/rails_chat/config/routes.rb
151
- - examples/rails_initializer.rb
146
+ - examples/ruby.png
152
147
  - examples/system_instructions.rb
153
148
  - lib/geminize.rb
154
149
  - lib/geminize/chat.rb
@@ -174,21 +169,11 @@ files:
174
169
  - lib/geminize/models/model.rb
175
170
  - lib/geminize/models/model_list.rb
176
171
  - lib/geminize/models/stream_response.rb
177
- - lib/geminize/rails.rb
178
- - lib/geminize/rails/app/controllers/concerns/geminize/controller.rb
179
- - lib/geminize/rails/app/helpers/geminize_helper.rb
180
- - lib/geminize/rails/controller_additions.rb
181
- - lib/geminize/rails/engine.rb
182
- - lib/geminize/rails/helper_additions.rb
183
- - lib/geminize/railtie.rb
184
172
  - lib/geminize/request_builder.rb
185
173
  - lib/geminize/text_generation.rb
186
174
  - lib/geminize/validators.rb
187
175
  - lib/geminize/vector_utils.rb
188
176
  - lib/geminize/version.rb
189
- - lib/generators/geminize/install_generator.rb
190
- - lib/generators/geminize/templates/README
191
- - lib/generators/geminize/templates/initializer.rb
192
177
  - sig/geminize.rbs
193
178
  homepage: https://github.com/nhlongnguyen/geminize
194
179
  licenses:
@@ -212,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
197
  - !ruby/object:Gem::Version
213
198
  version: '0'
214
199
  requirements: []
215
- rubygems_version: 3.6.2
200
+ rubygems_version: 3.6.8
216
201
  specification_version: 4
217
202
  summary: Ruby interface for Google's Gemini AI API
218
203
  test_files: []
@@ -1,69 +0,0 @@
1
- # Rails Chat Example
2
-
3
- This is a basic example of how to implement a chat application with the Geminize gem in a Rails application.
4
-
5
- ## Features
6
-
7
- - Chat interface with Google's Gemini AI
8
- - Conversation memory between requests using Rails session
9
- - Support for Turbo and JSON responses
10
- - Reset conversation functionality
11
-
12
- ## Implementation
13
-
14
- This example demonstrates:
15
-
16
- 1. How to include Geminize controller concerns
17
- 2. How to use Geminize view helpers
18
- 3. How to maintain conversation state in a Rails application
19
-
20
- ## File Structure
21
-
22
- - `app/controllers/chat_controller.rb` - Controller with Geminize integration
23
- - `app/views/chat/index.html.erb` - Chat interface view
24
- - `config/routes.rb` - Routes configuration
25
-
26
- ## Setup in Your Application
27
-
28
- 1. Add Geminize to your Gemfile:
29
-
30
- ```ruby
31
- gem 'geminize'
32
- ```
33
-
34
- 2. Run the installer:
35
-
36
- ```bash
37
- rails generate geminize:install
38
- ```
39
-
40
- 3. Configure your API key in `config/initializers/geminize.rb`
41
-
42
- 4. Include the Geminize helpers in your `ApplicationHelper`
43
-
44
- ```ruby
45
- module ApplicationHelper
46
- geminize_helper
47
- end
48
- ```
49
-
50
- 5. Create your controller with Geminize support
51
-
52
- ```ruby
53
- class YourChatController < ApplicationController
54
- geminize_controller
55
-
56
- # ... your controller actions
57
- end
58
- ```
59
-
60
- 6. Use the helper methods in your views
61
-
62
- ```erb
63
- <%= render_gemini_conversation %>
64
- <%= gemini_chat_form %>
65
- ```
66
-
67
- ## Styling
68
-
69
- This example includes basic CSS to style the chat interface. Feel free to customize it to match your application's design.
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ChatController < ApplicationController
4
- # Include Geminize controller functionality
5
- geminize_controller
6
-
7
- def index
8
- # Reset conversation if requested
9
- reset_gemini_conversation("Chat with Gemini") if params[:reset]
10
- end
11
-
12
- def create
13
- @response = send_gemini_message(params[:message])
14
-
15
- respond_to do |format|
16
- format.html { redirect_to chat_path }
17
- format.turbo_stream
18
- format.json { render json: {message: @response.text} }
19
- end
20
- end
21
-
22
- def reset
23
- reset_gemini_conversation("New Chat Session")
24
- redirect_to chat_path, notice: "Started a new conversation"
25
- end
26
- end
@@ -1,112 +0,0 @@
1
- <%# Chat index view %>
2
- <div class="chat-container">
3
- <div class="chat-header">
4
- <h1>Chat with Gemini</h1>
5
- <%= link_to "Start New Chat", reset_chat_path, class: "new-chat-button", data: { turbo_method: :post } %>
6
- </div>
7
-
8
- <div class="conversation-container">
9
- <div class="conversation">
10
- <%= render_gemini_conversation(nil, include_timestamps: true) %>
11
- </div>
12
- </div>
13
-
14
- <div class="chat-form-container">
15
- <%= gemini_chat_form(
16
- placeholder: "Ask me anything...",
17
- submit_text: "Send",
18
- form_class: "chat-form",
19
- input_class: "chat-input",
20
- submit_class: "chat-submit"
21
- ) %>
22
- </div>
23
- </div>
24
-
25
- <% content_for :styles do %>
26
- <style>
27
- .chat-container {
28
- max-width: 800px;
29
- margin: 0 auto;
30
- padding: 20px;
31
- font-family: system-ui, -apple-system, sans-serif;
32
- }
33
-
34
- .chat-header {
35
- display: flex;
36
- justify-content: space-between;
37
- align-items: center;
38
- margin-bottom: 20px;
39
- }
40
-
41
- .new-chat-button {
42
- background: #6200ee;
43
- color: white;
44
- padding: 8px 16px;
45
- border-radius: 4px;
46
- text-decoration: none;
47
- }
48
-
49
- .conversation-container {
50
- height: 400px;
51
- overflow-y: auto;
52
- border: 1px solid #e0e0e0;
53
- border-radius: 8px;
54
- margin-bottom: 20px;
55
- padding: 16px;
56
- background: #f8f9fa;
57
- }
58
-
59
- .gemini-message {
60
- margin-bottom: 16px;
61
- padding: 12px;
62
- border-radius: 8px;
63
- }
64
-
65
- .gemini-user-message {
66
- background: #e3f2fd;
67
- margin-left: 20px;
68
- }
69
-
70
- .gemini-ai-message {
71
- background: #f1f3f4;
72
- margin-right: 20px;
73
- }
74
-
75
- .gemini-message-role {
76
- font-weight: bold;
77
- margin-bottom: 8px;
78
- }
79
-
80
- .gemini-message-timestamp {
81
- font-size: 0.8em;
82
- color: #666;
83
- margin-top: 8px;
84
- text-align: right;
85
- }
86
-
87
- .chat-form {
88
- display: flex;
89
- gap: 8px;
90
- }
91
-
92
- .chat-input {
93
- flex: 1;
94
- padding: 12px;
95
- border: 1px solid #e0e0e0;
96
- border-radius: 4px;
97
- font-family: inherit;
98
- resize: none;
99
- height: 80px;
100
- }
101
-
102
- .chat-submit {
103
- background: #6200ee;
104
- color: white;
105
- border: none;
106
- padding: 12px 24px;
107
- border-radius: 4px;
108
- cursor: pointer;
109
- align-self: flex-end;
110
- }
111
- </style>
112
- <% end %>
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Rails.application.routes.draw do
4
- # Chat routes
5
- get "chat", to: "chat#index"
6
- post "chat", to: "chat#create"
7
- post "chat/reset", to: "chat#reset", as: :reset_chat
8
- end
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # config/initializers/geminize.rb
4
-
5
- # This is an example of how to configure the Geminize gem in a Rails application.
6
- # Place this file in your config/initializers directory.
7
-
8
- # Configure the Geminize gem with your API key and any other settings
9
- Geminize.configure do |config|
10
- # Required settings
11
-
12
- # Get the API key from environment variables (recommended approach)
13
- # config.api_key = ENV["GEMINI_API_KEY"]
14
-
15
- # Or set it directly (not recommended for production)
16
- config.api_key = "your-api-key-here"
17
-
18
- # Optional settings with defaults
19
-
20
- # API version to use
21
- config.api_version = "v1beta"
22
-
23
- # Default model to use when not specified in requests
24
- config.default_model = "gemini-1.5-pro-latest"
25
-
26
- # Request timeout in seconds
27
- config.timeout = 30
28
-
29
- # Connection open timeout in seconds
30
- config.open_timeout = 10
31
-
32
- # Enable request logging for development/debugging
33
- # In production, keep this false unless debugging an issue
34
- config.log_requests = Rails.env.development?
35
- end
36
-
37
- # Optionally validate the configuration during app initialization
38
- # This will raise Geminize::ConfigurationError if the configuration is invalid
39
- begin
40
- Geminize.validate_configuration!
41
- Rails.logger.info "Geminize configured successfully"
42
- rescue Geminize::ConfigurationError => e
43
- Rails.logger.error "Geminize configuration error: #{e.message}"
44
- # You might want to raise the error in development but not in production
45
- raise e if Rails.env.development?
46
- end
@@ -1,105 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Geminize
4
- # Controller concern for including Gemini functionality in Rails controllers
5
- module Controller
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- # Helper methods for controllers using Geminize
10
- helper_method :current_gemini_conversation if respond_to?(:helper_method)
11
- end
12
-
13
- # Current conversation for this controller context
14
- # Uses session to maintain conversation state between requests
15
- # @return [Geminize::Models::Conversation]
16
- def current_gemini_conversation
17
- return @current_gemini_conversation if defined?(@current_gemini_conversation)
18
-
19
- if session[:gemini_conversation_id]
20
- # Try to load existing conversation
21
- begin
22
- @current_gemini_conversation = Geminize.load_conversation(session[:gemini_conversation_id])
23
- rescue => e
24
- Rails.logger.error("Failed to load Gemini conversation: #{e.message}")
25
- # Create a new conversation if loading fails
26
- create_new_gemini_conversation
27
- end
28
- else
29
- # Create a new conversation if one doesn't exist
30
- create_new_gemini_conversation
31
- end
32
-
33
- @current_gemini_conversation
34
- end
35
-
36
- # Send a message in the current conversation
37
- # @param message [String] The message to send
38
- # @param model_name [String, nil] Optional model name override
39
- # @param params [Hash] Additional parameters for the message
40
- # @return [Geminize::Models::ChatResponse] The response
41
- def send_gemini_message(message, model_name = nil, params = {})
42
- response = Geminize.chat(message, current_gemini_conversation, model_name, params)
43
- Geminize.save_conversation(current_gemini_conversation)
44
- response
45
- end
46
-
47
- # Generate text using Gemini
48
- # @param prompt [String] The prompt to send
49
- # @param model_name [String, nil] Optional model name override
50
- # @param params [Hash] Additional parameters for generation
51
- # @return [Geminize::Models::ContentResponse] The response
52
- def generate_gemini_text(prompt, model_name = nil, params = {})
53
- Geminize.generate_text(prompt, model_name, params)
54
- end
55
-
56
- # Generate text with images using Gemini
57
- # @param prompt [String] The prompt to send
58
- # @param images [Array<Hash>] Array of image data
59
- # @param model_name [String, nil] Optional model name override
60
- # @param params [Hash] Additional parameters for generation
61
- # @return [Geminize::Models::ContentResponse] The response
62
- def generate_gemini_multimodal(prompt, images, model_name = nil, params = {})
63
- Geminize.generate_text_multimodal(prompt, images, model_name, params)
64
- end
65
-
66
- # Generate embeddings for text using Gemini
67
- # @param text [String, Array<String>] The text to embed
68
- # @param model_name [String, nil] Optional model name override
69
- # @param params [Hash] Additional parameters for embedding
70
- # @return [Geminize::Models::EmbeddingResponse] The embedding response
71
- def generate_gemini_embedding(text, model_name = nil, params = {})
72
- Geminize.generate_embedding(text, model_name, params)
73
- end
74
-
75
- # Start a new conversation and store its ID in the session
76
- # @param title [String, nil] Optional title for the conversation
77
- # @param system_instruction [String, nil] Optional system instruction to guide model behavior
78
- # @return [Geminize::Models::Conversation] The new conversation
79
- def reset_gemini_conversation(title = nil, system_instruction = nil)
80
- create_new_gemini_conversation(title, system_instruction)
81
- end
82
-
83
- # Set the system instruction for the current conversation
84
- # @param system_instruction [String] The system instruction to set
85
- # @return [Geminize::Models::Conversation] The updated conversation
86
- def set_gemini_system_instruction(system_instruction)
87
- current_gemini_conversation.system_instruction = system_instruction
88
- Geminize.save_conversation(current_gemini_conversation)
89
- current_gemini_conversation
90
- end
91
-
92
- private
93
-
94
- # Create a new conversation and store its ID in the session
95
- # @param title [String, nil] Optional title for the conversation
96
- # @param system_instruction [String, nil] Optional system instruction to guide model behavior
97
- # @return [Geminize::Models::Conversation] The new conversation
98
- def create_new_gemini_conversation(title = nil, system_instruction = nil)
99
- @current_gemini_conversation = Geminize.create_chat(title, system_instruction)
100
- session[:gemini_conversation_id] = @current_gemini_conversation.id
101
- Geminize.save_conversation(@current_gemini_conversation)
102
- @current_gemini_conversation
103
- end
104
- end
105
- end