omniai-google 1.9.1 → 1.9.3

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: 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: