geminize 0.1.1 → 1.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 +4 -4
- data/.cursor/mcp.json +3 -0
- data/.cursor/rules/isolation_rules/Core/command-execution.mdc +235 -0
- data/.cursor/rules/isolation_rules/Core/complexity-decision-tree.mdc +187 -0
- data/.cursor/rules/isolation_rules/Core/creative-phase-enforcement.mdc +145 -0
- data/.cursor/rules/isolation_rules/Core/creative-phase-metrics.mdc +195 -0
- data/.cursor/rules/isolation_rules/Core/file-verification.mdc +198 -0
- data/.cursor/rules/isolation_rules/Core/platform-awareness.mdc +71 -0
- data/.cursor/rules/isolation_rules/Level3/planning-comprehensive.mdc +159 -0
- data/.cursor/rules/isolation_rules/Level3/task-tracking-intermediate.mdc +135 -0
- data/.cursor/rules/isolation_rules/Phases/CreativePhase/creative-phase-architecture.mdc +187 -0
- data/.cursor/rules/isolation_rules/main.mdc +123 -0
- data/.cursor/rules/isolation_rules/visual-maps/archive-mode-map.mdc +277 -0
- data/.cursor/rules/isolation_rules/visual-maps/creative-mode-map.mdc +224 -0
- data/.cursor/rules/isolation_rules/visual-maps/implement-mode-map.mdc +321 -0
- data/.cursor/rules/isolation_rules/visual-maps/plan-mode-map.mdc +269 -0
- data/.cursor/rules/isolation_rules/visual-maps/qa-mode-map.mdc +495 -0
- data/.cursor/rules/isolation_rules/visual-maps/reflect-mode-map.mdc +234 -0
- data/.cursor/rules/isolation_rules/visual-maps/van-mode-map.mdc +902 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-complexity-determination.mdc +60 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-file-verification.mdc +49 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-mode-map.mdc +49 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-platform-detection.mdc +50 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-qa-checks/build-test.mdc +117 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-qa-checks/config-check.mdc +103 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-qa-checks/dependency-check.mdc +147 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-qa-checks/environment-check.mdc +104 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-qa-checks/file-verification.mdc +1 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-qa-main.mdc +142 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-qa-utils/common-fixes.mdc +92 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-qa-utils/mode-transitions.mdc +101 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-qa-utils/reports.mdc +149 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-qa-utils/rule-calling-guide.mdc +66 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-qa-utils/rule-calling-help.mdc +19 -0
- data/.cursor/rules/isolation_rules/visual-maps/van_mode_split/van-qa-validation.md.old +363 -0
- data/.env.example +7 -0
- data/.memory_bank/activeContext.md +78 -0
- data/.memory_bank/progress.md +80 -0
- data/.memory_bank/projectbrief.md +29 -0
- data/.memory_bank/systemPatterns.md +90 -0
- data/.memory_bank/tasks.md +98 -0
- data/.memory_bank/techContext.md +73 -0
- data/.tool-versions +1 -0
- data/CHANGELOG.md +27 -1
- data/README.md +34 -98
- data/examples/README.md +7 -28
- data/examples/embeddings.rb +18 -20
- data/examples/models_api.rb +125 -0
- data/examples/multimodal.rb +9 -9
- data/lib/geminize/configuration.rb +4 -4
- data/lib/geminize/model_info.rb +87 -8
- data/lib/geminize/models/content_request.rb +1 -1
- data/lib/geminize/models/model.rb +101 -109
- data/lib/geminize/models/model_list.rb +70 -28
- data/lib/geminize/request_builder.rb +29 -0
- data/lib/geminize/version.rb +1 -1
- data/lib/geminize.rb +71 -17
- metadata +46 -20
- data/examples/rails_chat/README.md +0 -69
- data/examples/rails_chat/app/controllers/chat_controller.rb +0 -26
- data/examples/rails_chat/app/views/chat/index.html.erb +0 -112
- data/examples/rails_chat/config/routes.rb +0 -8
- data/examples/rails_initializer.rb +0 -46
- data/geminize-0.1.0.gem +0 -0
- data/lib/geminize/rails/app/controllers/concerns/geminize/controller.rb +0 -105
- data/lib/geminize/rails/app/helpers/geminize_helper.rb +0 -125
- data/lib/geminize/rails/controller_additions.rb +0 -41
- data/lib/geminize/rails/engine.rb +0 -29
- data/lib/geminize/rails/helper_additions.rb +0 -37
- data/lib/geminize/rails.rb +0 -50
- data/lib/geminize/railtie.rb +0 -33
- data/lib/generators/geminize/install_generator.rb +0 -22
- data/lib/generators/geminize/templates/README +0 -31
- data/lib/generators/geminize/templates/initializer.rb +0 -38
data/examples/multimodal.rb
CHANGED
@@ -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: "
|
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 './
|
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: "
|
64
|
-
{source_type: "file", data: "
|
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 './
|
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("
|
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 './
|
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("
|
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
|
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."
|
@@ -17,7 +17,7 @@ module Geminize
|
|
17
17
|
DEFAULT_MODEL = "gemini-2.0-flash"
|
18
18
|
|
19
19
|
# Default embedding model
|
20
|
-
DEFAULT_EMBEDDING_MODEL = "embedding-
|
20
|
+
DEFAULT_EMBEDDING_MODEL = "gemini-embedding-exp-03-07"
|
21
21
|
|
22
22
|
# Default timeout values (in seconds)
|
23
23
|
DEFAULT_TIMEOUT = 30
|
@@ -69,9 +69,9 @@ module Geminize
|
|
69
69
|
# @return [void]
|
70
70
|
def reset!
|
71
71
|
@api_key = ENV["GEMINI_API_KEY"]
|
72
|
-
@api_version = DEFAULT_API_VERSION
|
73
|
-
@default_model = DEFAULT_MODEL
|
74
|
-
@default_embedding_model = DEFAULT_EMBEDDING_MODEL
|
72
|
+
@api_version = ENV["GEMINI_API_VERSION"] || DEFAULT_API_VERSION
|
73
|
+
@default_model = ENV["GEMINI_MODEL"] || DEFAULT_MODEL
|
74
|
+
@default_embedding_model = ENV["GEMINI_EMBEDDING_MODEL"] || DEFAULT_EMBEDDING_MODEL
|
75
75
|
@timeout = DEFAULT_TIMEOUT
|
76
76
|
@open_timeout = DEFAULT_OPEN_TIMEOUT
|
77
77
|
@streaming_timeout = DEFAULT_STREAMING_TIMEOUT
|
data/lib/geminize/model_info.rb
CHANGED
@@ -9,6 +9,9 @@ module Geminize
|
|
9
9
|
# @return [Geminize::Client] The HTTP client
|
10
10
|
attr_reader :client
|
11
11
|
|
12
|
+
# Default page size for listing models
|
13
|
+
DEFAULT_PAGE_SIZE = 50
|
14
|
+
|
12
15
|
# Initialize a new ModelInfo instance
|
13
16
|
# @param client [Geminize::Client, nil] The HTTP client to use
|
14
17
|
# @param options [Hash] Additional options for the client
|
@@ -20,19 +23,26 @@ module Geminize
|
|
20
23
|
end
|
21
24
|
|
22
25
|
# List available models from the Gemini API
|
26
|
+
# @param page_size [Integer, nil] Number of models to return per page (max 1000)
|
27
|
+
# @param page_token [String, nil] Token for retrieving a specific page
|
23
28
|
# @param force_refresh [Boolean] Force a refresh from the API instead of using cache
|
24
29
|
# @return [Geminize::Models::ModelList] List of available models
|
25
30
|
# @raise [Geminize::GeminizeError] If the request fails
|
26
|
-
def list_models(force_refresh: false)
|
27
|
-
cache_key = "
|
31
|
+
def list_models(page_size: nil, page_token: nil, force_refresh: false)
|
32
|
+
cache_key = "models_list_#{page_size}_#{page_token}"
|
28
33
|
|
29
34
|
# Check if we have a valid cached result
|
30
35
|
if !force_refresh && @cache[cache_key] && @cache_expiry[cache_key] > Time.now
|
31
36
|
return @cache[cache_key]
|
32
37
|
end
|
33
38
|
|
39
|
+
# Prepare query parameters
|
40
|
+
params = {}
|
41
|
+
params[:pageSize] = page_size if page_size
|
42
|
+
params[:pageToken] = page_token
|
43
|
+
|
34
44
|
# Make the API request
|
35
|
-
response = client.get("models")
|
45
|
+
response = client.get("models", params)
|
36
46
|
|
37
47
|
# Create a ModelList from the response
|
38
48
|
model_list = Models::ModelList.from_api_data(response)
|
@@ -44,13 +54,62 @@ module Geminize
|
|
44
54
|
model_list
|
45
55
|
end
|
46
56
|
|
57
|
+
# Get all available models, handling pagination automatically
|
58
|
+
# @param force_refresh [Boolean] Force a refresh from the API instead of using cache
|
59
|
+
# @return [Geminize::Models::ModelList] Complete list of all available models
|
60
|
+
# @raise [Geminize::GeminizeError] If any request fails
|
61
|
+
def list_all_models(force_refresh: false)
|
62
|
+
cache_key = "all_models_list"
|
63
|
+
|
64
|
+
# Check if we have a valid cached result
|
65
|
+
if !force_refresh && @cache[cache_key] && @cache_expiry[cache_key] > Time.now
|
66
|
+
return @cache[cache_key]
|
67
|
+
end
|
68
|
+
|
69
|
+
all_models = []
|
70
|
+
page_token = nil
|
71
|
+
|
72
|
+
# Fetch first page
|
73
|
+
model_list = list_models(
|
74
|
+
page_size: DEFAULT_PAGE_SIZE,
|
75
|
+
page_token: page_token,
|
76
|
+
force_refresh: force_refresh
|
77
|
+
)
|
78
|
+
all_models.concat(model_list.models)
|
79
|
+
|
80
|
+
# Fetch additional pages if available
|
81
|
+
while model_list.has_more_pages?
|
82
|
+
page_token = model_list.next_page_token
|
83
|
+
model_list = list_models(
|
84
|
+
page_size: DEFAULT_PAGE_SIZE,
|
85
|
+
page_token: page_token,
|
86
|
+
force_refresh: force_refresh
|
87
|
+
)
|
88
|
+
all_models.concat(model_list.models)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Create a consolidated model list
|
92
|
+
result = Models::ModelList.new(all_models)
|
93
|
+
|
94
|
+
# Cache the result
|
95
|
+
@cache[cache_key] = result
|
96
|
+
@cache_expiry[cache_key] = Time.now + @cache_ttl
|
97
|
+
|
98
|
+
result
|
99
|
+
end
|
100
|
+
|
47
101
|
# Get information about a specific model
|
48
|
-
# @param
|
102
|
+
# @param model_name [String] The model name to retrieve (models/{model})
|
49
103
|
# @param force_refresh [Boolean] Force a refresh from the API instead of using cache
|
50
104
|
# @return [Geminize::Models::Model] The model information
|
51
105
|
# @raise [Geminize::GeminizeError] If the request fails or model is not found
|
52
|
-
def get_model(
|
53
|
-
|
106
|
+
def get_model(model_name, force_refresh: false)
|
107
|
+
# Handle both formats: "models/gemini-1.5-pro" or just "gemini-1.5-pro"
|
108
|
+
unless model_name.start_with?("models/")
|
109
|
+
model_name = "models/#{model_name}"
|
110
|
+
end
|
111
|
+
|
112
|
+
cache_key = "model_#{model_name}"
|
54
113
|
|
55
114
|
# Check if we have a valid cached result
|
56
115
|
if !force_refresh && @cache[cache_key] && @cache_expiry[cache_key] > Time.now
|
@@ -59,7 +118,7 @@ module Geminize
|
|
59
118
|
|
60
119
|
# Make the API request
|
61
120
|
begin
|
62
|
-
response = client.get(
|
121
|
+
response = client.get(model_name)
|
63
122
|
|
64
123
|
# Create a Model from the response
|
65
124
|
model = Models::Model.from_api_data(response)
|
@@ -71,10 +130,30 @@ module Geminize
|
|
71
130
|
model
|
72
131
|
rescue Geminize::NotFoundError => e
|
73
132
|
# Re-raise with a more descriptive message
|
74
|
-
raise Geminize::NotFoundError.new("Model '#{
|
133
|
+
raise Geminize::NotFoundError.new("Model '#{model_name}' not found", e.code, e.http_status)
|
75
134
|
end
|
76
135
|
end
|
77
136
|
|
137
|
+
# Get models that support a specific generation method
|
138
|
+
# @param method [String] The generation method (e.g., "generateContent", "embedContent")
|
139
|
+
# @param force_refresh [Boolean] Force a refresh from the API instead of using cache
|
140
|
+
# @return [Geminize::Models::ModelList] List of models that support the method
|
141
|
+
# @raise [Geminize::GeminizeError] If the request fails
|
142
|
+
def get_models_by_method(method, force_refresh: false)
|
143
|
+
all_models = list_all_models(force_refresh: force_refresh)
|
144
|
+
all_models.filter_by_method(method)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Get models by base model ID
|
148
|
+
# @param base_model_id [String] The base model ID to filter by
|
149
|
+
# @param force_refresh [Boolean] Force a refresh from the API instead of using cache
|
150
|
+
# @return [Geminize::Models::ModelList] List of models with the specified base model ID
|
151
|
+
# @raise [Geminize::GeminizeError] If the request fails
|
152
|
+
def get_models_by_base_id(base_model_id, force_refresh: false)
|
153
|
+
all_models = list_all_models(force_refresh: force_refresh)
|
154
|
+
all_models.filter_by_base_model_id(base_model_id)
|
155
|
+
end
|
156
|
+
|
78
157
|
# Clear all cached model information
|
79
158
|
# @return [void]
|
80
159
|
def clear_cache
|
@@ -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
|
-
{
|
217
|
+
{text: part[:text]}
|
218
218
|
elsif part[:type] == "image"
|
219
219
|
{
|
220
220
|
inlineData: {
|
@@ -4,69 +4,131 @@ module Geminize
|
|
4
4
|
module Models
|
5
5
|
# Represents an AI model from the Gemini API.
|
6
6
|
class Model
|
7
|
-
# @return [String] The
|
8
|
-
attr_reader :id
|
9
|
-
|
10
|
-
# @return [String] The display name of the model
|
7
|
+
# @return [String] The resource name of the model
|
11
8
|
attr_reader :name
|
12
9
|
|
10
|
+
# @return [String] The base model ID
|
11
|
+
attr_reader :base_model_id
|
12
|
+
|
13
13
|
# @return [String] The model version
|
14
14
|
attr_reader :version
|
15
15
|
|
16
|
+
# @return [String] The display name of the model
|
17
|
+
attr_reader :display_name
|
18
|
+
|
16
19
|
# @return [String] The model description
|
17
20
|
attr_reader :description
|
18
21
|
|
19
|
-
# @return [
|
20
|
-
attr_reader :
|
22
|
+
# @return [Integer] Maximum number of input tokens allowed
|
23
|
+
attr_reader :input_token_limit
|
24
|
+
|
25
|
+
# @return [Integer] Maximum number of output tokens available
|
26
|
+
attr_reader :output_token_limit
|
21
27
|
|
22
|
-
# @return [
|
23
|
-
attr_reader :
|
28
|
+
# @return [Array<String>] Supported generation methods
|
29
|
+
attr_reader :supported_generation_methods
|
24
30
|
|
25
|
-
# @return [
|
26
|
-
attr_reader :
|
31
|
+
# @return [Float] Default temperature
|
32
|
+
attr_reader :temperature
|
33
|
+
|
34
|
+
# @return [Float] Maximum allowed temperature
|
35
|
+
attr_reader :max_temperature
|
36
|
+
|
37
|
+
# @return [Float] Default top_p value for nucleus sampling
|
38
|
+
attr_reader :top_p
|
39
|
+
|
40
|
+
# @return [Integer] Default top_k value for sampling
|
41
|
+
attr_reader :top_k
|
27
42
|
|
28
43
|
# @return [Hash] Raw model data from the API
|
29
44
|
attr_reader :raw_data
|
30
45
|
|
31
46
|
# Create a new Model instance
|
32
47
|
# @param attributes [Hash] Model attributes
|
33
|
-
# @option attributes [String] :
|
34
|
-
# @option attributes [String] :
|
48
|
+
# @option attributes [String] :name The resource name of the model
|
49
|
+
# @option attributes [String] :base_model_id The base model ID
|
35
50
|
# @option attributes [String] :version The model version
|
51
|
+
# @option attributes [String] :display_name The display name of the model
|
36
52
|
# @option attributes [String] :description The model description
|
37
|
-
# @option attributes [
|
38
|
-
# @option attributes [
|
39
|
-
# @option attributes [Array<String>] :
|
53
|
+
# @option attributes [Integer] :input_token_limit Maximum input tokens
|
54
|
+
# @option attributes [Integer] :output_token_limit Maximum output tokens
|
55
|
+
# @option attributes [Array<String>] :supported_generation_methods Supported methods
|
56
|
+
# @option attributes [Float] :temperature Default temperature
|
57
|
+
# @option attributes [Float] :max_temperature Maximum temperature
|
58
|
+
# @option attributes [Float] :top_p Default top_p value
|
59
|
+
# @option attributes [Integer] :top_k Default top_k value
|
40
60
|
# @option attributes [Hash] :raw_data Raw model data from API
|
41
61
|
def initialize(attributes = {})
|
42
|
-
@id = attributes[:id]
|
43
62
|
@name = attributes[:name]
|
63
|
+
@base_model_id = attributes[:base_model_id]
|
44
64
|
@version = attributes[:version]
|
65
|
+
@display_name = attributes[:display_name]
|
45
66
|
@description = attributes[:description]
|
46
|
-
@
|
47
|
-
@
|
48
|
-
@
|
67
|
+
@input_token_limit = attributes[:input_token_limit]
|
68
|
+
@output_token_limit = attributes[:output_token_limit]
|
69
|
+
@supported_generation_methods = attributes[:supported_generation_methods] || []
|
70
|
+
@temperature = attributes[:temperature]
|
71
|
+
@max_temperature = attributes[:max_temperature]
|
72
|
+
@top_p = attributes[:top_p]
|
73
|
+
@top_k = attributes[:top_k]
|
49
74
|
@raw_data = attributes[:raw_data] || {}
|
50
75
|
end
|
51
76
|
|
52
|
-
#
|
53
|
-
# @
|
54
|
-
|
55
|
-
|
56
|
-
|
77
|
+
# Shorthand accessor for the model ID (last part of the name path)
|
78
|
+
# @return [String] The model ID
|
79
|
+
def id
|
80
|
+
return nil unless @name
|
81
|
+
@name.split("/").last
|
82
|
+
end
|
83
|
+
|
84
|
+
# Check if model supports a specific generation method
|
85
|
+
# @param method [String] Generation method to check for
|
86
|
+
# @return [Boolean] True if the model supports the method
|
87
|
+
def supports_method?(method)
|
88
|
+
supported_generation_methods.include?(method.to_s)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Check if model supports content generation
|
92
|
+
# @return [Boolean] True if the model supports content generation
|
93
|
+
def supports_content_generation?
|
94
|
+
supports_method?("generateContent")
|
95
|
+
end
|
96
|
+
|
97
|
+
# Check if model supports message generation (chat)
|
98
|
+
# @return [Boolean] True if the model supports message generation
|
99
|
+
def supports_message_generation?
|
100
|
+
supports_method?("generateMessage")
|
101
|
+
end
|
102
|
+
|
103
|
+
# Check if model supports embedding generation
|
104
|
+
# @return [Boolean] True if the model supports embedding generation
|
105
|
+
def supports_embedding?
|
106
|
+
supports_method?("embedContent")
|
107
|
+
end
|
108
|
+
|
109
|
+
# Check if model supports streaming content generation
|
110
|
+
# @return [Boolean] True if the model supports streaming content generation
|
111
|
+
def supports_streaming?
|
112
|
+
supports_method?("streamGenerateContent")
|
57
113
|
end
|
58
114
|
|
59
115
|
# Convert model to a hash representation
|
60
116
|
# @return [Hash] Hash representation of the model
|
61
117
|
def to_h
|
62
118
|
{
|
63
|
-
id: id,
|
64
119
|
name: name,
|
120
|
+
id: id,
|
121
|
+
base_model_id: base_model_id,
|
65
122
|
version: version,
|
123
|
+
display_name: display_name,
|
66
124
|
description: description,
|
67
|
-
|
68
|
-
|
69
|
-
|
125
|
+
input_token_limit: input_token_limit,
|
126
|
+
output_token_limit: output_token_limit,
|
127
|
+
supported_generation_methods: supported_generation_methods,
|
128
|
+
temperature: temperature,
|
129
|
+
max_temperature: max_temperature,
|
130
|
+
top_p: top_p,
|
131
|
+
top_k: top_k
|
70
132
|
}
|
71
133
|
end
|
72
134
|
|
@@ -80,92 +142,22 @@ module Geminize
|
|
80
142
|
# @param data [Hash] Raw API response data
|
81
143
|
# @return [Model] New Model instance
|
82
144
|
def self.from_api_data(data)
|
83
|
-
# Extract capabilities from model data
|
84
|
-
capabilities = extract_capabilities(data)
|
85
|
-
|
86
|
-
# Extract limitations from model data
|
87
|
-
limitations = extract_limitations(data)
|
88
|
-
|
89
|
-
# Extract use cases from model data
|
90
|
-
use_cases = extract_use_cases(data)
|
91
|
-
|
92
145
|
new(
|
93
|
-
|
94
|
-
|
95
|
-
version:
|
146
|
+
name: data["name"],
|
147
|
+
base_model_id: data["baseModelId"],
|
148
|
+
version: data["version"],
|
149
|
+
display_name: data["displayName"],
|
96
150
|
description: data["description"],
|
97
|
-
|
98
|
-
|
99
|
-
|
151
|
+
input_token_limit: data["inputTokenLimit"],
|
152
|
+
output_token_limit: data["outputTokenLimit"],
|
153
|
+
supported_generation_methods: data["supportedGenerationMethods"] || [],
|
154
|
+
temperature: data["temperature"],
|
155
|
+
max_temperature: data["maxTemperature"],
|
156
|
+
top_p: data["topP"],
|
157
|
+
top_k: data["topK"],
|
100
158
|
raw_data: data
|
101
159
|
)
|
102
160
|
end
|
103
|
-
|
104
|
-
private_class_method def self.extract_version(data)
|
105
|
-
# Extract version from model name or other fields
|
106
|
-
# Example: if name is "gemini-1.0-pro", extract "1.0"
|
107
|
-
if data["displayName"]
|
108
|
-
match = data["displayName"].match(/[-_](\d+\.\d+)[-_]/)
|
109
|
-
return match[1] if match
|
110
|
-
|
111
|
-
# Try another pattern (e.g., "Gemini 1.5 Pro")
|
112
|
-
match = data["displayName"].match(/\s(\d+\.\d+)\s/)
|
113
|
-
return match[1] if match
|
114
|
-
end
|
115
|
-
nil
|
116
|
-
end
|
117
|
-
|
118
|
-
private_class_method def self.extract_capabilities(data)
|
119
|
-
capabilities = []
|
120
|
-
|
121
|
-
# Example capability extraction, adjust based on actual API response format
|
122
|
-
capabilities << "text" if data.dig("supportedGenerationMethods")&.include?("generateText")
|
123
|
-
capabilities << "chat" if data.dig("supportedGenerationMethods")&.include?("generateMessage")
|
124
|
-
capabilities << "vision" if data.dig("supportedGenerationMethods")&.include?("generateContent") &&
|
125
|
-
data.dig("inputSetting", "supportMultiModal")
|
126
|
-
capabilities << "embedding" if data.dig("supportedGenerationMethods")&.include?("embedContent")
|
127
|
-
|
128
|
-
capabilities
|
129
|
-
end
|
130
|
-
|
131
|
-
private_class_method def self.extract_limitations(data)
|
132
|
-
limitations = {}
|
133
|
-
|
134
|
-
# Extract token limits
|
135
|
-
if data.dig("inputTokenLimit")
|
136
|
-
limitations[:input_token_limit] = data["inputTokenLimit"]
|
137
|
-
end
|
138
|
-
|
139
|
-
if data.dig("outputTokenLimit")
|
140
|
-
limitations[:output_token_limit] = data["outputTokenLimit"]
|
141
|
-
end
|
142
|
-
|
143
|
-
# Extract any other limitations from the API data
|
144
|
-
limitations
|
145
|
-
end
|
146
|
-
|
147
|
-
private_class_method def self.extract_use_cases(data)
|
148
|
-
# Extract use cases from the description or other fields
|
149
|
-
# This is a simple implementation - adjust based on actual API data
|
150
|
-
use_cases = []
|
151
|
-
|
152
|
-
if data["description"]
|
153
|
-
if data["description"].include?("chat")
|
154
|
-
use_cases << "conversational_ai"
|
155
|
-
end
|
156
|
-
|
157
|
-
if data["description"].include?("vision") || data["description"].include?("image")
|
158
|
-
use_cases << "image_understanding"
|
159
|
-
end
|
160
|
-
|
161
|
-
if data["description"].include?("embedding")
|
162
|
-
use_cases << "semantic_search"
|
163
|
-
use_cases << "clustering"
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
use_cases
|
168
|
-
end
|
169
161
|
end
|
170
162
|
end
|
171
163
|
end
|
@@ -12,13 +12,18 @@ module Geminize
|
|
12
12
|
# @return [Array<Model>] The list of models
|
13
13
|
attr_reader :models
|
14
14
|
|
15
|
+
# @return [String, nil] Token for fetching the next page of results
|
16
|
+
attr_reader :next_page_token
|
17
|
+
|
15
18
|
# Delegate array methods to the underlying models array
|
16
19
|
def_delegators :@models, :[], :size, :length, :empty?, :first, :last
|
17
20
|
|
18
21
|
# Create a new ModelList
|
19
22
|
# @param models [Array<Model>] Initial list of models
|
20
|
-
|
23
|
+
# @param next_page_token [String, nil] Token for fetching the next page
|
24
|
+
def initialize(models = [], next_page_token = nil)
|
21
25
|
@models = models
|
26
|
+
@next_page_token = next_page_token
|
22
27
|
end
|
23
28
|
|
24
29
|
# Implement Enumerable's required each method
|
@@ -35,43 +40,50 @@ module Geminize
|
|
35
40
|
self
|
36
41
|
end
|
37
42
|
|
38
|
-
# Find a model by its
|
43
|
+
# Find a model by its resource name
|
44
|
+
# @param name [String] The model name to search for
|
45
|
+
# @return [Model, nil] The found model or nil
|
46
|
+
def find_by_name(name)
|
47
|
+
@models.find { |model| model.name == name }
|
48
|
+
end
|
49
|
+
|
50
|
+
# Find a model by its ID (last part of the resource name)
|
39
51
|
# @param id [String] The model ID to search for
|
40
52
|
# @return [Model, nil] The found model or nil
|
41
53
|
def find_by_id(id)
|
42
54
|
@models.find { |model| model.id == id }
|
43
55
|
end
|
44
56
|
|
45
|
-
# Find all models that support a specific
|
46
|
-
# @param
|
57
|
+
# Find all models that support a specific generation method
|
58
|
+
# @param method [String] The generation method to filter by
|
47
59
|
# @return [ModelList] A new ModelList containing only matching models
|
48
|
-
def
|
49
|
-
filtered = @models.select { |model| model.
|
50
|
-
ModelList.new(filtered)
|
60
|
+
def filter_by_method(method)
|
61
|
+
filtered = @models.select { |model| model.supports_method?(method) }
|
62
|
+
ModelList.new(filtered, nil)
|
51
63
|
end
|
52
64
|
|
53
|
-
# Find all models that support
|
54
|
-
# @return [ModelList] A new ModelList containing only
|
55
|
-
def
|
56
|
-
|
65
|
+
# Find all models that support content generation
|
66
|
+
# @return [ModelList] A new ModelList containing only content generation capable models
|
67
|
+
def content_generation_models
|
68
|
+
filter_by_method("generateContent")
|
57
69
|
end
|
58
70
|
|
59
|
-
# Find all models that support
|
60
|
-
# @return [ModelList] A new ModelList containing only
|
61
|
-
def
|
62
|
-
|
71
|
+
# Find all models that support streaming content generation
|
72
|
+
# @return [ModelList] A new ModelList containing only streaming capable models
|
73
|
+
def streaming_models
|
74
|
+
filter_by_method("streamGenerateContent")
|
63
75
|
end
|
64
76
|
|
65
|
-
# Find all models that support
|
66
|
-
# @return [ModelList] A new ModelList containing only
|
67
|
-
def
|
68
|
-
|
77
|
+
# Find all models that support embeddings
|
78
|
+
# @return [ModelList] A new ModelList containing only embedding-capable models
|
79
|
+
def embedding_models
|
80
|
+
filter_by_method("embedContent")
|
69
81
|
end
|
70
82
|
|
71
83
|
# Find all models that support chat/conversation
|
72
84
|
# @return [ModelList] A new ModelList containing only chat-capable models
|
73
85
|
def chat_models
|
74
|
-
|
86
|
+
filter_by_method("generateMessage")
|
75
87
|
end
|
76
88
|
|
77
89
|
# Filter models by version
|
@@ -79,16 +91,40 @@ module Geminize
|
|
79
91
|
# @return [ModelList] A new ModelList containing only matching models
|
80
92
|
def filter_by_version(version)
|
81
93
|
filtered = @models.select { |model| model.version == version }
|
82
|
-
ModelList.new(filtered)
|
94
|
+
ModelList.new(filtered, nil)
|
83
95
|
end
|
84
96
|
|
85
|
-
# Filter models by name pattern
|
86
|
-
# @param pattern [String, Regexp] The pattern to match model names against
|
97
|
+
# Filter models by display name pattern
|
98
|
+
# @param pattern [String, Regexp] The pattern to match model display names against
|
87
99
|
# @return [ModelList] A new ModelList containing only matching models
|
88
|
-
def
|
100
|
+
def filter_by_display_name(pattern)
|
89
101
|
pattern = Regexp.new(pattern.to_s, Regexp::IGNORECASE) if pattern.is_a?(String)
|
90
|
-
filtered = @models.select { |model| model.
|
91
|
-
ModelList.new(filtered)
|
102
|
+
filtered = @models.select { |model| model.display_name&.match?(pattern) }
|
103
|
+
ModelList.new(filtered, nil)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Filter models by base model ID
|
107
|
+
# @param base_model_id [String] The base model ID to filter by
|
108
|
+
# @return [ModelList] A new ModelList containing only matching models
|
109
|
+
def filter_by_base_model_id(base_model_id)
|
110
|
+
filtered = @models.select { |model| model.base_model_id == base_model_id }
|
111
|
+
ModelList.new(filtered, nil)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Find models with a minimum input token limit
|
115
|
+
# @param min_limit [Integer] The minimum input token limit
|
116
|
+
# @return [ModelList] A new ModelList containing only matching models
|
117
|
+
def filter_by_min_input_tokens(min_limit)
|
118
|
+
filtered = @models.select { |model| model.input_token_limit && model.input_token_limit >= min_limit }
|
119
|
+
ModelList.new(filtered, nil)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Find models with a minimum output token limit
|
123
|
+
# @param min_limit [Integer] The minimum output token limit
|
124
|
+
# @return [ModelList] A new ModelList containing only matching models
|
125
|
+
def filter_by_min_output_tokens(min_limit)
|
126
|
+
filtered = @models.select { |model| model.output_token_limit && model.output_token_limit >= min_limit }
|
127
|
+
ModelList.new(filtered, nil)
|
92
128
|
end
|
93
129
|
|
94
130
|
# Create a ModelList from API response data
|
@@ -96,16 +132,22 @@ module Geminize
|
|
96
132
|
# @return [ModelList] New ModelList instance
|
97
133
|
def self.from_api_data(data)
|
98
134
|
models = []
|
135
|
+
next_page_token = data["nextPageToken"]
|
99
136
|
|
100
137
|
# Process model data from API response
|
101
|
-
# The exact structure will depend on the Gemini API response format
|
102
138
|
if data.key?("models")
|
103
139
|
models = data["models"].map do |model_data|
|
104
140
|
Model.from_api_data(model_data)
|
105
141
|
end
|
106
142
|
end
|
107
143
|
|
108
|
-
new(models)
|
144
|
+
new(models, next_page_token)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Check if there are more pages of results available
|
148
|
+
# @return [Boolean] True if there are more pages
|
149
|
+
def has_more_pages?
|
150
|
+
!next_page_token.nil? && !next_page_token.empty?
|
109
151
|
end
|
110
152
|
|
111
153
|
# Convert to array of hashes representation
|