omniai-google 1.9.1 → 1.9.3

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: 6b089582dd7e1f47ae072ca9b715b18606054255eb630dab423f66e394aba73a
4
- data.tar.gz: e8efc5d1f56d1f1c7e0912edd1922da787d88a672a956c345499fbd63e4c432a
3
+ metadata.gz: 80e08395bc3710a72cc59b7c110cc50b1ba4a1dc64e15c622fcacb39448c1265
4
+ data.tar.gz: cccb64b57c0430caf449ebb1de2620e597409de0179379ef0cb26588d41418a2
5
5
  SHA512:
6
- metadata.gz: 732b07daa138c03068b1123ff95781a49a953645e2a121fbb948cbd84888bd2323da0d889130bcadc9ef55e0c5b43fe06ab4a892b7b25d33d8c02915c8be4f62
7
- data.tar.gz: 57692257e9c9dc10a62e2ad9019486eac432368cb9d6439c28837f3697f813e7733f1551fd2656af350f6638bba53f96f48c117efa3d234b535b2cf15a5657e2
6
+ metadata.gz: cf8a4e78c06a9808930300c1aa05b45211ab0f733a79bddc22bd5ac3ca2bfff1a00d075ca596122295c82aeb909372d2a9c7a66bc27566386d529428209beda7
7
+ data.tar.gz: 7324a4d99c3ce3a890129eb5a3091459facbd0acf5818b7ff0624d168d2fee94613656db1fe1c1091f8f001c6c34cc34c66a835b69fb7d90191075bde455de5b
data/Gemfile CHANGED
@@ -4,6 +4,7 @@ source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
6
 
7
+ gem 'logger'
7
8
  gem 'rake'
8
9
  gem 'rspec'
9
10
  gem 'rspec_junit_formatter'
data/README.md CHANGED
@@ -94,4 +94,38 @@ end
94
94
  client.chat('Be poetic.', stream:)
95
95
  ```
96
96
 
97
+ ### Upload
98
+
99
+ An upload is especially useful when processing audio / image / video / text files. To use:
100
+
101
+ ```ruby
102
+ CAT_URL = 'https://images.unsplash.com/photo-1472491235688-bdc81a63246e?fm=jpg'
103
+ DOG_URL = 'https://images.unsplash.com/photo-1517849845537-4d257902454a?fm=jpg'
104
+
105
+ begin
106
+ cat_upload = client.upload(CAT_URL)
107
+ dog_upload = client.upload(DOG_URL)
108
+
109
+ completion = client.chat(stream: $stdout) do |prompt|
110
+ prompt.user do |message|
111
+ message.text 'What are these photos of?'
112
+ message.url(cat_upload.uri, cat_upload.mime_type)
113
+ message.url(dog_upload.uri, dog_upload.mime_type)
114
+ end
115
+ end
116
+ ensure
117
+ cat_upload.delete!
118
+ dog_upload.delete!
119
+ end
120
+ ```
121
+
97
122
  [Google API Reference `stream`](https://ai.google.dev/gemini-api/docs/api-overview#stream)
123
+
124
+ ### Embed
125
+
126
+ Text can be converted into a vector embedding for similarity comparison usage via:
127
+
128
+ ```ruby
129
+ response = client.embed('The quick brown fox jumps over a lazy dog.')
130
+ response.embedding # [0.0, ...]
131
+ ```
@@ -6,8 +6,21 @@ module OmniAI
6
6
  # Overrides media serialize / deserialize.
7
7
  module MediaSerializer
8
8
  # @param media [OmniAI::Chat::Media]
9
- # @return [Hash]
10
- def self.serialize(media, *)
9
+ #
10
+ # @return [hash]
11
+ def self.serialize_as_file_data(media)
12
+ {
13
+ fileData: {
14
+ mimeType: media.type,
15
+ fileUri: media.uri,
16
+ },
17
+ }
18
+ end
19
+
20
+ # @param media [OmniAI::Chat::Media]
21
+ #
22
+ # @return [hash]
23
+ def self.serialize_as_inline_data(media)
11
24
  {
12
25
  inlineData: {
13
26
  mimeType: media.type,
@@ -15,6 +28,24 @@ module OmniAI
15
28
  },
16
29
  }
17
30
  end
31
+
32
+ # @param media [OmniAI::Chat::Media]
33
+ #
34
+ # @return [Hash]
35
+ def self.serialize(media, *)
36
+ if media.is_a?(OmniAI::Chat::URL) && use_file_data?(URI.parse(media.uri))
37
+ serialize_as_file_data(media)
38
+ else
39
+ serialize_as_inline_data(media)
40
+ end
41
+ end
42
+
43
+ # @param uri [URI]
44
+ #
45
+ # @return [Boolean]
46
+ def self.use_file_data?(uri)
47
+ uri.host.eql?('generativelanguage.googleapis.com') || uri.scheme.eql?('gs')
48
+ end
18
49
  end
19
50
  end
20
51
  end
@@ -59,6 +59,32 @@ module OmniAI
59
59
  def chat(messages = nil, model: Chat::DEFAULT_MODEL, temperature: nil, format: nil, stream: nil, tools: nil, &)
60
60
  Chat.process!(messages, model:, temperature:, format:, stream:, tools:, client: self, &)
61
61
  end
62
+
63
+ # @param io [File, String] required - a file or URL
64
+ #
65
+ # @raise [OmniAI::Google::Upload::FetchError]
66
+ #
67
+ # @return [OmniAI::Google::Upload::File]
68
+ def upload(io)
69
+ Upload.process!(client: self, io:)
70
+ end
71
+
72
+ # @raise [OmniAI::Error]
73
+ #
74
+ # @param input [String, Array<String>, Array<Integer>] required
75
+ # @param model [String] optional
76
+ def embed(input, model: Embed::DEFAULT_MODEL)
77
+ Embed.process!(input, model:, client: self)
78
+ end
79
+
80
+ # @return [String]
81
+ def path
82
+ if @project_id
83
+ "/#{@version}/projects/#{@project_id}/locations/#{@location}/publishers/google"
84
+ else
85
+ "/#{@version}"
86
+ end
87
+ end
62
88
  end
63
89
  end
64
90
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ module Google
5
+ # An Google embed implementation.
6
+ #
7
+ # Usage:
8
+ #
9
+ # input = "..."
10
+ # response = OmniAI::Google::Embed.process!(input, client: client)
11
+ # response.embedding [0.0, ...]
12
+ class Embed < OmniAI::Embed
13
+ module Model
14
+ TEXT_EMBEDDING_004 = 'text-embedding-004'
15
+ TEXT_MULTILINGUAL_EMBEDDING_002 = 'text-multilingual-embedding-002'
16
+ EMBEDDING = TEXT_EMBEDDING_004
17
+ MULTILINGUAL_EMBEDDING = TEXT_MULTILINGUAL_EMBEDDING_002
18
+ end
19
+
20
+ DEFAULT_MODEL = Model::EMBEDDING
21
+
22
+ EMBEDDINGS_DESERIALIZER = proc do |data, *|
23
+ data['embeddings'].map { |embedding| embedding['values'] }
24
+ end
25
+
26
+ # @return [Context]
27
+ CONTEXT = Context.build do |context|
28
+ context.deserializers[:embeddings] = EMBEDDINGS_DESERIALIZER
29
+ end
30
+
31
+ protected
32
+
33
+ # @param response [HTTP::Response]
34
+ # @return [Response]
35
+ def parse!(response:)
36
+ Response.new(data: response.parse, context: CONTEXT)
37
+ end
38
+
39
+ # @return [Array<Hash<{ text: String }>]
40
+ def requests
41
+ arrayify(@input).map do |text|
42
+ {
43
+ model: "models/#{@model}",
44
+ content: { parts: [{ text: text }] },
45
+ }
46
+ end
47
+ end
48
+
49
+ # @return [Hash]
50
+ def payload
51
+ { requests: }
52
+ end
53
+
54
+ # @return [String]
55
+ def path
56
+ "/#{@client.path}/models/#{@model}:batchEmbedContents?key=#{@client.api_key}"
57
+ end
58
+
59
+ def arrayify(input)
60
+ input.is_a?(Array) ? input : [input]
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ module Google
5
+ class Upload
6
+ # A file that can be used for generating chat completions.
7
+ class File
8
+ class DeleteError < HTTPError; end
9
+
10
+ # @!attribute [rw] name
11
+ # @return [String]
12
+ attr_accessor :name
13
+
14
+ # @attribute [rw] uri
15
+ # @return [String]
16
+ attr_accessor :uri
17
+
18
+ # @attribute [rw] state
19
+ # @return [String]
20
+ attr_accessor :state
21
+
22
+ # @attribute [rw] mime_type
23
+ # @return [String]
24
+ attr_accessor :mime_type
25
+
26
+ # @param client [Client]
27
+ # @param data [Hash]
28
+ #
29
+ # @return [File]
30
+ def self.parse(client:, data:)
31
+ new(
32
+ client: client,
33
+ name: data['name'],
34
+ uri: data['uri'],
35
+ state: data['state'],
36
+ mime_type: data['mimeType']
37
+ )
38
+ end
39
+
40
+ # @param client [Client]
41
+ # @param name [String]
42
+ # @param uri [String]
43
+ # @param state [String]
44
+ # @param mime_type [String]
45
+ def initialize(client:, name:, uri:, state:, mime_type:)
46
+ @client = client
47
+ @name = name
48
+ @uri = uri
49
+ @state = state
50
+ @mime_type = mime_type
51
+ end
52
+
53
+ # @raise [DeleteError]
54
+ def delete!
55
+ response = @client.connection
56
+ .delete("/#{@client.version}/#{@name}", params: { key: @client.api_key })
57
+
58
+ raise DeleteError, response unless response.status.success?
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ module Google
5
+ # Uploads a file to Google to be used when generating completions.
6
+ class Upload
7
+ class FetchError < HTTPError; end
8
+
9
+ # @param client [Client]
10
+ # @param io [IO]
11
+ # @param mime_type [String]
12
+ def self.process!(client:, io:)
13
+ new(client:, io:).process!
14
+ end
15
+
16
+ # @param client [Client]
17
+ # @param file [File]
18
+ # @param mime_type [String]
19
+ def initialize(client:, io:)
20
+ @client = client
21
+ @io = io
22
+ end
23
+
24
+ # @raise [HTTPError]
25
+ #
26
+ # @return [Upload::File]
27
+ def process!
28
+ response = io! do |io|
29
+ response = @client
30
+ .connection
31
+ .headers({ 'X-Goog-Upload-Protocol' => 'raw' })
32
+ .post("/upload/#{@client.version}/files?key=#{@client.api_key}", body: HTTP::FormData::File.new(io))
33
+ end
34
+
35
+ raise OmniAI::HTTPError, response.flush unless response.status.ok?
36
+
37
+ File.parse(client: @client, data: response.parse['file'])
38
+ end
39
+
40
+ protected
41
+
42
+ # @raise [FetchError]
43
+ #
44
+ # @yield [io]
45
+ # @yieldparam io [IO]
46
+ def io!(&block)
47
+ case @io
48
+ when File, IO then block.call(@io)
49
+ else fetch!(&block)
50
+ end
51
+ end
52
+
53
+ # @raise [FetchError]
54
+ #
55
+ # @yield [tempfile]
56
+ # @yieldparam tempfile [Tempfile]
57
+ def fetch!
58
+ tempfile = Tempfile.new
59
+ tempfile.binmode
60
+
61
+ response = HTTP.follow.get(@io)
62
+ raise FetchError, response.flush unless response.status.success?
63
+
64
+ response.body.each { |chunk| tempfile.write(chunk) }
65
+ tempfile.rewind
66
+
67
+ yield(tempfile)
68
+ ensure
69
+ tempfile.close
70
+ tempfile.unlink
71
+ end
72
+ end
73
+ end
74
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module OmniAI
4
4
  module Google
5
- VERSION = '1.9.1'
5
+ VERSION = '1.9.3'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniai-google
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.1
4
+ version: 1.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Sylvestre
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-05 00:00:00.000000000 Z
11
+ date: 2024-11-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: event_stream_parser
@@ -76,6 +76,9 @@ files:
76
76
  - lib/omniai/google/chat/usage_serializer.rb
77
77
  - lib/omniai/google/client.rb
78
78
  - lib/omniai/google/config.rb
79
+ - lib/omniai/google/embed.rb
80
+ - lib/omniai/google/upload.rb
81
+ - lib/omniai/google/upload/file.rb
79
82
  - lib/omniai/google/version.rb
80
83
  homepage: https://github.com/ksylvest/omniai-google
81
84
  licenses: