gemini-ai 3.1.0 → 4.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: 36be77448ab7ba00008ac7548c25fdca45b92980762303631de5d6bdbcd2d01a
4
- data.tar.gz: e0772790afa6019424282e8ac665fb0049da13a76ecc43909b147655f6f95a3a
3
+ metadata.gz: b66c146b7230d838c888d5f90107f07bcc2827c7710b77c1284c52315b3c9515
4
+ data.tar.gz: c125664051e260270bb08b81ecc932a3e4b730ea1c69601ba93af4749af54fcf
5
5
  SHA512:
6
- metadata.gz: e4d6c7391dff2ce75a46e3ceb5c7ef9c07c6cdcfc55477df68be1df2e06f77ff77d795ee6e70abc9ad73001e8dd583d39949a394140b129d08c2db94c2b8f7c4
7
- data.tar.gz: 2acedebdfe562b7b68d19046a2f2b06bec6fbe75768cc7066b7c1e31cb72bc4caa551a8d656ffc6537c714f0d11965f3cc9f74542e7bc9315f0998f35390d5f4
6
+ metadata.gz: dd67f092295620ff45cb75f07b67dc0753d54c92ff598284a0f10ce4a45e7f395aad0235320fb95ab86bb12f9033c21e4b3fe776bb99bd6d98f8228054bc6bca
7
+ data.tar.gz: c03ab797796745870124159762e11f0ea5a56ee9cb033f97c7b62088dd0a2d2dae85f1fa874245ddc3fa3482ae7739f1a311546807ee78e1dbd17e7f5807cc52
data/.gitignore CHANGED
@@ -1,2 +1,7 @@
1
1
  *.gem
2
2
  .devcontainer
3
+ .env
4
+ *.tmp
5
+ *.temp
6
+ temp.rb
7
+ tmp.rb
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ source 'https://rubygems.org'
5
5
  gemspec
6
6
 
7
7
  group :test, :development do
8
+ gem 'dotenv', '~> 3.1', '>= 3.1.2'
8
9
  gem 'pry-byebug', '~> 3.10', '>= 3.10.1'
9
- gem 'rubocop', '~> 1.58'
10
+ gem 'rubocop', '~> 1.63', '>= 1.63.5'
10
11
  end
data/Gemfile.lock CHANGED
@@ -1,10 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gemini-ai (3.1.0)
4
+ gemini-ai (4.0.0)
5
5
  event_stream_parser (~> 1.0)
6
- faraday (~> 2.8, >= 2.8.1)
7
- googleauth (~> 1.9, >= 1.9.1)
6
+ faraday (~> 2.9)
7
+ faraday-typhoeus (~> 1.1)
8
+ googleauth (~> 1.8)
9
+ typhoeus (~> 1.4, >= 1.4.1)
8
10
 
9
11
  GEM
10
12
  remote: https://rubygems.org/
@@ -15,29 +17,38 @@ GEM
15
17
  base64 (0.2.0)
16
18
  byebug (11.1.3)
17
19
  coderay (1.1.3)
20
+ dotenv (3.1.2)
21
+ ethon (0.16.0)
22
+ ffi (>= 1.15.0)
18
23
  event_stream_parser (1.0.0)
19
- faraday (2.8.1)
20
- base64
21
- faraday-net_http (>= 2.0, < 3.1)
22
- ruby2_keywords (>= 0.0.4)
23
- faraday-net_http (3.0.2)
24
- google-cloud-env (2.1.0)
24
+ faraday (2.9.0)
25
+ faraday-net_http (>= 2.0, < 3.2)
26
+ faraday-net_http (3.1.0)
27
+ net-http
28
+ faraday-typhoeus (1.1.0)
29
+ faraday (~> 2.0)
30
+ typhoeus (~> 1.4)
31
+ ffi (1.16.3)
32
+ google-cloud-env (2.1.1)
25
33
  faraday (>= 1.0, < 3.a)
26
- googleauth (1.9.1)
34
+ googleauth (1.11.0)
27
35
  faraday (>= 1.0, < 3.a)
28
36
  google-cloud-env (~> 2.1)
29
37
  jwt (>= 1.4, < 3.0)
30
38
  multi_json (~> 1.11)
31
39
  os (>= 0.9, < 2.0)
32
40
  signet (>= 0.16, < 2.a)
33
- json (2.7.1)
34
- jwt (2.7.1)
41
+ json (2.7.2)
42
+ jwt (2.8.1)
43
+ base64
35
44
  language_server-protocol (3.17.0.3)
36
- method_source (1.0.0)
45
+ method_source (1.1.0)
37
46
  multi_json (1.15.0)
47
+ net-http (0.4.1)
48
+ uri
38
49
  os (1.1.4)
39
50
  parallel (1.24.0)
40
- parser (3.2.2.4)
51
+ parser (3.3.1.0)
41
52
  ast (~> 2.4.1)
42
53
  racc
43
54
  pry (0.14.2)
@@ -46,40 +57,45 @@ GEM
46
57
  pry-byebug (3.10.1)
47
58
  byebug (~> 11.0)
48
59
  pry (>= 0.13, < 0.15)
49
- public_suffix (5.0.4)
60
+ public_suffix (5.0.5)
50
61
  racc (1.7.3)
51
62
  rainbow (3.1.1)
52
- regexp_parser (2.8.3)
53
- rexml (3.2.6)
54
- rubocop (1.59.0)
63
+ regexp_parser (2.9.2)
64
+ rexml (3.2.8)
65
+ strscan (>= 3.0.9)
66
+ rubocop (1.63.5)
55
67
  json (~> 2.3)
56
68
  language_server-protocol (>= 3.17.0)
57
69
  parallel (~> 1.10)
58
- parser (>= 3.2.2.4)
70
+ parser (>= 3.3.0.2)
59
71
  rainbow (>= 2.2.2, < 4.0)
60
72
  regexp_parser (>= 1.8, < 3.0)
61
73
  rexml (>= 3.2.5, < 4.0)
62
- rubocop-ast (>= 1.30.0, < 2.0)
74
+ rubocop-ast (>= 1.31.1, < 2.0)
63
75
  ruby-progressbar (~> 1.7)
64
76
  unicode-display_width (>= 2.4.0, < 3.0)
65
- rubocop-ast (1.30.0)
66
- parser (>= 3.2.1.0)
77
+ rubocop-ast (1.31.3)
78
+ parser (>= 3.3.1.0)
67
79
  ruby-progressbar (1.13.0)
68
- ruby2_keywords (0.0.5)
69
- signet (0.18.0)
80
+ signet (0.19.0)
70
81
  addressable (~> 2.8)
71
82
  faraday (>= 0.17.5, < 3.a)
72
83
  jwt (>= 1.5, < 3.0)
73
84
  multi_json (~> 1.10)
85
+ strscan (3.1.0)
86
+ typhoeus (1.4.1)
87
+ ethon (>= 0.9.0)
74
88
  unicode-display_width (2.5.0)
89
+ uri (0.13.0)
75
90
 
76
91
  PLATFORMS
77
92
  x86_64-linux
78
93
 
79
94
  DEPENDENCIES
95
+ dotenv (~> 3.1, >= 3.1.2)
80
96
  gemini-ai!
81
97
  pry-byebug (~> 3.10, >= 3.10.1)
82
- rubocop (~> 1.58)
98
+ rubocop (~> 1.63, >= 1.63.5)
83
99
 
84
100
  BUNDLED WITH
85
101
  2.4.22
data/README.md CHANGED
@@ -9,7 +9,7 @@ A Ruby Gem for interacting with [Gemini](https://deepmind.google/technologies/ge
9
9
  ## TL;DR and Quick Start
10
10
 
11
11
  ```ruby
12
- gem 'gemini-ai', '~> 3.1.0'
12
+ gem 'gemini-ai', '~> 4.0.0'
13
13
  ```
14
14
 
15
15
  ```ruby
@@ -73,39 +73,46 @@ Result:
73
73
  - [TL;DR and Quick Start](#tldr-and-quick-start)
74
74
  - [Index](#index)
75
75
  - [Setup](#setup)
76
- - [Installing](#installing)
77
- - [Credentials](#credentials)
78
- - [Option 1: API Key (Generative Language API)](#option-1-api-key-generative-language-api)
79
- - [Option 2: Service Account Credentials File (Vertex AI API)](#option-2-service-account-credentials-file-vertex-ai-api)
80
- - [Option 3: Application Default Credentials (Vertex AI API)](#option-3-application-default-credentials-vertex-ai-api)
81
- - [Required Data](#required-data)
76
+ - [Installing](#installing)
77
+ - [Credentials](#credentials)
78
+ - [Option 1: API Key (Generative Language API)](#option-1-api-key-generative-language-api)
79
+ - [Option 2: Service Account Credentials File (Vertex AI API)](#option-2-service-account-credentials-file-vertex-ai-api)
80
+ - [Option 3: Application Default Credentials (Vertex AI API)](#option-3-application-default-credentials-vertex-ai-api)
81
+ - [Required Data](#required-data)
82
+ - [Custom Version](#custom-version)
83
+ - [Available Models](#available-models)
82
84
  - [Usage](#usage)
83
- - [Client](#client)
84
- - [Methods](#methods)
85
- - [stream_generate_content](#stream_generate_content)
86
- - [Receiving Stream Events](#receiving-stream-events)
87
- - [Without Events](#without-events)
88
- - [generate_content](#generate_content)
89
- - [Modes](#modes)
90
- - [Text](#text)
91
- - [Image](#image)
92
- - [Video](#video)
93
- - [Streaming vs. Server-Sent Events (SSE)](#streaming-vs-server-sent-events-sse)
94
- - [Server-Sent Events (SSE) Hang](#server-sent-events-sse-hang)
95
- - [Non-Streaming](#non-streaming)
96
- - [Back-and-Forth Conversations](#back-and-forth-conversations)
97
- - [Tools (Functions) Calling](#tools-functions-calling)
98
- - [New Functionalities and APIs](#new-functionalities-and-apis)
99
- - [Request Options](#request-options)
100
- - [Timeout](#timeout)
101
- - [Error Handling](#error-handling)
102
- - [Rescuing](#rescuing)
103
- - [For Short](#for-short)
104
- - [Errors](#errors)
85
+ - [Client](#client)
86
+ - [Methods](#methods)
87
+ - [Chat](#chat)
88
+ - [stream_generate_content](#stream_generate_content)
89
+ - [Receiving Stream Events](#receiving-stream-events)
90
+ - [Without Events](#without-events)
91
+ - [generate_content](#generate_content)
92
+ - [Embeddings](#embeddings)
93
+ - [predict](#predict)
94
+ - [embed_content](#embed_content)
95
+ - [Modes](#modes)
96
+ - [Text](#text)
97
+ - [Image](#image)
98
+ - [Video](#video)
99
+ - [Streaming vs. Server-Sent Events (SSE)](#streaming-vs-server-sent-events-sse)
100
+ - [Server-Sent Events (SSE) Hang](#server-sent-events-sse-hang)
101
+ - [Non-Streaming](#non-streaming)
102
+ - [Back-and-Forth Conversations](#back-and-forth-conversations)
103
+ - [Tools (Functions) Calling](#tools-functions-calling)
104
+ - [New Functionalities and APIs](#new-functionalities-and-apis)
105
+ - [Request Options](#request-options)
106
+ - [Adapter](#adapter)
107
+ - [Timeout](#timeout)
108
+ - [Error Handling](#error-handling)
109
+ - [Rescuing](#rescuing)
110
+ - [For Short](#for-short)
111
+ - [Errors](#errors)
105
112
  - [Development](#development)
106
- - [Purpose](#purpose)
107
- - [Publish to RubyGems](#publish-to-rubygems)
108
- - [Updating the README](#updating-the-readme)
113
+ - [Purpose](#purpose)
114
+ - [Publish to RubyGems](#publish-to-rubygems)
115
+ - [Updating the README](#updating-the-readme)
109
116
  - [Resources and References](#resources-and-references)
110
117
  - [Disclaimer](#disclaimer)
111
118
 
@@ -114,11 +121,11 @@ Result:
114
121
  ### Installing
115
122
 
116
123
  ```sh
117
- gem install gemini-ai -v 3.1.0
124
+ gem install gemini-ai -v 4.0.0
118
125
  ```
119
126
 
120
127
  ```sh
121
- gem 'gemini-ai', '~> 3.1.0'
128
+ gem 'gemini-ai', '~> 4.0.0'
122
129
  ```
123
130
 
124
131
  ### Credentials
@@ -270,6 +277,80 @@ You might want to explicitly set a Google Cloud Project ID, which you can do as
270
277
  }
271
278
  ```
272
279
 
280
+ ### Custom Version
281
+
282
+ By default, the gem uses the `v1` version of the APIs. You may want to use a different version:
283
+
284
+ ```ruby
285
+ # With an API key
286
+ client = Gemini.new(
287
+ credentials: {
288
+ service: 'generative-language-api',
289
+ api_key: ENV['GOOGLE_API_KEY'],
290
+ version: 'v1beta'
291
+ },
292
+ options: { model: 'gemini-pro', server_sent_events: true }
293
+ )
294
+
295
+ # With a Service Account Credentials File
296
+ client = Gemini.new(
297
+ credentials: {
298
+ service: 'vertex-ai-api',
299
+ file_path: 'google-credentials.json',
300
+ region: 'us-east4',
301
+ version: 'v1beta'
302
+ },
303
+ options: { model: 'gemini-pro', server_sent_events: true }
304
+ )
305
+
306
+ # With Application Default Credentials
307
+ client = Gemini.new(
308
+ credentials: {
309
+ service: 'vertex-ai-api',
310
+ region: 'us-east4',
311
+ version: 'v1beta'
312
+ },
313
+ options: { model: 'gemini-pro', server_sent_events: true }
314
+ )
315
+ ```
316
+
317
+ ## Available Models
318
+
319
+ These models are accessible to the repository **author** as of May 2025 in the `us-east4` region. Access to models may vary by region, user, and account. All models here are expected to work, if you can access them. This is just a reference of what a "typical" user may expect to have access to right away:
320
+
321
+ | Model | Vertex AI | Generative Language |
322
+ |------------------------------------------|:---------:|:-------------------:|
323
+ | gemini-pro-vision | ✅ | 🔒 |
324
+ | gemini-pro | ✅ | ✅ |
325
+ | gemini-1.5-pro-preview-0514 | ✅ | 🔒 |
326
+ | gemini-1.5-pro-preview-0409 | ✅ | 🔒 |
327
+ | gemini-1.5-pro | 🔒 | 🔒 |
328
+ | gemini-1.5-flash-preview-0514 | ✅ | 🔒 |
329
+ | gemini-1.5-flash | 🔒 | 🔒 |
330
+ | gemini-1.0-pro-vision-latest | 🔒 | 🔒 |
331
+ | gemini-1.0-pro-vision-001 | ✅ | 🔒 |
332
+ | gemini-1.0-pro-vision | ✅ | 🔒 |
333
+ | gemini-1.0-pro-latest | 🔒 | ✅ |
334
+ | gemini-1.0-pro-002 | ✅ | 🔒 |
335
+ | gemini-1.0-pro-001 | ✅ | ✅ |
336
+ | gemini-1.0-pro | ✅ | ✅ |
337
+ | text-embedding-004 | ✅ | ✅ |
338
+ | embedding-001 | 🔒 | ✅ |
339
+ | text-multilingual-embedding-002 | ✅ | 🔒 |
340
+ | textembedding-gecko-multilingual@001 | ✅ | 🔒 |
341
+ | textembedding-gecko-multilingual@latest | ✅ | 🔒 |
342
+ | textembedding-gecko@001 | ✅ | 🔒 |
343
+ | textembedding-gecko@002 | ✅ | 🔒 |
344
+ | textembedding-gecko@003 | ✅ | 🔒 |
345
+ | textembedding-gecko@latest | ✅ | 🔒 |
346
+
347
+ You can follow new models at:
348
+
349
+ - [Google models](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models)
350
+ - [Model versions and lifecycle](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versioning)
351
+
352
+ This is [the code](https://gist.github.com/gbaptista/d7390901293bce81ee12ff4ec5fed62c) used for generating this table that you can use to explore your own access.
353
+
273
354
  ## Usage
274
355
 
275
356
  ### Client
@@ -310,9 +391,11 @@ client = Gemini.new(
310
391
 
311
392
  ### Methods
312
393
 
313
- #### stream_generate_content
394
+ #### Chat
395
+
396
+ ##### stream_generate_content
314
397
 
315
- ##### Receiving Stream Events
398
+ ###### Receiving Stream Events
316
399
 
317
400
  Ensure that you have enabled [Server-Sent Events](#streaming-vs-server-sent-events-sse) before using blocks for streaming:
318
401
 
@@ -344,7 +427,7 @@ Event:
344
427
  } }
345
428
  ```
346
429
 
347
- ##### Without Events
430
+ ###### Without Events
348
431
 
349
432
  You can use `stream_generate_content` without events:
350
433
 
@@ -384,7 +467,7 @@ result = client.stream_generate_content(
384
467
  end
385
468
  ```
386
469
 
387
- #### generate_content
470
+ ##### generate_content
388
471
 
389
472
  ```ruby
390
473
  result = client.generate_content(
@@ -413,6 +496,58 @@ Result:
413
496
 
414
497
  As of the writing of this README, only the `generative-language-api` service supports the `generate_content` method; `vertex-ai-api` does not.
415
498
 
499
+ #### Embeddings
500
+
501
+ ##### predict
502
+
503
+ Vertex AI API generates embeddings through the `predict` method ([documentation](https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-text-embeddings)), and you need a client set up to use an embedding model (e.g. `text-embedding-004`):
504
+
505
+ ```ruby
506
+ result = client.predict(
507
+ { instances: [{ content: 'What is life?' }],
508
+ parameters: { autoTruncate: true } }
509
+ )
510
+ ```
511
+
512
+ Result:
513
+ ```ruby
514
+ { 'predictions' =>
515
+ [{ 'embeddings' =>
516
+ { 'statistics' => { 'truncated' => false, 'token_count' => 4 },
517
+ 'values' =>
518
+ [-0.006861076690256596,
519
+ 0.00020840796059928834,
520
+ -0.028549950569868088,
521
+ # ...
522
+ 0.0020092015620321035,
523
+ 0.03279878571629524,
524
+ -0.014905261807143688] } }],
525
+ 'metadata' => { 'billableCharacterCount' => 11 } }
526
+ ```
527
+
528
+ ##### embed_content
529
+
530
+ Generative Language API generates embeddings through the `embed_content` method ([documentation](https://ai.google.dev/api/rest/v1/models/embedContent)), and you need a client set up to use an embedding model (e.g. `text-embedding-004`):
531
+
532
+ ```ruby
533
+ result = client.embed_content(
534
+ { content: { parts: [{ text: 'What is life?' }] } }
535
+ )
536
+ ```
537
+
538
+ Result:
539
+ ```ruby
540
+ { 'embedding' =>
541
+ { 'values' =>
542
+ [-0.0065307906,
543
+ -0.0001632607,
544
+ -0.028370803,
545
+
546
+ 0.0019950708,
547
+ 0.032798845,
548
+ -0.014878989] } }
549
+ ```
550
+
416
551
  ### Modes
417
552
 
418
553
  #### Text
@@ -865,17 +1000,48 @@ Which will result in:
865
1000
 
866
1001
  ### New Functionalities and APIs
867
1002
 
868
- Google may launch a new endpoint that we haven't covered in the Gem yet. If that's the case, you may still be able to use it through the `request` method. For example, `stream_generate_content` is just a wrapper for `google/models/gemini-pro:streamGenerateContent`, which you can call directly like this:
1003
+ Google may launch a new endpoint that we haven't covered in the Gem yet. If that's the case, you may still be able to use it through the `request` method. For example, `stream_generate_content` is just a wrapper for `models/gemini-pro:streamGenerateContent` (Generative Language API) or `publishers/google/models/gemini-pro:streamGenerateContent` (Vertex AI API), which you can call directly like this:
869
1004
 
870
1005
  ```ruby
1006
+ # Generative Language API
871
1007
  result = client.request(
872
- 'streamGenerateContent',
873
- { contents: { role: 'user', parts: { text: 'hi!' } } }
1008
+ 'models/gemini-pro:streamGenerateContent',
1009
+ { contents: { role: 'user', parts: { text: 'hi!' } } },
1010
+ request_method: 'POST',
1011
+ server_sent_events: true
1012
+ )
1013
+ ```
1014
+
1015
+ ```ruby
1016
+ # Vertex AI API
1017
+ result = client.request(
1018
+ 'publishers/google/models/gemini-pro:streamGenerateContent',
1019
+ { contents: { role: 'user', parts: { text: 'hi!' } } },
1020
+ request_method: 'POST',
1021
+ server_sent_events: true
874
1022
  )
875
1023
  ```
876
1024
 
877
1025
  ### Request Options
878
1026
 
1027
+ #### Adapter
1028
+
1029
+ To enable streaming, the gem uses [Faraday](https://github.com/lostisland/faraday) with the [Typhoeus](https://github.com/typhoeus/typhoeus) adapter by default.
1030
+
1031
+ You can use a different adapter if you want:
1032
+
1033
+ ```ruby
1034
+ require 'faraday/net_http'
1035
+
1036
+ client = Gemini.new(
1037
+ credentials: { service: 'vertex-ai-api', region: 'us-east4' },
1038
+ options: {
1039
+ model: 'gemini-pro',
1040
+ connection: { adapter: :net_http }
1041
+ }
1042
+ )
1043
+ ```
1044
+
879
1045
  #### Timeout
880
1046
 
881
1047
  You can set the maximum number of seconds to wait for the request to complete with the `timeout` option:
@@ -967,6 +1133,8 @@ RequestError
967
1133
  ```bash
968
1134
  bundle
969
1135
  rubocop -A
1136
+
1137
+ bundle exec ruby spec/tasks/run-client.rb
970
1138
  ```
971
1139
 
972
1140
  ### Purpose
@@ -980,7 +1148,7 @@ gem build gemini-ai.gemspec
980
1148
 
981
1149
  gem signin
982
1150
 
983
- gem push gemini-ai-3.1.0.gem
1151
+ gem push gemini-ai-4.0.0.gem
984
1152
  ```
985
1153
 
986
1154
  ### Updating the README
@@ -1024,6 +1192,9 @@ These resources and references may be useful throughout your learning process.
1024
1192
  - [Gemini API Documentation](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/gemini)
1025
1193
  - [Vertex AI API Documentation](https://cloud.google.com/vertex-ai/docs/reference)
1026
1194
  - [REST Documentation](https://cloud.google.com/vertex-ai/docs/reference/rest)
1195
+ - [Get text embeddings](https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-text-embeddings)
1196
+ - [Google models](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models)
1197
+ - [Model versions and lifecycle](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versioning)
1027
1198
  - [Google DeepMind Gemini](https://deepmind.google/technologies/gemini/)
1028
1199
  - [Stream responses from Generative AI models](https://cloud.google.com/vertex-ai/docs/generative-ai/learn/streaming)
1029
1200
  - [Function calling](https://cloud.google.com/vertex-ai/docs/generative-ai/multimodal/function-calling)
@@ -2,17 +2,28 @@
2
2
 
3
3
  require 'event_stream_parser'
4
4
  require 'faraday'
5
+ require 'faraday/typhoeus'
5
6
  require 'json'
6
7
  require 'googleauth'
7
8
 
8
- require_relative '../ports/dsl/gemini-ai/errors'
9
+ require_relative '../components/errors'
9
10
 
10
11
  module Gemini
11
12
  module Controllers
12
13
  class Client
13
14
  ALLOWED_REQUEST_OPTIONS = %i[timeout open_timeout read_timeout write_timeout].freeze
14
15
 
16
+ DEFAULT_FARADAY_ADAPTER = :typhoeus
17
+
18
+ DEFAULT_SERVICE_VERSION = 'v1'
19
+
15
20
  def initialize(config)
21
+ @service = config[:credentials][:service]
22
+
23
+ unless %w[vertex-ai-api generative-language-api].include?(@service)
24
+ raise Errors::UnsupportedServiceError, "Unsupported service: #{@service}"
25
+ end
26
+
16
27
  if config[:credentials][:api_key]
17
28
  @authentication = :api_key
18
29
  @api_key = config[:credentials][:api_key]
@@ -30,24 +41,31 @@ module Gemini
30
41
  if @authentication == :service_account || @authentication == :default_credentials
31
42
  @project_id = config[:credentials][:project_id] || @authorizer.project_id || @authorizer.quota_project_id
32
43
 
33
- raise MissingProjectIdError, 'Could not determine project_id, which is required.' if @project_id.nil?
44
+ raise Errors::MissingProjectIdError, 'Could not determine project_id, which is required.' if @project_id.nil?
34
45
  end
35
46
 
36
- @service = config[:credentials][:service]
47
+ @service_version = config.dig(:credentials, :version) || DEFAULT_SERVICE_VERSION
37
48
 
38
- @address = case @service
39
- when 'vertex-ai-api'
40
- "https://#{config[:credentials][:region]}-aiplatform.googleapis.com/v1/projects/#{@project_id}/locations/#{config[:credentials][:region]}/publishers/google/models/#{config[:options][:model]}"
41
- when 'generative-language-api'
42
- "https://generativelanguage.googleapis.com/v1/models/#{config[:options][:model]}"
43
- else
44
- raise UnsupportedServiceError, "Unsupported service: #{@service}"
45
- end
49
+ @base_address = case @service
50
+ when 'vertex-ai-api'
51
+ "https://#{config[:credentials][:region]}-aiplatform.googleapis.com/#{@service_version}/projects/#{@project_id}/locations/#{config[:credentials][:region]}"
52
+ when 'generative-language-api'
53
+ "https://generativelanguage.googleapis.com/#{@service_version}"
54
+ end
46
55
 
47
- @server_sent_events = config[:options][:server_sent_events]
56
+ @model_address = case @service
57
+ when 'vertex-ai-api'
58
+ "publishers/google/models/#{config[:options][:model]}"
59
+ when 'generative-language-api'
60
+ "models/#{config[:options][:model]}"
61
+ end
62
+
63
+ @server_sent_events = config.dig(:options, :server_sent_events)
48
64
 
49
65
  @request_options = config.dig(:options, :connection, :request)
50
66
 
67
+ @faraday_adapter = config.dig(:options, :connection, :adapter) || DEFAULT_FARADAY_ADAPTER
68
+
51
69
  @request_options = if @request_options.is_a?(Hash)
52
70
  @request_options.select do |key, _|
53
71
  ALLOWED_REQUEST_OPTIONS.include?(key)
@@ -57,21 +75,59 @@ module Gemini
57
75
  end
58
76
  end
59
77
 
78
+ def predict(payload, server_sent_events: nil, &callback)
79
+ result = request(
80
+ "#{@model_address}:predict", payload,
81
+ server_sent_events:, &callback
82
+ )
83
+
84
+ return result.first if result.is_a?(Array) && result.size == 1
85
+
86
+ result
87
+ end
88
+
89
+ def embed_content(payload, server_sent_events: nil, &callback)
90
+ result = request(
91
+ "#{@model_address}:embedContent", payload,
92
+ server_sent_events:, &callback
93
+ )
94
+
95
+ return result.first if result.is_a?(Array) && result.size == 1
96
+
97
+ result
98
+ end
99
+
60
100
  def stream_generate_content(payload, server_sent_events: nil, &callback)
61
- request('streamGenerateContent', payload, server_sent_events:, &callback)
101
+ request("#{@model_address}:streamGenerateContent", payload, server_sent_events:, &callback)
102
+ end
103
+
104
+ def models(_server_sent_events: nil, &callback)
105
+ result = request(
106
+ 'models',
107
+ nil, server_sent_events: false, request_method: 'GET', &callback
108
+ )
109
+
110
+ return result.first if result.is_a?(Array) && result.size == 1
111
+
112
+ result
62
113
  end
63
114
 
64
115
  def generate_content(payload, server_sent_events: nil, &callback)
65
- result = request('generateContent', payload, server_sent_events:, &callback)
116
+ result = request(
117
+ "#{@model_address}:generateContent", payload,
118
+ server_sent_events:, &callback
119
+ )
66
120
 
67
121
  return result.first if result.is_a?(Array) && result.size == 1
68
122
 
69
123
  result
70
124
  end
71
125
 
72
- def request(path, payload, server_sent_events: nil, &callback)
126
+ def request(path, payload, server_sent_events: nil, request_method: 'POST', &callback)
73
127
  server_sent_events_enabled = server_sent_events.nil? ? @server_sent_events : server_sent_events
74
- url = "#{@address}:#{path}"
128
+
129
+ url = "#{@base_address}/#{path}"
130
+
75
131
  params = []
76
132
 
77
133
  params << 'alt=sse' if server_sent_events_enabled
@@ -80,25 +136,29 @@ module Gemini
80
136
  url += "?#{params.join('&')}" if params.size.positive?
81
137
 
82
138
  if !callback.nil? && !server_sent_events_enabled
83
- raise BlockWithoutServerSentEventsError,
139
+ raise Errors::BlockWithoutServerSentEventsError,
84
140
  'You are trying to use a block without Server Sent Events (SSE) enabled.'
85
141
  end
86
142
 
87
143
  results = []
88
144
 
145
+ method_to_call = request_method.to_s.strip.downcase.to_sym
146
+
89
147
  response = Faraday.new(request: @request_options) do |faraday|
148
+ faraday.adapter @faraday_adapter
90
149
  faraday.response :raise_error
91
- faraday.options.timeout = @timeout if @timeout
92
- end.post do |request|
150
+ end.send(method_to_call) do |request|
93
151
  request.url url
94
152
  request.headers['Content-Type'] = 'application/json'
95
153
  if @authentication == :service_account || @authentication == :default_credentials
96
154
  request.headers['Authorization'] = "Bearer #{@authorizer.fetch_access_token!['access_token']}"
97
155
  end
98
156
 
99
- request.body = payload.to_json
157
+ request.body = payload.to_json unless payload.nil?
100
158
 
101
159
  if server_sent_events_enabled
160
+ partial_json = ''
161
+
102
162
  parser = EventStreamParser::Parser.new
103
163
 
104
164
  request.options.on_data = proc do |chunk, bytes, env|
@@ -108,19 +168,28 @@ module Gemini
108
168
  end
109
169
 
110
170
  parser.feed(chunk) do |type, data, id, reconnection_time|
111
- parsed_data = safe_parse_json(data)
112
- result = {
113
- event: safe_parse_json(data),
114
- parsed: { type:, data:, id:, reconnection_time: },
115
- raw: { chunk:, bytes:, env: }
116
- }
171
+ partial_json += data
172
+
173
+ parsed_json = safe_parse_json(partial_json)
174
+
175
+ if parsed_json
176
+ result = {
177
+ event: parsed_json,
178
+ parsed: { type:, data:, id:, reconnection_time: },
179
+ raw: { chunk:, bytes:, env: }
180
+ }
181
+
182
+ callback.call(result[:event], result[:parsed], result[:raw]) unless callback.nil?
117
183
 
118
- callback.call(result[:event], result[:parsed], result[:raw]) unless callback.nil?
184
+ results << result
119
185
 
120
- results << result
186
+ partial_json = ''
121
187
 
122
- parsed_data['candidates'].find do |candidate|
123
- !candidate['finishReason'].nil? && candidate['finishReason'] != ''
188
+ if parsed_json['candidates']
189
+ parsed_json['candidates'].find do |candidate|
190
+ !candidate['finishReason'].nil? && candidate['finishReason'] != ''
191
+ end
192
+ end
124
193
  end
125
194
  end
126
195
  end
@@ -131,13 +200,13 @@ module Gemini
131
200
 
132
201
  results.map { |result| result[:event] }
133
202
  rescue Faraday::ServerError => e
134
- raise RequestError.new(e.message, request: e, payload:)
203
+ raise Errors::RequestError.new(e.message, request: e, payload:)
135
204
  end
136
205
 
137
206
  def safe_parse_json(raw)
138
- raw.start_with?('{', '[') ? JSON.parse(raw) : raw
207
+ raw.to_s.lstrip.start_with?('{', '[') ? JSON.parse(raw) : nil
139
208
  rescue JSON::ParserError
140
- raw
209
+ nil
141
210
  end
142
211
  end
143
212
  end
data/gemini-ai.gemspec CHANGED
@@ -30,8 +30,14 @@ Gem::Specification.new do |spec|
30
30
  spec.require_paths = ['ports/dsl']
31
31
 
32
32
  spec.add_dependency 'event_stream_parser', '~> 1.0'
33
- spec.add_dependency 'faraday', '~> 2.8', '>= 2.8.1'
34
- spec.add_dependency 'googleauth', '~> 1.9', '>= 1.9.1'
33
+ spec.add_dependency 'faraday', '~> 2.9'
34
+ spec.add_dependency 'faraday-typhoeus', '~> 1.1'
35
+
36
+ # Before upgrading, check this:
37
+ # https://github.com/gbaptista/gemini-ai/pull/10
38
+ spec.add_dependency 'googleauth', '~> 1.8'
39
+
40
+ spec.add_dependency 'typhoeus', '~> 1.4', '>= 1.4.1'
35
41
 
36
42
  spec.metadata['rubygems_mfa_required'] = 'true'
37
43
  end
data/static/gem.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Gemini
4
4
  GEM = {
5
5
  name: 'gemini-ai',
6
- version: '3.1.0',
6
+ version: '4.0.0',
7
7
  author: 'gbaptista',
8
8
  summary: "Interact with Google's Gemini AI.",
9
9
  description: "A Ruby Gem for interacting with Gemini through Vertex AI, Generative Language API, or AI Studio, Google's generative AI services.",
@@ -23,7 +23,7 @@
23
23
  (remove nil?))]
24
24
  (->> processed-lines
25
25
  (map (fn [{:keys [level title link]}]
26
- (str (apply str (repeat (* 4 (- level 2)) " "))
26
+ (str (apply str (repeat (* 2 (- level 2)) " "))
27
27
  "- ["
28
28
  title
29
29
  "](#"
data/template.md CHANGED
@@ -9,7 +9,7 @@ A Ruby Gem for interacting with [Gemini](https://deepmind.google/technologies/ge
9
9
  ## TL;DR and Quick Start
10
10
 
11
11
  ```ruby
12
- gem 'gemini-ai', '~> 3.1.0'
12
+ gem 'gemini-ai', '~> 4.0.0'
13
13
  ```
14
14
 
15
15
  ```ruby
@@ -77,11 +77,11 @@ Result:
77
77
  ### Installing
78
78
 
79
79
  ```sh
80
- gem install gemini-ai -v 3.1.0
80
+ gem install gemini-ai -v 4.0.0
81
81
  ```
82
82
 
83
83
  ```sh
84
- gem 'gemini-ai', '~> 3.1.0'
84
+ gem 'gemini-ai', '~> 4.0.0'
85
85
  ```
86
86
 
87
87
  ### Credentials
@@ -233,6 +233,80 @@ You might want to explicitly set a Google Cloud Project ID, which you can do as
233
233
  }
234
234
  ```
235
235
 
236
+ ### Custom Version
237
+
238
+ By default, the gem uses the `v1` version of the APIs. You may want to use a different version:
239
+
240
+ ```ruby
241
+ # With an API key
242
+ client = Gemini.new(
243
+ credentials: {
244
+ service: 'generative-language-api',
245
+ api_key: ENV['GOOGLE_API_KEY'],
246
+ version: 'v1beta'
247
+ },
248
+ options: { model: 'gemini-pro', server_sent_events: true }
249
+ )
250
+
251
+ # With a Service Account Credentials File
252
+ client = Gemini.new(
253
+ credentials: {
254
+ service: 'vertex-ai-api',
255
+ file_path: 'google-credentials.json',
256
+ region: 'us-east4',
257
+ version: 'v1beta'
258
+ },
259
+ options: { model: 'gemini-pro', server_sent_events: true }
260
+ )
261
+
262
+ # With Application Default Credentials
263
+ client = Gemini.new(
264
+ credentials: {
265
+ service: 'vertex-ai-api',
266
+ region: 'us-east4',
267
+ version: 'v1beta'
268
+ },
269
+ options: { model: 'gemini-pro', server_sent_events: true }
270
+ )
271
+ ```
272
+
273
+ ## Available Models
274
+
275
+ These models are accessible to the repository **author** as of May 2025 in the `us-east4` region. Access to models may vary by region, user, and account. All models here are expected to work, if you can access them. This is just a reference of what a "typical" user may expect to have access to right away:
276
+
277
+ | Model | Vertex AI | Generative Language |
278
+ |------------------------------------------|:---------:|:-------------------:|
279
+ | gemini-pro-vision | ✅ | 🔒 |
280
+ | gemini-pro | ✅ | ✅ |
281
+ | gemini-1.5-pro-preview-0514 | ✅ | 🔒 |
282
+ | gemini-1.5-pro-preview-0409 | ✅ | 🔒 |
283
+ | gemini-1.5-pro | 🔒 | 🔒 |
284
+ | gemini-1.5-flash-preview-0514 | ✅ | 🔒 |
285
+ | gemini-1.5-flash | 🔒 | 🔒 |
286
+ | gemini-1.0-pro-vision-latest | 🔒 | 🔒 |
287
+ | gemini-1.0-pro-vision-001 | ✅ | 🔒 |
288
+ | gemini-1.0-pro-vision | ✅ | 🔒 |
289
+ | gemini-1.0-pro-latest | 🔒 | ✅ |
290
+ | gemini-1.0-pro-002 | ✅ | 🔒 |
291
+ | gemini-1.0-pro-001 | ✅ | ✅ |
292
+ | gemini-1.0-pro | ✅ | ✅ |
293
+ | text-embedding-004 | ✅ | ✅ |
294
+ | embedding-001 | 🔒 | ✅ |
295
+ | text-multilingual-embedding-002 | ✅ | 🔒 |
296
+ | textembedding-gecko-multilingual@001 | ✅ | 🔒 |
297
+ | textembedding-gecko-multilingual@latest | ✅ | 🔒 |
298
+ | textembedding-gecko@001 | ✅ | 🔒 |
299
+ | textembedding-gecko@002 | ✅ | 🔒 |
300
+ | textembedding-gecko@003 | ✅ | 🔒 |
301
+ | textembedding-gecko@latest | ✅ | 🔒 |
302
+
303
+ You can follow new models at:
304
+
305
+ - [Google models](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models)
306
+ - [Model versions and lifecycle](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versioning)
307
+
308
+ This is [the code](https://gist.github.com/gbaptista/d7390901293bce81ee12ff4ec5fed62c) used for generating this table that you can use to explore your own access.
309
+
236
310
  ## Usage
237
311
 
238
312
  ### Client
@@ -273,9 +347,11 @@ client = Gemini.new(
273
347
 
274
348
  ### Methods
275
349
 
276
- #### stream_generate_content
350
+ #### Chat
351
+
352
+ ##### stream_generate_content
277
353
 
278
- ##### Receiving Stream Events
354
+ ###### Receiving Stream Events
279
355
 
280
356
  Ensure that you have enabled [Server-Sent Events](#streaming-vs-server-sent-events-sse) before using blocks for streaming:
281
357
 
@@ -307,7 +383,7 @@ Event:
307
383
  } }
308
384
  ```
309
385
 
310
- ##### Without Events
386
+ ###### Without Events
311
387
 
312
388
  You can use `stream_generate_content` without events:
313
389
 
@@ -347,7 +423,7 @@ result = client.stream_generate_content(
347
423
  end
348
424
  ```
349
425
 
350
- #### generate_content
426
+ ##### generate_content
351
427
 
352
428
  ```ruby
353
429
  result = client.generate_content(
@@ -376,6 +452,58 @@ Result:
376
452
 
377
453
  As of the writing of this README, only the `generative-language-api` service supports the `generate_content` method; `vertex-ai-api` does not.
378
454
 
455
+ #### Embeddings
456
+
457
+ ##### predict
458
+
459
+ Vertex AI API generates embeddings through the `predict` method ([documentation](https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-text-embeddings)), and you need a client set up to use an embedding model (e.g. `text-embedding-004`):
460
+
461
+ ```ruby
462
+ result = client.predict(
463
+ { instances: [{ content: 'What is life?' }],
464
+ parameters: { autoTruncate: true } }
465
+ )
466
+ ```
467
+
468
+ Result:
469
+ ```ruby
470
+ { 'predictions' =>
471
+ [{ 'embeddings' =>
472
+ { 'statistics' => { 'truncated' => false, 'token_count' => 4 },
473
+ 'values' =>
474
+ [-0.006861076690256596,
475
+ 0.00020840796059928834,
476
+ -0.028549950569868088,
477
+ # ...
478
+ 0.0020092015620321035,
479
+ 0.03279878571629524,
480
+ -0.014905261807143688] } }],
481
+ 'metadata' => { 'billableCharacterCount' => 11 } }
482
+ ```
483
+
484
+ ##### embed_content
485
+
486
+ Generative Language API generates embeddings through the `embed_content` method ([documentation](https://ai.google.dev/api/rest/v1/models/embedContent)), and you need a client set up to use an embedding model (e.g. `text-embedding-004`):
487
+
488
+ ```ruby
489
+ result = client.embed_content(
490
+ { content: { parts: [{ text: 'What is life?' }] } }
491
+ )
492
+ ```
493
+
494
+ Result:
495
+ ```ruby
496
+ { 'embedding' =>
497
+ { 'values' =>
498
+ [-0.0065307906,
499
+ -0.0001632607,
500
+ -0.028370803,
501
+
502
+ 0.0019950708,
503
+ 0.032798845,
504
+ -0.014878989] } }
505
+ ```
506
+
379
507
  ### Modes
380
508
 
381
509
  #### Text
@@ -828,17 +956,48 @@ Which will result in:
828
956
 
829
957
  ### New Functionalities and APIs
830
958
 
831
- Google may launch a new endpoint that we haven't covered in the Gem yet. If that's the case, you may still be able to use it through the `request` method. For example, `stream_generate_content` is just a wrapper for `google/models/gemini-pro:streamGenerateContent`, which you can call directly like this:
959
+ Google may launch a new endpoint that we haven't covered in the Gem yet. If that's the case, you may still be able to use it through the `request` method. For example, `stream_generate_content` is just a wrapper for `models/gemini-pro:streamGenerateContent` (Generative Language API) or `publishers/google/models/gemini-pro:streamGenerateContent` (Vertex AI API), which you can call directly like this:
832
960
 
833
961
  ```ruby
962
+ # Generative Language API
834
963
  result = client.request(
835
- 'streamGenerateContent',
836
- { contents: { role: 'user', parts: { text: 'hi!' } } }
964
+ 'models/gemini-pro:streamGenerateContent',
965
+ { contents: { role: 'user', parts: { text: 'hi!' } } },
966
+ request_method: 'POST',
967
+ server_sent_events: true
968
+ )
969
+ ```
970
+
971
+ ```ruby
972
+ # Vertex AI API
973
+ result = client.request(
974
+ 'publishers/google/models/gemini-pro:streamGenerateContent',
975
+ { contents: { role: 'user', parts: { text: 'hi!' } } },
976
+ request_method: 'POST',
977
+ server_sent_events: true
837
978
  )
838
979
  ```
839
980
 
840
981
  ### Request Options
841
982
 
983
+ #### Adapter
984
+
985
+ To enable streaming, the gem uses [Faraday](https://github.com/lostisland/faraday) with the [Typhoeus](https://github.com/typhoeus/typhoeus) adapter by default.
986
+
987
+ You can use a different adapter if you want:
988
+
989
+ ```ruby
990
+ require 'faraday/net_http'
991
+
992
+ client = Gemini.new(
993
+ credentials: { service: 'vertex-ai-api', region: 'us-east4' },
994
+ options: {
995
+ model: 'gemini-pro',
996
+ connection: { adapter: :net_http }
997
+ }
998
+ )
999
+ ```
1000
+
842
1001
  #### Timeout
843
1002
 
844
1003
  You can set the maximum number of seconds to wait for the request to complete with the `timeout` option:
@@ -930,6 +1089,8 @@ RequestError
930
1089
  ```bash
931
1090
  bundle
932
1091
  rubocop -A
1092
+
1093
+ bundle exec ruby spec/tasks/run-client.rb
933
1094
  ```
934
1095
 
935
1096
  ### Purpose
@@ -943,7 +1104,7 @@ gem build gemini-ai.gemspec
943
1104
 
944
1105
  gem signin
945
1106
 
946
- gem push gemini-ai-3.1.0.gem
1107
+ gem push gemini-ai-4.0.0.gem
947
1108
  ```
948
1109
 
949
1110
  ### Updating the README
@@ -987,6 +1148,9 @@ These resources and references may be useful throughout your learning process.
987
1148
  - [Gemini API Documentation](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/gemini)
988
1149
  - [Vertex AI API Documentation](https://cloud.google.com/vertex-ai/docs/reference)
989
1150
  - [REST Documentation](https://cloud.google.com/vertex-ai/docs/reference/rest)
1151
+ - [Get text embeddings](https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-text-embeddings)
1152
+ - [Google models](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models)
1153
+ - [Model versions and lifecycle](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versioning)
990
1154
  - [Google DeepMind Gemini](https://deepmind.google/technologies/gemini/)
991
1155
  - [Stream responses from Generative AI models](https://cloud.google.com/vertex-ai/docs/generative-ai/learn/streaming)
992
1156
  - [Function calling](https://cloud.google.com/vertex-ai/docs/generative-ai/multimodal/function-calling)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gemini-ai
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gbaptista
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-26 00:00:00.000000000 Z
11
+ date: 2024-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: event_stream_parser
@@ -30,43 +30,65 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.8'
34
- - - ">="
35
- - !ruby/object:Gem::Version
36
- version: 2.8.1
33
+ version: '2.9'
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
37
  requirements:
41
38
  - - "~>"
42
39
  - !ruby/object:Gem::Version
43
- version: '2.8'
44
- - - ">="
40
+ version: '2.9'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday-typhoeus
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
45
53
  - !ruby/object:Gem::Version
46
- version: 2.8.1
54
+ version: '1.1'
47
55
  - !ruby/object:Gem::Dependency
48
56
  name: googleauth
49
57
  requirement: !ruby/object:Gem::Requirement
50
58
  requirements:
51
59
  - - "~>"
52
60
  - !ruby/object:Gem::Version
53
- version: '1.9'
61
+ version: '1.8'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.8'
69
+ - !ruby/object:Gem::Dependency
70
+ name: typhoeus
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.4'
54
76
  - - ">="
55
77
  - !ruby/object:Gem::Version
56
- version: 1.9.1
78
+ version: 1.4.1
57
79
  type: :runtime
58
80
  prerelease: false
59
81
  version_requirements: !ruby/object:Gem::Requirement
60
82
  requirements:
61
83
  - - "~>"
62
84
  - !ruby/object:Gem::Version
63
- version: '1.9'
85
+ version: '1.4'
64
86
  - - ">="
65
87
  - !ruby/object:Gem::Version
66
- version: 1.9.1
88
+ version: 1.4.1
67
89
  description: A Ruby Gem for interacting with Gemini through Vertex AI, Generative
68
90
  Language API, or AI Studio, Google's generative AI services.
69
- email:
91
+ email:
70
92
  executables: []
71
93
  extensions: []
72
94
  extra_rdoc_files: []
@@ -94,7 +116,7 @@ metadata:
94
116
  homepage_uri: https://github.com/gbaptista/gemini-ai
95
117
  source_code_uri: https://github.com/gbaptista/gemini-ai
96
118
  rubygems_mfa_required: 'true'
97
- post_install_message:
119
+ post_install_message:
98
120
  rdoc_options: []
99
121
  require_paths:
100
122
  - ports/dsl
@@ -110,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
132
  version: '0'
111
133
  requirements: []
112
134
  rubygems_version: 3.3.3
113
- signing_key:
135
+ signing_key:
114
136
  specification_version: 4
115
137
  summary: Interact with Google's Gemini AI.
116
138
  test_files: []