omniai 0.0.1 → 0.0.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: 54cb0309adb2c49473342a47f964d2ddb8035a42d8d8fe1d9fa6960ac0987cf4
4
- data.tar.gz: 5f6792e26172ad6383308cd98501d6b53f4607411efba7317d90c6525fbb2473
3
+ metadata.gz: 8d54c88d48becdd4c496114b93841cf6dd32ba294a5cbf9828a0d0d4d28a023e
4
+ data.tar.gz: 8f8bb67797a1fa993cd5dc202d60e78c041ec184cf8120eae170e1b821228c62
5
5
  SHA512:
6
- metadata.gz: f065076a409f5acc450eb020edbeb840d1f66ece51085b8493e2663132210e38cf02d12709e5932ecdeef88f50c8e61541c9b0d676281e7cd22e397ae9cb4f30
7
- data.tar.gz: c44b00b48485d903c9f44f63137367fc71a0bf97c38d1d80274f8a51073339125ddbfeb1a427bbd459b496e4fe1c8f7921c5e5c7534af1499a2471621c3be6d5
6
+ metadata.gz: 8f0a3651c5eb608d0aba74c8c8ae06d4def73fc519fc4cbef6c8b2a8c3434d00cd469e24eaafc8f07193cb028c93984e459c7ffc65e89e56bfc30e0ebc879a05
7
+ data.tar.gz: 21be334bdd435bfb7b9c449556cce86dde4e33dd0d84bcd285cb4b52e438ed93ca387356821f76bce3064f3bc31be3446f43773456156976d0f33fcdceb89243
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ gem 'rake'
8
+
9
+ gem 'rspec'
10
+ gem 'rspec_junit_formatter'
11
+ gem 'rubocop'
12
+ gem 'rubocop-rake'
13
+ gem 'rubocop-rspec'
data/bin/console ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'omniai'
6
+
7
+ require 'irb'
8
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ class Chat
5
+ # A choice returned by the API.
6
+ class Choice
7
+ attr_accessor :index, :message, :role
8
+
9
+ # @param index [Integer]
10
+ # @param message [OmniAI::Chat::Message]
11
+ # @param role [String]
12
+ def initialize(index:, message:)
13
+ @index = index
14
+ @message = message
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ class Chat
5
+ # A message returned by the API.
6
+ class Message
7
+ attr_accessor :index, :message, :role
8
+
9
+ # @param content [Integer]
10
+ # @param role [String]
11
+ def initialize(content:, role:)
12
+ @content = content
13
+ @role = role
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ class Chat
5
+ # An abstract class that provides a consistent interface for processing chat requests.
6
+ #
7
+ # Usage:
8
+ #
9
+ # class OmniAI::OpenAI::ChatGPT::Completion < OmniAI::Chat::Completion
10
+ # module Model
11
+ # CHAT = "davinci"
12
+ # end
13
+ # def completion(messages, model:, temperature: 0.0, format: :text)
14
+ # end
15
+ # end
16
+ #
17
+ # Once defined, the subclass can be used to interface with the vendor's chat API as follows:
18
+ #
19
+ # client.chat.completion(messages, model: "...", temperature: 0.0, format: :text)
20
+ class Request
21
+ # @param client [OmniAI::Client] the client
22
+ # @param messages [String]
23
+ # @param model [String]
24
+ # @param temperature [Float]
25
+ # @param format [Symbol] either :text or :json
26
+ def initialize(client:, messages:, model:, temperature: 0.0, format: :text)
27
+ @client = client
28
+ @messages = messages
29
+ @model = model
30
+ @temperature = temperature
31
+ @format = format
32
+ end
33
+
34
+ # @param prompt [String, Message]
35
+ # @param model [String]
36
+ # @param format [Symbol] either :text or :json
37
+ # @param temperature [Float]
38
+ # @return [Hash]
39
+ # @raise [ExecutionError]
40
+ def process!
41
+ response = request!
42
+ raise HTTPError, response unless response.status.ok?
43
+
44
+ parse!(response:)
45
+ end
46
+
47
+ protected
48
+
49
+ # @param response [HTTP::Response]
50
+ # @return [OmniAI::Chat::Completion::Response]
51
+ def parse!(response:)
52
+ raise NotImplementedError, "#{self.class.name}#parse! undefined"
53
+ end
54
+
55
+ # @return [Hash]
56
+ def payload
57
+ raise NotImplementedError, "#{self.class.name}#payload undefined"
58
+ end
59
+
60
+ # @return [String]
61
+ def path
62
+ raise NotImplementedError, "#{self.class.name}#path undefined"
63
+ end
64
+
65
+ # @return [HTTP::Response]
66
+ def request!
67
+ @client
68
+ .connection
69
+ .accept(:json)
70
+ .post(path, json: payload)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ class Chat
5
+ # An abstract class that provides a consistent interface for processing chat responses.
6
+ #
7
+ # Usage:
8
+ #
9
+ # class OmniAI::OpenAI::Chat::Response < OmniAI::Chat::Response
10
+ # def choices
11
+ # # TODO: implement
12
+ # end
13
+ # end
14
+ class Response
15
+ attr_accessor :data
16
+
17
+ # @param data [Hash]
18
+ def initialize(data:)
19
+ @data = data
20
+ end
21
+
22
+ # @param [index] [Integer]
23
+ # @return [OmniAI::Chat::Choice]
24
+ def choice(index: 0)
25
+ choices[index]
26
+ end
27
+
28
+ # @return [Array<OmniAI::Chat::Choice>]
29
+ def choices
30
+ raise NotImplementedError, "#{self.class.name}#choices undefined"
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ # An abstract class that provides an interface for chatting for various vendors (e.g. OpenAI::ChatGPT).
5
+ #
6
+ # Usage:
7
+ #
8
+ # class OmniAI::OpenAI::Chat < OmniAI::Chat
9
+ # def completion(messages, model:, temperature: 0.0, format: :text)
10
+ # # TODO: implement
11
+ # end
12
+ # end
13
+ #
14
+ # Once defined, it can be used to interface with the vendor's chat API as follows:
15
+ #
16
+ # client.chat.completion("...", model: "...", temperature: 0.0, format: :text)
17
+ #
18
+ # @param client [OmniAI::Client] the client
19
+ class Chat
20
+ def initialize(client:)
21
+ @client = client
22
+ end
23
+
24
+ # @raise [OmniAI::Error]
25
+ #
26
+ # @param messages [String]
27
+ # @param model [String]
28
+ # @param format [Symbol] either :text or :json
29
+ # @param temperature [Float]
30
+ #
31
+ # @return [OmniAI::Chat::Request]
32
+ def completion(messages, model:, temperature: 0.0, format: :text)
33
+ raise NotImplementedError, "#{self.class.name}#completion undefined"
34
+ end
35
+ end
36
+ end
data/lib/omniai/client.rb CHANGED
@@ -1,27 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Usage:
4
- #
5
- # require "omniai"
6
- # require "omniai-anthropic"
7
- # require "omniai-google"
8
- # require "omniai-mistral"
9
- # require "omniai-openai"
10
- #
11
- # anthropic = OmniAI::Anthropic.new(api_key: ENV.fetch("OPENAI_API_KEY"))
12
- # google = OmniAI::Google.new(api_key: ENV.fetch("OPENAI_API_KEY"))
13
- # mistral = OmniAI::Mistral.new(api_key: ENV.fetch("OPENAI_API_KEY"))
14
- # openai = OmniAI::OpenAI.new(api_key: ENV.fetch("OPENAI_API_KEY"))
3
+ module OmniAI
4
+ # An abstract class that must be subclassed (e.g. OmniAI::OpenAI::Client).
5
+ #
6
+ # Usage:
7
+ #
8
+ # class OmniAI::OpenAI::Client < OmniAI::Client
9
+ # def initialize(api_key: ENV.fetch('OPENAI_API_KEY'))
10
+ # super
11
+ # end
12
+ #
13
+ # @return [OmniAI::OpenAI::Chat]
14
+ # def chat
15
+ # # TODO: implement
16
+ # end
17
+ # end
18
+ class Client
19
+ class Error < StandardError; end
15
20
 
16
- module OmniAI::Client
17
- class Error < StandardError; end
21
+ attr_accessor :api_key
18
22
 
19
- # @param api_key [String] The API key to use for requests
20
- def initialize(api_key:)
21
- @api_key = api_key
22
- end
23
+ # @param api_key [String]
24
+ def initialize(api_key:)
25
+ @api_key = api_key
26
+ end
27
+
28
+ # @return [HTTP::Client]
29
+ def connection
30
+ HTTP.auth("Bearer #{api_key}")
31
+ end
23
32
 
24
- def http
25
- HTTP.auth("Bearer #{@api_key}")
33
+ # @return [OmniAI::Chat] an instance of OmniAI::Chat
34
+ def chat
35
+ raise NotImplementedError, "#{self.class.name}#chat undefined"
36
+ end
26
37
  end
27
38
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OmniAI
4
- VERSION = "0.0.1"
4
+ VERSION = '0.0.3'
5
5
  end
data/lib/omniai.rb CHANGED
@@ -1,7 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "omniai/version"
3
+ require 'http'
4
+ require 'zeitwerk'
5
+
6
+ loader = Zeitwerk::Loader.for_gem
7
+ loader.inflector.inflect 'omniai' => 'OmniAI'
8
+ loader.setup
4
9
 
5
10
  module OmniAI
6
11
  class Error < StandardError; end
12
+
13
+ # An error that wraps an HTTP::Response for non-OK requests.
14
+ class HTTPError < Error
15
+ attr_accessor :response
16
+
17
+ # @param response [HTTP::Response]
18
+ def initialize(response)
19
+ super("status=#{response.status} headers=#{response.headers} body=#{response.body}")
20
+ @response = response
21
+ end
22
+ end
7
23
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Sylvestre
@@ -25,52 +25,45 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rspec
28
+ name: zeitwerk
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: rubocop
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
34
+ type: :runtime
49
35
  prerelease: false
50
36
  version_requirements: !ruby/object:Gem::Requirement
51
37
  requirements:
52
38
  - - ">="
53
39
  - !ruby/object:Gem::Version
54
40
  version: '0'
55
- description: Gives a consistent interface for interacting with OpenAI's ChatGPT, Google's
56
- Gemini, Anthropic's Claude, Mistral's LeChat, and more.
41
+ description: An interface for OpenAI's ChatGPT, Google's Gemini, Anthropic's Claude,
42
+ Mistral's LeChat, etc.
57
43
  email:
58
44
  - kevin@ksylvest.com
59
45
  executables: []
60
46
  extensions: []
61
47
  extra_rdoc_files: []
62
48
  files:
63
- - ".rspec"
64
- - ".rubocop.yml"
49
+ - Gemfile
65
50
  - README.md
66
- - Rakefile
51
+ - bin/console
52
+ - bin/setup
67
53
  - lib/omniai.rb
54
+ - lib/omniai/chat.rb
55
+ - lib/omniai/chat/choice.rb
56
+ - lib/omniai/chat/message.rb
57
+ - lib/omniai/chat/request.rb
58
+ - lib/omniai/chat/response.rb
68
59
  - lib/omniai/client.rb
69
60
  - lib/omniai/version.rb
70
- - sig/omniai.rbs
71
61
  homepage: https://github.com/ksylvest/omniai
72
62
  licenses: []
73
- metadata: {}
63
+ metadata:
64
+ homepage_uri: https://github.com/ksylvest/omniai
65
+ changelog_uri: https://github.com/ksylvest/omniai/releases
66
+ rubygems_mfa_required: 'true'
74
67
  post_install_message:
75
68
  rdoc_options: []
76
69
  require_paths:
@@ -79,7 +72,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
72
  requirements:
80
73
  - - ">="
81
74
  - !ruby/object:Gem::Version
82
- version: 3.0.0
75
+ version: 3.3.0
83
76
  required_rubygems_version: !ruby/object:Gem::Requirement
84
77
  requirements:
85
78
  - - ">="
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
data/.rubocop.yml DELETED
@@ -1,2 +0,0 @@
1
- AllCops:
2
- TargetRubyVersion: 3.0
data/Rakefile DELETED
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
5
-
6
- RSpec::Core::RakeTask.new(:spec)
7
-
8
- require "rubocop/rake_task"
9
-
10
- RuboCop::RakeTask.new
11
-
12
- task default: %i[spec rubocop]
data/sig/omniai.rbs DELETED
@@ -1,3 +0,0 @@
1
- module OmniAI
2
- VERSION: String
3
- end