ruby-gemini-api 0.1.0 → 0.1.2
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/CHANGELOG.md +6 -1
- data/README.md +53 -4
- data/lib/gemini/client.rb +22 -30
- data/lib/gemini/http_headers.rb +1 -1
- data/lib/gemini/response.rb +2 -5
- data/lib/gemini/tool_definition.rb +68 -0
- data/lib/gemini/version.rb +1 -1
- data/lib/gemini.rb +3 -2
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36071e1dcc5fb406f9f49318cc2cffdb0e4159a0811c74da0aebd48293d9ef02
|
4
|
+
data.tar.gz: cdccba0ec67eb7fa2cd69ffcb8ddcd79c7056d6a636dcb3ccd0d05af14f5acbd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e50e268d2c015f45bf6db61d07e5b124aa07b967a278999aa00c29f760e1c41d1465af8582055764fc64454156f15130f498318cdc264cd78d342dc28cec4030
|
7
|
+
data.tar.gz: 21a68ce8106b7b2d0e5e9468d0464f91a18b62cbfad7c6c6924280d58bf525f9b4ac7e87ffe0e06076bd03b9f2b77fe0b6e35b9ba93bdfaedfbcc65afc6abc40
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
[README ‐ 日本語](https://github.com/rira100000000/ruby-gemini/wiki/README-%E2%80%90-%E6%97%A5%E6%9C%AC%E8%AA%9E)
|
2
|
-
# Ruby-Gemini
|
1
|
+
[README ‐ 日本語](https://github.com/rira100000000/ruby-gemini-api/wiki/README-%E2%80%90-%E6%97%A5%E6%9C%AC%E8%AA%9E)
|
2
|
+
# Ruby-Gemini-API
|
3
3
|
|
4
4
|
A Ruby client library for Google's Gemini API. This gem provides a simple, intuitive interface for interacting with Gemini's generative AI capabilities, following patterns similar to other AI client libraries.
|
5
5
|
|
@@ -18,12 +18,61 @@ This project is inspired by and pays homage to [ruby-openai](https://github.com/
|
|
18
18
|
- Document processing (PDFs and other formats)
|
19
19
|
- Context caching for efficient processing
|
20
20
|
|
21
|
+
### How to use Function Calling
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'gemini'
|
25
|
+
|
26
|
+
# Initialize Gemini client
|
27
|
+
client = Gemini::Client.new(ENV['GEMINI_API_KEY'])
|
28
|
+
|
29
|
+
# Define function declarations for Function Calling
|
30
|
+
# Note: Use camelCase (functionDeclarations) for Gemini API compatibility
|
31
|
+
tools = [
|
32
|
+
{
|
33
|
+
functionDeclarations: [
|
34
|
+
{
|
35
|
+
name: "get_current_weather",
|
36
|
+
description: "Get the current weather information",
|
37
|
+
parameters: {
|
38
|
+
type: "object",
|
39
|
+
properties: {
|
40
|
+
location: {
|
41
|
+
type: "string",
|
42
|
+
description: "City name, e.g., Tokyo"
|
43
|
+
}
|
44
|
+
},
|
45
|
+
required: ["location"]
|
46
|
+
}
|
47
|
+
}
|
48
|
+
]
|
49
|
+
}
|
50
|
+
]
|
51
|
+
|
52
|
+
# User prompt
|
53
|
+
user_prompt = "Tell me the current weather in Tokyo."
|
54
|
+
|
55
|
+
# Send request with Function Calling tools
|
56
|
+
response = client.generate_content(
|
57
|
+
user_prompt,
|
58
|
+
model: "gemini-2.0-flash",
|
59
|
+
tools: tools
|
60
|
+
)
|
61
|
+
|
62
|
+
# Parse function call from the response
|
63
|
+
unless response.function_calls.empty?
|
64
|
+
function_call = response.function_calls.first
|
65
|
+
puts "Function name to call: #{function_call["name"]}"
|
66
|
+
puts "Function arguments: #{function_call["args"]}"
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
21
70
|
## Installation
|
22
71
|
|
23
72
|
Add this line to your application's Gemfile:
|
24
73
|
|
25
74
|
```ruby
|
26
|
-
gem 'ruby-gemini'
|
75
|
+
gem 'ruby-gemini-api'
|
27
76
|
```
|
28
77
|
|
29
78
|
And then execute:
|
@@ -35,7 +84,7 @@ $ bundle install
|
|
35
84
|
Or install it yourself as:
|
36
85
|
|
37
86
|
```bash
|
38
|
-
$ gem install ruby-gemini
|
87
|
+
$ gem install ruby-gemini-api
|
39
88
|
```
|
40
89
|
|
41
90
|
## Quick Start
|
data/lib/gemini/client.rb
CHANGED
@@ -116,36 +116,30 @@ module Gemini
|
|
116
116
|
|
117
117
|
# Helper methods for convenience
|
118
118
|
|
119
|
-
|
119
|
+
# Method with usage similar to OpenAI's chat
|
120
120
|
def generate_content(prompt, model: "gemini-2.0-flash-lite", system_instruction: nil,
|
121
|
-
response_mime_type: nil, response_schema: nil, **parameters, &stream_callback)
|
122
|
-
# For image/text combinations, the prompt is passed as an array
|
123
|
-
# example: [{type: "text", text: "What is this?"}, {type: "image_url", image_url: {url: "https://example.com/image.jpg"}}]
|
121
|
+
response_mime_type: nil, response_schema: nil, temperature: 0.5, tools: nil, **parameters, &stream_callback)
|
124
122
|
content = format_content(prompt)
|
125
123
|
params = {
|
126
124
|
contents: [content],
|
127
125
|
model: model
|
128
126
|
}
|
129
|
-
|
127
|
+
|
130
128
|
if system_instruction
|
131
129
|
params[:system_instruction] = format_content(system_instruction)
|
132
130
|
end
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
if response_mime_type
|
138
|
-
params[:generation_config]["response_mime_type"] = response_mime_type
|
139
|
-
end
|
140
|
-
|
141
|
-
if response_schema
|
142
|
-
params[:generation_config]["response_schema"] = response_schema
|
143
|
-
end
|
131
|
+
params[:generation_config] ||= {}
|
132
|
+
params[:generation_config]["temperature"] = temperature
|
133
|
+
if response_mime_type
|
134
|
+
params[:generation_config]["response_mime_type"] = response_mime_type
|
144
135
|
end
|
145
|
-
|
146
|
-
|
136
|
+
|
137
|
+
if response_schema
|
138
|
+
params[:generation_config]["response_schema"] = response_schema
|
139
|
+
end
|
140
|
+
params[:tools] = tools if tools
|
147
141
|
params.merge!(parameters)
|
148
|
-
|
142
|
+
|
149
143
|
if block_given?
|
150
144
|
chat(parameters: params, &stream_callback)
|
151
145
|
else
|
@@ -155,7 +149,7 @@ module Gemini
|
|
155
149
|
|
156
150
|
# Streaming text generation
|
157
151
|
def generate_content_stream(prompt, model: "gemini-2.0-flash-lite", system_instruction: nil,
|
158
|
-
response_mime_type: nil, response_schema: nil, **parameters, &block)
|
152
|
+
response_mime_type: nil, response_schema: nil, temperature: 0.5, **parameters, &block)
|
159
153
|
raise ArgumentError, "Block is required for streaming" unless block_given?
|
160
154
|
|
161
155
|
content = format_content(prompt)
|
@@ -168,18 +162,16 @@ module Gemini
|
|
168
162
|
params[:system_instruction] = format_content(system_instruction)
|
169
163
|
end
|
170
164
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
params[:generation_config][:response_mime_type] = response_mime_type
|
176
|
-
end
|
177
|
-
|
178
|
-
if response_schema
|
179
|
-
params[:generation_config][:response_schema] = response_schema
|
180
|
-
end
|
165
|
+
params[:generation_config] ||= {}
|
166
|
+
|
167
|
+
if response_mime_type
|
168
|
+
params[:generation_config][:response_mime_type] = response_mime_type
|
181
169
|
end
|
182
170
|
|
171
|
+
if response_schema
|
172
|
+
params[:generation_config][:response_schema] = response_schema
|
173
|
+
end
|
174
|
+
params[:generation_config]["temperature"] = temperature
|
183
175
|
# Merge other parameters
|
184
176
|
params.merge!(parameters)
|
185
177
|
|
data/lib/gemini/http_headers.rb
CHANGED
data/lib/gemini/response.rb
CHANGED
@@ -138,11 +138,8 @@ module Gemini
|
|
138
138
|
|
139
139
|
# Get function call information
|
140
140
|
def function_calls
|
141
|
-
|
142
|
-
|
143
|
-
first_candidate&.dig("content", "parts")
|
144
|
-
&.select { |part| part.key?("functionCall") }
|
145
|
-
&.map { |part| part["functionCall"] } || []
|
141
|
+
parts = first_candidate.dig("content", "parts") || []
|
142
|
+
parts.map { |part| part["functionCall"] }.compact
|
146
143
|
end
|
147
144
|
|
148
145
|
# Get response role (usually "model")
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Gemini
|
2
|
+
class ToolDefinition
|
3
|
+
def initialize(&block)
|
4
|
+
@functions = {}
|
5
|
+
instance_eval(&block) if block_given?
|
6
|
+
end
|
7
|
+
|
8
|
+
def function(name, description:, &block)
|
9
|
+
@functions[name] = {
|
10
|
+
name: name,
|
11
|
+
description: description,
|
12
|
+
parameters: {
|
13
|
+
type: 'object',
|
14
|
+
properties: {},
|
15
|
+
required: []
|
16
|
+
}
|
17
|
+
}
|
18
|
+
@current_function = name
|
19
|
+
instance_eval(&block) if block_given?
|
20
|
+
@current_function = nil
|
21
|
+
end
|
22
|
+
alias add_function function
|
23
|
+
|
24
|
+
def property(name, type:, description:, required: false)
|
25
|
+
raise 'property must be defined within a function block' unless @current_function
|
26
|
+
|
27
|
+
@functions[@current_function][:parameters][:properties][name] = {
|
28
|
+
type: type.to_s,
|
29
|
+
description: description
|
30
|
+
}
|
31
|
+
@functions[@current_function][:parameters][:required] << name if required
|
32
|
+
end
|
33
|
+
|
34
|
+
def +(other)
|
35
|
+
raise ArgumentError, 'can only merge with another ToolDefinition' unless other.is_a?(ToolDefinition)
|
36
|
+
|
37
|
+
new_definition = dup
|
38
|
+
other.instance_variable_get(:@functions).each do |name, definition|
|
39
|
+
new_definition.instance_variable_get(:@functions)[name] = definition
|
40
|
+
end
|
41
|
+
new_definition
|
42
|
+
end
|
43
|
+
|
44
|
+
def delete_function(name)
|
45
|
+
@functions.delete(name)
|
46
|
+
end
|
47
|
+
|
48
|
+
def list_functions
|
49
|
+
@functions.keys
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_h
|
53
|
+
{
|
54
|
+
function_declarations: @functions.values
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_json(*args)
|
59
|
+
to_h.to_json(*args)
|
60
|
+
end
|
61
|
+
|
62
|
+
def dup
|
63
|
+
new_instance = self.class.new
|
64
|
+
new_instance.instance_variable_set(:@functions, @functions.dup)
|
65
|
+
new_instance
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/gemini/version.rb
CHANGED
data/lib/gemini.rb
CHANGED
@@ -3,7 +3,8 @@ require "faraday/multipart"
|
|
3
3
|
require "json"
|
4
4
|
require 'dotenv/load'
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative 'gemini/version'
|
7
|
+
require_relative 'gemini/tool_definition'
|
7
8
|
require_relative "gemini/http_headers"
|
8
9
|
require_relative "gemini/http"
|
9
10
|
require_relative "gemini/client"
|
@@ -73,7 +74,7 @@ module Gemini
|
|
73
74
|
color = level == :error ? "\033[31m" : "\033[33m"
|
74
75
|
logger = Logger.new($stdout)
|
75
76
|
logger.formatter = proc do |_severity, _datetime, _progname, msg|
|
76
|
-
"#{color}#{prefix} (spotted in ruby-gemini #{VERSION}): #{msg}\n\033[0m"
|
77
|
+
"#{color}#{prefix} (spotted in ruby-gemini-api #{VERSION}): #{msg}\n\033[0m"
|
77
78
|
end
|
78
79
|
logger.send(level, message)
|
79
80
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-gemini-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- rira100000000
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -161,15 +161,16 @@ files:
|
|
161
161
|
- lib/gemini/response.rb
|
162
162
|
- lib/gemini/runs.rb
|
163
163
|
- lib/gemini/threads.rb
|
164
|
+
- lib/gemini/tool_definition.rb
|
164
165
|
- lib/gemini/version.rb
|
165
166
|
- lib/ruby/gemini.rb
|
166
|
-
homepage: https://github.com/rira100000000/ruby-gemini
|
167
|
+
homepage: https://github.com/rira100000000/ruby-gemini-api
|
167
168
|
licenses:
|
168
169
|
- MIT
|
169
170
|
metadata:
|
170
|
-
homepage_uri: https://github.com/rira100000000/ruby-gemini
|
171
|
-
source_code_uri: https://github.com/rira100000000/ruby-gemini
|
172
|
-
changelog_uri: https://github.com/rira100000000/ruby-gemini/blob/main/CHANGELOG.md
|
171
|
+
homepage_uri: https://github.com/rira100000000/ruby-gemini-api
|
172
|
+
source_code_uri: https://github.com/rira100000000/ruby-gemini-api
|
173
|
+
changelog_uri: https://github.com/rira100000000/ruby-gemini-api/blob/main/CHANGELOG.md
|
173
174
|
rubygems_mfa_required: 'true'
|
174
175
|
post_install_message:
|
175
176
|
rdoc_options: []
|