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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1d3fab54be3c9a6830811a1ee33e72aa775d8f313a9aaaa702219b2fbd9393db
4
- data.tar.gz: 64a8c2089d56cad74c8847ebb58cf34d810bbb1bc77e7b7500151c268a7f88d5
3
+ metadata.gz: 36071e1dcc5fb406f9f49318cc2cffdb0e4159a0811c74da0aebd48293d9ef02
4
+ data.tar.gz: cdccba0ec67eb7fa2cd69ffcb8ddcd79c7056d6a636dcb3ccd0d05af14f5acbd
5
5
  SHA512:
6
- metadata.gz: 3e6155154922f2b29c55271c35483b1e4a29aa406117d6b880235b501a7af2b10234f997b5149ed6f1a2c708889a652140debc91132854f9bca7139c3130958a
7
- data.tar.gz: d2257648e0a703931e16d057b2a62c340ce595e385c160a00b3a43abf9604ded4f9619401c96b3b8765159d4f2b8efcde9bb34c3623d27fa258004252320c0e9
6
+ metadata.gz: e50e268d2c015f45bf6db61d07e5b124aa07b967a278999aa00c29f760e1c41d1465af8582055764fc64454156f15130f498318cdc264cd78d342dc28cec4030
7
+ data.tar.gz: 21a68ce8106b7b2d0e5e9468d0464f91a18b62cbfad7c6c6924280d58bf525f9b4ac7e87ffe0e06076bd03b9f2b77fe0b6e35b9ba93bdfaedfbcc65afc6abc40
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## [Unreleased]
2
2
 
3
3
  ## [0.1.0] - 2025-04-05
4
-
5
4
  - Initial release
5
+
6
+ ## [0.1.1] - 2025-05-04
7
+ - Changed generate_contents to accept temperature parameter
8
+
9
+ ## [0.1.2] - 2025-07-10
10
+ - Add function calling
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
- # Method with usage similar to OpenAI's chat
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
- if response_mime_type || response_schema
135
- params[:generation_config] ||= {}
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
- # Merge other parameters
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
- if response_mime_type || response_schema
172
- params[:generation_config] ||= {}
173
-
174
- if response_mime_type
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
 
@@ -13,7 +13,7 @@ module Gemini
13
13
  def default_headers
14
14
  {
15
15
  "Content-Type" => "application/json",
16
- "User-Agent" => "ruby-gemini/#{Gemini::VERSION}"
16
+ "User-Agent" => "ruby-gemini-api/#{Gemini::VERSION}"
17
17
  }
18
18
  end
19
19
 
@@ -138,11 +138,8 @@ module Gemini
138
138
 
139
139
  # Get function call information
140
140
  def function_calls
141
- return [] unless valid?
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gemini
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
5
5
  end
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 "gemini/version"
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.0
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-04-13 00:00:00.000000000 Z
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: []