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 +4 -4
- data/.gitignore +5 -0
- data/Gemfile +2 -1
- data/Gemfile.lock +41 -25
- data/README.md +213 -42
- data/controllers/client.rb +102 -33
- data/gemini-ai.gemspec +8 -2
- data/static/gem.rb +1 -1
- data/tasks/generate-readme.clj +1 -1
- data/template.md +175 -11
- metadata +39 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b66c146b7230d838c888d5f90107f07bcc2827c7710b77c1284c52315b3c9515
|
|
4
|
+
data.tar.gz: c125664051e260270bb08b81ecc932a3e4b730ea1c69601ba93af4749af54fcf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dd67f092295620ff45cb75f07b67dc0753d54c92ff598284a0f10ce4a45e7f395aad0235320fb95ab86bb12f9033c21e4b3fe776bb99bd6d98f8228054bc6bca
|
|
7
|
+
data.tar.gz: c03ab797796745870124159762e11f0ea5a56ee9cb033f97c7b62088dd0a2d2dae85f1fa874245ddc3fa3482ae7739f1a311546807ee78e1dbd17e7f5807cc52
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
gemini-ai (
|
|
4
|
+
gemini-ai (4.0.0)
|
|
5
5
|
event_stream_parser (~> 1.0)
|
|
6
|
-
faraday (~> 2.
|
|
7
|
-
|
|
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.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
faraday-
|
|
24
|
-
|
|
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.
|
|
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.
|
|
34
|
-
jwt (2.
|
|
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.
|
|
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.
|
|
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.
|
|
60
|
+
public_suffix (5.0.5)
|
|
50
61
|
racc (1.7.3)
|
|
51
62
|
rainbow (3.1.1)
|
|
52
|
-
regexp_parser (2.
|
|
53
|
-
rexml (3.2.
|
|
54
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
66
|
-
parser (>= 3.
|
|
77
|
+
rubocop-ast (1.31.3)
|
|
78
|
+
parser (>= 3.3.1.0)
|
|
67
79
|
ruby-progressbar (1.13.0)
|
|
68
|
-
|
|
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.
|
|
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', '~>
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
- [
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
- [
|
|
97
|
-
|
|
98
|
-
- [
|
|
99
|
-
- [
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
|
124
|
+
gem install gemini-ai -v 4.0.0
|
|
118
125
|
```
|
|
119
126
|
|
|
120
127
|
```sh
|
|
121
|
-
gem 'gemini-ai', '~>
|
|
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
|
-
####
|
|
394
|
+
#### Chat
|
|
395
|
+
|
|
396
|
+
##### stream_generate_content
|
|
314
397
|
|
|
315
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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-
|
|
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)
|
data/controllers/client.rb
CHANGED
|
@@ -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 '../
|
|
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
|
-
@
|
|
47
|
+
@service_version = config.dig(:credentials, :version) || DEFAULT_SERVICE_VERSION
|
|
37
48
|
|
|
38
|
-
@
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
@
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
184
|
+
results << result
|
|
119
185
|
|
|
120
|
-
|
|
186
|
+
partial_json = ''
|
|
121
187
|
|
|
122
|
-
|
|
123
|
-
|
|
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) :
|
|
207
|
+
raw.to_s.lstrip.start_with?('{', '[') ? JSON.parse(raw) : nil
|
|
139
208
|
rescue JSON::ParserError
|
|
140
|
-
|
|
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.
|
|
34
|
-
spec.add_dependency '
|
|
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: '
|
|
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.",
|
data/tasks/generate-readme.clj
CHANGED
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', '~>
|
|
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
|
|
80
|
+
gem install gemini-ai -v 4.0.0
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
```sh
|
|
84
|
-
gem 'gemini-ai', '~>
|
|
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
|
-
####
|
|
350
|
+
#### Chat
|
|
351
|
+
|
|
352
|
+
##### stream_generate_content
|
|
277
353
|
|
|
278
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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-
|
|
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:
|
|
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:
|
|
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.
|
|
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.
|
|
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:
|
|
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.
|
|
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.
|
|
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.
|
|
85
|
+
version: '1.4'
|
|
64
86
|
- - ">="
|
|
65
87
|
- !ruby/object:Gem::Version
|
|
66
|
-
version: 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: []
|