geminize 0.1.1 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 276d207ee68fba0c8b4ea894c819254d660cd1c8b520df5d21a6de89d2cf0b25
4
- data.tar.gz: b9447a5ce82b5f10bfda7c09cdd2a658a5d540f1482a741f8ae7651826cce8bd
3
+ metadata.gz: c08ca1105b496592ec06cd7b7aab2b1b9a1dde2cb0f1c31be6feda85281683a2
4
+ data.tar.gz: ae7352a06b607dbd1e98cf30cd069551765156d088513a4cf780f94033d8ab89
5
5
  SHA512:
6
- metadata.gz: 8f0f49ad1678d7edd5e39329ae5dd11749094bdbc4c5fa11676af9c5962a316baf9b96f78967cc159e1de9839ee21bc3693b8e9c5d130eae4bba70fe81e5dcc5
7
- data.tar.gz: bb0b7e7437cbbfeda3b522ab737c9521f78fe2252a6cb8b885bbb34b33bc402230dbb24bc9c761857c005c1d595a7c7aa85fe214a338f53a8a1bc4d6fee4305f
6
+ metadata.gz: 9041ba768b03996f4b2a6fdd9d45dd9a1430298d6d555e54951a9736e24ac713397b1010ffb640bd3a3bcb5b647eb37d15193852e0df31cdfb9bafe6da6a6779
7
+ data.tar.gz: 3a99e5d5a7e2a7b1d3b8ac7d6ca3450a8a54dd4636b614fa53b4e6175e0ead68981ecb7390b00f9d6c7f5f4fd3bcb9bb44e46b84d9e97702cdca7803227fc022
data/CHANGELOG.md CHANGED
@@ -1,4 +1,10 @@
1
- ## [Unreleased]
1
+ ## [1.0.0] - 2025-05-02
2
+
3
+ ### Removed
4
+
5
+ - Removed Rails-related integration from the gem, simplifying usage.
6
+
7
+ ## [0.1.1] - 2025-05-01
2
8
 
3
9
  ### Added
4
10
 
data/README.md CHANGED
@@ -11,7 +11,6 @@ A convenient and robust Ruby interface for the Google Gemini API, enabling easy
11
11
  - Embeddings generation
12
12
  - Support for streaming responses
13
13
  - Comprehensive error handling
14
- - Rails integration with controller concerns and view helpers
15
14
 
16
15
  ## Installation
17
16
 
@@ -311,120 +310,20 @@ end
311
310
  puts "\n" # Add a newline after streaming
312
311
  ```
313
312
 
314
- ## Rails Integration
315
-
316
- Geminize provides seamless integration with Rails applications.
317
-
318
- ### Setup
319
-
320
- 1. Add Geminize to your Gemfile:
321
-
322
- ```ruby
323
- gem 'geminize'
324
- ```
325
-
326
- 2. Run the installer generator:
327
-
328
- ```bash
329
- rails generate geminize:install
330
- ```
331
-
332
- This creates a configuration initializer at `config/initializers/geminize.rb`
333
-
334
- 3. Add your API key to the initializer or via environment variables.
335
-
336
- ### Controller Integration
337
-
338
- In your controllers, include the Geminize controller concern:
339
-
340
- ```ruby
341
- class ChatController < ApplicationController
342
- # Add Geminize functionality to this controller
343
- geminize_controller
344
-
345
- def index
346
- # Optionally reset the conversation
347
- # reset_gemini_conversation("New chat session") if params[:reset]
348
- end
349
-
350
- def create
351
- # Send a message to Gemini and get the response
352
- @response = send_gemini_message(params[:message])
353
-
354
- respond_to do |format|
355
- format.html { redirect_to chat_path }
356
- format.turbo_stream
357
- format.json { render json: { message: @response.text } }
358
- end
359
- end
360
- end
361
- ```
362
-
363
- The concern provides the following methods:
364
-
365
- - `current_gemini_conversation` - Access the current conversation (stored in session)
366
- - `send_gemini_message(message, model_name=nil, params={})` - Send a message in the current conversation
367
- - `generate_gemini_text(prompt, model_name=nil, params={})` - Generate text with Gemini
368
- - `generate_gemini_multimodal(prompt, images, model_name=nil, params={})` - Generate text with images
369
- - `generate_gemini_embedding(text, model_name=nil, params={})` - Generate embeddings
370
- - `reset_gemini_conversation(title=nil)` - Start a new conversation
371
-
372
- ### View Integration
373
-
374
- Include the Geminize view helpers in your application:
375
-
376
- ```ruby
377
- # In app/helpers/application_helper.rb
378
- module ApplicationHelper
379
- # Include Geminize view helpers
380
- geminize_helper
381
- end
382
- ```
383
-
384
- This provides the following helper methods:
385
-
386
- - `render_gemini_conversation(conversation=nil, options={})` - Render the conversation as HTML
387
- - `render_gemini_message(message, options={})` - Render a single message
388
- - `gemini_chat_form(options={})` - Create a chat form
389
- - `markdown_to_html(text, options={})` - Render Markdown as HTML (requires redcarpet gem)
390
- - `highlight_code(html)` - Add syntax highlighting to code blocks (requires rouge gem)
391
-
392
- Example view:
393
-
394
- ```erb
395
- <%# app/views/chat/index.html.erb %>
396
- <div class="chat-container">
397
- <h1>Chat with Gemini</h1>
398
-
399
- <div class="conversation">
400
- <%= render_gemini_conversation %>
401
- </div>
402
-
403
- <div class="chat-form">
404
- <%= gemini_chat_form(placeholder: "Ask me anything...", submit_text: "Send") %>
405
- </div>
406
- </div>
407
- ```
408
-
409
- ## Example Applications
410
-
411
313
  Check out these example applications to see Geminize in action:
412
314
 
413
315
  - [Configuration Example](examples/configuration.rb)
414
316
  - [Embeddings Example](examples/embeddings.rb)
415
317
  - [Multimodal Example](examples/multimodal.rb)
416
- - [Rails Initializer Example](examples/rails_initializer.rb)
417
318
  - [System Instructions Example](examples/system_instructions.rb)
418
- - [Rails Chat Application](examples/rails_chat)
419
319
 
420
320
  ## Compatibility
421
321
 
422
322
  Ruby version: 3.1.0 or later
423
- Rails version: 6.0 or later (for Rails integration)
424
323
 
425
324
  ## Development
426
325
 
427
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
326
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
428
327
 
429
328
  To install this gem onto your local machine, run `bundle exec rake install`.
430
329
 
data/examples/README.md CHANGED
@@ -11,10 +11,9 @@ Before running these examples, ensure you have:
11
11
  3. **Project dependencies installed**: Run `bundle install` from the project root directory (`../`).
12
12
  4. **Google Gemini API Key configured**: Create a `.env` file in the project root (`../`) by copying `.env.example` and adding your API key:
13
13
  ```bash
14
- # In ../.env
15
- GOOGLE_AI_API_KEY=your_api_key_here
14
+ # In .env
15
+ GEMINI_API_KEY=your_api_key_here
16
16
  ```
17
- Alternatively, ensure the `GEMINI_API_KEY` environment variable is set.
18
17
 
19
18
  ## Running Examples
20
19
 
@@ -25,7 +24,7 @@ All examples should be run from the **project root directory** (the directory co
25
24
  Demonstrates different ways to configure the Geminize client.
26
25
 
27
26
  ```bash
28
- ruby examples/configuration.rb
27
+ bundle exec ruby examples/configuration.rb
29
28
  ```
30
29
 
31
30
  ### 2. Embeddings (`embeddings.rb`)
@@ -33,7 +32,7 @@ ruby examples/configuration.rb
33
32
  Shows how to generate text embeddings and calculate cosine similarity.
34
33
 
35
34
  ```bash
36
- ruby examples/embeddings.rb
35
+ bundle exec ruby examples/embeddings.rb
37
36
  ```
38
37
 
39
38
  ### 3. Multimodal (`multimodal.rb`)
@@ -43,33 +42,13 @@ Illustrates sending text and image inputs to the Gemini API.
43
42
  _Note: You may need to update the image file paths within the script (`path/to/image.jpg`) to point to actual image files on your system._
44
43
 
45
44
  ```bash
46
- ruby examples/multimodal.rb
45
+ bundle exec ruby examples/multimodal.rb
47
46
  ```
48
47
 
49
- ### 4. Rails Initializer (`rails_initializer.rb`)
50
-
51
- Shows the configuration structure typically used in a Rails initializer (this script is meant for illustration and doesn't require a Rails app to run).
52
-
53
- ```bash
54
- ruby examples/rails_initializer.rb
55
- ```
56
-
57
- ### 5. System Instructions (`system_instructions.rb`)
48
+ ### 4. System Instructions (`system_instructions.rb`)
58
49
 
59
50
  Demonstrates using system instructions to guide the model's behavior and personality.
60
51
 
61
52
  ```bash
62
- ruby examples/system_instructions.rb
53
+ bundle exec ruby examples/system_instructions.rb
63
54
  ```
64
-
65
- ### 6. Rails Chat Application (`rails_chat/`)
66
-
67
- This directory contains a sample Rails application demonstrating Geminize integration. It requires a separate setup:
68
-
69
- 1. Navigate into the directory: `cd examples/rails_chat`
70
- 2. Install dependencies: `bundle install`
71
- 3. Run database migrations (if applicable): `rails db:migrate`
72
- 4. Start the Rails server: `rails server`
73
- 5. Open your web browser to `http://localhost:3000`
74
-
75
- Refer to the README within the `rails_chat/` directory (if available) for more specific instructions.
@@ -55,7 +55,6 @@ begin
55
55
 
56
56
  puts "\nGenerated #{embeddings.size} embeddings."
57
57
  puts "Total tokens (approximated by summing individual calls): #{total_tokens}"
58
-
59
58
  rescue => e
60
59
  puts "Error: #{e.message}"
61
60
  end
@@ -85,25 +84,24 @@ end
85
84
  puts "\n============================================================"
86
85
  puts "Example 4: Batch processing for large arrays (COMMENTED OUT)"
87
86
  puts "============================================================"
88
- =begin # Commenting out Example 4 due to potential model/API limitations with batching
89
- begin
90
- # Create a larger array of texts
91
- many_texts = Array.new(120) { |i| "This is sample text number #{i}" }
92
-
93
- # Generate embeddings with automatic batch processing
94
- response = Geminize.generate_embedding(
95
- many_texts,
96
- nil, # Use default model
97
- batch_size: 40 # Process in batches of 40 texts each
98
- )
99
-
100
- puts "Generated embeddings for #{response.batch_size} texts"
101
- puts "First text embedding dimensions: #{response.embedding_size}"
102
- puts "Total tokens processed: #{response.total_tokens}"
103
- rescue => e
104
- puts "Error: #{e.message}"
105
- end
106
- =end
87
+ # # Commenting out Example 4 due to potential model/API limitations with batching
88
+ # begin
89
+ # # Create a larger array of texts
90
+ # many_texts = Array.new(120) { |i| "This is sample text number #{i}" }
91
+ #
92
+ # # Generate embeddings with automatic batch processing
93
+ # response = Geminize.generate_embedding(
94
+ # many_texts,
95
+ # nil, # Use default model
96
+ # batch_size: 40 # Process in batches of 40 texts each
97
+ # )
98
+ #
99
+ # puts "Generated embeddings for #{response.batch_size} texts"
100
+ # puts "First text embedding dimensions: #{response.embedding_size}"
101
+ # puts "Total tokens processed: #{response.total_tokens}"
102
+ # rescue => e
103
+ # puts "Error: #{e.message}"
104
+ # end
107
105
  puts "# Example 4 skipped due to potential issues with batch embedding support."
108
106
 
109
107
  puts "\n============================================================"
@@ -20,7 +20,7 @@ begin
20
20
  # Generate content with an image from a file
21
21
  response = Geminize.generate_text_multimodal(
22
22
  "Describe this image in detail:",
23
- [{source_type: "file", data: "./examples/ruby.png"}] # Updated path
23
+ [{source_type: "file", data: File.join(File.dirname(__FILE__), "ruby.png")}] # Use relative path from script
24
24
  )
25
25
 
26
26
  puts "Response:"
@@ -28,7 +28,7 @@ begin
28
28
  puts "\nFinish reason: #{response.finish_reason}"
29
29
  rescue => e
30
30
  puts "Error: #{e.message}"
31
- puts "Make sure the path './examples/ruby.png' is correct relative to the project root."
31
+ puts "Make sure the path './ruby.png' is correct relative to the project root."
32
32
  end
33
33
 
34
34
  puts "\n============================================================"
@@ -60,8 +60,8 @@ begin
60
60
  response = Geminize.generate_text_multimodal(
61
61
  "Compare these two images and describe the differences (they might be the same):",
62
62
  [
63
- {source_type: "file", data: "./examples/ruby.png"}, # Updated path
64
- {source_type: "file", data: "./examples/ruby.png"} # Updated path
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
65
65
  ],
66
66
  "gemini-1.5-pro-latest", # Explicitly specify model
67
67
  max_tokens: 500
@@ -71,7 +71,7 @@ begin
71
71
  puts response.text
72
72
  rescue => e
73
73
  puts "Error: #{e.message}"
74
- puts "Make sure the path './examples/ruby.png' is correct."
74
+ puts "Make sure the path './ruby.png' is correct."
75
75
  end
76
76
 
77
77
  puts "\n============================================================"
@@ -80,7 +80,7 @@ puts "============================================================"
80
80
 
81
81
  begin
82
82
  # Read image directly into bytes
83
- image_bytes = File.binread("./examples/ruby.png") # Updated path
83
+ image_bytes = File.binread(File.join(File.dirname(__FILE__), "ruby.png")) # Use relative path from script
84
84
 
85
85
  # Generate content with raw image bytes
86
86
  response = Geminize.generate_text_multimodal(
@@ -92,7 +92,7 @@ begin
92
92
  puts response.text
93
93
  rescue => e
94
94
  puts "Error: #{e.message}"
95
- puts "Make sure the path './examples/ruby.png' is correct."
95
+ puts "Make sure the path './ruby.png' is correct."
96
96
  end
97
97
 
98
98
  puts "\n============================================================"
@@ -112,7 +112,7 @@ begin
112
112
  )
113
113
 
114
114
  # Add multiple images using different methods
115
- request.add_image_from_file("./examples/ruby.png") # Updated path
115
+ request.add_image_from_file(File.join(File.dirname(__FILE__), "ruby.png")) # Use relative path from script
116
116
  request.add_image_from_url("https://miro.medium.com/v2/resize:fit:720/format:webp/1*zkA1cWgJDlMUxI5TRcIHdQ.jpeg") # Updated URL
117
117
 
118
118
  # Generate the response
@@ -122,7 +122,7 @@ begin
122
122
  puts response.text
123
123
 
124
124
  # Check if usage data is available before accessing it
125
- if response.usage && response.usage.total_tokens
125
+ if response.usage&.total_tokens
126
126
  puts "\nUsed #{response.usage.total_tokens} tokens total"
127
127
  else
128
128
  puts "\nUsage data not available in the response."
@@ -214,7 +214,7 @@ module Geminize
214
214
  # Map content_parts to the structure the API expects
215
215
  api_parts = @content_parts.map do |part|
216
216
  if part[:type] == "text"
217
- { text: part[:text] }
217
+ {text: part[:text]}
218
218
  elsif part[:type] == "image"
219
219
  {
220
220
  inlineData: {
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Geminize
4
- VERSION = "0.1.1"
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,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geminize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nhat Long Nguyen
@@ -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,14 +143,8 @@ 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
152
146
  - examples/ruby.png
153
147
  - examples/system_instructions.rb
154
- - geminize-0.1.0.gem
155
148
  - lib/geminize.rb
156
149
  - lib/geminize/chat.rb
157
150
  - lib/geminize/client.rb
@@ -176,21 +169,11 @@ files:
176
169
  - lib/geminize/models/model.rb
177
170
  - lib/geminize/models/model_list.rb
178
171
  - lib/geminize/models/stream_response.rb
179
- - lib/geminize/rails.rb
180
- - lib/geminize/rails/app/controllers/concerns/geminize/controller.rb
181
- - lib/geminize/rails/app/helpers/geminize_helper.rb
182
- - lib/geminize/rails/controller_additions.rb
183
- - lib/geminize/rails/engine.rb
184
- - lib/geminize/rails/helper_additions.rb
185
- - lib/geminize/railtie.rb
186
172
  - lib/geminize/request_builder.rb
187
173
  - lib/geminize/text_generation.rb
188
174
  - lib/geminize/validators.rb
189
175
  - lib/geminize/vector_utils.rb
190
176
  - lib/geminize/version.rb
191
- - lib/generators/geminize/install_generator.rb
192
- - lib/generators/geminize/templates/README
193
- - lib/generators/geminize/templates/initializer.rb
194
177
  - sig/geminize.rbs
195
178
  homepage: https://github.com/nhlongnguyen/geminize
196
179
  licenses:
@@ -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
data/geminize-0.1.0.gem DELETED
Binary file
@@ -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
@@ -1,125 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GeminizeHelper
4
- # Render the Gemini conversation as HTML
5
- # @param conversation [Geminize::Models::Conversation, nil] Conversation to render (defaults to current_gemini_conversation)
6
- # @param options [Hash] Optional rendering options
7
- # @option options [String] :user_class CSS class for user messages
8
- # @option options [String] :ai_class CSS class for AI messages
9
- # @option options [Boolean] :include_timestamps Include message timestamps
10
- # @return [String] HTML representation of the conversation
11
- def render_gemini_conversation(conversation = nil, options = {})
12
- conversation ||= current_gemini_conversation if respond_to?(:current_gemini_conversation)
13
- return content_tag(:div, "No conversation available", class: "gemini-empty-conversation") unless conversation
14
-
15
- content_tag(:div, class: "gemini-conversation") do
16
- conversation.messages.map do |message|
17
- render_gemini_message(message, options)
18
- end.join.html_safe
19
- end
20
- end
21
-
22
- # Render a single message from the conversation
23
- # @param message [Geminize::Models::Message] The message to render
24
- # @param options [Hash] Optional rendering options
25
- # @return [String] HTML representation of the message
26
- def render_gemini_message(message, options = {})
27
- is_user = message.role == "user"
28
-
29
- message_class = if is_user
30
- options[:user_class] || "gemini-user-message"
31
- else
32
- options[:ai_class] || "gemini-ai-message"
33
- end
34
-
35
- content_tag(:div, class: "gemini-message #{message_class}") do
36
- output = []
37
-
38
- # Add the role label
39
- output << content_tag(:div, is_user ? "You" : "AI", class: "gemini-message-role")
40
-
41
- # Add the message content (convert newlines to <br> tags)
42
- output << content_tag(:div, simple_format(message.parts.first["text"]), class: "gemini-message-content")
43
-
44
- # Add timestamp if requested
45
- if options[:include_timestamps] && message.respond_to?(:timestamp) && message.timestamp
46
- timestamp = message.timestamp.is_a?(Time) ? message.timestamp : Time.parse(message.timestamp.to_s)
47
- output << content_tag(:div, timestamp.strftime("%Y-%m-%d %H:%M:%S"), class: "gemini-message-timestamp")
48
- end
49
-
50
- output.join.html_safe
51
- end
52
- end
53
-
54
- # Create a chat form that handles submitting messages to Gemini
55
- # @param options [Hash] Form options
56
- # @option options [String] :submit_text Text for the submit button (default: "Send")
57
- # @option options [String] :placeholder Placeholder text (default: "Type your message...")
58
- # @option options [String] :form_class CSS class for the form
59
- # @option options [String] :input_class CSS class for the input field
60
- # @option options [String] :submit_class CSS class for the submit button
61
- # @option options [String] :url URL to submit the form to (default: current URL)
62
- # @return [String] HTML form
63
- def gemini_chat_form(options = {})
64
- default_options = {
65
- submit_text: "Send",
66
- placeholder: "Type your message...",
67
- form_class: "gemini-chat-form",
68
- input_class: "gemini-chat-input",
69
- submit_class: "gemini-chat-submit",
70
- url: request.path
71
- }
72
-
73
- opts = default_options.merge(options)
74
-
75
- form_tag(opts[:url], method: :post, class: opts[:form_class]) do
76
- output = []
77
- output << text_area_tag(:message, nil, placeholder: opts[:placeholder], class: opts[:input_class])
78
- output << submit_tag(opts[:submit_text], class: opts[:submit_class])
79
- output.join.html_safe
80
- end
81
- end
82
-
83
- # Render Markdown text as HTML
84
- # @param text [String] Markdown text to render
85
- # @param options [Hash] Options for rendering
86
- # @return [String] HTML content
87
- def markdown_to_html(text, options = {})
88
- return "" if text.blank?
89
-
90
- # Check if the markdown gem is available
91
- if defined?(Redcarpet)
92
- renderer = Redcarpet::Render::HTML.new(hard_wrap: true, filter_html: false)
93
- markdown = Redcarpet::Markdown.new(renderer, options)
94
- markdown.render(text).html_safe
95
- else
96
- # Fall back to simple formatting if Redcarpet is not available
97
- simple_format(text)
98
- end
99
- end
100
-
101
- # Add syntax highlighting to code blocks
102
- # @param html [String] HTML content that may contain code blocks
103
- # @return [String] HTML with syntax highlighting applied
104
- def highlight_code(html)
105
- return html unless defined?(Rouge)
106
-
107
- formatter = Rouge::Formatters::HTML.new
108
-
109
- # Find all code blocks and apply syntax highlighting
110
- doc = Nokogiri::HTML::DocumentFragment.parse(html)
111
- doc.css("pre code").each do |code|
112
- lang = code["class"]&.sub("language-", "") || "text"
113
- lexer = Rouge::Lexer.find(lang) || Rouge::Lexers::PlainText.new
114
-
115
- # Get the code content and format it
116
- code_text = code.text
117
- highlighted = formatter.format(lexer.lex(code_text))
118
-
119
- # Replace the original code block with the highlighted version
120
- code.parent.replace("<pre class=\"highlight #{lang}\">#{highlighted}</pre>")
121
- end
122
-
123
- doc.to_html.html_safe
124
- end
125
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Geminize
4
- module Rails
5
- # Module for adding Geminize functionality to controllers
6
- # Provides methods that make it easy to include Geminize controller concerns.
7
- #
8
- # This module is automatically included in ActionController::Base
9
- # when the gem is used in a Rails application.
10
- #
11
- # @example Including in a specific controller
12
- # class ChatController < ApplicationController
13
- # geminize_controller
14
- #
15
- # def create
16
- # @response = send_gemini_message(params[:message])
17
- # render :show
18
- # end
19
- # end
20
- module ControllerAdditions
21
- # Add Geminize functionality to a controller
22
- # This method includes the Geminize::Controller concern in your controller,
23
- # which provides methods for working with the Gemini API.
24
- #
25
- # @return [void]
26
- # @example
27
- # class ApplicationController < ActionController::Base
28
- # include Geminize::Rails::ControllerAdditions
29
- # geminize_controller
30
- # end
31
- def geminize_controller
32
- include Geminize::Controller
33
- end
34
- end
35
- end
36
- end
37
-
38
- # Add the module to ActionController::Base if it exists
39
- ActiveSupport.on_load(:action_controller) do
40
- include Geminize::Rails::ControllerAdditions
41
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Geminize
4
- module Rails
5
- # Rails engine for Geminize
6
- # Provides Rails integration for the Gemini API.
7
- class Engine < ::Rails::Engine
8
- isolate_namespace Geminize
9
-
10
- initializer "geminize.configure" do |app|
11
- # Set up configuration if needed
12
- end
13
-
14
- initializer "geminize.load_concerns" do
15
- ActiveSupport.on_load(:action_controller) do
16
- require "geminize/rails/app/controllers/concerns/geminize/controller"
17
- end
18
-
19
- ActiveSupport.on_load(:action_view) do
20
- require "geminize/rails/app/helpers/geminize_helper"
21
- end
22
- end
23
-
24
- config.to_prepare do
25
- # Load any dependencies that need to be available
26
- end
27
- end
28
- end
29
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Geminize
4
- module Rails
5
- # Module for adding Geminize view helpers to Rails applications
6
- # Provides methods to simplify the inclusion of Geminize helpers in views.
7
- #
8
- # This module is automatically included in ActionView::Base
9
- # when the gem is used in a Rails application.
10
- #
11
- # @example Using Geminize helpers in a view
12
- # <%# After including the helpers in ApplicationHelper %>
13
- # <%= render_gemini_conversation %>
14
- # <%= gemini_chat_form %>
15
- module HelperAdditions
16
- # Add Geminize helpers to views
17
- # This method includes the GeminizeHelper module in your view context,
18
- # providing helper methods for rendering Gemini conversations, chat forms,
19
- # and formatting responses.
20
- #
21
- # @return [void]
22
- # @example
23
- # module ApplicationHelper
24
- # include Geminize::Rails::HelperAdditions
25
- # geminize_helper
26
- # end
27
- def geminize_helper
28
- include GeminizeHelper
29
- end
30
- end
31
- end
32
- end
33
-
34
- # Add our helpers module to ActionView::Base if it exists
35
- ActiveSupport.on_load(:action_view) do
36
- include Geminize::Rails::HelperAdditions
37
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "geminize/rails/engine" if defined?(::Rails::Engine)
4
- require "geminize/railtie" if defined?(::Rails::Railtie)
5
- require "geminize/rails/controller_additions" if defined?(::ActionController::Base)
6
- require "geminize/rails/helper_additions" if defined?(::ActionView::Base)
7
-
8
- module Geminize
9
- # Rails integration module for Geminize
10
- # Provides Rails integration for the Google Gemini API.
11
- #
12
- # The integration includes:
13
- # - A Rails engine to load all required components
14
- # - Controller concerns with helper methods for Gemini operations
15
- # - View helpers for rendering conversations and responses
16
- # - Generators for creating configuration files
17
- #
18
- # @example Setting up in a Rails application
19
- # # In config/initializers/geminize.rb (created by the generator)
20
- # Geminize.configure do |config|
21
- # config.api_key = ENV.fetch("GEMINI_API_KEY")
22
- # end
23
- #
24
- # # In app/controllers/chat_controller.rb
25
- # class ChatController < ApplicationController
26
- # geminize_controller
27
- #
28
- # def create
29
- # @response = send_gemini_message(params[:message])
30
- # redirect_to chat_path
31
- # end
32
- # end
33
- #
34
- # # In app/views/chat/show.html.erb
35
- # <%= render_gemini_conversation %>
36
- # <%= gemini_chat_form %>
37
- module Rails
38
- # Returns true if running in a Rails environment
39
- # Useful for conditionally executing code only in Rails apps.
40
- #
41
- # @return [Boolean] true if Rails is defined
42
- # @example
43
- # if Geminize::Rails.rails?
44
- # # Rails-specific code
45
- # end
46
- def self.rails?
47
- defined?(::Rails)
48
- end
49
- end
50
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Geminize
4
- # Railtie for lightweight Rails integration
5
- # Provides basic Rails integration when the full engine is not required.
6
- # This is automatically loaded when the gem is used in a Rails application.
7
- #
8
- # @example Basic usage in a Rails application
9
- # # No additional setup needed - Railtie is loaded automatically
10
- # # In your controller:
11
- # class ExamplesController < ApplicationController
12
- # def example
13
- # @response = Geminize.generate_text("What is Ruby on Rails?").text
14
- # end
15
- # end
16
- class Railtie < ::Rails::Railtie
17
- # Configure Geminize when used in a Rails application
18
- # @return [void]
19
- initializer "geminize.configure" do |app|
20
- # Set up configuration for Geminize when used in a Rails app
21
- Geminize.configure do |config|
22
- # Set conversations path to Rails tmp directory by default
23
- config.conversations_path = Rails.root.join("tmp", "conversations") if config.conversations_path.nil?
24
- end
25
- end
26
-
27
- # Set up any rake tasks if needed
28
- # @return [void]
29
- rake_tasks do
30
- # Define rake tasks here if needed
31
- end
32
- end
33
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators/base"
4
-
5
- module Geminize
6
- module Generators
7
- # Generator for installing Geminize Rails integration
8
- # This generator creates an initializer with default configuration
9
- class InstallGenerator < Rails::Generators::Base
10
- source_root File.expand_path("templates", __dir__)
11
- desc "Creates a Geminize initializer for Rails."
12
-
13
- def create_initializer_file
14
- template "initializer.rb", "config/initializers/geminize.rb"
15
- end
16
-
17
- def show_readme
18
- readme "README" if behavior == :invoke
19
- end
20
- end
21
- end
22
- end
@@ -1,31 +0,0 @@
1
- ===============================================================================
2
-
3
- Geminize has been successfully installed!
4
-
5
- A configuration initializer has been created at:
6
- config/initializers/geminize.rb
7
-
8
- You need to edit the initializer and add your Google Gemini API key.
9
- You can get an API key from https://ai.google.dev/
10
-
11
- ===============================================================================
12
-
13
- Usage Examples:
14
-
15
- # Basic text generation
16
- text = Geminize.generate_text("What is Ruby on Rails?").text
17
- puts text
18
-
19
- # Create a chat session
20
- chat = Geminize.create_chat("My Support Chat")
21
- response = Geminize.chat("How can I create a Ruby gem?", chat)
22
- puts response.text
23
-
24
- # Follow-up question (keeps conversation context)
25
- response = Geminize.chat("What about adding a Rails engine to my gem?", chat)
26
- puts response.text
27
-
28
- # For more examples, see the documentation at:
29
- # https://github.com/nhlongnguyen/geminize
30
-
31
- ===============================================================================
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Geminize Configuration
4
- #
5
- # This file contains the configuration for the Geminize gem.
6
- # It is used to set up the Google Gemini API integration.
7
-
8
- Geminize.configure do |config|
9
- # Your Google Gemini API key
10
- # You can get one from https://ai.google.dev/
11
- # Can also be set via GEMINI_API_KEY environment variable
12
- # config.api_key = ENV.fetch("GEMINI_API_KEY", nil)
13
-
14
- # The API version to use (default: v1beta)
15
- # config.api_version = "v1beta"
16
-
17
- # The default model to use (default: gemini-2.0-flash)
18
- # config.default_model = "gemini-2.0-flash"
19
-
20
- # The base URL for the Gemini API (default: https://generativelanguage.googleapis.com)
21
- # config.api_base_url = "https://generativelanguage.googleapis.com"
22
-
23
- # Logging level for Geminize (default: :info)
24
- # Valid values: :debug, :info, :warn, :error, :fatal
25
- # config.log_level = Rails.env.production? ? :info : :debug
26
-
27
- # Where to store conversation data (default: Rails.root.join("tmp", "conversations"))
28
- # Only applicable when using FileConversationRepository
29
- # config.conversations_path = Rails.root.join("tmp", "conversations")
30
-
31
- # Default parameters for text generation
32
- # config.generation_defaults = {
33
- # temperature: 0.7,
34
- # max_tokens: 500,
35
- # top_p: 0.95,
36
- # top_k: 40
37
- # }
38
- end