geminize 0.1.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 +7 -0
- data/.rspec +3 -0
- data/.standard.yml +3 -0
- data/.yardopts +14 -0
- data/CHANGELOG.md +24 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/CONTRIBUTING.md +109 -0
- data/LICENSE.txt +21 -0
- data/README.md +423 -0
- data/Rakefile +10 -0
- data/examples/README.md +75 -0
- data/examples/configuration.rb +58 -0
- data/examples/embeddings.rb +195 -0
- data/examples/multimodal.rb +126 -0
- data/examples/rails_chat/README.md +69 -0
- data/examples/rails_chat/app/controllers/chat_controller.rb +26 -0
- data/examples/rails_chat/app/views/chat/index.html.erb +112 -0
- data/examples/rails_chat/config/routes.rb +8 -0
- data/examples/rails_initializer.rb +46 -0
- data/examples/system_instructions.rb +101 -0
- data/lib/geminize/chat.rb +98 -0
- data/lib/geminize/client.rb +318 -0
- data/lib/geminize/configuration.rb +98 -0
- data/lib/geminize/conversation_repository.rb +161 -0
- data/lib/geminize/conversation_service.rb +126 -0
- data/lib/geminize/embeddings.rb +145 -0
- data/lib/geminize/error_mapper.rb +96 -0
- data/lib/geminize/error_parser.rb +120 -0
- data/lib/geminize/errors.rb +185 -0
- data/lib/geminize/middleware/error_handler.rb +72 -0
- data/lib/geminize/model_info.rb +91 -0
- data/lib/geminize/models/chat_request.rb +186 -0
- data/lib/geminize/models/chat_response.rb +118 -0
- data/lib/geminize/models/content_request.rb +530 -0
- data/lib/geminize/models/content_response.rb +99 -0
- data/lib/geminize/models/conversation.rb +156 -0
- data/lib/geminize/models/embedding_request.rb +222 -0
- data/lib/geminize/models/embedding_response.rb +1064 -0
- data/lib/geminize/models/memory.rb +88 -0
- data/lib/geminize/models/message.rb +140 -0
- data/lib/geminize/models/model.rb +171 -0
- data/lib/geminize/models/model_list.rb +124 -0
- data/lib/geminize/models/stream_response.rb +99 -0
- data/lib/geminize/rails/app/controllers/concerns/geminize/controller.rb +105 -0
- data/lib/geminize/rails/app/helpers/geminize_helper.rb +125 -0
- data/lib/geminize/rails/controller_additions.rb +41 -0
- data/lib/geminize/rails/engine.rb +29 -0
- data/lib/geminize/rails/helper_additions.rb +37 -0
- data/lib/geminize/rails.rb +50 -0
- data/lib/geminize/railtie.rb +33 -0
- data/lib/geminize/request_builder.rb +57 -0
- data/lib/geminize/text_generation.rb +285 -0
- data/lib/geminize/validators.rb +150 -0
- data/lib/geminize/vector_utils.rb +164 -0
- data/lib/geminize/version.rb +5 -0
- data/lib/geminize.rb +527 -0
- data/lib/generators/geminize/install_generator.rb +22 -0
- data/lib/generators/geminize/templates/README +31 -0
- data/lib/generators/geminize/templates/initializer.rb +38 -0
- data/sig/geminize.rbs +4 -0
- metadata +218 -0
@@ -0,0 +1,195 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "geminize"
|
5
|
+
|
6
|
+
# This example demonstrates how to use the Geminize embedding API
|
7
|
+
# to generate vector embeddings for text
|
8
|
+
|
9
|
+
# Configure with your API key
|
10
|
+
Geminize.configure do |config|
|
11
|
+
# Use environment variable or set directly
|
12
|
+
config.api_key = ENV["GEMINI_API_KEY"] || "your-api-key-here"
|
13
|
+
|
14
|
+
# Optional: Set a default embedding model
|
15
|
+
config.default_embedding_model = "text-embedding-004"
|
16
|
+
end
|
17
|
+
|
18
|
+
puts "============================================================"
|
19
|
+
puts "Example 1: Generate embedding for a single text"
|
20
|
+
puts "============================================================"
|
21
|
+
|
22
|
+
begin
|
23
|
+
# Generate embedding for a single text
|
24
|
+
text = "What is the meaning of life?"
|
25
|
+
response = Geminize.generate_embedding(text)
|
26
|
+
|
27
|
+
puts "Generated embedding with #{response.embedding_size} dimensions"
|
28
|
+
puts "First 5 values: #{response.embedding.take(5).inspect}"
|
29
|
+
puts "Total tokens: #{response.total_tokens}"
|
30
|
+
rescue => e
|
31
|
+
puts "Error: #{e.message}"
|
32
|
+
end
|
33
|
+
|
34
|
+
puts "\n============================================================"
|
35
|
+
puts "Example 2: Generate embeddings for multiple texts"
|
36
|
+
puts "============================================================"
|
37
|
+
|
38
|
+
begin
|
39
|
+
# Generate embeddings for multiple texts in a single API call
|
40
|
+
texts = [
|
41
|
+
"What is the meaning of life?",
|
42
|
+
"How much wood would a woodchuck chuck?",
|
43
|
+
"How does the brain work?"
|
44
|
+
]
|
45
|
+
|
46
|
+
response = Geminize.generate_embedding(texts)
|
47
|
+
|
48
|
+
puts "Generated #{response.batch_size} embeddings, each with #{response.embedding_size} dimensions"
|
49
|
+
|
50
|
+
# Access individual embeddings
|
51
|
+
texts.each_with_index do |text, i|
|
52
|
+
puts "\nText: \"#{text}\""
|
53
|
+
puts "First 5 values: #{response.embedding_at(i).take(5).inspect}"
|
54
|
+
end
|
55
|
+
|
56
|
+
puts "\nTotal tokens: #{response.total_tokens}"
|
57
|
+
rescue => e
|
58
|
+
puts "Error: #{e.message}"
|
59
|
+
end
|
60
|
+
|
61
|
+
puts "\n============================================================"
|
62
|
+
puts "Example 3: Generate embeddings with task type and dimensions"
|
63
|
+
puts "============================================================"
|
64
|
+
|
65
|
+
begin
|
66
|
+
text = "This is a sample text for similarity comparison"
|
67
|
+
|
68
|
+
# Generate with specific task type for better performance
|
69
|
+
response = Geminize.generate_embedding(
|
70
|
+
text,
|
71
|
+
"text-embedding-004", # You can specify a model explicitly
|
72
|
+
task_type: "SEMANTIC_SIMILARITY", # Optimize for similarity comparisons
|
73
|
+
dimensions: 768 # Request specific dimensions (if supported by model)
|
74
|
+
)
|
75
|
+
|
76
|
+
puts "Generated embedding optimized for SEMANTIC_SIMILARITY"
|
77
|
+
puts "Dimensions: #{response.embedding_size}"
|
78
|
+
puts "First 5 values: #{response.embedding.take(5).inspect}"
|
79
|
+
rescue => e
|
80
|
+
puts "Error: #{e.message}"
|
81
|
+
end
|
82
|
+
|
83
|
+
puts "\n============================================================"
|
84
|
+
puts "Example 4: Batch processing for large arrays"
|
85
|
+
puts "============================================================"
|
86
|
+
|
87
|
+
begin
|
88
|
+
# Create a larger array of texts
|
89
|
+
many_texts = Array.new(120) { |i| "This is sample text number #{i}" }
|
90
|
+
|
91
|
+
# Generate embeddings with automatic batch processing
|
92
|
+
response = Geminize.generate_embedding(
|
93
|
+
many_texts,
|
94
|
+
nil, # Use default model
|
95
|
+
batch_size: 40 # Process in batches of 40 texts each
|
96
|
+
)
|
97
|
+
|
98
|
+
puts "Generated embeddings for #{response.batch_size} texts"
|
99
|
+
puts "First text embedding dimensions: #{response.embedding_size}"
|
100
|
+
puts "Total tokens processed: #{response.total_tokens}"
|
101
|
+
rescue => e
|
102
|
+
puts "Error: #{e.message}"
|
103
|
+
end
|
104
|
+
|
105
|
+
puts "\n============================================================"
|
106
|
+
puts "Example 5: Vector operations with embeddings"
|
107
|
+
puts "============================================================"
|
108
|
+
|
109
|
+
begin
|
110
|
+
# Generate embeddings for two related texts
|
111
|
+
text1 = "Artificial intelligence is changing the world"
|
112
|
+
text2 = "Machine learning technologies are transforming industries"
|
113
|
+
|
114
|
+
response1 = Geminize.generate_embedding(text1)
|
115
|
+
response2 = Geminize.generate_embedding(text2)
|
116
|
+
|
117
|
+
# Calculate cosine similarity
|
118
|
+
similarity = Geminize.cosine_similarity(response1.embedding, response2.embedding)
|
119
|
+
|
120
|
+
puts "Similarity between related texts: #{similarity.round(4)}"
|
121
|
+
|
122
|
+
# Compare with unrelated text
|
123
|
+
text3 = "The quick brown fox jumps over the lazy dog"
|
124
|
+
response3 = Geminize.generate_embedding(text3)
|
125
|
+
|
126
|
+
unrelated_similarity = Geminize.cosine_similarity(response1.embedding, response3.embedding)
|
127
|
+
|
128
|
+
puts "Similarity with unrelated text: #{unrelated_similarity.round(4)}"
|
129
|
+
|
130
|
+
# Calculate average embedding
|
131
|
+
avg_embedding = Geminize.average_vectors([response1.embedding, response2.embedding])
|
132
|
+
puts "Created average embedding vector with #{avg_embedding.size} dimensions"
|
133
|
+
rescue => e
|
134
|
+
puts "Error: #{e.message}"
|
135
|
+
end
|
136
|
+
|
137
|
+
puts "\n============================================================"
|
138
|
+
puts "Example 6: Using different task types for specific use cases"
|
139
|
+
puts "============================================================"
|
140
|
+
|
141
|
+
begin
|
142
|
+
# Sample texts for different use cases
|
143
|
+
question = "What is the capital of France?"
|
144
|
+
code_query = "how to sort an array in javascript"
|
145
|
+
document = "Paris is the capital and most populous city of France, with an estimated population of 2,175,601 residents."
|
146
|
+
fact = "The Earth revolves around the Sun."
|
147
|
+
|
148
|
+
puts "Demonstrating different task types for embeddings:"
|
149
|
+
|
150
|
+
# Question answering
|
151
|
+
qa_response = Geminize.generate_embedding(
|
152
|
+
question,
|
153
|
+
nil, # Use default model
|
154
|
+
task_type: Geminize::Models::EmbeddingRequest::QUESTION_ANSWERING
|
155
|
+
)
|
156
|
+
puts "\n1. QUESTION_ANSWERING task type:"
|
157
|
+
puts " Text: \"#{question}\""
|
158
|
+
puts " First 5 values: #{qa_response.embedding.take(5).inspect}"
|
159
|
+
|
160
|
+
# Code retrieval
|
161
|
+
code_response = Geminize.generate_embedding(
|
162
|
+
code_query,
|
163
|
+
nil, # Use default model
|
164
|
+
task_type: Geminize::Models::EmbeddingRequest::CODE_RETRIEVAL_QUERY
|
165
|
+
)
|
166
|
+
puts "\n2. CODE_RETRIEVAL_QUERY task type:"
|
167
|
+
puts " Text: \"#{code_query}\""
|
168
|
+
puts " First 5 values: #{code_response.embedding.take(5).inspect}"
|
169
|
+
|
170
|
+
# Document retrieval
|
171
|
+
document_response = Geminize.generate_embedding(
|
172
|
+
document,
|
173
|
+
nil, # Use default model
|
174
|
+
task_type: Geminize::Models::EmbeddingRequest::RETRIEVAL_DOCUMENT,
|
175
|
+
title: "Paris Facts" # Titles can be used with RETRIEVAL_DOCUMENT
|
176
|
+
)
|
177
|
+
puts "\n3. RETRIEVAL_DOCUMENT task type with title:"
|
178
|
+
puts " Title: \"Paris Facts\""
|
179
|
+
puts " First 5 values: #{document_response.embedding.take(5).inspect}"
|
180
|
+
|
181
|
+
# Fact verification
|
182
|
+
fact_response = Geminize.generate_embedding(
|
183
|
+
fact,
|
184
|
+
nil, # Use default model
|
185
|
+
task_type: Geminize::Models::EmbeddingRequest::FACT_VERIFICATION
|
186
|
+
)
|
187
|
+
puts "\n4. FACT_VERIFICATION task type:"
|
188
|
+
puts " Text: \"#{fact}\""
|
189
|
+
puts " First 5 values: #{fact_response.embedding.take(5).inspect}"
|
190
|
+
|
191
|
+
puts "\nNote: Different task types optimize the embeddings for different use cases."
|
192
|
+
puts "Choose the appropriate task type based on your application needs."
|
193
|
+
rescue => e
|
194
|
+
puts "Error: #{e.message}"
|
195
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "geminize"
|
4
|
+
|
5
|
+
# Configure with your API key
|
6
|
+
Geminize.configure do |config|
|
7
|
+
# Use environment variable or set directly
|
8
|
+
config.api_key = ENV["GEMINI_API_KEY"] || "your-api-key-here"
|
9
|
+
|
10
|
+
# Specify the model to use (optional)
|
11
|
+
config.default_model = "gemini-2.0-flash" # This model supports multimodal inputs
|
12
|
+
end
|
13
|
+
|
14
|
+
puts "============================================================"
|
15
|
+
puts "Example 1: Basic image and text input using a file path"
|
16
|
+
puts "============================================================"
|
17
|
+
|
18
|
+
begin
|
19
|
+
# Generate content with an image from a file
|
20
|
+
response = Geminize.generate_text_multimodal(
|
21
|
+
"Describe this image in detail:",
|
22
|
+
[{source_type: "file", data: "path/to/image.jpg"}]
|
23
|
+
)
|
24
|
+
|
25
|
+
puts "Response:"
|
26
|
+
puts response.text
|
27
|
+
puts "\nFinish reason: #{response.finish_reason}"
|
28
|
+
rescue => e
|
29
|
+
puts "Error: #{e.message}"
|
30
|
+
puts "Make sure to update the image path to a real image on your system."
|
31
|
+
end
|
32
|
+
|
33
|
+
puts "\n============================================================"
|
34
|
+
puts "Example 2: Using image URL"
|
35
|
+
puts "============================================================"
|
36
|
+
|
37
|
+
begin
|
38
|
+
# Generate content with an image from a URL
|
39
|
+
response = Geminize.generate_text_multimodal(
|
40
|
+
"What's in this image?",
|
41
|
+
[{source_type: "url", data: "https://example.com/sample-image.jpg"}],
|
42
|
+
nil, # Use default model
|
43
|
+
temperature: 0.7
|
44
|
+
)
|
45
|
+
|
46
|
+
puts "Response with temperature=0.7:"
|
47
|
+
puts response.text
|
48
|
+
rescue => e
|
49
|
+
puts "Error: #{e.message}"
|
50
|
+
puts "Make sure to use a valid image URL."
|
51
|
+
end
|
52
|
+
|
53
|
+
puts "\n============================================================"
|
54
|
+
puts "Example 3: Multiple images comparison"
|
55
|
+
puts "============================================================"
|
56
|
+
|
57
|
+
begin
|
58
|
+
# Generate content comparing multiple images
|
59
|
+
response = Geminize.generate_text_multimodal(
|
60
|
+
"Compare these two images and describe the differences:",
|
61
|
+
[
|
62
|
+
{source_type: "file", data: "path/to/image1.jpg"},
|
63
|
+
{source_type: "file", data: "path/to/image2.jpg"}
|
64
|
+
],
|
65
|
+
"gemini-1.5-pro-latest", # Explicitly specify model
|
66
|
+
max_tokens: 500
|
67
|
+
)
|
68
|
+
|
69
|
+
puts "Response (max_tokens=500):"
|
70
|
+
puts response.text
|
71
|
+
rescue => e
|
72
|
+
puts "Error: #{e.message}"
|
73
|
+
puts "Make sure to update the image paths to real images on your system."
|
74
|
+
end
|
75
|
+
|
76
|
+
puts "\n============================================================"
|
77
|
+
puts "Example 4: Using raw image bytes with MIME type"
|
78
|
+
puts "============================================================"
|
79
|
+
|
80
|
+
begin
|
81
|
+
# Read image directly into bytes
|
82
|
+
image_bytes = File.binread("path/to/image.jpg")
|
83
|
+
|
84
|
+
# Generate content with raw image bytes
|
85
|
+
response = Geminize.generate_text_multimodal(
|
86
|
+
"Analyze this image:",
|
87
|
+
[{source_type: "bytes", data: image_bytes, mime_type: "image/jpeg"}]
|
88
|
+
)
|
89
|
+
|
90
|
+
puts "Response for raw bytes input:"
|
91
|
+
puts response.text
|
92
|
+
rescue => e
|
93
|
+
puts "Error: #{e.message}"
|
94
|
+
puts "Make sure to update the image path to a real image on your system."
|
95
|
+
end
|
96
|
+
|
97
|
+
puts "\n============================================================"
|
98
|
+
puts "Example 5: Using ContentRequest directly for more control"
|
99
|
+
puts "============================================================"
|
100
|
+
|
101
|
+
begin
|
102
|
+
# Create a generator
|
103
|
+
generator = Geminize::TextGeneration.new
|
104
|
+
|
105
|
+
# Create a content request
|
106
|
+
request = Geminize::Models::ContentRequest.new(
|
107
|
+
"Tell me about these images:",
|
108
|
+
"gemini-1.5-pro-latest",
|
109
|
+
temperature: 0.3,
|
110
|
+
max_tokens: 800
|
111
|
+
)
|
112
|
+
|
113
|
+
# 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")
|
116
|
+
|
117
|
+
# Generate the response
|
118
|
+
response = generator.generate(request)
|
119
|
+
|
120
|
+
puts "Response using ContentRequest directly:"
|
121
|
+
puts response.text
|
122
|
+
puts "\nUsed #{response.usage.total_tokens} tokens total"
|
123
|
+
rescue => e
|
124
|
+
puts "Error: #{e.message}"
|
125
|
+
puts "Make sure to update the paths to real images."
|
126
|
+
end
|
@@ -0,0 +1,69 @@
|
|
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.
|
@@ -0,0 +1,26 @@
|
|
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
|
@@ -0,0 +1,112 @@
|
|
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 %>
|
@@ -0,0 +1,46 @@
|
|
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
|
@@ -0,0 +1,101 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "geminize"
|
6
|
+
|
7
|
+
# This example demonstrates how to use system instructions with Geminize
|
8
|
+
# System instructions allow you to guide the model's behavior and provide context
|
9
|
+
# that influences all responses.
|
10
|
+
|
11
|
+
# Configure with your API key
|
12
|
+
Geminize.configure do |config|
|
13
|
+
config.api_key = ENV["GOOGLE_AI_API_KEY"] || ENV["GEMINI_API_KEY"]
|
14
|
+
end
|
15
|
+
|
16
|
+
puts "EXAMPLE 1: Basic system instruction with generate_text"
|
17
|
+
puts "====================================================="
|
18
|
+
|
19
|
+
response = Geminize.generate_text(
|
20
|
+
"Tell me about yourself",
|
21
|
+
"gemini-2.0-flash",
|
22
|
+
system_instruction: "You are a cat named Whiskers. Always speak like a cat."
|
23
|
+
)
|
24
|
+
|
25
|
+
puts "Response:\n#{response.text}"
|
26
|
+
puts "\n"
|
27
|
+
|
28
|
+
puts "EXAMPLE 2: Using system instructions with ContentRequest directly"
|
29
|
+
puts "=============================================================="
|
30
|
+
|
31
|
+
request = Geminize::Models::ContentRequest.new(
|
32
|
+
"Explain quantum computing",
|
33
|
+
"gemini-2.0-flash",
|
34
|
+
temperature: 0.7,
|
35
|
+
max_tokens: 150
|
36
|
+
)
|
37
|
+
|
38
|
+
request.system_instruction = "You are a science teacher speaking to a 10-year-old. Use simple language."
|
39
|
+
|
40
|
+
generator = Geminize::TextGeneration.new
|
41
|
+
response = generator.generate(request)
|
42
|
+
|
43
|
+
puts "Response:\n#{response.text}"
|
44
|
+
puts "\n"
|
45
|
+
|
46
|
+
puts "EXAMPLE 3: System instructions with conversation"
|
47
|
+
puts "=============================================="
|
48
|
+
|
49
|
+
# Start a new conversation with a system instruction
|
50
|
+
conversation = Geminize.create_chat("Role-playing Chat")
|
51
|
+
|
52
|
+
# The system instruction guides the entire conversation
|
53
|
+
conversation.set_system_instruction("You are a ship's computer named HAL on a spaceship. Respond in a calm, slightly robotic manner with space-related terminology.")
|
54
|
+
|
55
|
+
# First message
|
56
|
+
response_hash = Geminize.chat("Hello there, who are you?", conversation)
|
57
|
+
puts "Response 1:\n#{response_hash[:response].text}\n"
|
58
|
+
|
59
|
+
# Follow-up
|
60
|
+
response_hash = Geminize.chat("What can you help me with?", conversation)
|
61
|
+
puts "Response 2:\n#{response_hash[:response].text}\n"
|
62
|
+
|
63
|
+
puts "EXAMPLE 4: Streaming with system instructions"
|
64
|
+
puts "==========================================="
|
65
|
+
|
66
|
+
puts "Response:"
|
67
|
+
Geminize.generate_text_stream(
|
68
|
+
"Write a short introduction to a mystery novel",
|
69
|
+
"gemini-2.0-flash",
|
70
|
+
{
|
71
|
+
stream_mode: :delta,
|
72
|
+
max_tokens: 150,
|
73
|
+
system_instruction: "You are a noir detective writer from the 1940s."
|
74
|
+
}
|
75
|
+
) do |chunk|
|
76
|
+
print chunk unless chunk.is_a?(Hash)
|
77
|
+
end
|
78
|
+
|
79
|
+
puts "\n\nEXAMPLE 5: Different personas with system instructions"
|
80
|
+
puts "====================================================="
|
81
|
+
|
82
|
+
personas = [
|
83
|
+
"You are a Victorian-era poet. Use flowery, elaborate language.",
|
84
|
+
"You are a modern tech startup founder. Use buzzwords and be enthusiastic.",
|
85
|
+
"You are a grumpy old professor. Be critical and reference obscure theories."
|
86
|
+
]
|
87
|
+
|
88
|
+
prompt = "What do you think about social media?"
|
89
|
+
|
90
|
+
personas.each_with_index do |persona, i|
|
91
|
+
puts "\nPersona #{i + 1}:"
|
92
|
+
puts "-" * 50
|
93
|
+
response = Geminize.generate_text(
|
94
|
+
prompt,
|
95
|
+
"gemini-2.0-flash",
|
96
|
+
system_instruction: persona,
|
97
|
+
max_tokens: 150
|
98
|
+
)
|
99
|
+
puts response.text
|
100
|
+
puts "-" * 50
|
101
|
+
end
|