ruby-gemini-api 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.
@@ -0,0 +1,127 @@
1
+ module Gemini
2
+ class Audio
3
+ def initialize(client:)
4
+ @client = client
5
+ end
6
+
7
+ # Transcribe an audio file
8
+ def transcribe(parameters: {})
9
+ file = parameters.delete(:file)
10
+ file_uri = parameters.delete(:file_uri)
11
+ model = parameters.delete(:model) || "gemini-1.5-flash"
12
+ language = parameters.delete(:language)
13
+ content_text = parameters.delete(:content_text) || "Transcribe this audio clip"
14
+
15
+ if !file && !file_uri
16
+ raise ArgumentError, "No audio file specified"
17
+ end
18
+
19
+ if file_uri
20
+ return transcribe_with_file_uri(file_uri, model, language, content_text, parameters)
21
+ end
22
+
23
+ # Get MIME type (simple detection)
24
+ mime_type = determine_mime_type(file)
25
+
26
+ # Base64 encode the file
27
+ file.rewind
28
+ require 'base64'
29
+ file_data = Base64.strict_encode64(file.read)
30
+
31
+ # Language setting for transcription request
32
+ if language
33
+ content_text += " in #{language}"
34
+ end
35
+
36
+ # Build request parameters
37
+ request_params = {
38
+ contents: [{
39
+ parts: [
40
+ { text: content_text },
41
+ {
42
+ inline_data: {
43
+ mime_type: mime_type,
44
+ data: file_data
45
+ }
46
+ }
47
+ ]
48
+ }]
49
+ }
50
+
51
+ # Merge additional parameters (add to top level except contents)
52
+ parameters.each do |key, value|
53
+ request_params[key] = value unless key == :contents
54
+ end
55
+
56
+ # Send generateContent request
57
+ response = @client.json_post(
58
+ path: "models/#{model}:generateContent",
59
+ parameters: request_params
60
+ )
61
+
62
+ Gemini::Response.new(response)
63
+ end
64
+
65
+ private
66
+
67
+ # Transcribe using pre-uploaded file URI
68
+ def transcribe_with_file_uri(file_uri, model, language, content_text, parameters)
69
+ # Language setting for transcription request
70
+ if language
71
+ content_text += " in #{language}"
72
+ end
73
+
74
+ # Build request parameters
75
+ request_params = {
76
+ contents: [{
77
+ parts: [
78
+ { text: content_text },
79
+ {
80
+ file_data: {
81
+ mime_type: "audio/mp3", # Cannot determine MIME type from URI, so using default value
82
+ file_uri: file_uri
83
+ }
84
+ }
85
+ ]
86
+ }]
87
+ }
88
+
89
+ # Merge additional parameters (add to top level except contents)
90
+ parameters.each do |key, value|
91
+ request_params[key] = value unless key == :contents
92
+ end
93
+
94
+ # Send generateContent request
95
+ response = @client.json_post(
96
+ path: "models/#{model}:generateContent",
97
+ parameters: request_params
98
+ )
99
+
100
+ Gemini::Response.new(response)
101
+ end
102
+
103
+ # Simple MIME type determination from file extension
104
+ def determine_mime_type(file)
105
+ return "application/octet-stream" unless file.respond_to?(:path)
106
+
107
+ ext = File.extname(file.path).downcase
108
+ case ext
109
+ when ".wav"
110
+ "audio/wav"
111
+ when ".mp3"
112
+ "audio/mp3"
113
+ when ".aiff"
114
+ "audio/aiff"
115
+ when ".aac"
116
+ "audio/aac"
117
+ when ".ogg"
118
+ "audio/ogg"
119
+ when ".flac"
120
+ "audio/flac"
121
+ else
122
+ # Default value (assume mp3)
123
+ "audio/mp3"
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,151 @@
1
+ module Gemini
2
+ class CachedContent
3
+ def initialize(client:)
4
+ @client = client
5
+ end
6
+
7
+ # コンテンツをキャッシュに保存
8
+ def create(file_path: nil, file_uri: nil, system_instruction: nil, mime_type: nil, model: nil, ttl: "86400s", **parameters)
9
+ # ファイルパスが指定されている場合はアップロード
10
+ if file_path && !file_uri
11
+ file = File.open(file_path, "rb")
12
+ begin
13
+ upload_result = @client.files.upload(file: file)
14
+ file_uri = upload_result["file"]["uri"]
15
+ ensure
16
+ file.close
17
+ end
18
+ end
19
+
20
+ # file_uriが必須
21
+ raise ArgumentError, "file_uri parameter is required" unless file_uri
22
+
23
+ # MIMEタイプを判定
24
+ mime_type ||= file_path ? @client.determine_mime_type(file_path) : "application/octet-stream"
25
+
26
+ # モデルを取得(models/プレフィックスを追加)
27
+ model_name = model || parameters[:model] || "gemini-1.5-flash"
28
+ model_name = "models/#{model_name}" unless model_name.start_with?("models/")
29
+
30
+ # キャッシュリクエストを構築(キャメルケースに注意)
31
+ request = {
32
+ model: model_name,
33
+ contents: [
34
+ {
35
+ parts: [
36
+ { file_data: { mime_type: mime_type, file_uri: file_uri } }
37
+ ],
38
+ role: "user"
39
+ }
40
+ ],
41
+ ttl: ttl
42
+ }
43
+
44
+ # システム指示が指定されている場合は追加(キャメルケースで指定)
45
+ if system_instruction
46
+ request[:systemInstruction] = {
47
+ parts: [{ text: system_instruction }],
48
+ role: "system"
49
+ }
50
+ end
51
+
52
+ # その他のパラメータを追加(ただしmime_typeとmodelは除外)
53
+ parameters.each do |key, value|
54
+ next if [:mime_type, :model].include?(key)
55
+
56
+ # スネークケースをキャメルケースに変換(必要に応じて)
57
+ camel_key = key.to_s.gsub(/_([a-z])/) { $1.upcase }.to_sym
58
+ request[camel_key] = value
59
+ end
60
+
61
+ # リクエストURLを直接構築
62
+ full_url = "https://generativelanguage.googleapis.com/v1beta/cachedContents"
63
+
64
+ # 直接Faradayを使用してリクエストを送信
65
+ conn = @client.conn
66
+ response = conn.post(full_url) do |req|
67
+ # ここでheadersメソッドを直接使用するのではなく、Content-Typeを手動で設定
68
+ req.headers = { 'Content-Type' => 'application/json' }
69
+ req.params = { key: @client.api_key }
70
+ req.body = request.to_json
71
+ end
72
+
73
+ parsed_response = begin
74
+ JSON.parse(response.body)
75
+ rescue JSON::ParserError
76
+ response.body
77
+ end
78
+
79
+ Gemini::Response.new(parsed_response)
80
+ end
81
+
82
+ # キャッシュの一覧を取得
83
+ def list(parameters: {})
84
+ # パラメータをキャメルケースに変換
85
+ camel_params = {}
86
+ parameters.each do |key, value|
87
+ camel_key = key.to_s.gsub(/_([a-z])/) { $1.upcase }
88
+ camel_params[camel_key] = value
89
+ end
90
+
91
+ # 直接URLを構築
92
+ full_url = "https://generativelanguage.googleapis.com/v1beta/cachedContents"
93
+
94
+ # 直接Faradayを使用
95
+ conn = @client.conn
96
+ response = conn.get(full_url) do |req|
97
+ # ここでheadersメソッドを直接使用するのではなく、Content-Typeを手動で設定
98
+ req.headers = { 'Content-Type' => 'application/json' }
99
+ req.params = camel_params.merge(key: @client.api_key)
100
+ end
101
+
102
+ parsed_response = begin
103
+ JSON.parse(response.body)
104
+ rescue JSON::ParserError
105
+ response.body
106
+ end
107
+
108
+ Gemini::Response.new(parsed_response)
109
+ end
110
+
111
+ # キャッシュを更新
112
+ def update(name:, ttl: "86400s")
113
+ full_url = "https://generativelanguage.googleapis.com/v1beta/#{name}"
114
+
115
+ conn = @client.conn
116
+ response = conn.patch(full_url) do |req|
117
+ # ここでheadersメソッドを直接使用するのではなく、Content-Typeを手動で設定
118
+ req.headers = { 'Content-Type' => 'application/json' }
119
+ req.params = { key: @client.api_key }
120
+ req.body = { ttl: ttl }.to_json
121
+ end
122
+
123
+ parsed_response = begin
124
+ JSON.parse(response.body)
125
+ rescue JSON::ParserError
126
+ response.body
127
+ end
128
+
129
+ Gemini::Response.new(parsed_response)
130
+ end
131
+
132
+ def delete(name:)
133
+ full_url = "https://generativelanguage.googleapis.com/v1beta/#{name}"
134
+
135
+ conn = @client.conn
136
+ response = conn.delete(full_url) do |req|
137
+ # ここでheadersメソッドを直接使用するのではなく、Content-Typeを手動で設定
138
+ req.headers = { 'Content-Type' => 'application/json' }
139
+ req.params = { key: @client.api_key }
140
+ end
141
+
142
+ parsed_response = begin
143
+ JSON.parse(response.body)
144
+ rescue JSON::ParserError
145
+ response.body
146
+ end
147
+
148
+ Gemini::Response.new(parsed_response)
149
+ end
150
+ end
151
+ end