gemini-ai 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b66c146b7230d838c888d5f90107f07bcc2827c7710b77c1284c52315b3c9515
4
- data.tar.gz: c125664051e260270bb08b81ecc932a3e4b730ea1c69601ba93af4749af54fcf
3
+ metadata.gz: eda19196e43e0d519127fd3e91c477835d03035115d837849ac398788901d50a
4
+ data.tar.gz: dad8ccd200487954be14b3cd2e459848e5e557bb10961bcbfdedc70733191742
5
5
  SHA512:
6
- metadata.gz: dd67f092295620ff45cb75f07b67dc0753d54c92ff598284a0f10ce4a45e7f395aad0235320fb95ab86bb12f9033c21e4b3fe776bb99bd6d98f8228054bc6bca
7
- data.tar.gz: c03ab797796745870124159762e11f0ea5a56ee9cb033f97c7b62088dd0a2d2dae85f1fa874245ddc3fa3482ae7739f1a311546807ee78e1dbd17e7f5807cc52
6
+ metadata.gz: ee6e3a097d57d1a4f81d74bcec541a03aa23e1829d36b0296817345da6503fc1a198baad7e333e68996654f586ddc822704572159c297afe05e41ba687e2bba3
7
+ data.tar.gz: 55eae644861d7c4a45ab2551357e17c44b4490f0d73b706adeb26b12a1931f65db77a5ca64b589b2447367404fea7951cc15710ba12ce2b4561a7b12f84fc05e
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml CHANGED
@@ -4,3 +4,6 @@ AllCops:
4
4
 
5
5
  Style/Documentation:
6
6
  Enabled: false
7
+
8
+ require:
9
+ - rubocop-rspec
data/Gemfile CHANGED
@@ -7,5 +7,7 @@ gemspec
7
7
  group :test, :development do
8
8
  gem 'dotenv', '~> 3.1', '>= 3.1.2'
9
9
  gem 'pry-byebug', '~> 3.10', '>= 3.10.1'
10
- gem 'rubocop', '~> 1.63', '>= 1.63.5'
10
+ gem 'rspec', '~> 3.13'
11
+ gem 'rubocop', '~> 1.64', '>= 1.64.1'
12
+ gem 'rubocop-rspec', '~> 3.0', '>= 3.0.1'
11
13
  end
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gemini-ai (4.0.0)
4
+ gemini-ai (4.1.0)
5
5
  event_stream_parser (~> 1.0)
6
- faraday (~> 2.9)
6
+ faraday (~> 2.9, >= 2.9.2)
7
7
  faraday-typhoeus (~> 1.1)
8
8
  googleauth (~> 1.8)
9
9
  typhoeus (~> 1.4, >= 1.4.1)
@@ -11,24 +11,25 @@ PATH
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- addressable (2.8.6)
15
- public_suffix (>= 2.0.2, < 6.0)
14
+ addressable (2.8.7)
15
+ public_suffix (>= 2.0.2, < 7.0)
16
16
  ast (2.4.2)
17
17
  base64 (0.2.0)
18
18
  byebug (11.1.3)
19
19
  coderay (1.1.3)
20
+ diff-lcs (1.5.1)
20
21
  dotenv (3.1.2)
21
22
  ethon (0.16.0)
22
23
  ffi (>= 1.15.0)
23
24
  event_stream_parser (1.0.0)
24
- faraday (2.9.0)
25
+ faraday (2.9.2)
25
26
  faraday-net_http (>= 2.0, < 3.2)
26
27
  faraday-net_http (3.1.0)
27
28
  net-http
28
29
  faraday-typhoeus (1.1.0)
29
30
  faraday (~> 2.0)
30
31
  typhoeus (~> 1.4)
31
- ffi (1.16.3)
32
+ ffi (1.17.0)
32
33
  google-cloud-env (2.1.1)
33
34
  faraday (>= 1.0, < 3.a)
34
35
  googleauth (1.11.0)
@@ -39,7 +40,7 @@ GEM
39
40
  os (>= 0.9, < 2.0)
40
41
  signet (>= 0.16, < 2.a)
41
42
  json (2.7.2)
42
- jwt (2.8.1)
43
+ jwt (2.8.2)
43
44
  base64
44
45
  language_server-protocol (3.17.0.3)
45
46
  method_source (1.1.0)
@@ -47,8 +48,8 @@ GEM
47
48
  net-http (0.4.1)
48
49
  uri
49
50
  os (1.1.4)
50
- parallel (1.24.0)
51
- parser (3.3.1.0)
51
+ parallel (1.25.1)
52
+ parser (3.3.3.0)
52
53
  ast (~> 2.4.1)
53
54
  racc
54
55
  pry (0.14.2)
@@ -57,13 +58,26 @@ GEM
57
58
  pry-byebug (3.10.1)
58
59
  byebug (~> 11.0)
59
60
  pry (>= 0.13, < 0.15)
60
- public_suffix (5.0.5)
61
- racc (1.7.3)
61
+ public_suffix (6.0.0)
62
+ racc (1.8.0)
62
63
  rainbow (3.1.1)
63
64
  regexp_parser (2.9.2)
64
- rexml (3.2.8)
65
- strscan (>= 3.0.9)
66
- rubocop (1.63.5)
65
+ rexml (3.3.0)
66
+ strscan
67
+ rspec (3.13.0)
68
+ rspec-core (~> 3.13.0)
69
+ rspec-expectations (~> 3.13.0)
70
+ rspec-mocks (~> 3.13.0)
71
+ rspec-core (3.13.0)
72
+ rspec-support (~> 3.13.0)
73
+ rspec-expectations (3.13.1)
74
+ diff-lcs (>= 1.2.0, < 2.0)
75
+ rspec-support (~> 3.13.0)
76
+ rspec-mocks (3.13.1)
77
+ diff-lcs (>= 1.2.0, < 2.0)
78
+ rspec-support (~> 3.13.0)
79
+ rspec-support (3.13.1)
80
+ rubocop (1.64.1)
67
81
  json (~> 2.3)
68
82
  language_server-protocol (>= 3.17.0)
69
83
  parallel (~> 1.10)
@@ -76,6 +90,8 @@ GEM
76
90
  unicode-display_width (>= 2.4.0, < 3.0)
77
91
  rubocop-ast (1.31.3)
78
92
  parser (>= 3.3.1.0)
93
+ rubocop-rspec (3.0.1)
94
+ rubocop (~> 1.61)
79
95
  ruby-progressbar (1.13.0)
80
96
  signet (0.19.0)
81
97
  addressable (~> 2.8)
@@ -95,7 +111,9 @@ DEPENDENCIES
95
111
  dotenv (~> 3.1, >= 3.1.2)
96
112
  gemini-ai!
97
113
  pry-byebug (~> 3.10, >= 3.10.1)
98
- rubocop (~> 1.63, >= 1.63.5)
114
+ rspec (~> 3.13)
115
+ rubocop (~> 1.64, >= 1.64.1)
116
+ rubocop-rspec (~> 3.0, >= 3.0.1)
99
117
 
100
118
  BUNDLED WITH
101
119
  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', '~> 4.0.0'
12
+ gem 'gemini-ai', '~> 4.1.0'
13
13
  ```
14
14
 
15
15
  ```ruby
@@ -34,6 +34,17 @@ client = Gemini.new(
34
34
  options: { model: 'gemini-pro', server_sent_events: true }
35
35
  )
36
36
 
37
+ # With the Service Account Credentials File contents
38
+ client = Gemini.new(
39
+ credentials: {
40
+ service: 'vertex-ai-api',
41
+ file_contents: File.read('google-credentials.json'),
42
+ # file_contents: ENV['GOOGLE_CREDENTIALS_FILE_CONTENTS'],
43
+ region: 'us-east4'
44
+ },
45
+ options: { model: 'gemini-pro', server_sent_events: true }
46
+ )
47
+
37
48
  # With Application Default Credentials
38
49
  client = Gemini.new(
39
50
  credentials: {
@@ -100,6 +111,11 @@ Result:
100
111
  - [Server-Sent Events (SSE) Hang](#server-sent-events-sse-hang)
101
112
  - [Non-Streaming](#non-streaming)
102
113
  - [Back-and-Forth Conversations](#back-and-forth-conversations)
114
+ - [Safety Settings](#safety-settings)
115
+ - [System Instructions](#system-instructions)
116
+ - [JSON Format Responses](#json-format-responses)
117
+ - [JSON Schema](#json-schema)
118
+ - [Models That Support JSON](#models-that-support-json)
103
119
  - [Tools (Functions) Calling](#tools-functions-calling)
104
120
  - [New Functionalities and APIs](#new-functionalities-and-apis)
105
121
  - [Request Options](#request-options)
@@ -121,11 +137,11 @@ Result:
121
137
  ### Installing
122
138
 
123
139
  ```sh
124
- gem install gemini-ai -v 4.0.0
140
+ gem install gemini-ai -v 4.1.0
125
141
  ```
126
142
 
127
143
  ```sh
128
- gem 'gemini-ai', '~> 4.0.0'
144
+ gem 'gemini-ai', '~> 4.1.0'
129
145
  ```
130
146
 
131
147
  ### Credentials
@@ -207,7 +223,7 @@ Similar to [Option 2](#option-2-service-account-credentials-file-vertex-ai-api),
207
223
  For local development, you can generate your default credentials using the [gcloud CLI](https://cloud.google.com/sdk/gcloud) as follows:
208
224
 
209
225
  ```sh
210
- gcloud auth application-default login
226
+ gcloud auth application-default login
211
227
  ```
212
228
 
213
229
  For more details about alternative methods and different environments, check the official documentation:
@@ -245,6 +261,23 @@ Remember that hardcoding your API key in code is unsafe; it's preferable to use
245
261
  }
246
262
  ```
247
263
 
264
+ Alternatively, you can pass the file contents instead of the path:
265
+ ```ruby
266
+ {
267
+ service: 'vertex-ai-api',
268
+ file_contents: File.read('google-credentials.json'),
269
+ region: 'us-east4'
270
+ }
271
+ ```
272
+
273
+ ```ruby
274
+ {
275
+ service: 'vertex-ai-api',
276
+ file_contents: ENV['GOOGLE_CREDENTIALS_FILE_CONTENTS'],
277
+ region: 'us-east4'
278
+ }
279
+ ```
280
+
248
281
  **Option 3**: For _Application Default Credentials_, omit both the `api_key` and the `file_path`:
249
282
 
250
283
  ```ruby
@@ -303,6 +336,17 @@ client = Gemini.new(
303
336
  options: { model: 'gemini-pro', server_sent_events: true }
304
337
  )
305
338
 
339
+ # With the Service Account Credentials File contents
340
+ client = Gemini.new(
341
+ credentials: {
342
+ service: 'vertex-ai-api',
343
+ file_contents: File.read('google-credentials.json'),
344
+ # file_contents: ENV['GOOGLE_CREDENTIALS_FILE_CONTENTS'],
345
+ region: 'us-east4'
346
+ },
347
+ options: { model: 'gemini-pro', server_sent_events: true }
348
+ )
349
+
306
350
  # With Application Default Credentials
307
351
  client = Gemini.new(
308
352
  credentials: {
@@ -316,7 +360,7 @@ client = Gemini.new(
316
360
 
317
361
  ## Available Models
318
362
 
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:
363
+ These models are accessible to the repository **author** as of June 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
364
 
321
365
  | Model | Vertex AI | Generative Language |
322
366
  |------------------------------------------|:---------:|:-------------------:|
@@ -324,9 +368,9 @@ These models are accessible to the repository **author** as of May 2025 in the `
324
368
  | gemini-pro | ✅ | ✅ |
325
369
  | gemini-1.5-pro-preview-0514 | ✅ | 🔒 |
326
370
  | gemini-1.5-pro-preview-0409 | ✅ | 🔒 |
327
- | gemini-1.5-pro | 🔒 | 🔒 |
371
+ | gemini-1.5-pro | | |
328
372
  | gemini-1.5-flash-preview-0514 | ✅ | 🔒 |
329
- | gemini-1.5-flash | 🔒 | 🔒 |
373
+ | gemini-1.5-flash | | |
330
374
  | gemini-1.0-pro-vision-latest | 🔒 | 🔒 |
331
375
  | gemini-1.0-pro-vision-001 | ✅ | 🔒 |
332
376
  | gemini-1.0-pro-vision | ✅ | 🔒 |
@@ -334,6 +378,11 @@ These models are accessible to the repository **author** as of May 2025 in the `
334
378
  | gemini-1.0-pro-002 | ✅ | 🔒 |
335
379
  | gemini-1.0-pro-001 | ✅ | ✅ |
336
380
  | gemini-1.0-pro | ✅ | ✅ |
381
+ | gemini-ultra | 🔒 | 🔒 |
382
+ | gemini-1.0-ultra | 🔒 | 🔒 |
383
+ | gemini-1.0-ultra-001 | 🔒 | 🔒 |
384
+ | text-embedding-preview-0514 | 🔒 | 🔒 |
385
+ | text-embedding-preview-0409 | 🔒 | 🔒 |
337
386
  | text-embedding-004 | ✅ | ✅ |
338
387
  | embedding-001 | 🔒 | ✅ |
339
388
  | text-multilingual-embedding-002 | ✅ | 🔒 |
@@ -379,6 +428,17 @@ client = Gemini.new(
379
428
  options: { model: 'gemini-pro', server_sent_events: true }
380
429
  )
381
430
 
431
+ # With the Service Account Credentials File contents
432
+ client = Gemini.new(
433
+ credentials: {
434
+ service: 'vertex-ai-api',
435
+ file_contents: File.read('google-credentials.json'),
436
+ # file_contents: ENV['GOOGLE_CREDENTIALS_FILE_CONTENTS'],
437
+ region: 'us-east4'
438
+ },
439
+ options: { model: 'gemini-pro', server_sent_events: true }
440
+ )
441
+
382
442
  # With Application Default Credentials
383
443
  client = Gemini.new(
384
444
  credentials: {
@@ -853,6 +913,208 @@ Result:
853
913
  } }]
854
914
  ```
855
915
 
916
+ ### Safety Settings
917
+
918
+ You can [configure safety attributes](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/configure-safety-attributes) for your requests.
919
+
920
+ Harm Categories:
921
+ > `HARM_CATEGORY_UNSPECIFIED`, `HARM_CATEGORY_HARASSMENT`, `HARM_CATEGORY_HATE_SPEECH`, `HARM_CATEGORY_SEXUALLY_EXPLICIT`, `HARM_CATEGORY_DANGEROUS_CONTENT`.
922
+
923
+ Thresholds:
924
+ > `BLOCK_NONE`, `BLOCK_ONLY_HIGH`, `BLOCK_MEDIUM_AND_ABOVE`, `BLOCK_LOW_AND_ABOVE`, `HARM_BLOCK_THRESHOLD_UNSPECIFIED`.
925
+
926
+ Example:
927
+ ```ruby
928
+ client.stream_generate_content(
929
+ {
930
+ contents: { role: 'user', parts: { text: 'hi!' } },
931
+ safetySettings: [
932
+ {
933
+ category: 'HARM_CATEGORY_UNSPECIFIED',
934
+ threshold: 'BLOCK_ONLY_HIGH'
935
+ },
936
+ {
937
+ category: 'HARM_CATEGORY_HARASSMENT',
938
+ threshold: 'BLOCK_ONLY_HIGH'
939
+ },
940
+ {
941
+ category: 'HARM_CATEGORY_HATE_SPEECH',
942
+ threshold: 'BLOCK_ONLY_HIGH'
943
+ },
944
+ {
945
+ category: 'HARM_CATEGORY_SEXUALLY_EXPLICIT',
946
+ threshold: 'BLOCK_ONLY_HIGH'
947
+ },
948
+ {
949
+ category: 'HARM_CATEGORY_DANGEROUS_CONTENT',
950
+ threshold: 'BLOCK_ONLY_HIGH'
951
+ }
952
+ ]
953
+ }
954
+ )
955
+ ```
956
+
957
+ Google started to block the usage of `BLOCK_NONE` unless:
958
+
959
+ > _User has requested a restricted HarmBlockThreshold setting BLOCK_NONE. You can get access either (a) through an allowlist via your Google account team, or (b) by switching your account type to monthly invoiced billing via this instruction: https://cloud.google.com/billing/docs/how-to/invoiced-billing_
960
+
961
+ ### System Instructions
962
+
963
+ Some models support [system instructions](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/prompts/system-instructions):
964
+
965
+ ```ruby
966
+ client.stream_generate_content(
967
+ { contents: { role: 'user', parts: { text: 'Hi! Who are you?' } },
968
+ system_instruction: { role: 'user', parts: { text: 'Your name is Neko.' } } }
969
+ )
970
+ ```
971
+
972
+ Output:
973
+ ```text
974
+ Hi! I'm Neko, a factual language model from Google AI.
975
+ ```
976
+
977
+ ```ruby
978
+ client.stream_generate_content(
979
+ { contents: { role: 'user', parts: { text: 'Hi! Who are you?' } },
980
+ system_instruction: {
981
+ role: 'user', parts: [
982
+ { text: 'You are a cat.' },
983
+ { text: 'Your name is Neko.' }
984
+ ]
985
+ } }
986
+ )
987
+ ```
988
+
989
+ Output:
990
+ ```text
991
+ Meow! I'm Neko, a fluffy and playful cat. :3
992
+ ```
993
+
994
+ ### JSON Format Responses
995
+
996
+ > _As of the writing of this README, only the `vertex-ai-api` service and `gemini` models version `1.5` support this feature._
997
+
998
+ The Gemini API provides a configuration parameter to [request a response in JSON](https://ai.google.dev/gemini-api/docs/api-overview#json) format:
999
+
1000
+ ```ruby
1001
+ require 'json'
1002
+
1003
+ result = client.stream_generate_content(
1004
+ {
1005
+ contents: {
1006
+ role: 'user',
1007
+ parts: {
1008
+ text: 'List 3 random colors.'
1009
+ }
1010
+ },
1011
+ generation_config: {
1012
+ response_mime_type: 'application/json'
1013
+ }
1014
+
1015
+ }
1016
+ )
1017
+
1018
+ json_string = result
1019
+ .map { |response| response.dig('candidates', 0, 'content', 'parts') }
1020
+ .map { |parts| parts.map { |part| part['text'] }.join }
1021
+ .join
1022
+
1023
+ puts JSON.parse(json_string).inspect
1024
+ ```
1025
+
1026
+ Output:
1027
+ ```ruby
1028
+ { 'colors' => ['Dark Salmon', 'Indigo', 'Lavender'] }
1029
+ ```
1030
+
1031
+ #### JSON Schema
1032
+
1033
+ > _While Gemini 1.5 Flash models only accept a text description of the JSON schema you want returned, the Gemini 1.5 Pro models let you pass a schema object (or a Python type equivalent), and the model output will strictly follow that schema. This is also known as controlled generation or constrained decoding._
1034
+
1035
+ You can also provide a [JSON Schema](https://json-schema.org) for the expected JSON output:
1036
+
1037
+ ```ruby
1038
+ require 'json'
1039
+
1040
+ result = client.stream_generate_content(
1041
+ {
1042
+ contents: {
1043
+ role: 'user',
1044
+ parts: {
1045
+ text: 'List 3 random colors.'
1046
+ }
1047
+ },
1048
+ generation_config: {
1049
+ response_mime_type: 'application/json',
1050
+ response_schema: {
1051
+ type: 'object',
1052
+ properties: {
1053
+ colors: {
1054
+ type: 'array',
1055
+ items: {
1056
+ type: 'object',
1057
+ properties: {
1058
+ name: {
1059
+ type: 'string'
1060
+ }
1061
+ }
1062
+ }
1063
+ }
1064
+ }
1065
+ }
1066
+ }
1067
+ }
1068
+ )
1069
+
1070
+ json_string = result
1071
+ .map { |response| response.dig('candidates', 0, 'content', 'parts') }
1072
+ .map { |parts| parts.map { |part| part['text'] }.join }
1073
+ .join
1074
+
1075
+ puts JSON.parse(json_string).inspect
1076
+ ```
1077
+
1078
+ Output:
1079
+
1080
+ ```ruby
1081
+ { 'colors' => [
1082
+ { 'name' => 'Lavender Blush' },
1083
+ { 'name' => 'Medium Turquoise' },
1084
+ { 'name' => 'Dark Slate Gray' }
1085
+ ] }
1086
+ ```
1087
+
1088
+ #### Models That Support JSON
1089
+
1090
+ These models are accessible to the repository **author** as of June 2025 in the `us-east4` region. Access to models may vary by region, user, and account.
1091
+
1092
+ - ❌ Does not support JSON mode.
1093
+ - 🟡 Supports JSON mode but not Schema.
1094
+ - ✅ Supports JSON mode and Schema.
1095
+ - 🔒 I don't have access to the model.
1096
+
1097
+ | Model | Vertex AI | Generative Language |
1098
+ |------------------------------------------|:---------:|:-------------------:|
1099
+ | gemini-pro-vision | ❌ | 🔒 |
1100
+ | gemini-pro | 🟡 | ❌ |
1101
+ | gemini-1.5-pro-preview-0514 | ✅ | 🔒 |
1102
+ | gemini-1.5-pro-preview-0409 | ✅ | 🔒 |
1103
+ | gemini-1.5-pro | ✅ | ❌ |
1104
+ | gemini-1.5-flash-preview-0514 | 🟡 | 🔒 |
1105
+ | gemini-1.5-flash | 🟡 | ❌ |
1106
+ | gemini-1.0-pro-vision-latest | 🔒 | 🔒 |
1107
+ | gemini-1.0-pro-vision-001 | ❌ | 🔒 |
1108
+ | gemini-1.0-pro-vision | ❌ | 🔒 |
1109
+ | gemini-1.0-pro-latest | 🔒 | ❌ |
1110
+ | gemini-1.0-pro-002 | 🟡 | 🔒 |
1111
+ | gemini-1.0-pro-001 | ❌ | ❌ |
1112
+ | gemini-1.0-pro | 🟡 | ❌ |
1113
+ | gemini-ultra | 🔒 | 🔒 |
1114
+ | gemini-1.0-ultra | 🔒 | 🔒 |
1115
+ | gemini-1.0-ultra-001 | 🔒 | 🔒 |
1116
+
1117
+
856
1118
  ### Tools (Functions) Calling
857
1119
 
858
1120
  > As of the writing of this README, only the `vertex-ai-api` service and the `gemini-pro` model [supports](https://cloud.google.com/vertex-ai/docs/generative-ai/multimodal/function-calling#supported_models) tools (functions) calls.
@@ -1123,6 +1385,7 @@ GeminiError
1123
1385
 
1124
1386
  MissingProjectIdError
1125
1387
  UnsupportedServiceError
1388
+ ConflictingCredentialsError
1126
1389
  BlockWithoutServerSentEventsError
1127
1390
 
1128
1391
  RequestError
@@ -1134,7 +1397,14 @@ RequestError
1134
1397
  bundle
1135
1398
  rubocop -A
1136
1399
 
1137
- bundle exec ruby spec/tasks/run-client.rb
1400
+ rspec
1401
+
1402
+ bundle exec ruby spec/tasks/run-available-models.rb
1403
+ bundle exec ruby spec/tasks/run-embed.rb
1404
+ bundle exec ruby spec/tasks/run-generate.rb
1405
+ bundle exec ruby spec/tasks/run-json.rb
1406
+ bundle exec ruby spec/tasks/run-safety.rb
1407
+ bundle exec ruby spec/tasks/run-system.rb
1138
1408
  ```
1139
1409
 
1140
1410
  ### Purpose
@@ -1148,7 +1418,7 @@ gem build gemini-ai.gemspec
1148
1418
 
1149
1419
  gem signin
1150
1420
 
1151
- gem push gemini-ai-4.0.0.gem
1421
+ gem push gemini-ai-4.1.0.gem
1152
1422
  ```
1153
1423
 
1154
1424
  ### Updating the README
@@ -1193,6 +1463,8 @@ These resources and references may be useful throughout your learning process.
1193
1463
  - [Vertex AI API Documentation](https://cloud.google.com/vertex-ai/docs/reference)
1194
1464
  - [REST Documentation](https://cloud.google.com/vertex-ai/docs/reference/rest)
1195
1465
  - [Get text embeddings](https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-text-embeddings)
1466
+ - [Use system instructions](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/prompts/system-instructions)
1467
+ - [Configure safety attributes](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/configure-safety-attributes)
1196
1468
  - [Google models](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models)
1197
1469
  - [Model versions and lifecycle](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versioning)
1198
1470
  - [Google DeepMind Gemini](https://deepmind.google/technologies/gemini/)
data/components/errors.rb CHANGED
@@ -4,12 +4,13 @@ module Gemini
4
4
  module Errors
5
5
  class GeminiError < StandardError
6
6
  def initialize(message = nil)
7
- super(message)
7
+ super
8
8
  end
9
9
  end
10
10
 
11
11
  class MissingProjectIdError < GeminiError; end
12
12
  class UnsupportedServiceError < GeminiError; end
13
+ class ConflictingCredentialsError < GeminiError; end
13
14
  class BlockWithoutServerSentEventsError < GeminiError; end
14
15
 
15
16
  class RequestError < GeminiError
@@ -21,16 +21,24 @@ module Gemini
21
21
  @service = config[:credentials][:service]
22
22
 
23
23
  unless %w[vertex-ai-api generative-language-api].include?(@service)
24
- raise Errors::UnsupportedServiceError, "Unsupported service: #{@service}"
24
+ raise Errors::UnsupportedServiceError, "Unsupported service: '#{@service}'."
25
25
  end
26
26
 
27
+ avoid_conflicting_credentials!(config[:credentials])
28
+
27
29
  if config[:credentials][:api_key]
28
30
  @authentication = :api_key
29
31
  @api_key = config[:credentials][:api_key]
30
- elsif config[:credentials][:file_path]
32
+ elsif config[:credentials][:file_path] || config[:credentials][:file_contents]
31
33
  @authentication = :service_account
34
+ json_key_io = if config[:credentials][:file_path]
35
+ File.open(config[:credentials][:file_path])
36
+ else
37
+ StringIO.new(config[:credentials][:file_contents])
38
+ end
39
+
32
40
  @authorizer = ::Google::Auth::ServiceAccountCredentials.make_creds(
33
- json_key_io: File.open(config[:credentials][:file_path]),
41
+ json_key_io:,
34
42
  scope: 'https://www.googleapis.com/auth/cloud-platform'
35
43
  )
36
44
  else
@@ -75,6 +83,21 @@ module Gemini
75
83
  end
76
84
  end
77
85
 
86
+ def avoid_conflicting_credentials!(credentials)
87
+ conflicting_keys = %i[api_key file_path file_contents]
88
+
89
+ found = credentials.keys.filter { |key| conflicting_keys.include?(key) }
90
+
91
+ return unless found.size > 1
92
+
93
+ message = found.sort.each_with_index.map do |key, i|
94
+ i == found.size - 1 ? "or '#{key}'" : "'#{key}'"
95
+ end.join(', ')
96
+
97
+ raise Errors::ConflictingCredentialsError,
98
+ "You must choose either #{message}."
99
+ end
100
+
78
101
  def predict(payload, server_sent_events: nil, &callback)
79
102
  result = request(
80
103
  "#{@model_address}:predict", payload,
data/gemini-ai.gemspec CHANGED
@@ -30,7 +30,7 @@ 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.9'
33
+ spec.add_dependency 'faraday', '~> 2.9', '>= 2.9.2'
34
34
  spec.add_dependency 'faraday-typhoeus', '~> 1.1'
35
35
 
36
36
  # Before upgrading, check this:
data/static/gem.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Gemini
4
4
  GEM = {
5
5
  name: 'gemini-ai',
6
- version: '4.0.0',
6
+ version: '4.1.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/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', '~> 4.0.0'
12
+ gem 'gemini-ai', '~> 4.1.0'
13
13
  ```
14
14
 
15
15
  ```ruby
@@ -34,6 +34,17 @@ client = Gemini.new(
34
34
  options: { model: 'gemini-pro', server_sent_events: true }
35
35
  )
36
36
 
37
+ # With the Service Account Credentials File contents
38
+ client = Gemini.new(
39
+ credentials: {
40
+ service: 'vertex-ai-api',
41
+ file_contents: File.read('google-credentials.json'),
42
+ # file_contents: ENV['GOOGLE_CREDENTIALS_FILE_CONTENTS'],
43
+ region: 'us-east4'
44
+ },
45
+ options: { model: 'gemini-pro', server_sent_events: true }
46
+ )
47
+
37
48
  # With Application Default Credentials
38
49
  client = Gemini.new(
39
50
  credentials: {
@@ -77,11 +88,11 @@ Result:
77
88
  ### Installing
78
89
 
79
90
  ```sh
80
- gem install gemini-ai -v 4.0.0
91
+ gem install gemini-ai -v 4.1.0
81
92
  ```
82
93
 
83
94
  ```sh
84
- gem 'gemini-ai', '~> 4.0.0'
95
+ gem 'gemini-ai', '~> 4.1.0'
85
96
  ```
86
97
 
87
98
  ### Credentials
@@ -163,7 +174,7 @@ Similar to [Option 2](#option-2-service-account-credentials-file-vertex-ai-api),
163
174
  For local development, you can generate your default credentials using the [gcloud CLI](https://cloud.google.com/sdk/gcloud) as follows:
164
175
 
165
176
  ```sh
166
- gcloud auth application-default login
177
+ gcloud auth application-default login
167
178
  ```
168
179
 
169
180
  For more details about alternative methods and different environments, check the official documentation:
@@ -201,6 +212,23 @@ Remember that hardcoding your API key in code is unsafe; it's preferable to use
201
212
  }
202
213
  ```
203
214
 
215
+ Alternatively, you can pass the file contents instead of the path:
216
+ ```ruby
217
+ {
218
+ service: 'vertex-ai-api',
219
+ file_contents: File.read('google-credentials.json'),
220
+ region: 'us-east4'
221
+ }
222
+ ```
223
+
224
+ ```ruby
225
+ {
226
+ service: 'vertex-ai-api',
227
+ file_contents: ENV['GOOGLE_CREDENTIALS_FILE_CONTENTS'],
228
+ region: 'us-east4'
229
+ }
230
+ ```
231
+
204
232
  **Option 3**: For _Application Default Credentials_, omit both the `api_key` and the `file_path`:
205
233
 
206
234
  ```ruby
@@ -259,6 +287,17 @@ client = Gemini.new(
259
287
  options: { model: 'gemini-pro', server_sent_events: true }
260
288
  )
261
289
 
290
+ # With the Service Account Credentials File contents
291
+ client = Gemini.new(
292
+ credentials: {
293
+ service: 'vertex-ai-api',
294
+ file_contents: File.read('google-credentials.json'),
295
+ # file_contents: ENV['GOOGLE_CREDENTIALS_FILE_CONTENTS'],
296
+ region: 'us-east4'
297
+ },
298
+ options: { model: 'gemini-pro', server_sent_events: true }
299
+ )
300
+
262
301
  # With Application Default Credentials
263
302
  client = Gemini.new(
264
303
  credentials: {
@@ -272,7 +311,7 @@ client = Gemini.new(
272
311
 
273
312
  ## Available Models
274
313
 
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:
314
+ These models are accessible to the repository **author** as of June 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
315
 
277
316
  | Model | Vertex AI | Generative Language |
278
317
  |------------------------------------------|:---------:|:-------------------:|
@@ -280,9 +319,9 @@ These models are accessible to the repository **author** as of May 2025 in the `
280
319
  | gemini-pro | ✅ | ✅ |
281
320
  | gemini-1.5-pro-preview-0514 | ✅ | 🔒 |
282
321
  | gemini-1.5-pro-preview-0409 | ✅ | 🔒 |
283
- | gemini-1.5-pro | 🔒 | 🔒 |
322
+ | gemini-1.5-pro | | |
284
323
  | gemini-1.5-flash-preview-0514 | ✅ | 🔒 |
285
- | gemini-1.5-flash | 🔒 | 🔒 |
324
+ | gemini-1.5-flash | | |
286
325
  | gemini-1.0-pro-vision-latest | 🔒 | 🔒 |
287
326
  | gemini-1.0-pro-vision-001 | ✅ | 🔒 |
288
327
  | gemini-1.0-pro-vision | ✅ | 🔒 |
@@ -290,6 +329,11 @@ These models are accessible to the repository **author** as of May 2025 in the `
290
329
  | gemini-1.0-pro-002 | ✅ | 🔒 |
291
330
  | gemini-1.0-pro-001 | ✅ | ✅ |
292
331
  | gemini-1.0-pro | ✅ | ✅ |
332
+ | gemini-ultra | 🔒 | 🔒 |
333
+ | gemini-1.0-ultra | 🔒 | 🔒 |
334
+ | gemini-1.0-ultra-001 | 🔒 | 🔒 |
335
+ | text-embedding-preview-0514 | 🔒 | 🔒 |
336
+ | text-embedding-preview-0409 | 🔒 | 🔒 |
293
337
  | text-embedding-004 | ✅ | ✅ |
294
338
  | embedding-001 | 🔒 | ✅ |
295
339
  | text-multilingual-embedding-002 | ✅ | 🔒 |
@@ -335,6 +379,17 @@ client = Gemini.new(
335
379
  options: { model: 'gemini-pro', server_sent_events: true }
336
380
  )
337
381
 
382
+ # With the Service Account Credentials File contents
383
+ client = Gemini.new(
384
+ credentials: {
385
+ service: 'vertex-ai-api',
386
+ file_contents: File.read('google-credentials.json'),
387
+ # file_contents: ENV['GOOGLE_CREDENTIALS_FILE_CONTENTS'],
388
+ region: 'us-east4'
389
+ },
390
+ options: { model: 'gemini-pro', server_sent_events: true }
391
+ )
392
+
338
393
  # With Application Default Credentials
339
394
  client = Gemini.new(
340
395
  credentials: {
@@ -809,6 +864,208 @@ Result:
809
864
  } }]
810
865
  ```
811
866
 
867
+ ### Safety Settings
868
+
869
+ You can [configure safety attributes](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/configure-safety-attributes) for your requests.
870
+
871
+ Harm Categories:
872
+ > `HARM_CATEGORY_UNSPECIFIED`, `HARM_CATEGORY_HARASSMENT`, `HARM_CATEGORY_HATE_SPEECH`, `HARM_CATEGORY_SEXUALLY_EXPLICIT`, `HARM_CATEGORY_DANGEROUS_CONTENT`.
873
+
874
+ Thresholds:
875
+ > `BLOCK_NONE`, `BLOCK_ONLY_HIGH`, `BLOCK_MEDIUM_AND_ABOVE`, `BLOCK_LOW_AND_ABOVE`, `HARM_BLOCK_THRESHOLD_UNSPECIFIED`.
876
+
877
+ Example:
878
+ ```ruby
879
+ client.stream_generate_content(
880
+ {
881
+ contents: { role: 'user', parts: { text: 'hi!' } },
882
+ safetySettings: [
883
+ {
884
+ category: 'HARM_CATEGORY_UNSPECIFIED',
885
+ threshold: 'BLOCK_ONLY_HIGH'
886
+ },
887
+ {
888
+ category: 'HARM_CATEGORY_HARASSMENT',
889
+ threshold: 'BLOCK_ONLY_HIGH'
890
+ },
891
+ {
892
+ category: 'HARM_CATEGORY_HATE_SPEECH',
893
+ threshold: 'BLOCK_ONLY_HIGH'
894
+ },
895
+ {
896
+ category: 'HARM_CATEGORY_SEXUALLY_EXPLICIT',
897
+ threshold: 'BLOCK_ONLY_HIGH'
898
+ },
899
+ {
900
+ category: 'HARM_CATEGORY_DANGEROUS_CONTENT',
901
+ threshold: 'BLOCK_ONLY_HIGH'
902
+ }
903
+ ]
904
+ }
905
+ )
906
+ ```
907
+
908
+ Google started to block the usage of `BLOCK_NONE` unless:
909
+
910
+ > _User has requested a restricted HarmBlockThreshold setting BLOCK_NONE. You can get access either (a) through an allowlist via your Google account team, or (b) by switching your account type to monthly invoiced billing via this instruction: https://cloud.google.com/billing/docs/how-to/invoiced-billing_
911
+
912
+ ### System Instructions
913
+
914
+ Some models support [system instructions](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/prompts/system-instructions):
915
+
916
+ ```ruby
917
+ client.stream_generate_content(
918
+ { contents: { role: 'user', parts: { text: 'Hi! Who are you?' } },
919
+ system_instruction: { role: 'user', parts: { text: 'Your name is Neko.' } } }
920
+ )
921
+ ```
922
+
923
+ Output:
924
+ ```text
925
+ Hi! I'm Neko, a factual language model from Google AI.
926
+ ```
927
+
928
+ ```ruby
929
+ client.stream_generate_content(
930
+ { contents: { role: 'user', parts: { text: 'Hi! Who are you?' } },
931
+ system_instruction: {
932
+ role: 'user', parts: [
933
+ { text: 'You are a cat.' },
934
+ { text: 'Your name is Neko.' }
935
+ ]
936
+ } }
937
+ )
938
+ ```
939
+
940
+ Output:
941
+ ```text
942
+ Meow! I'm Neko, a fluffy and playful cat. :3
943
+ ```
944
+
945
+ ### JSON Format Responses
946
+
947
+ > _As of the writing of this README, only the `vertex-ai-api` service and `gemini` models version `1.5` support this feature._
948
+
949
+ The Gemini API provides a configuration parameter to [request a response in JSON](https://ai.google.dev/gemini-api/docs/api-overview#json) format:
950
+
951
+ ```ruby
952
+ require 'json'
953
+
954
+ result = client.stream_generate_content(
955
+ {
956
+ contents: {
957
+ role: 'user',
958
+ parts: {
959
+ text: 'List 3 random colors.'
960
+ }
961
+ },
962
+ generation_config: {
963
+ response_mime_type: 'application/json'
964
+ }
965
+
966
+ }
967
+ )
968
+
969
+ json_string = result
970
+ .map { |response| response.dig('candidates', 0, 'content', 'parts') }
971
+ .map { |parts| parts.map { |part| part['text'] }.join }
972
+ .join
973
+
974
+ puts JSON.parse(json_string).inspect
975
+ ```
976
+
977
+ Output:
978
+ ```ruby
979
+ { 'colors' => ['Dark Salmon', 'Indigo', 'Lavender'] }
980
+ ```
981
+
982
+ #### JSON Schema
983
+
984
+ > _While Gemini 1.5 Flash models only accept a text description of the JSON schema you want returned, the Gemini 1.5 Pro models let you pass a schema object (or a Python type equivalent), and the model output will strictly follow that schema. This is also known as controlled generation or constrained decoding._
985
+
986
+ You can also provide a [JSON Schema](https://json-schema.org) for the expected JSON output:
987
+
988
+ ```ruby
989
+ require 'json'
990
+
991
+ result = client.stream_generate_content(
992
+ {
993
+ contents: {
994
+ role: 'user',
995
+ parts: {
996
+ text: 'List 3 random colors.'
997
+ }
998
+ },
999
+ generation_config: {
1000
+ response_mime_type: 'application/json',
1001
+ response_schema: {
1002
+ type: 'object',
1003
+ properties: {
1004
+ colors: {
1005
+ type: 'array',
1006
+ items: {
1007
+ type: 'object',
1008
+ properties: {
1009
+ name: {
1010
+ type: 'string'
1011
+ }
1012
+ }
1013
+ }
1014
+ }
1015
+ }
1016
+ }
1017
+ }
1018
+ }
1019
+ )
1020
+
1021
+ json_string = result
1022
+ .map { |response| response.dig('candidates', 0, 'content', 'parts') }
1023
+ .map { |parts| parts.map { |part| part['text'] }.join }
1024
+ .join
1025
+
1026
+ puts JSON.parse(json_string).inspect
1027
+ ```
1028
+
1029
+ Output:
1030
+
1031
+ ```ruby
1032
+ { 'colors' => [
1033
+ { 'name' => 'Lavender Blush' },
1034
+ { 'name' => 'Medium Turquoise' },
1035
+ { 'name' => 'Dark Slate Gray' }
1036
+ ] }
1037
+ ```
1038
+
1039
+ #### Models That Support JSON
1040
+
1041
+ These models are accessible to the repository **author** as of June 2025 in the `us-east4` region. Access to models may vary by region, user, and account.
1042
+
1043
+ - ❌ Does not support JSON mode.
1044
+ - 🟡 Supports JSON mode but not Schema.
1045
+ - ✅ Supports JSON mode and Schema.
1046
+ - 🔒 I don't have access to the model.
1047
+
1048
+ | Model | Vertex AI | Generative Language |
1049
+ |------------------------------------------|:---------:|:-------------------:|
1050
+ | gemini-pro-vision | ❌ | 🔒 |
1051
+ | gemini-pro | 🟡 | ❌ |
1052
+ | gemini-1.5-pro-preview-0514 | ✅ | 🔒 |
1053
+ | gemini-1.5-pro-preview-0409 | ✅ | 🔒 |
1054
+ | gemini-1.5-pro | ✅ | ❌ |
1055
+ | gemini-1.5-flash-preview-0514 | 🟡 | 🔒 |
1056
+ | gemini-1.5-flash | 🟡 | ❌ |
1057
+ | gemini-1.0-pro-vision-latest | 🔒 | 🔒 |
1058
+ | gemini-1.0-pro-vision-001 | ❌ | 🔒 |
1059
+ | gemini-1.0-pro-vision | ❌ | 🔒 |
1060
+ | gemini-1.0-pro-latest | 🔒 | ❌ |
1061
+ | gemini-1.0-pro-002 | 🟡 | 🔒 |
1062
+ | gemini-1.0-pro-001 | ❌ | ❌ |
1063
+ | gemini-1.0-pro | 🟡 | ❌ |
1064
+ | gemini-ultra | 🔒 | 🔒 |
1065
+ | gemini-1.0-ultra | 🔒 | 🔒 |
1066
+ | gemini-1.0-ultra-001 | 🔒 | 🔒 |
1067
+
1068
+
812
1069
  ### Tools (Functions) Calling
813
1070
 
814
1071
  > As of the writing of this README, only the `vertex-ai-api` service and the `gemini-pro` model [supports](https://cloud.google.com/vertex-ai/docs/generative-ai/multimodal/function-calling#supported_models) tools (functions) calls.
@@ -1079,6 +1336,7 @@ GeminiError
1079
1336
 
1080
1337
  MissingProjectIdError
1081
1338
  UnsupportedServiceError
1339
+ ConflictingCredentialsError
1082
1340
  BlockWithoutServerSentEventsError
1083
1341
 
1084
1342
  RequestError
@@ -1090,7 +1348,14 @@ RequestError
1090
1348
  bundle
1091
1349
  rubocop -A
1092
1350
 
1093
- bundle exec ruby spec/tasks/run-client.rb
1351
+ rspec
1352
+
1353
+ bundle exec ruby spec/tasks/run-available-models.rb
1354
+ bundle exec ruby spec/tasks/run-embed.rb
1355
+ bundle exec ruby spec/tasks/run-generate.rb
1356
+ bundle exec ruby spec/tasks/run-json.rb
1357
+ bundle exec ruby spec/tasks/run-safety.rb
1358
+ bundle exec ruby spec/tasks/run-system.rb
1094
1359
  ```
1095
1360
 
1096
1361
  ### Purpose
@@ -1104,7 +1369,7 @@ gem build gemini-ai.gemspec
1104
1369
 
1105
1370
  gem signin
1106
1371
 
1107
- gem push gemini-ai-4.0.0.gem
1372
+ gem push gemini-ai-4.1.0.gem
1108
1373
  ```
1109
1374
 
1110
1375
  ### Updating the README
@@ -1149,6 +1414,8 @@ These resources and references may be useful throughout your learning process.
1149
1414
  - [Vertex AI API Documentation](https://cloud.google.com/vertex-ai/docs/reference)
1150
1415
  - [REST Documentation](https://cloud.google.com/vertex-ai/docs/reference/rest)
1151
1416
  - [Get text embeddings](https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-text-embeddings)
1417
+ - [Use system instructions](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/prompts/system-instructions)
1418
+ - [Configure safety attributes](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/configure-safety-attributes)
1152
1419
  - [Google models](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models)
1153
1420
  - [Model versions and lifecycle](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versioning)
1154
1421
  - [Google DeepMind Gemini](https://deepmind.google/technologies/gemini/)
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.0.0
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gbaptista
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-19 00:00:00.000000000 Z
11
+ date: 2024-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: event_stream_parser
@@ -31,6 +31,9 @@ dependencies:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '2.9'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 2.9.2
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -38,6 +41,9 @@ dependencies:
38
41
  - - "~>"
39
42
  - !ruby/object:Gem::Version
40
43
  version: '2.9'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.9.2
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: faraday-typhoeus
43
49
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +100,7 @@ extensions: []
94
100
  extra_rdoc_files: []
95
101
  files:
96
102
  - ".gitignore"
103
+ - ".rspec"
97
104
  - ".rubocop.yml"
98
105
  - ".ruby-version"
99
106
  - Gemfile