gen-ai 0.1.0 → 0.2.1

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: a51511a0ca7cd09a4505151799e5d797d87d4418bb4a250e0436fab78317ac1b
4
- data.tar.gz: 1719adc9ca432e9da3420492651ea3ef2a10b7f990fe3607c28cf8187f4c6811
3
+ metadata.gz: 8fd6ea8e9dbcde79c04b1d37681d8d96e8722b09e2e24d0d9766b97319f065b0
4
+ data.tar.gz: 6e0599dd926747a2d71065ccc43c77648e9a0f3cdd10357540fb847606dfa656
5
5
  SHA512:
6
- metadata.gz: f482fba1992856a4009aabdebd849cf245d8069426da935999c3cbb323b02a36e916c2ab299c6fffd0ba7e5c320ddda001a9abb625063ea9c8a202376151f225
7
- data.tar.gz: 155f5f3e8d9b5c0234075635d4623300c0dcbed2fb63b2a8ee4bf2199a5bb75a6dbe8d864028078e5275b72c79a05836c7e26a4b4f49e179d80744caa8dd881d
6
+ metadata.gz: 6c1f85d0be4dc4a345afa45af335226a933a2d044a64fa787cb81d3985e986f921231862f1ff91de002a66769382ba7fab2240d5f9c0f6827d9a0ef76744472b
7
+ data.tar.gz: 54d9de6a6ac83d6a6ef59f75d39e7aa5042e202d2b1c4ea8dbaff7f001f00b56b2e4b52d89ded9dab333a548185d317158db80e2202b1148e7112839aeeff579
data/CHANGELOG.md CHANGED
@@ -1,4 +1,5 @@
1
- ## [Unreleased]
1
+ ## [0.2.0] - 2023-10-22
2
+ - Add image generation abilities
2
3
 
3
4
  ## [0.1.0] - 2023-10-13
4
5
 
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Alex Chaplinsky
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,24 +1,167 @@
1
- # Gen::Ai
1
+ # GenAI
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
3
+ Generative AI toolset for Ruby
4
4
 
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/gen/ai`. To experiment with that code, run `bin/console` for an interactive prompt.
5
+ GenAI allows you to easily integrate Generative AI model providers like OpenAI, Google Vertex AI, Stability AI, etc. Easily add Large Language Models, Stable Diffusion image generation, and other AI model integrations into your application!
6
6
 
7
- ## Installation
7
+ ![Tests](https://github.com/alchaplinsky/gen-ai/actions/workflows/main.yml/badge.svg?branch=main)
8
+ [![Gem Version](https://badge.fury.io/rb/gen-ai.svg)](https://badge.fury.io/rb/gen-ai)
9
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/alchaplinsky/gen-ai/blob/main/LICENSE.txt)
8
10
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
11
+ ## Installation
10
12
 
11
13
  Install the gem and add to the application's Gemfile by executing:
12
14
 
13
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
15
+ $ bundle add gen-ai
14
16
 
15
17
  If bundler is not being used to manage dependencies, install the gem by executing:
16
18
 
17
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
19
+ $ gem install gen-ai
18
20
 
19
21
  ## Usage
20
22
 
21
- TODO: Write usage instructions here
23
+ ### Feature support
24
+ ✅ - Supported | ❌ - Not supported | 🛠️ - Work in progress
25
+
26
+ Language models capabilities
27
+
28
+ | Provider | Embedding | Completion | Conversation | Sentiment | Summarization |
29
+ | ---------------- | --------- | :--------: | :----------: | :-------: | :-----------: |
30
+ | **OpenAI** | ✅ | ✅ | ✅ | 🛠️ | 🛠️ |
31
+ | **Google Palm2** | ✅ | ✅ | ✅ | 🛠️ | 🛠️ |
32
+
33
+
34
+ Image generation model capabilities
35
+
36
+ | Provider | Generate | Variations | Edit | Upscale |
37
+ | ---------------- | --------- | :--------: | :----------: | :-------: |
38
+ | **OpenAI** | ✅ | ✅ | ✅ | ❌ |
39
+ | **StabilityAI** | ✅ | ❌ | ✅ | ✅ |
40
+
41
+ ### Language
42
+
43
+ Instantiate a language model client by passing a provider name and an API token.
44
+
45
+ ```ruby
46
+ model = GenAI::Language.new(:open_ai, ENV['OPEN_AI_TOKEN'])
47
+ ```
48
+
49
+ Generate **embedding(s)** for text using provider/model that fits your needs
50
+
51
+ ```ruby
52
+ result = model.embed('Hi, how are you?')
53
+ # => #<GenAI::Result:0x0000000110be6f20...>
54
+
55
+ result.value
56
+ # => [-0.013577374, 0.0021624255, 0.0019274801, ... ]
57
+
58
+ result = model.embed(['Hello', 'Bonjour', 'Cześć'])
59
+ # => #<GenAI::Result:0x0000000110be6f34...>
60
+
61
+ result.values
62
+ # => [[-0.021834826, -0.007176527, -0.02836839,, ... ], [...], [...]]
63
+ ```
64
+
65
+ Generate text **completions** using Large Language Models
66
+
67
+ ```ruby
68
+ result = model.complete('London is a ', temperature: 0, max_tokens: 11)
69
+ # => #<GenAI::Result:0x0000000110be6d21...>
70
+
71
+ result.value
72
+ # => "vibrant and diverse city located in the United Kingdom"
73
+
74
+
75
+ result = model.complete('London is a ', max_tokens: 12, n: 2)
76
+ # => #<GenAI::Result:0x0000000110c25c70...>
77
+
78
+ result.values
79
+ # => ["thriving, bustling city known for its rich history.", "major global city and the capital of the United Kingdom."]
80
+
81
+ ```
82
+
83
+ Have a **conversation** with Large Language Model.
84
+
85
+ ```ruby
86
+ result = model.chat('Hi, how are you?')
87
+ # = >#<GenAI::Result:0x0000000106ff3d20...>
88
+
89
+ result.value
90
+ # => "Hello! I'm an AI, so I don't have feelings, but I'm here to help. How can I assist you today?"
91
+
92
+ history = [
93
+ {role: 'user', content: 'What is the capital of Great Britain?'},
94
+ {role: 'assistant', content: 'London'},
95
+ ]
96
+
97
+ result = model.chat("what about France?", history: history)
98
+ # => #<GenAI::Result:0x00000001033c3bc0...>
99
+
100
+ result.value
101
+ # => "Paris"
102
+ ```
103
+
104
+ ### Image
105
+
106
+ Instantiate a image generation model client by passing a provider name and an API token.
107
+
108
+ ```ruby
109
+ model = GenAI::Image.new(:open_ai, ENV['OPEN_AI_TOKEN'])
110
+ ```
111
+
112
+ Generate **image(s)** using provider/model that fits your needs
113
+
114
+ ```ruby
115
+ result = model.generate('A painting of a dog')
116
+ # => #<GenAI::Result:0x0000000110be6f20...>
117
+
118
+ result.value
119
+ # => Base64 encoded image
120
+
121
+ # Save image to file
122
+ File.open('dog.jpg', 'wb') do |f|
123
+ f.write(Base64.decode64(result.value))
124
+ end
125
+ ```
126
+ ![dog](https://github.com/alchaplinsky/gen-ai/assets/695947/27a2af5d-530b-4966-94e8-6cdf628b6cac)
127
+
128
+
129
+ Get more **variations** of the same image
130
+
131
+ ```ruby
132
+ result = model.variations('./dog.jpg')
133
+ # => #<GenAI::Result:0x0000000116a1ec50...>
134
+
135
+ result.value
136
+ # => Base64 encoded image
137
+
138
+ # Save image to file
139
+ File.open('dog_variation.jpg', 'wb') do |f|
140
+ f.write(Base64.decode64(result.value))
141
+ end
142
+
143
+ ```
144
+ ![dog_variation](https://github.com/alchaplinsky/gen-ai/assets/695947/977f5238-0114-4085-8e61-8f8b356ce308)
145
+
146
+
147
+ **Editing** existing images with additional prompt
148
+
149
+ ```ruby
150
+ result = model.edit('./llama.jpg', 'A cute llama wearing a beret', mask: './mask.png')
151
+ # => #<GenAI::Result:0x0000000116a1ec50...>
152
+
153
+ result.value
154
+ # => Base64 encoded image
155
+
156
+ # Save image to file
157
+ File.open('dog_edited.jpg', 'wb') do |f|
158
+ f.write(Base64.decode64(result.value))
159
+ end
160
+ ```
161
+
162
+ ![llama](https://github.com/alchaplinsky/gen-ai/assets/695947/9c862c6c-428e-463c-b935-ca749a6a33df)
163
+ ![llama_edited](https://github.com/alchaplinsky/gen-ai/assets/695947/070d8e6a-07a0-4ed2-826f-8b9aabd183ae)
164
+
22
165
 
23
166
  ## Development
24
167
 
@@ -28,8 +171,8 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
28
171
 
29
172
  ## Contributing
30
173
 
31
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/gen-ai. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/gen-ai/blob/main/CODE_OF_CONDUCT.md).
174
+ Bug reports and pull requests are welcome on GitHub at https://github.com/alchaplinsky/gen-ai. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/alchaplinsky/gen-ai/blob/main/CODE_OF_CONDUCT.md).
32
175
 
33
176
  ## Code of Conduct
34
177
 
35
- Everyone interacting in the Gen::Ai project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/gen-ai/blob/main/CODE_OF_CONDUCT.md).
178
+ Everyone interacting in the GenAI project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [code of conduct](https://github.com/alchaplinsky/gen-ai/blob/main/CODE_OF_CONDUCT.md).
data/gen-ai.gemspec CHANGED
@@ -32,6 +32,8 @@ Gem::Specification.new do |spec|
32
32
  spec.require_paths = ['lib']
33
33
 
34
34
  # Uncomment to register a new dependency of your gem
35
+ spec.add_dependency 'faraday', '~> 2.7'
36
+ spec.add_dependency 'faraday-multipart'
35
37
  spec.add_dependency 'zeitwerk', '~> 2.6'
36
38
 
37
39
  spec.add_development_dependency 'google_palm_api', '~> 0.1'
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'faraday/multipart'
5
+
6
+ module GenAI
7
+ module Api
8
+ class Client
9
+ def initialize(url:, token:)
10
+ @url = url
11
+ @token = token
12
+ end
13
+
14
+ def post(path, body, options = {})
15
+ multipart = options.delete(:multipart) || false
16
+ payload = multipart ? body : JSON.generate(body)
17
+
18
+ handle_response do
19
+ connection(multipart: multipart).post(path, payload)
20
+ end
21
+ end
22
+
23
+ def get(path, options)
24
+ handle_response do
25
+ connection.get(path, options)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :url, :token
32
+
33
+ def connection(multipart: false)
34
+ Faraday.new(url: url, headers: {
35
+ 'Accept' => 'application/json',
36
+ 'Content-Type' => multipart ? 'multipart/form-data' : 'application/json',
37
+ 'Authorization' => "Bearer #{token}"
38
+ }) do |conn|
39
+ conn.request :multipart if multipart
40
+ conn.request :url_encoded
41
+ end
42
+ end
43
+
44
+ def handle_response
45
+ response = yield
46
+
47
+ raise GenAI::ApiError, "API error: #{JSON.parse(response.body)}" unless response.success?
48
+
49
+ JSON.parse(response.body)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GenAI
4
+ class Base
5
+ include GenAI::Dependency
6
+
7
+ private
8
+
9
+ attr_reader :client
10
+
11
+ def handle_errors
12
+ response = yield
13
+ return if !response || response.empty?
14
+
15
+ raise GenAI::ApiError, "#{api_provider_name} API error: #{response.dig('error', 'message')}" if response['error']
16
+
17
+ response
18
+ end
19
+
20
+ def provider_name
21
+ api_provider_name.gsub(/(.)([A-Z])/, '\1_\2').downcase
22
+ end
23
+
24
+ def api_provider_name
25
+ self.class.name.split('::').last
26
+ end
27
+
28
+ def build_result(model:, raw:, parsed:)
29
+ GenAI::Result.new(provider: provider_name.to_sym, model: model, raw: raw, values: parsed)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GenAI
4
+ class Image
5
+ class Base < GenAI::Base
6
+ def generate(...)
7
+ raise NotImplementedError, "#{self.class.name} does not support generate"
8
+ end
9
+
10
+ def variations(...)
11
+ raise NotImplementedError, "#{self.class.name} does not support variations"
12
+ end
13
+
14
+ def edit(...)
15
+ raise NotImplementedError, "#{self.class.name} does not support editing"
16
+ end
17
+
18
+ def upscale(...)
19
+ raise NotImplementedError, "#{self.class.name} does not support upscaling"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GenAI
4
+ class Image
5
+ class OpenAI < Base
6
+ DEFAULT_SIZE = '256x256'
7
+ RESPONSE_FORMAT = 'b64_json'
8
+
9
+ def initialize(token:, options: {})
10
+ depends_on 'ruby-openai'
11
+
12
+ @client = ::OpenAI::Client.new(access_token: token)
13
+ end
14
+
15
+ def generate(prompt, options = {})
16
+ parameters = build_generation_options(prompt, options)
17
+
18
+ response = handle_errors { @client.images.generate(parameters: parameters) }
19
+
20
+ build_result(
21
+ raw: response,
22
+ model: 'dall-e',
23
+ parsed: response['data'].map { |datum| datum[RESPONSE_FORMAT] }
24
+ )
25
+ end
26
+
27
+ def variations(image, options = {})
28
+ parameters = build_variations_options(image, options)
29
+
30
+ response = handle_errors { @client.images.variations(parameters: parameters) }
31
+
32
+ build_result(
33
+ raw: response,
34
+ model: 'dall-e',
35
+ parsed: response['data'].map { |datum| datum[RESPONSE_FORMAT] }
36
+ )
37
+ end
38
+
39
+ def edit(image, prompt, options = {})
40
+ parameters = build_edit_options(image, prompt, options)
41
+
42
+ response = handle_errors { @client.images.edit(parameters: parameters) }
43
+
44
+ build_result(
45
+ raw: response,
46
+ model: 'dall-e',
47
+ parsed: response['data'].map { |datum| datum[RESPONSE_FORMAT] }
48
+ )
49
+ end
50
+
51
+ private
52
+
53
+ def build_generation_options(prompt, options)
54
+ {
55
+ prompt: prompt,
56
+ size: options.delete(:size) || DEFAULT_SIZE,
57
+ response_format: options.delete(:response_format) || RESPONSE_FORMAT
58
+ }.merge(options)
59
+ end
60
+
61
+ def build_variations_options(image, options)
62
+ {
63
+ image: image,
64
+ size: options.delete(:size) || DEFAULT_SIZE,
65
+ response_format: options.delete(:response_format) || RESPONSE_FORMAT
66
+ }.merge(options)
67
+ end
68
+
69
+ def build_edit_options(image, prompt, options)
70
+ {
71
+ image: image,
72
+ prompt: prompt,
73
+ size: options.delete(:size) || DEFAULT_SIZE,
74
+ response_format: options.delete(:response_format) || RESPONSE_FORMAT
75
+ }.merge(options)
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+
5
+ module GenAI
6
+ class Image
7
+ class StabilityAI < Base
8
+ DEFAULT_SIZE = '256x256'
9
+ API_BASE_URL = 'https://api.stability.ai'
10
+ DEFAULT_MODEL = 'stable-diffusion-xl-beta-v2-2-2'
11
+ UPSCALE_MODEL = 'stable-diffusion-x4-latent-upscaler'
12
+
13
+ def initialize(token:, options: {})
14
+ build_client(token)
15
+ end
16
+
17
+ def generate(prompt, options = {})
18
+ model = options[:model] || DEFAULT_MODEL
19
+ url = "/v1/generation/#{model}/text-to-image"
20
+
21
+ response = client.post url, build_generation_body(prompt, options)
22
+
23
+ build_result(
24
+ raw: response,
25
+ model: model,
26
+ parsed: response['artifacts'].map { |artifact| artifact['base64'] }
27
+ )
28
+ end
29
+
30
+ def edit(image, prompt, options = {})
31
+ model = options[:model] || DEFAULT_MODEL
32
+ url = "/v1/generation/#{model}/image-to-image"
33
+
34
+ response = client.post url, build_edit_body(image, prompt, options), multipart: true
35
+
36
+ build_result(
37
+ raw: response,
38
+ model: model,
39
+ parsed: response['artifacts'].map { |artifact| artifact['base64'] }
40
+ )
41
+ end
42
+
43
+ def upscale(image, options = {})
44
+ model = options[:model] || UPSCALE_MODEL
45
+ url = "/v1/generation/#{model}/image-to-image/upscale"
46
+
47
+ response = client.post url, build_upscale_body(image, options), multipart: true
48
+
49
+ build_result(
50
+ raw: response,
51
+ model: model,
52
+ parsed: response['artifacts'].map { |artifact| artifact['base64'] }
53
+ )
54
+ end
55
+
56
+ private
57
+
58
+ def build_client(token)
59
+ @client = GenAI::Api::Client.new(url: API_BASE_URL, token: token)
60
+ end
61
+
62
+ def build_generation_body(prompt, options)
63
+ w, h = size(options)
64
+
65
+ {
66
+ text_prompts: [{ text: prompt }],
67
+ height: h,
68
+ width: w
69
+ }.merge(options)
70
+ end
71
+
72
+ def build_edit_body(image, prompt, options)
73
+ params = {
74
+ init_image: File.binread(image),
75
+ 'text_prompts[0][text]' => prompt,
76
+ 'text_prompts[0][weight]' => 1.0
77
+ }
78
+ params.merge!(mask: File.binread(options.delete(:mask))) if options[:mask]
79
+ params.merge(options)
80
+ end
81
+
82
+ def build_upscale_body(image, options)
83
+ w, = size(options)
84
+ {
85
+ image: File.binread(image),
86
+ width: w
87
+ }.merge(options)
88
+ end
89
+
90
+ def size(options)
91
+ size = options.delete(:size) || DEFAULT_SIZE
92
+ size.split('x').map(&:to_i)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GenAI
4
+ class Image
5
+ def initialize(provider, token, options: {})
6
+ build_client(provider, token, options)
7
+ end
8
+
9
+ def generate(prompt, options = {})
10
+ client.generate(prompt, options)
11
+ end
12
+
13
+ def variations(image, options = {})
14
+ client.variations(image, options)
15
+ end
16
+
17
+ def edit(image, prompt, options = {})
18
+ client.edit(image, prompt, options)
19
+ end
20
+
21
+ def upscale(image, options = {})
22
+ client.upscale(image, options)
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :client
28
+
29
+ def build_client(provider, token, options)
30
+ klass = GenAI::Image.constants.find do |const|
31
+ const.to_s.downcase == provider.to_s.downcase.gsub('_', '')
32
+ end
33
+
34
+ raise UnsupportedProvider, "Unsupported Image provider '#{provider}'" unless klass
35
+
36
+ @client = GenAI::Image.const_get(klass).new(token: token, options: options)
37
+ end
38
+ end
39
+ end
@@ -2,9 +2,7 @@
2
2
 
3
3
  module GenAI
4
4
  class Language
5
- class Base
6
- include GenAI::Dependency
7
-
5
+ class Base < GenAI::Base
8
6
  DEFAULT_ROLE = 'user'
9
7
 
10
8
  def embed(...)
@@ -18,29 +16,6 @@ module GenAI
18
16
  def chat(...)
19
17
  raise NotImplementedError, "#{self.class.name} does not support conversations"
20
18
  end
21
-
22
- private
23
-
24
- attr_reader :client
25
-
26
- def handle_errors
27
- response = yield
28
- return if response.empty?
29
-
30
- if response['error']
31
- raise GenAI::ApiError, "#{api_provider_name} API error: #{response.dig('error', 'message')}"
32
- end
33
-
34
- response
35
- end
36
-
37
- def api_provider_name
38
- self.class.name.split('::').last
39
- end
40
-
41
- def build_result(model:, raw:, parsed:)
42
- GenAI::Result.new(provider: @provider, model: model, raw: raw, values: parsed)
43
- end
44
19
  end
45
20
  end
46
21
  end
@@ -11,7 +11,6 @@ module GenAI
11
11
  def initialize(token:, options: {})
12
12
  depends_on 'google_palm_api'
13
13
 
14
- @provider = :google_palm
15
14
  @client = ::GooglePalmApi::Client.new(api_key: token)
16
15
  end
17
16
 
@@ -8,7 +8,7 @@ module GenAI
8
8
 
9
9
  def initialize(token:, options: {})
10
10
  depends_on 'ruby-openai'
11
- @provider = :openai
11
+
12
12
  @client = ::OpenAI::Client.new(access_token: token)
13
13
  end
14
14
 
data/lib/gen_ai/result.rb CHANGED
@@ -33,7 +33,11 @@ module GenAI
33
33
  private
34
34
 
35
35
  def usage
36
- raw['usage']
36
+ raw['usage'] || {
37
+ 'prompt_tokens' => nil,
38
+ 'completion_tokens' => nil,
39
+ 'total_tokens' => nil
40
+ }
37
41
  end
38
42
  end
39
43
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GenAI
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.1'
5
5
  end
data/lib/gen_ai.rb CHANGED
@@ -4,7 +4,11 @@ require 'zeitwerk'
4
4
  require 'pry'
5
5
 
6
6
  loader = Zeitwerk::Loader.for_gem
7
- loader.inflector.inflect('gen_ai' => 'GenAI', 'open_ai' => 'OpenAI')
7
+ loader.inflector.inflect(
8
+ 'gen_ai' => 'GenAI',
9
+ 'open_ai' => 'OpenAI',
10
+ 'stability_ai' => 'StabilityAI'
11
+ )
8
12
  loader.setup
9
13
 
10
14
  module GenAI
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gen-ai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Chaplinsky
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-19 00:00:00.000000000 Z
11
+ date: 2023-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday-multipart
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: zeitwerk
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -63,11 +91,18 @@ files:
63
91
  - ".rubocop.yml"
64
92
  - CHANGELOG.md
65
93
  - CODE_OF_CONDUCT.md
94
+ - LICENSE
66
95
  - README.md
67
96
  - Rakefile
68
97
  - gen-ai.gemspec
69
98
  - lib/gen_ai.rb
99
+ - lib/gen_ai/api/client.rb
100
+ - lib/gen_ai/base.rb
70
101
  - lib/gen_ai/dependency.rb
102
+ - lib/gen_ai/image.rb
103
+ - lib/gen_ai/image/base.rb
104
+ - lib/gen_ai/image/open_ai.rb
105
+ - lib/gen_ai/image/stability_ai.rb
71
106
  - lib/gen_ai/language.rb
72
107
  - lib/gen_ai/language/base.rb
73
108
  - lib/gen_ai/language/google_palm.rb