omniai-google 2.2.1 → 2.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b09fe2dc85e70bef186e70d5e6da204bf003fab07907147c9de01fcc86cfe5e2
4
- data.tar.gz: 2869a79e69a256b7420eccc72f33f9cabae2683d12c8f6fc8911fdbfd2e9ccbd
3
+ metadata.gz: ef7814ad2fd60f7d89dd87a2350c23496d4846e172393bb0b8fbf3ffde48347f
4
+ data.tar.gz: 7ead40b0168c010885d0af4fb8633d5da67ef187508777aa506528a5946bef75
5
5
  SHA512:
6
- metadata.gz: a9b7cce4e8fb35a74e7b03e63a819a4bec124b07d232931e5ceb52ddab3b500b10d881edec565e73c1d92c1657cc6ea8903683484092933d219b93458e054591
7
- data.tar.gz: 7b3f222ddf9d002b9467ed9a54a177257c6981a1d6f70fbaaddecce939920e5d5f4b4c9fa419bd1cc8b3b0bb8c03d39c37e59ed2ba70e5ccf523d72a5a3a3516
6
+ metadata.gz: f49152ce0896a0c4ed9668dcc5f4abce7363d4dfe907fd79a7511363fa5e8b7ec1797d1449653c22fb5dfbb9f49054359d7d57102607ec59699c113975d7fdb4
7
+ data.tar.gz: 8a88be48a793faefd52d98928fc57b9b1acdc84e1ad0d82735ca6605e63cfdfb7119c6835dc88c51d323cb4d0155a61d5c49995ae2f7b546b937ab333bb90471
data/README.md CHANGED
@@ -35,57 +35,34 @@ A client may also be passed the following options:
35
35
 
36
36
  Vertex AI and Google AI offer different options for interacting w/ Google's AI APIs. Checkout the [Vertex AI and Google AI differences](https://cloud.google.com/vertex-ai/generative-ai/docs/overview#how-gemini-vertex-different-gemini-aistudio) to determine which option best fits your requirements.
37
37
 
38
- #### Authentication
38
+ #### Configuration w/ Google AI
39
39
 
40
- **w/ `api_key`**
41
-
42
- The quickest way to authenticate (available if using Google AI) is by using an API key:
43
-
44
- ```ruby
45
- OmniAI::Google.configure do |config|
46
- config.api_key = 'sk-...' # default: ENV['GOOGLE_API_KEY']
47
- end
48
- ```
49
-
50
- **w/ `credentials`**
51
-
52
- An alternative approach for authentication (required if using Vertex AI) is to use credentials directly:
40
+ If using Gemini simply provide an `api_key`:
53
41
 
54
42
  ```ruby
55
- require 'googleauth'
56
-
57
- credentials = Google::Auth::ServiceAccountCredentials.make_creds(
58
- json_key_io: File.open('credentials.json'),
59
- scope: 'https://www.googleapis.com/auth/cloud-platform'
60
- )
61
-
62
43
  OmniAI::Google.configure do |config|
63
- config.credentials = credentials
44
+ config.api_key = 'sk-...' # defaults is `ENV['GOOGLE_API_KEY']`
64
45
  end
65
46
  ```
66
47
 
67
- #### Host
48
+ #### Configuration w/ Vertex AI
68
49
 
69
- The host (defaults to `https://generativelanguage.googleapis.com`) may be changed (required if using Vertex AI) using:
50
+ If using Vertex supply the `credentials`, `host`, `location_id` and `project_id`:
70
51
 
71
52
  ```ruby
72
53
  OmniAI::Google.configure do |config|
73
- config.host = 'https://us-east4-aiplatform.googleapis.com' # see https://cloud.google.com/vertex-ai/docs/general/locations
54
+ config.credentials = File.open("./credentials.json") # default is `ENV['GOOGLE_CREDENTIALS_PATH']` / `ENV['GOOGLE_CREDENTIALS_JSON']`
55
+ config.host = 'https://us-east4-aiplatform.googleapis.com' # default is `ENV['GOOGLE_HOST']`
56
+ config.location_id = 'us-east4' # defaults is `ENV['GOOGLE_LOCATION_ID']`
57
+ config.project_id = '...' # defaults is `ENV['GOOGLE_PROJECT_ID']`
74
58
  end
75
59
  ```
76
60
 
77
- #### Version
78
-
79
- The version (defaults to `v1beta`) may be changed using:
80
-
81
- ```ruby
82
- OmniAI::Google.configure do |config|
83
- # ...
84
- config.version = OmniAI::Google::Config::Version::STABLE # see https://ai.google.dev/gemini-api/docs/api-versions
85
- end
86
- ```
61
+ Credentials may be configured using:
87
62
 
88
- _The default API version is configured to **v1beta** instead of **v1** due to various missing features in **v1**._
63
+ 1. A `File` / `String` / `Pathname`.
64
+ 2. Assigning `ENV['GOOGLE_CREDENTIALS_PATH']` as the path to the `credentials.json`.
65
+ 3. Assigning `ENV['GOOGLE_CREDENTIALS_JSON']` to the contents of `credentials.json`.
89
66
 
90
67
  ### Chat
91
68
 
@@ -73,7 +73,7 @@ module OmniAI
73
73
  .connection
74
74
  .accept(:json)
75
75
  .post(path, params: {
76
- key: @client.api_key,
76
+ key: (@client.api_key unless @client.credentials?),
77
77
  alt: ("sse" if stream?),
78
78
  }.compact, json: payload)
79
79
  end
@@ -99,7 +99,7 @@ module OmniAI
99
99
 
100
100
  # @return [Hash]
101
101
  def generation_config
102
- response_mime_type = (JSON_MIME_TYPE if json_mime_type?)
102
+ response_mime_type = (JSON_MIME_TYPE if @format.eql?(:json))
103
103
 
104
104
  return unless @temperature || response_mime_type
105
105
 
@@ -109,12 +109,6 @@ module OmniAI
109
109
  }.compact
110
110
  end
111
111
 
112
- # Checks if setting a jsonMimeType is supported
113
- # @return [Boolean]
114
- def json_mime_type?
115
- @client.version == OmniAI::Google::Config::Version::BETA && @format.eql?(:json)
116
- end
117
-
118
112
  # @return [String]
119
113
  def path
120
114
  "#{@client.path}/models/#{@model}:#{operation}"
@@ -25,6 +25,8 @@ module OmniAI
25
25
  attr_accessor :version
26
26
 
27
27
  # @param api_key [String] default is `OmniAI::Google.config.api_key`
28
+ # @param project_id [String] default is `OmniAI::Google.config.project_id`
29
+ # @param location_id [String] default is `OmniAI::Google.config.location_id`
28
30
  # @param credentials [Google::Auth::ServiceAccountCredentials] default is `OmniAI::Google.config.credentials`
29
31
  # @param host [String] default is `OmniAI::Google.config.host`
30
32
  # @param version [String] default is `OmniAI::Google.config.version`
@@ -32,6 +34,8 @@ module OmniAI
32
34
  # @param timeout [Integer] default is `OmniAI::Google.config.timeout`
33
35
  def initialize(
34
36
  api_key: OmniAI::Google.config.api_key,
37
+ project_id: OmniAI::Google.config.project_id,
38
+ location_id: OmniAI::Google.config.location_id,
35
39
  credentials: OmniAI::Google.config.credentials,
36
40
  logger: OmniAI::Google.config.logger,
37
41
  host: OmniAI::Google.config.host,
@@ -44,6 +48,8 @@ module OmniAI
44
48
 
45
49
  super(api_key:, host:, logger:, timeout:)
46
50
 
51
+ @project_id = project_id
52
+ @location_id = location_id
47
53
  @credentials = credentials
48
54
  @version = version
49
55
  end
@@ -84,8 +90,8 @@ module OmniAI
84
90
 
85
91
  # @return [String]
86
92
  def path
87
- if project && location
88
- "/#{@version}/projects/#{project}/locations/#{location}/publishers/google"
93
+ if @project_id && @location_id
94
+ "/#{@version}/projects/#{@project_id}/locations/#{@location_id}/publishers/google"
89
95
  else
90
96
  "/#{@version}"
91
97
  end
@@ -94,30 +100,22 @@ module OmniAI
94
100
  # @return [HTTP::Client]
95
101
  def connection
96
102
  http = super
97
- http = http.auth(auth) if auth?
103
+ http = http.auth(auth) if credentials?
98
104
  http
99
105
  end
100
106
 
101
- private
102
-
103
- # @return [String, nil]
104
- def location
105
- @location ||= begin
106
- match = @host.match(%r{//(?<location>[\w\-]+)-aiplatform\.googleapis\.com})
107
- match[:location] if match
108
- end
109
- end
110
-
111
- # @return [String, nil]
112
- def project
113
- @credentials&.project_id
107
+ # @return [Boolean]
108
+ def credentials?
109
+ !@credentials.nil?
114
110
  end
115
111
 
116
112
  # @return [Boolean]
117
- def auth?
118
- !@credentials.nil?
113
+ def vertex?
114
+ @host.include?("aiplatform.googleapis.com")
119
115
  end
120
116
 
117
+ private
118
+
121
119
  # @return [String] e.g. "Bearer ..."
122
120
  def auth
123
121
  @credentials.fetch_access_token!
@@ -10,33 +10,50 @@ module OmniAI
10
10
  end
11
11
 
12
12
  DEFAULT_HOST = "https://generativelanguage.googleapis.com"
13
- DEFAULT_VERSION = Version::BETA
14
13
 
15
- # @!attribute [rw] version
14
+ # @!attribute [rw] project_id
16
15
  # @return [String, nil]
17
- attr_accessor :version
16
+ attr_accessor :project_id
18
17
 
19
- # @!attribute [rw] credentials
18
+ # @!attribute [rw] location_id
20
19
  # @return [String, nil]
21
- attr_accessor :credentials
20
+ attr_accessor :location_id
22
21
 
23
22
  # @param api_key [String, nil] optional - defaults to `ENV['GOOGLE_API_KEY']`
24
- # @param credentials [Google::Auth::ServiceAccountCredentials, nil] optional
23
+ # @param project_id [String, nil] optional - defaults to `ENV['GOOGLE_PROJECT_ID']`
24
+ # @param location_id [String, nil] optional - defaults to `ENV['GOOGLE_LOCATION_ID']`
25
25
  # @param host [String, nil] optional - defaults to `ENV['GOOGLE_HOST'] w/ fallback to `DEFAULT_HOST`
26
26
  # @param version [String, nil] optional - defaults to `ENV['GOOGLE_VERSION'] w/ fallback to `DEFAULT_VERSION`
27
27
  # @param logger [Logger, nil] optional
28
28
  # @param timeout [Integer, Hash, nil] optional
29
29
  def initialize(
30
30
  api_key: ENV.fetch("GOOGLE_API_KEY", nil),
31
- credentials: nil,
31
+ project_id: ENV.fetch("GOOGLE_PROJECT_ID", nil),
32
+ location_id: ENV.fetch("GOOGLE_LOCATION_ID", nil),
32
33
  host: ENV.fetch("GOOGLE_HOST", DEFAULT_HOST),
33
- version: ENV.fetch("GOOGLE_VERSION", DEFAULT_VERSION),
34
34
  logger: nil,
35
35
  timeout: nil
36
36
  )
37
37
  super(api_key:, host:, logger:, timeout:)
38
- @credentials = credentials
39
- @version = version
38
+ @project_id = project_id
39
+ @location_id = location_id
40
+ end
41
+
42
+ # @return [String]
43
+ def version
44
+ @host.eql?(DEFAULT_HOST) ? Version::BETA : Version::STABLE
45
+ end
46
+
47
+ # @return [Google::Auth::ServiceAccountCredentials, nil]
48
+ def credentials
49
+ return @credentials if defined?(@credentials)
50
+
51
+ Credentials.detect
52
+ end
53
+
54
+ # @param value [String, File, Google::Auth::ServiceAccountCredentials, nil]
55
+ def credentials=(value)
56
+ @credentials = Credentials.parse(value)
40
57
  end
41
58
  end
42
59
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ module Google
5
+ # @example
6
+ # OmniAI::Google::Credentials.parse(Google::Auth::ServiceAccountCredentials.make_creds(...))
7
+ # OmniAI::Google::Credentials.parse(File.open("./credentials.json"))
8
+ # OmniAI::Google::Credentials.parse("./credentials.json")
9
+ module Credentials
10
+ SCOPE = %w[https://www.googleapis.com/auth/cloud-platform].join(",")
11
+
12
+ # @return [Google::Auth::ServiceAccountCredentials, nil]
13
+ def self.detect
14
+ case
15
+ when ENV.key?("GOOGLE_CREDENTIALS_PATH") then parse(Pathname.new(ENV.fetch("GOOGLE_CREDENTIALS_PATH")))
16
+ when ENV.key?("GOOGLE_CREDENTIALS_JSON") then parse(StringIO.new(ENV.fetch("GOOGLE_CREDENTIALS_JSON")))
17
+ end
18
+ end
19
+
20
+ # @param value [Google::Auth::ServiceAccountCredentials, IO, Pathname, String nil]
21
+ # @return [Google::Auth::ServiceAccountCredentials]
22
+ def self.parse(value)
23
+ case value
24
+ when ::Google::Auth::ServiceAccountCredentials then value
25
+ when IO, StringIO then ::Google::Auth::ServiceAccountCredentials.make_creds(json_key_io: value, scope: SCOPE)
26
+ when Pathname then parse(File.open(value))
27
+ when String then parse(StringIO.new(value))
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -12,6 +12,7 @@ module OmniAI
12
12
  class Embed < OmniAI::Embed
13
13
  module Model
14
14
  TEXT_EMBEDDING_004 = "text-embedding-004"
15
+ TEXT_EMBEDDING_005 = "text-embedding-005"
15
16
  TEXT_MULTILINGUAL_EMBEDDING_002 = "text-multilingual-embedding-002"
16
17
  EMBEDDING = TEXT_EMBEDDING_004
17
18
  MULTILINGUAL_EMBEDDING = TEXT_MULTILINGUAL_EMBEDDING_002
@@ -19,24 +20,48 @@ module OmniAI
19
20
 
20
21
  DEFAULT_MODEL = Model::EMBEDDING
21
22
 
22
- EMBEDDINGS_DESERIALIZER = proc do |data, *|
23
+ DEFAULT_EMBEDDINGS_DESERIALIZER = proc do |data, *|
23
24
  data["embeddings"].map { |embedding| embedding["values"] }
24
25
  end
25
26
 
27
+ VERTEX_EMBEDDINGS_DESERIALIZER = proc do |data, *|
28
+ data["predictions"].map { |prediction| prediction["embeddings"]["values"] }
29
+ end
30
+
31
+ # @return [Context]
32
+ DEFAULT_CONTEXT = Context.build do |context|
33
+ context.deserializers[:embeddings] = DEFAULT_EMBEDDINGS_DESERIALIZER
34
+ end
35
+
26
36
  # @return [Context]
27
- CONTEXT = Context.build do |context|
28
- context.deserializers[:embeddings] = EMBEDDINGS_DESERIALIZER
37
+ VERTEX_CONTEXT = Context.build do |context|
38
+ context.deserializers[:embeddings] = VERTEX_EMBEDDINGS_DESERIALIZER
29
39
  end
30
40
 
31
41
  protected
32
42
 
43
+ # @return [Boolean]
44
+ def vertex?
45
+ @client.vertex?
46
+ end
47
+
48
+ # @return [Context]
49
+ def context
50
+ vertex? ? VERTEX_CONTEXT : DEFAULT_CONTEXT
51
+ end
52
+
33
53
  # @param response [HTTP::Response]
34
54
  # @return [Response]
35
55
  def parse!(response:)
36
- Response.new(data: response.parse, context: CONTEXT)
56
+ Response.new(data: response.parse, context:)
57
+ end
58
+
59
+ # @return [Array[Hash]]
60
+ def instances
61
+ arrayify(@input).map { |content| { content: } }
37
62
  end
38
63
 
39
- # @return [Array<Hash<{ text: String }>]
64
+ # @return [Array[Hash]]
40
65
  def requests
41
66
  arrayify(@input).map do |text|
42
67
  {
@@ -48,14 +73,26 @@ module OmniAI
48
73
 
49
74
  # @return [Hash]
50
75
  def payload
51
- { requests: }
76
+ vertex? ? { instances: } : { requests: }
77
+ end
78
+
79
+ # @return [Hash]
80
+ def params
81
+ { key: (@client.api_key unless @client.credentials?) }.compact
52
82
  end
53
83
 
54
84
  # @return [String]
55
85
  def path
56
- "/#{@client.path}/models/#{@model}:batchEmbedContents?key=#{@client.api_key}"
86
+ "/#{@client.path}/models/#{@model}:#{procedure}"
87
+ end
88
+
89
+ # @return [String]
90
+ def procedure
91
+ vertex? ? "predict" : "batchEmbedContents"
57
92
  end
58
93
 
94
+ # @param input [Object]
95
+ # @return [Array]
59
96
  def arrayify(input)
60
97
  input.is_a?(Array) ? input : [input]
61
98
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module OmniAI
4
4
  module Google
5
- VERSION = "2.2.1"
5
+ VERSION = "2.3.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniai-google
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Sylvestre
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-03-31 00:00:00.000000000 Z
10
+ date: 2025-04-04 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: event_stream_parser
@@ -43,14 +43,14 @@ dependencies:
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '2.2'
46
+ version: '2.3'
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '2.2'
53
+ version: '2.3'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: zeitwerk
56
56
  requirement: !ruby/object:Gem::Requirement
@@ -90,6 +90,7 @@ files:
90
90
  - lib/omniai/google/chat/usage_serializer.rb
91
91
  - lib/omniai/google/client.rb
92
92
  - lib/omniai/google/config.rb
93
+ - lib/omniai/google/credentials.rb
93
94
  - lib/omniai/google/embed.rb
94
95
  - lib/omniai/google/upload.rb
95
96
  - lib/omniai/google/upload/file.rb