ruby-gemini-ai 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/gem-push.yml +48 -0
- data/.gitignore +56 -0
- data/.rspec +1 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +69 -0
- data/LICENSE +22 -0
- data/README.md +381 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/gemini-ai/client.rb +76 -0
- data/lib/gemini-ai/compatibility.rb +10 -0
- data/lib/gemini-ai/errors.rb +18 -0
- data/lib/gemini-ai/http.rb +117 -0
- data/lib/gemini-ai/http_headers.rb +16 -0
- data/lib/gemini-ai/version.rb +3 -0
- data/lib/gemini-ai.rb +87 -0
- data/lib/ruby/gemini-ai.rb +2 -0
- data/ruby-gemini-ai.gemspec +31 -0
- metadata +112 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d7b4f9c65b80cb5b10a2a1440b29b78b40ca6161ae7297642ef1f33b4dfb3501
|
4
|
+
data.tar.gz: 3580107b3720e3299cca98c5f9f039b61bc4c891915dd94aca25d648452d333f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c46abb842e6cefdbe2a59bf6e646f5136b6d68eac4f8de6f12bb224483fa66eb1709a6935daf447927ec0cf75cad763376357e37cfbb528d75db813fac010a4d
|
7
|
+
data.tar.gz: 58c436b5d93829a68e996a7f152478c5fca9170850346ce1ce4614ad8be52b258f724005de7b02d19f49c22ca71effdeb1762be525b41fd1634e1b74f88eba72
|
@@ -0,0 +1,48 @@
|
|
1
|
+
name: Ruby Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ "master" ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ "master" ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
build:
|
11
|
+
name: Build + Publish
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
permissions:
|
14
|
+
contents: read
|
15
|
+
packages: write
|
16
|
+
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v3
|
19
|
+
- name: Set up Ruby 2.6.7
|
20
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
21
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
22
|
+
# uses: ruby/setup-ruby@v1
|
23
|
+
uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
|
24
|
+
with:
|
25
|
+
ruby-version: 2.6.7
|
26
|
+
|
27
|
+
- name: Publish to GPR
|
28
|
+
run: |
|
29
|
+
mkdir -p $HOME/.gem
|
30
|
+
touch $HOME/.gem/credentials
|
31
|
+
chmod 0600 $HOME/.gem/credentials
|
32
|
+
printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
33
|
+
gem build *.gemspec
|
34
|
+
gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
|
35
|
+
env:
|
36
|
+
GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
|
37
|
+
OWNER: ${{ github.repository_owner }}
|
38
|
+
|
39
|
+
- name: Publish to RubyGems
|
40
|
+
run: |
|
41
|
+
mkdir -p $HOME/.gem
|
42
|
+
touch $HOME/.gem/credentials
|
43
|
+
chmod 0600 $HOME/.gem/credentials
|
44
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
45
|
+
gem build *.gemspec
|
46
|
+
gem push *.gem
|
47
|
+
env:
|
48
|
+
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|
data/.gitignore
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# Ignore bundler config.
|
2
|
+
/.bundle
|
3
|
+
|
4
|
+
# Ignore local development configuration.
|
5
|
+
/config/*.yml
|
6
|
+
|
7
|
+
# Ignore test and spec directories.
|
8
|
+
/spec/tmp
|
9
|
+
/spec/fixtures
|
10
|
+
/spec/reports
|
11
|
+
/spec/examples
|
12
|
+
|
13
|
+
# Ignore coverage report generated by SimpleCov.
|
14
|
+
/coverage
|
15
|
+
|
16
|
+
# Ignore environment-specific files.
|
17
|
+
.env
|
18
|
+
.env.local
|
19
|
+
.env.development.local
|
20
|
+
.env.test.local
|
21
|
+
.env.production.local
|
22
|
+
|
23
|
+
# Ignore local database files.
|
24
|
+
/db/*.sqlite3
|
25
|
+
/db/*.sqlite3-journal
|
26
|
+
|
27
|
+
# Ignore the output of 'gem build'.
|
28
|
+
/*.gem
|
29
|
+
|
30
|
+
# rspec failure tracking
|
31
|
+
.rspec_status
|
32
|
+
|
33
|
+
# IDE
|
34
|
+
.idea
|
35
|
+
.idea/
|
36
|
+
.idea/*
|
37
|
+
.vscode
|
38
|
+
.vs/
|
39
|
+
*.iml
|
40
|
+
*.sublime-project
|
41
|
+
*.sublime-workspace
|
42
|
+
/.vscode
|
43
|
+
|
44
|
+
# Mac
|
45
|
+
.DS_Store
|
46
|
+
|
47
|
+
# Ignore system and application-specific files.
|
48
|
+
*.log
|
49
|
+
*.swp
|
50
|
+
*.bak
|
51
|
+
Thumbs.db
|
52
|
+
|
53
|
+
# Ignore gem artifacts.
|
54
|
+
/pkg
|
55
|
+
*.gem
|
56
|
+
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ruby-gemini-ai (0.1.0)
|
5
|
+
event_stream_parser (>= 0.3.0, < 2.0.0)
|
6
|
+
faraday (>= 1)
|
7
|
+
googleauth (~> 1.8)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
addressable (2.8.6)
|
13
|
+
public_suffix (>= 2.0.2, < 6.0)
|
14
|
+
byebug (11.1.3)
|
15
|
+
diff-lcs (1.5.1)
|
16
|
+
dotenv (2.8.1)
|
17
|
+
event_stream_parser (1.0.0)
|
18
|
+
faraday (2.9.0)
|
19
|
+
faraday-net_http (>= 2.0, < 3.2)
|
20
|
+
faraday-net_http (3.1.0)
|
21
|
+
net-http
|
22
|
+
google-cloud-env (2.1.1)
|
23
|
+
faraday (>= 1.0, < 3.a)
|
24
|
+
googleauth (1.11.0)
|
25
|
+
faraday (>= 1.0, < 3.a)
|
26
|
+
google-cloud-env (~> 2.1)
|
27
|
+
jwt (>= 1.4, < 3.0)
|
28
|
+
multi_json (~> 1.11)
|
29
|
+
os (>= 0.9, < 2.0)
|
30
|
+
signet (>= 0.16, < 2.a)
|
31
|
+
jwt (2.7.1)
|
32
|
+
multi_json (1.15.0)
|
33
|
+
net-http (0.4.1)
|
34
|
+
uri
|
35
|
+
os (1.1.4)
|
36
|
+
public_suffix (5.0.4)
|
37
|
+
rake (13.1.0)
|
38
|
+
rspec (3.13.0)
|
39
|
+
rspec-core (~> 3.13.0)
|
40
|
+
rspec-expectations (~> 3.13.0)
|
41
|
+
rspec-mocks (~> 3.13.0)
|
42
|
+
rspec-core (3.13.0)
|
43
|
+
rspec-support (~> 3.13.0)
|
44
|
+
rspec-expectations (3.13.0)
|
45
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
46
|
+
rspec-support (~> 3.13.0)
|
47
|
+
rspec-mocks (3.13.0)
|
48
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
49
|
+
rspec-support (~> 3.13.0)
|
50
|
+
rspec-support (3.13.0)
|
51
|
+
signet (0.19.0)
|
52
|
+
addressable (~> 2.8)
|
53
|
+
faraday (>= 0.17.5, < 3.a)
|
54
|
+
jwt (>= 1.5, < 3.0)
|
55
|
+
multi_json (~> 1.10)
|
56
|
+
uri (0.13.0)
|
57
|
+
|
58
|
+
PLATFORMS
|
59
|
+
arm64-darwin-22
|
60
|
+
|
61
|
+
DEPENDENCIES
|
62
|
+
byebug (~> 11.1.3)
|
63
|
+
dotenv (~> 2.8.1)
|
64
|
+
rake (~> 13.1)
|
65
|
+
rspec (~> 3.12)
|
66
|
+
ruby-gemini-ai!
|
67
|
+
|
68
|
+
BUNDLED WITH
|
69
|
+
2.3.22
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 GeminiAI
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,381 @@
|
|
1
|
+
# Ruby GeminiAi
|
2
|
+
|
3
|
+
This guide explains how to seamlessly integrate the powerful Gemini AI API into your Ruby projects. Utilize Gemini's cutting-edge language capabilities for generating text, translating languages, and more.
|
4
|
+
|
5
|
+
# Table of Contents
|
6
|
+
|
7
|
+
- [Installation](#installation)
|
8
|
+
- [Bundler](#bundler)
|
9
|
+
- [Gem Install](#gem-install)
|
10
|
+
- [Credentials](#credentials)
|
11
|
+
- [Option 1: API Key (Generative Language API)](#option-1-api-key-generative-language-api)
|
12
|
+
- [Option 2: Service Account Credentials File (Vertex AI API)](#option-2-service-account-credentials-file-vertex-ai-api)
|
13
|
+
- [Option 3: Application Default Credentials (Vertex AI API)](#option-3-application-default-credentials-vertex-ai-api)
|
14
|
+
- [Usage](#usage)
|
15
|
+
- [Quickstart](#quickstart)
|
16
|
+
- [With Config](#with-config)
|
17
|
+
- [Verbose Logging](#verbose-logging)
|
18
|
+
- [Methods](#methods)
|
19
|
+
- [stream_generate_content](#stream_generate_content)
|
20
|
+
- [generate_content](#generate_content)
|
21
|
+
- [Development](#development)
|
22
|
+
- [Compatibility](#compatibility)
|
23
|
+
- [License](#license)
|
24
|
+
- [Resources and References](#resources-and-references)
|
25
|
+
- [Additional Notes](#additional-notes)
|
26
|
+
|
27
|
+
## Installation
|
28
|
+
|
29
|
+
### Bundler
|
30
|
+
|
31
|
+
Add this line to your application's Gemfile:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
gem "ruby-gemini-ai"
|
35
|
+
```
|
36
|
+
|
37
|
+
And then execute:
|
38
|
+
|
39
|
+
```bash
|
40
|
+
$ bundle install
|
41
|
+
```
|
42
|
+
|
43
|
+
### Gem install
|
44
|
+
|
45
|
+
Or install with:
|
46
|
+
|
47
|
+
```bash
|
48
|
+
$ gem install ruby-gemini-ai
|
49
|
+
```
|
50
|
+
|
51
|
+
and require with:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
require "gemini-ai"
|
55
|
+
```
|
56
|
+
|
57
|
+
## Credentials
|
58
|
+
|
59
|
+
- [Option 1: API Key (Generative Language API)](#option-1-api-key-generative-language-api)
|
60
|
+
- [Option 2: Service Account Credentials File (Vertex AI API)](#option-2-service-account-credentials-file-vertex-ai-api)
|
61
|
+
- [Option 3: Application Default Credentials (Vertex AI API)](#option-3-application-default-credentials-vertex-ai-api)
|
62
|
+
|
63
|
+
#### Option 1: API Key (Generative Language API):
|
64
|
+
|
65
|
+
Obtain an API Key from your Google Cloud project: [Google Cloud](https://console.cloud.google.com) through the Google Cloud Console: [https://console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials).
|
66
|
+
|
67
|
+
Enable the Generative Language API service in your Google Cloud Console. which can be done [here](https://console.cloud.google.com/apis/library/generativelanguage.googleapis.com).
|
68
|
+
|
69
|
+
Alternatively, you can generate an API Key through Google AI Studio [here](https://makersuite.google.com/app/apikey), which will automatically create a project for you.
|
70
|
+
|
71
|
+
#### Option 2: Service Account Credentials File (Vertex AI API)
|
72
|
+
|
73
|
+
For the Vertex AI API, create a [Google Cloud](https://console.cloud.google.com) Project and a [_Service Account_](https://cloud.google.com/iam/docs/service-account-overview). Enable the [Vertex AI] (https://cloud.google.com/vertex-ai) API for your project [here](https://console.cloud.google.com/apis/library/aiplatform.googleapis.com).
|
74
|
+
|
75
|
+
Generate credentials for your Service Account [here](https://console.cloud.google.com/apis/credentials) and download a JSON file named google-credentials.json.
|
76
|
+
|
77
|
+
```json
|
78
|
+
{
|
79
|
+
"type": "service_account",
|
80
|
+
"project_id": "YOUR_PROJECT_ID",
|
81
|
+
"private_key_id": "a00...",
|
82
|
+
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
|
83
|
+
"client_email": "PROJECT_ID@PROJECT_ID.iam.gserviceaccount.com",
|
84
|
+
"client_id": "000...",
|
85
|
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
86
|
+
"token_uri": "https://oauth2.googleapis.com/token",
|
87
|
+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
88
|
+
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/..."
|
89
|
+
}
|
90
|
+
```
|
91
|
+
|
92
|
+
Ensure the necessary [policies](https://cloud.google.com/iam/docs/policies) (`roles/aiplatform.user` and possibly `roles/ml.admin`) are in place use the Vertex AI API.
|
93
|
+
|
94
|
+
You can add them by navigating to the [IAM Console](https://console.cloud.google.com/iam-admin/iam) and clicking on the _"Edit principal"_ (✏️ pencil icon) next to your _Service Account_.
|
95
|
+
|
96
|
+
Alternatively, you can add them through the [gcloud CLI](https://cloud.google.com/sdk/gcloud) as follows:
|
97
|
+
|
98
|
+
```sh
|
99
|
+
gcloud projects add-iam-policy-binding PROJECT_ID \
|
100
|
+
--member='serviceAccount:PROJECT_ID@PROJECT_ID.iam.gserviceaccount.com' \
|
101
|
+
--role='roles/aiplatform.user'
|
102
|
+
```
|
103
|
+
|
104
|
+
Some people reported having trouble accessing the API, and adding the role `roles/ml.admin` fixed it:
|
105
|
+
|
106
|
+
```sh
|
107
|
+
gcloud projects add-iam-policy-binding PROJECT_ID \
|
108
|
+
--member='serviceAccount:PROJECT_ID@PROJECT_ID.iam.gserviceaccount.com' \
|
109
|
+
--role='roles/ml.admin'
|
110
|
+
```
|
111
|
+
|
112
|
+
If you are not using a _Service Account_:
|
113
|
+
```sh
|
114
|
+
gcloud projects add-iam-policy-binding PROJECT_ID \
|
115
|
+
--member='user:YOUR@MAIL.COM' \
|
116
|
+
--role='roles/aiplatform.user'
|
117
|
+
|
118
|
+
gcloud projects add-iam-policy-binding PROJECT_ID \
|
119
|
+
--member='user:YOUR@MAIL.COM' \
|
120
|
+
--role='roles/ml.admin'
|
121
|
+
```
|
122
|
+
|
123
|
+
#### Option 3: Application Default Credentials (Vertex AI API)
|
124
|
+
|
125
|
+
|
126
|
+
Similar to [Option 2](#option-2-service-account-credentials-file-vertex-ai-api), but you don't need to download a `google-credentials.json`. These automatically find credentials based on your environment. [_Application Default Credentials_](https://cloud.google.com/docs/authentication/application-default-credentials).
|
127
|
+
|
128
|
+
Generate them using the gcloud CLI before local development. [gcloud CLI](https://cloud.google.com/sdk/gcloud):
|
129
|
+
|
130
|
+
```sh
|
131
|
+
gcloud auth application-default login
|
132
|
+
```
|
133
|
+
|
134
|
+
For more details about alternative methods and different environments, check the official documentation:
|
135
|
+
[Set up Application Default Credentials](https://cloud.google.com/docs/authentication/provide-credentials-adc)
|
136
|
+
|
137
|
+
|
138
|
+
## Usage
|
139
|
+
|
140
|
+
### Quickstart
|
141
|
+
|
142
|
+
For a quick test you can pass your token directly to a new client:
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
client = GeminiAi::Client.new(api_key: "gemini_api_key")
|
146
|
+
```
|
147
|
+
|
148
|
+
### With Config
|
149
|
+
|
150
|
+
We can configure Gemini with Ruby using three options.
|
151
|
+
|
152
|
+
**Option 1**, API KEY
|
153
|
+
|
154
|
+
For a more robust setup, you can configure the gem with your API keys, for example in an `gemini.rb` initializer file. Never hardcode secrets into your codebase - instead use something like [dotenv](https://github.com/motdotla/dotenv) to pass the keys safely into your environments.
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
GeminiAi.configure do |config|
|
158
|
+
config.api_key = ENV.fetch("GEMINI_API_KEY")
|
159
|
+
config.service = ENV.fetch("GEMINI_API_SERVICE")
|
160
|
+
end
|
161
|
+
```
|
162
|
+
|
163
|
+
**Option 2**, Service Account
|
164
|
+
|
165
|
+
For the Service Account, provide a `google-credentials.json` file and a `REGION`:
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
GeminiAi.configure do |config|
|
169
|
+
config.service = 'vertex-ai-api'
|
170
|
+
config.region = 'us-east4'
|
171
|
+
config.file_path = 'google-credentials.json'
|
172
|
+
end
|
173
|
+
```
|
174
|
+
|
175
|
+
**Option 3**, Default Credentials
|
176
|
+
|
177
|
+
For _Application Default Credentials_, omit both the `api_key` and the `file_path`:
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
GeminiAi.configure do |config|
|
181
|
+
config.region = 'us-east4'
|
182
|
+
config.service = 'vertex-ai-api'
|
183
|
+
end
|
184
|
+
```
|
185
|
+
|
186
|
+
Then you can create a client like this:
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
client = GeminiAi::Client.new
|
190
|
+
```
|
191
|
+
|
192
|
+
|
193
|
+
## Methods
|
194
|
+
|
195
|
+
### stream_generate_content(contents, model):
|
196
|
+
|
197
|
+
- Streams generated text in real-time.
|
198
|
+
- contents (hash): User input and role information.
|
199
|
+
- model (string): Optional model name (e.g., gemini-pro).
|
200
|
+
- Returns an array of candidates objects with generated text and safety ratings.
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
client = GeminiAi::Client.new
|
204
|
+
# Assuming you configured with your API key or credentials
|
205
|
+
|
206
|
+
contents = {
|
207
|
+
contents: {
|
208
|
+
role: 'user',
|
209
|
+
parts: {
|
210
|
+
text: 'Write a poem about the ocean.'
|
211
|
+
}
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
stream = client.stream_generate_content(contents, model: 'gemini-pro')
|
216
|
+
```
|
217
|
+
|
218
|
+
In this case, the result will be an array with all the received events:
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
[{ 'candidates' =>
|
222
|
+
[{ 'content' => {
|
223
|
+
'role' => 'model',
|
224
|
+
'parts' => [{ 'text' => 'exmaple poem content.......' }]
|
225
|
+
},
|
226
|
+
'finishReason' => 'STOP',
|
227
|
+
'safetyRatings' =>
|
228
|
+
[{ 'category' => 'HARM_CATEGORY_HARASSMENT', 'probability' => 'NEGLIGIBLE' },
|
229
|
+
{ 'category' => 'HARM_CATEGORY_HATE_SPEECH', 'probability' => 'NEGLIGIBLE' },
|
230
|
+
{ 'category' => 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'probability' => 'NEGLIGIBLE' },
|
231
|
+
{ 'category' => 'HARM_CATEGORY_DANGEROUS_CONTENT', 'probability' => 'NEGLIGIBLE' }] }],
|
232
|
+
'usageMetadata' => {
|
233
|
+
'promptTokenCount' => 2,
|
234
|
+
'candidatesTokenCount' => 8,
|
235
|
+
'totalTokenCount' => 10
|
236
|
+
} }]
|
237
|
+
```
|
238
|
+
|
239
|
+
#### with stream
|
240
|
+
|
241
|
+
```ruby
|
242
|
+
client = GeminiAi::Client.new
|
243
|
+
# Assuming you configured with your API key or credentials
|
244
|
+
|
245
|
+
contents = {
|
246
|
+
contents: {
|
247
|
+
role: 'user',
|
248
|
+
parts: {
|
249
|
+
text: 'Write a poem about the ocean.'
|
250
|
+
}
|
251
|
+
}
|
252
|
+
}
|
253
|
+
|
254
|
+
client.stream_generate_content(contents, model: 'gemini-pro', stream: true) do |part_text, event, parsed, raw|
|
255
|
+
puts text
|
256
|
+
end
|
257
|
+
```
|
258
|
+
OR
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
client = GeminiAi::Client.new
|
262
|
+
# Assuming you configured with your API key or credentials
|
263
|
+
|
264
|
+
contents = {
|
265
|
+
contents: {
|
266
|
+
role: 'user',
|
267
|
+
parts: {
|
268
|
+
text: 'Write a poem about the ocean.'
|
269
|
+
}
|
270
|
+
}
|
271
|
+
}
|
272
|
+
|
273
|
+
# Assuming you have a block or procedure (proc) defined
|
274
|
+
stream_proc = Proc.new do |part_text, event, parsed, raw|
|
275
|
+
puts part_text
|
276
|
+
end
|
277
|
+
|
278
|
+
client.stream_generate_content(contents, model: 'gemini-pro', stream: true, &stream_proc)
|
279
|
+
```
|
280
|
+
|
281
|
+
|
282
|
+
In this case, the result will be an array with all the received events:
|
283
|
+
|
284
|
+
```ruby
|
285
|
+
'exmaple poem content.......'
|
286
|
+
```
|
287
|
+
|
288
|
+
### generate_content(contents, model)
|
289
|
+
|
290
|
+
- Generates text in a single request.
|
291
|
+
- contents (hash): User input and role information.
|
292
|
+
- model (string): Optional model name (e.g., gemini-pro).
|
293
|
+
- Returns a hash with generated text, safety ratings, and prompt feedback
|
294
|
+
|
295
|
+
```ruby
|
296
|
+
result = client.generate_content(
|
297
|
+
{ contents: { role: 'user', parts: { text: 'hi!' } } }, model: 'gemini-pro'
|
298
|
+
)
|
299
|
+
```
|
300
|
+
|
301
|
+
```ruby
|
302
|
+
client = GeminiAi::Client.new
|
303
|
+
# Assuming you configured with your API key or credentials
|
304
|
+
|
305
|
+
contents = {
|
306
|
+
contents: {
|
307
|
+
role: 'user',
|
308
|
+
parts: {
|
309
|
+
text: 'Write a poem about the ocean.'
|
310
|
+
}
|
311
|
+
}
|
312
|
+
}
|
313
|
+
|
314
|
+
stream = client.generate_content(contents, model: 'gemini-pro')
|
315
|
+
```
|
316
|
+
|
317
|
+
|
318
|
+
Result:
|
319
|
+
```ruby
|
320
|
+
{ 'candidates' =>
|
321
|
+
[{ 'content' => { 'parts' => [{ 'text' => 'exampled poem.......' }], 'role' => 'model' },
|
322
|
+
'finishReason' => 'STOP',
|
323
|
+
'index' => 0,
|
324
|
+
'safetyRatings' =>
|
325
|
+
[{ 'category' => 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'probability' => 'NEGLIGIBLE' },
|
326
|
+
{ 'category' => 'HARM_CATEGORY_HATE_SPEECH', 'probability' => 'NEGLIGIBLE' },
|
327
|
+
{ 'category' => 'HARM_CATEGORY_HARASSMENT', 'probability' => 'NEGLIGIBLE' },
|
328
|
+
{ 'category' => 'HARM_CATEGORY_DANGEROUS_CONTENT', 'probability' => 'NEGLIGIBLE' }] }],
|
329
|
+
'promptFeedback' =>
|
330
|
+
{ 'safetyRatings' =>
|
331
|
+
[{ 'category' => 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'probability' => 'NEGLIGIBLE' },
|
332
|
+
{ 'category' => 'HARM_CATEGORY_HATE_SPEECH', 'probability' => 'NEGLIGIBLE' },
|
333
|
+
{ 'category' => 'HARM_CATEGORY_HARASSMENT', 'probability' => 'NEGLIGIBLE' },
|
334
|
+
{ 'category' => 'HARM_CATEGORY_DANGEROUS_CONTENT', 'probability' => 'NEGLIGIBLE' }] } }
|
335
|
+
```
|
336
|
+
|
337
|
+
#### Verbose Logging
|
338
|
+
|
339
|
+
You can pass [Faraday middleware](https://lostisland.github.io/faraday/#/middleware/index) to the client in a block, eg. to enable verbose logging with Ruby's [Logger](https://ruby-doc.org/3.2.2/stdlibs/logger/Logger.html):
|
340
|
+
|
341
|
+
```ruby
|
342
|
+
client = GeminiAi::Client.new do |f|
|
343
|
+
f.response :logger, Logger.new($stdout), bodies: true
|
344
|
+
end
|
345
|
+
```
|
346
|
+
|
347
|
+
## Development
|
348
|
+
|
349
|
+
1) Clone the repository.
|
350
|
+
2) Run **bin/setup** to install dependencies.
|
351
|
+
3) Use **bin/console** for interactive exploration.
|
352
|
+
4) Run **bundle exec** rake install to install the gem locally.
|
353
|
+
|
354
|
+
## Compatibility
|
355
|
+
|
356
|
+
ruby-gemini-ai gem is compatible with Ruby versions 2.6.7 and higher.
|
357
|
+
|
358
|
+
## License
|
359
|
+
|
360
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
361
|
+
|
362
|
+
## Resources and References
|
363
|
+
|
364
|
+
Explore the following curated list of resources and references to enhance your understanding throughout the learning process:
|
365
|
+
|
366
|
+
- [Google AI for Developers](https://ai.google.dev): Stay updated on the latest developments and resources in the field of Artificial Intelligence by visiting Google AI for Developers.
|
367
|
+
- [Get started with the Gemini API](https://ai.google.dev/docs): Initiate your journey into the Gemini API with comprehensive guides and documentation provided by Google.
|
368
|
+
- [Getting Started with the Vertex AI Gemini API with cURL](https://github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/getting-started/intro_gemini_curl.ipynb): Explore hands-on examples and tutorials using cURL to kickstart your experience with the Vertex AI Gemini API.
|
369
|
+
- [Gemini API Documentation](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/gemini): Refer to the official Gemini API documentation for detailed information on model references and implementation guidelines.
|
370
|
+
- [Vertex AI API Documentation](https://cloud.google.com/vertex-ai/docs/reference): Dive into the Vertex AI API documentation to gain a comprehensive understanding of Vertex AI services.
|
371
|
+
- [REST Documentation](https://cloud.google.com/vertex-ai/docs/reference/rest): Explore the RESTful API documentation for Vertex AI to facilitate seamless integration with your applications.
|
372
|
+
- [Google DeepMind Gemini](https://deepmind.google/technologies/gemini/): Gain insights into Google DeepMind's Gemini technology, a cutting-edge advancement in the field of Artificial Intelligence.
|
373
|
+
- [Stream responses from Generative AI models](https://cloud.google.com/vertex-ai/docs/generative-ai/learn/streaming): Learn how to effectively stream responses from Generative AI models by consulting this specific guide within the Vertex AI documentation.
|
374
|
+
- [Function calling](https://cloud.google.com/vertex-ai/docs/generative-ai/multimodal/function-calling): Understand the intricacies of function calling in the context of Generative AI models with this guide from the Vertex AI documentation.
|
375
|
+
|
376
|
+
These resources collectively provide a comprehensive foundation for your exploration of the Gemini API and Vertex AI services.
|
377
|
+
|
378
|
+
## Additional Notes
|
379
|
+
|
380
|
+
- As of now, only generate_content is supported with the `vertex-ai-api` service.
|
381
|
+
- For detailed API documentation and advanced usage, refer to the official Gemini AI documentation Consider adding examples and error handling for a more user-friendly experience.
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "gemini-ai"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'event_stream_parser'
|
4
|
+
require 'faraday'
|
5
|
+
require 'json'
|
6
|
+
require 'googleauth'
|
7
|
+
require 'uri'
|
8
|
+
|
9
|
+
require_relative 'errors'
|
10
|
+
|
11
|
+
module GeminiAi
|
12
|
+
class Client
|
13
|
+
include GeminiAi::HTTP
|
14
|
+
|
15
|
+
CONFIG_KEYS = %i[ api_key region file_path version service ].freeze
|
16
|
+
attr_accessor :authentication, :authorizer, :project_id, :service_version
|
17
|
+
attr_reader *CONFIG_KEYS, :faraday_middleware
|
18
|
+
|
19
|
+
def initialize(config = {}, &faraday_middleware)
|
20
|
+
CONFIG_KEYS.each do |key|
|
21
|
+
# Set instance variables like service authentication etc
|
22
|
+
instance_variable_set("@#{key}", config[key] || GeminiAi.configuration.send(key))
|
23
|
+
end
|
24
|
+
@service_version = @version || DEFAULT_SERVICE_VERSION
|
25
|
+
case
|
26
|
+
when @api_key
|
27
|
+
@authentication = :api_key
|
28
|
+
when @file_path
|
29
|
+
@authentication = :service_account
|
30
|
+
@authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
|
31
|
+
json_key_io: File.open(@file_path),
|
32
|
+
scope: 'https://www.googleapis.com/auth/cloud-platform'
|
33
|
+
)
|
34
|
+
else
|
35
|
+
@authentication = :default_credentials
|
36
|
+
@authorizer = Google::Auth.get_application_default
|
37
|
+
end
|
38
|
+
|
39
|
+
if @authentication == :service_account || @authentication == :default_credentials
|
40
|
+
@project_id = @authorizer.project_id || @authorizer.quota_project_id
|
41
|
+
raise Errors::MissingProjectIdError, 'Could not determine project_id, which is required.' if @project_id.nil?
|
42
|
+
end
|
43
|
+
@faraday_middleware = faraday_middleware
|
44
|
+
end
|
45
|
+
|
46
|
+
def stream_generate_content(payload, model: nil, stream: nil, &callback)
|
47
|
+
path = build_request_url('streamGenerateContent', model, stream)
|
48
|
+
json_post(path: path, parameters: payload, &callback)
|
49
|
+
end
|
50
|
+
|
51
|
+
def generate_content(payload, model: nil, stream: nil, &callback)
|
52
|
+
path = build_request_url('generateContent', model, stream)
|
53
|
+
json_post(path: path, parameters: payload, &callback)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def build_request_url(path, model, stream)
|
59
|
+
base_url = case @service
|
60
|
+
when 'vertex-ai-api'
|
61
|
+
"https://#{@region}-aiplatform.googleapis.com/#{service_version}/projects/#{@project_id}/locations/#{@region}/publishers/google/models/#{model}"
|
62
|
+
when 'generative-language-api'
|
63
|
+
"https://generativelanguage.googleapis.com/#{service_version}/models/#{model}"
|
64
|
+
end
|
65
|
+
|
66
|
+
params = {}
|
67
|
+
params[:alt] = 'sse' if stream
|
68
|
+
params[:key] = @api_key if @authentication == :api_key
|
69
|
+
|
70
|
+
uri = URI("#{base_url}:#{path}")
|
71
|
+
uri.query = URI.encode_www_form(params) if params.present?
|
72
|
+
uri.to_s
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module GeminiAi
|
2
|
+
module Errors
|
3
|
+
class GeminiAiError < StandardError; end
|
4
|
+
class MissingProjectIdError < GeminiAiError; end
|
5
|
+
class UnsupportedServiceError < GeminiAiError; end
|
6
|
+
class BlockWithoutServerSentEventsError < GeminiAiError; end
|
7
|
+
|
8
|
+
class RequestError < GeminiAiError
|
9
|
+
attr_reader :request, :payload
|
10
|
+
|
11
|
+
def initialize(message = nil, request: nil, payload: nil)
|
12
|
+
@request = request
|
13
|
+
@payload = payload
|
14
|
+
super(message)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require "event_stream_parser"
|
2
|
+
|
3
|
+
require_relative "http_headers"
|
4
|
+
|
5
|
+
module GeminiAi
|
6
|
+
module HTTP
|
7
|
+
include HTTPHeaders
|
8
|
+
|
9
|
+
def json_post(path:, parameters:, &callback)
|
10
|
+
conn.post(path) do |req|
|
11
|
+
configure_json_post_request(req, parameters, &callback)
|
12
|
+
end&.body
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def parse_json(response)
|
18
|
+
return unless response
|
19
|
+
return response unless response.is_a?(String)
|
20
|
+
|
21
|
+
# Convert a multiline string of JSON objects to a JSON array.
|
22
|
+
response = response.gsub("}\n{", "},{").prepend("[").concat("]")
|
23
|
+
|
24
|
+
JSON.parse(response)
|
25
|
+
end
|
26
|
+
|
27
|
+
#===================================================================================================
|
28
|
+
|
29
|
+
def to_json_stream(&callback)
|
30
|
+
partial_json = ''
|
31
|
+
parser = EventStreamParser::Parser.new
|
32
|
+
|
33
|
+
proc do |chunk, bytes, env|
|
34
|
+
if env && env.status != 200
|
35
|
+
raise_error = Faraday::Response::RaiseError.new
|
36
|
+
raise_error.on_complete(env.merge(body: chunk))
|
37
|
+
end
|
38
|
+
|
39
|
+
parser.feed(chunk) do |type, data, id, reconnection_time|
|
40
|
+
partial_json += data
|
41
|
+
parsed_json = parse_partial_json(partial_json)
|
42
|
+
|
43
|
+
if parsed_json
|
44
|
+
parsed_json_text = extract_text_from_json(parsed_json)
|
45
|
+
result = {
|
46
|
+
text: parsed_json_text,
|
47
|
+
event: parsed_json,
|
48
|
+
parsed: { type: type, data: data, id: id, reconnection_time: reconnection_time },
|
49
|
+
raw: { chunk: chunk, bytes: bytes, env: env }
|
50
|
+
}
|
51
|
+
|
52
|
+
callback.call(result[:text], result[:event], result[:parsed], result[:raw]) unless callback.nil?
|
53
|
+
|
54
|
+
partial_json = ''
|
55
|
+
|
56
|
+
if parsed_json['candidates']
|
57
|
+
parsed_json['candidates'].find do |candidate|
|
58
|
+
!candidate['finishReason'].nil? && candidate['finishReason'] != ''
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def extract_text_from_json(parsed_json)
|
68
|
+
parsed_json["candidates"].map do |candidate|
|
69
|
+
candidate["content"]["parts"].map { |part| part["text"] }
|
70
|
+
end.join(" ")
|
71
|
+
end
|
72
|
+
|
73
|
+
def parse_partial_json(response)
|
74
|
+
return unless response
|
75
|
+
return response unless response.is_a?(String)
|
76
|
+
response.to_s.lstrip.start_with?('{', '[') ? JSON.parse(response) : nil
|
77
|
+
rescue JSON::ParserError
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
|
81
|
+
#===================================================================================================
|
82
|
+
|
83
|
+
def conn(multipart: false)
|
84
|
+
connection = Faraday.new do |f|
|
85
|
+
f.options[:timeout] = @request_timeout
|
86
|
+
f.request(:multipart) if multipart
|
87
|
+
f.use MiddlewareErrors
|
88
|
+
f.response :raise_error
|
89
|
+
f.response :json
|
90
|
+
end
|
91
|
+
|
92
|
+
@faraday_middleware&.call(connection)
|
93
|
+
|
94
|
+
connection
|
95
|
+
end
|
96
|
+
|
97
|
+
def configure_json_post_request(req, parameters, &callback)
|
98
|
+
req_parameters = parameters.dup
|
99
|
+
if req.params["alt"].eql?("sse")
|
100
|
+
req.options.on_data = to_json_stream(&callback)
|
101
|
+
elsif req.params["alt"]
|
102
|
+
raise ArgumentError, "The alt parameter value must be a sse"
|
103
|
+
end
|
104
|
+
|
105
|
+
req.headers = headers
|
106
|
+
req.body = req_parameters.to_json
|
107
|
+
end
|
108
|
+
|
109
|
+
def try_parse_json(maybe_json)
|
110
|
+
JSON.parse(maybe_json)
|
111
|
+
rescue JSON::ParserError
|
112
|
+
maybe_json
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module GeminiAi
|
2
|
+
module HTTPHeaders
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
def headers
|
7
|
+
default_headers = {
|
8
|
+
"Content-Type" => "application/json"
|
9
|
+
}
|
10
|
+
if @authentication == :service_account || @authentication == :default_credentials
|
11
|
+
default_headers.merge!("Authorization": "Bearer #{@authorizer.fetch_access_token!['access_token']}")
|
12
|
+
end
|
13
|
+
default_headers
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/gemini-ai.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require "faraday"
|
2
|
+
|
3
|
+
require_relative "gemini-ai/http"
|
4
|
+
require_relative "gemini-ai/client"
|
5
|
+
require_relative "gemini-ai/errors"
|
6
|
+
require_relative "gemini-ai/version"
|
7
|
+
|
8
|
+
module GeminiAi
|
9
|
+
class Error < StandardError; end
|
10
|
+
|
11
|
+
class ConfigurationError < Error; end
|
12
|
+
|
13
|
+
class MiddlewareErrors < Faraday::Middleware
|
14
|
+
def call(env)
|
15
|
+
@app.call(env)
|
16
|
+
rescue Faraday::Error => e
|
17
|
+
raise e unless e.response.is_a?(Hash)
|
18
|
+
|
19
|
+
logger = Logger.new($stdout)
|
20
|
+
logger.formatter = proc do |_severity, _datetime, _progname, msg|
|
21
|
+
"\033[31mGemini AI HTTP Error (spotted in ruby-gemini-ai #{VERSION}): #{msg}\n\033[0m"
|
22
|
+
end
|
23
|
+
logger.error(e.response[:body])
|
24
|
+
|
25
|
+
raise e
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Configuration
|
30
|
+
attr_writer :api_key, :region, :file_path, :version, :service
|
31
|
+
DEFAULT_SERVICE_VERSION = 'v1'.freeze
|
32
|
+
DEFAULT_SERVICE = 'generative-language-api'.freeze
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
@api_key = nil
|
36
|
+
@region = nil
|
37
|
+
@file_path = nil
|
38
|
+
@version = DEFAULT_SERVICE_VERSION
|
39
|
+
@service = DEFAULT_SERVICE
|
40
|
+
end
|
41
|
+
|
42
|
+
def api_key
|
43
|
+
@api_key
|
44
|
+
end
|
45
|
+
|
46
|
+
def service
|
47
|
+
unless %w[vertex-ai-api generative-language-api].include?(@service)
|
48
|
+
raise Errors::UnsupportedServiceError, "Unsupported service: #{@service}"
|
49
|
+
end
|
50
|
+
@service
|
51
|
+
end
|
52
|
+
|
53
|
+
def version
|
54
|
+
@version
|
55
|
+
end
|
56
|
+
|
57
|
+
def file_path
|
58
|
+
@file_path
|
59
|
+
end
|
60
|
+
|
61
|
+
def region
|
62
|
+
@region
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
class << self
|
68
|
+
attr_writer :configuration
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.configuration
|
72
|
+
@configuration ||= GeminiAi::Configuration.new
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.configure
|
76
|
+
yield(configuration)
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.parsed_response(response, join_val: " ")
|
80
|
+
response.flat_map do |entry|
|
81
|
+
entry["candidates"].map do |candidate|
|
82
|
+
candidate.dig("content", "parts").map { |part| part["text"] }.join(join_val)
|
83
|
+
end
|
84
|
+
end.join(join_val)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative "lib/gemini-ai/version"
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "ruby-gemini-ai"
|
5
|
+
spec.version = GeminiAi::VERSION
|
6
|
+
spec.authors = ["Saurav Saini"]
|
7
|
+
spec.email = ["sainisaurav019@gmai.com"]
|
8
|
+
|
9
|
+
spec.summary = "Gemini API"
|
10
|
+
spec.homepage = "https://github.com/sauravsaini98/ruby-gemini-ai"
|
11
|
+
spec.license = "MIT"
|
12
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
|
13
|
+
|
14
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
15
|
+
spec.metadata["source_code_uri"] = "https://github.com/sauravsaini98/ruby-gemini-ai"
|
16
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
17
|
+
|
18
|
+
# Specify which files should be added to the gem when it is released.
|
19
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
20
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
21
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
22
|
+
end
|
23
|
+
spec.bindir = "exe"
|
24
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
|
+
spec.require_paths = ["lib"]
|
26
|
+
|
27
|
+
spec.add_dependency "event_stream_parser", ">= 0.3.0", "< 2.0.0"
|
28
|
+
spec.add_dependency "faraday", ">= 1"
|
29
|
+
spec.add_dependency 'googleauth', '~> 1.8'
|
30
|
+
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-gemini-ai
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Saurav Saini
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-02-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: event_stream_parser
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.3.0
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.0.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.3.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.0.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: faraday
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: googleauth
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.8'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.8'
|
61
|
+
description:
|
62
|
+
email:
|
63
|
+
- sainisaurav019@gmai.com
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files: []
|
67
|
+
files:
|
68
|
+
- ".github/workflows/gem-push.yml"
|
69
|
+
- ".gitignore"
|
70
|
+
- ".rspec"
|
71
|
+
- Gemfile
|
72
|
+
- Gemfile.lock
|
73
|
+
- LICENSE
|
74
|
+
- README.md
|
75
|
+
- bin/console
|
76
|
+
- bin/setup
|
77
|
+
- lib/gemini-ai.rb
|
78
|
+
- lib/gemini-ai/client.rb
|
79
|
+
- lib/gemini-ai/compatibility.rb
|
80
|
+
- lib/gemini-ai/errors.rb
|
81
|
+
- lib/gemini-ai/http.rb
|
82
|
+
- lib/gemini-ai/http_headers.rb
|
83
|
+
- lib/gemini-ai/version.rb
|
84
|
+
- lib/ruby/gemini-ai.rb
|
85
|
+
- ruby-gemini-ai.gemspec
|
86
|
+
homepage: https://github.com/sauravsaini98/ruby-gemini-ai
|
87
|
+
licenses:
|
88
|
+
- MIT
|
89
|
+
metadata:
|
90
|
+
homepage_uri: https://github.com/sauravsaini98/ruby-gemini-ai
|
91
|
+
source_code_uri: https://github.com/sauravsaini98/ruby-gemini-ai
|
92
|
+
rubygems_mfa_required: 'true'
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 2.6.0
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubygems_version: 3.2.3
|
109
|
+
signing_key:
|
110
|
+
specification_version: 4
|
111
|
+
summary: Gemini API
|
112
|
+
test_files: []
|