omniai 1.0.0 → 1.0.2
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 +4 -4
- data/README.md +4 -4
- data/lib/omniai/chat.rb +96 -18
- data/lib/omniai/client.rb +10 -7
- data/lib/omniai/version.rb +1 -1
- metadata +6 -7
- data/lib/omniai/chat/request.rb +0 -105
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ffc27287a50c39e3aab00622ea1e389f2e2da0828e5ec5b01f0e62bf7ec63c58
|
4
|
+
data.tar.gz: 3979a4a92abd12706cc36ff66d4befab252a48a2deb7d5b3db3a81162af41b50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32f6f70655128b1eb60bcc1add45eb53cd312550a521fd3a7a7663f09f4084809d139ecb2a617464266b12199f590db26bfa240be9c5fb90b6d1e264b1bd57c9
|
7
|
+
data.tar.gz: d7b170ae465c6e72e4faa5fde86a216bd8317205c9c1630753f527424aa9e59b60f6f1dca32fcecd242824485f7fc328368d9fd8bcff92658fdfd078a5d4080f
|
data/README.md
CHANGED
@@ -65,7 +65,7 @@ Clients that support chat (e.g. Anthropic w/ "Claude", Google w/ "Gemini", Mistr
|
|
65
65
|
#### w/ a Simple Prompt
|
66
66
|
|
67
67
|
```ruby
|
68
|
-
completion = client.chat
|
68
|
+
completion = client.chat('Tell me a joke.')
|
69
69
|
puts(completion.choice.message.content) # '...'
|
70
70
|
```
|
71
71
|
|
@@ -82,7 +82,7 @@ messages = [
|
|
82
82
|
content: 'What is the capital of Canada?',
|
83
83
|
},
|
84
84
|
]
|
85
|
-
completion = client.chat
|
85
|
+
completion = client.chat(messages, model: '...', temperature: 0.7, format: :json)
|
86
86
|
puts(completion.choice.message.content) # '...'
|
87
87
|
```
|
88
88
|
|
@@ -102,7 +102,7 @@ message = {
|
|
102
102
|
]
|
103
103
|
}
|
104
104
|
|
105
|
-
completion = client.chat
|
105
|
+
completion = client.chat(message)
|
106
106
|
puts(completion.choice.message.content) # '...'
|
107
107
|
```
|
108
108
|
|
@@ -112,5 +112,5 @@ puts(completion.choice.message.content) # '...'
|
|
112
112
|
stream = proc do |chunk|
|
113
113
|
print(chunk.choice.delta.content) # '...'
|
114
114
|
end
|
115
|
-
client.chat
|
115
|
+
client.chat('Tell me a joke.', stream:)
|
116
116
|
```
|
data/lib/omniai/chat.rb
CHANGED
@@ -1,21 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module OmniAI
|
4
|
-
# An abstract class that provides
|
4
|
+
# An abstract class that provides a consistent interface for processing chat requests.
|
5
5
|
#
|
6
6
|
# Usage:
|
7
7
|
#
|
8
8
|
# class OmniAI::OpenAI::Chat < OmniAI::Chat
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# module Model
|
10
|
+
# GPT_4O = "gpt-4o"
|
11
11
|
# end
|
12
|
-
# end
|
13
12
|
#
|
14
|
-
#
|
13
|
+
# protected
|
15
14
|
#
|
16
|
-
#
|
15
|
+
# # @return [Hash]
|
16
|
+
# def payload
|
17
|
+
# raise NotImplementedError, "#{self.class.name}#payload undefined"
|
18
|
+
# end
|
17
19
|
#
|
18
|
-
# @
|
20
|
+
# # @return [String]
|
21
|
+
# def path
|
22
|
+
# raise NotImplementedError, "#{self.class.name}#path undefined"
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# client.chat(messages, model: "...", temperature: 0.0, format: :text)
|
19
27
|
class Chat
|
20
28
|
JSON_PROMPT = 'Respond with valid JSON. Do not include any non-JSON in the response.'
|
21
29
|
|
@@ -25,21 +33,91 @@ module OmniAI
|
|
25
33
|
SYSTEM = 'system'
|
26
34
|
end
|
27
35
|
|
28
|
-
def
|
29
|
-
|
36
|
+
def self.process!(...)
|
37
|
+
new(...).process!
|
30
38
|
end
|
31
39
|
|
32
|
-
# @
|
33
|
-
#
|
34
|
-
# @param
|
35
|
-
# @param model [String] optional
|
36
|
-
# @param format [Symbol] optional :text or :json
|
40
|
+
# @param messages [String] required
|
41
|
+
# @param client [OmniAI::Client] the client
|
42
|
+
# @param model [String] required
|
37
43
|
# @param temperature [Float, nil] optional
|
38
44
|
# @param stream [Proc, nil] optional
|
39
|
-
#
|
40
|
-
|
41
|
-
|
42
|
-
|
45
|
+
# @param format [Symbol, nil] optional - :json
|
46
|
+
def initialize(messages, client:, model:, temperature: nil, stream: nil, format: nil)
|
47
|
+
@messages = messages
|
48
|
+
@client = client
|
49
|
+
@model = model
|
50
|
+
@temperature = temperature
|
51
|
+
@stream = stream
|
52
|
+
@format = format
|
53
|
+
end
|
54
|
+
|
55
|
+
# @raise [ExecutionError]
|
56
|
+
def process!
|
57
|
+
response = request!
|
58
|
+
raise HTTPError, response unless response.status.ok?
|
59
|
+
|
60
|
+
parse!(response:)
|
61
|
+
end
|
62
|
+
|
63
|
+
protected
|
64
|
+
|
65
|
+
# @return [Hash]
|
66
|
+
def payload
|
67
|
+
raise NotImplementedError, "#{self.class.name}#payload undefined"
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [String]
|
71
|
+
def path
|
72
|
+
raise NotImplementedError, "#{self.class.name}#path undefined"
|
73
|
+
end
|
74
|
+
|
75
|
+
# @param response [HTTP::Response]
|
76
|
+
# @return [OmniAI::Chat::Completion]
|
77
|
+
def parse!(response:)
|
78
|
+
if @stream
|
79
|
+
stream!(response:)
|
80
|
+
else
|
81
|
+
complete!(response:)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# @param response [OmniAI::Chat::Completion]
|
86
|
+
def complete!(response:)
|
87
|
+
Completion.new(data: response.parse)
|
88
|
+
end
|
89
|
+
|
90
|
+
# @param response [HTTP::Response]
|
91
|
+
# @return [OmniAI::Chat::Stream]
|
92
|
+
def stream!(response:)
|
93
|
+
raise Error, "#{self.class.name}#stream! unstreamable" unless @stream
|
94
|
+
|
95
|
+
Stream.new(response:).stream! { |chunk| @stream.call(chunk) }
|
96
|
+
end
|
97
|
+
|
98
|
+
# @return [Array<Hash>]
|
99
|
+
def messages
|
100
|
+
arrayify(@messages).map do |content|
|
101
|
+
case content
|
102
|
+
when String then { role: OmniAI::Chat::Role::USER, content: }
|
103
|
+
when Hash then content
|
104
|
+
else raise Error, "Unsupported content=#{content.inspect}"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# @param value [Object, Array<Object>]
|
110
|
+
# @return [Array<Object>]
|
111
|
+
def arrayify(value)
|
112
|
+
value.is_a?(Array) ? value : [value]
|
113
|
+
end
|
114
|
+
|
115
|
+
# @return [HTTP::Response]
|
116
|
+
def request!
|
117
|
+
@client
|
118
|
+
.connection
|
119
|
+
.accept(:json)
|
120
|
+
.post(path, json: payload)
|
43
121
|
end
|
44
122
|
end
|
45
123
|
end
|
data/lib/omniai/client.rb
CHANGED
@@ -9,11 +9,6 @@ module OmniAI
|
|
9
9
|
# def initialize(api_key: ENV.fetch('OPENAI_API_KEY'), logger: nil)
|
10
10
|
# super
|
11
11
|
# end
|
12
|
-
#
|
13
|
-
# @return [OmniAI::OpenAI::Chat]
|
14
|
-
# def chat
|
15
|
-
# # TODO: implement
|
16
|
-
# end
|
17
12
|
# end
|
18
13
|
class Client
|
19
14
|
class Error < StandardError; end
|
@@ -38,8 +33,16 @@ module OmniAI
|
|
38
33
|
raise NotImplementedError, "#{self.class.name}#connection undefined"
|
39
34
|
end
|
40
35
|
|
41
|
-
# @
|
42
|
-
|
36
|
+
# @raise [OmniAI::Error]
|
37
|
+
#
|
38
|
+
# @param messages [String, Array, Hash]
|
39
|
+
# @param model [String] optional
|
40
|
+
# @param format [Symbol] optional :text or :json
|
41
|
+
# @param temperature [Float, nil] optional
|
42
|
+
# @param stream [Proc, nil] optional
|
43
|
+
#
|
44
|
+
# @return [OmniAI::Chat::Completion]
|
45
|
+
def chat(messages, model:, temperature: nil, format: nil, stream: nil)
|
43
46
|
raise NotImplementedError, "#{self.class.name}#chat undefined"
|
44
47
|
end
|
45
48
|
end
|
data/lib/omniai/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: omniai
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Sylvestre
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-06-
|
11
|
+
date: 2024-06-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: event_stream_parser
|
@@ -72,7 +72,6 @@ files:
|
|
72
72
|
- lib/omniai/chat/content.rb
|
73
73
|
- lib/omniai/chat/delta.rb
|
74
74
|
- lib/omniai/chat/message.rb
|
75
|
-
- lib/omniai/chat/request.rb
|
76
75
|
- lib/omniai/chat/stream.rb
|
77
76
|
- lib/omniai/chat/usage.rb
|
78
77
|
- lib/omniai/client.rb
|
@@ -84,7 +83,7 @@ metadata:
|
|
84
83
|
homepage_uri: https://github.com/ksylvest/omniai
|
85
84
|
changelog_uri: https://github.com/ksylvest/omniai/releases
|
86
85
|
rubygems_mfa_required: 'true'
|
87
|
-
post_install_message:
|
86
|
+
post_install_message:
|
88
87
|
rdoc_options: []
|
89
88
|
require_paths:
|
90
89
|
- lib
|
@@ -99,8 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
98
|
- !ruby/object:Gem::Version
|
100
99
|
version: '0'
|
101
100
|
requirements: []
|
102
|
-
rubygems_version: 3.5.
|
103
|
-
signing_key:
|
101
|
+
rubygems_version: 3.5.3
|
102
|
+
signing_key:
|
104
103
|
specification_version: 4
|
105
104
|
summary: A generalized framework for interacting with many AI services
|
106
105
|
test_files: []
|
data/lib/omniai/chat/request.rb
DELETED
@@ -1,105 +0,0 @@
|
|
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::Request < OmniAI::Chat::Request
|
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] required
|
23
|
-
# @param model [String] required
|
24
|
-
# @param temperature [Float, nil] optional
|
25
|
-
# @param stream [Proc, nil] optional
|
26
|
-
# @param format [Symbol, nil] optional - :json
|
27
|
-
def initialize(client:, messages:, model:, temperature: nil, stream: nil, format: nil)
|
28
|
-
@client = client
|
29
|
-
@messages = messages
|
30
|
-
@model = model
|
31
|
-
@temperature = temperature
|
32
|
-
@stream = stream
|
33
|
-
@format = format
|
34
|
-
end
|
35
|
-
|
36
|
-
# @raise [ExecutionError]
|
37
|
-
def process!
|
38
|
-
response = request!
|
39
|
-
raise HTTPError, response unless response.status.ok?
|
40
|
-
|
41
|
-
parse!(response:)
|
42
|
-
end
|
43
|
-
|
44
|
-
protected
|
45
|
-
|
46
|
-
# @return [Hash]
|
47
|
-
def payload
|
48
|
-
raise NotImplementedError, "#{self.class.name}#payload undefined"
|
49
|
-
end
|
50
|
-
|
51
|
-
# @return [String]
|
52
|
-
def path
|
53
|
-
raise NotImplementedError, "#{self.class.name}#path undefined"
|
54
|
-
end
|
55
|
-
|
56
|
-
# @param response [HTTP::Response]
|
57
|
-
# @return [OmniAI::Chat::Completion]
|
58
|
-
def parse!(response:)
|
59
|
-
if @stream
|
60
|
-
stream!(response:)
|
61
|
-
else
|
62
|
-
complete!(response:)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# @param response [OmniAI::Chat::Completion]
|
67
|
-
def complete!(response:)
|
68
|
-
Completion.new(data: response.parse)
|
69
|
-
end
|
70
|
-
|
71
|
-
# @param response [HTTP::Response]
|
72
|
-
# @return [OmniAI::Chat::Stream]
|
73
|
-
def stream!(response:)
|
74
|
-
raise Error, "#{self.class.name}#stream! unstreamable" unless @stream
|
75
|
-
|
76
|
-
Stream.new(response:).stream! { |chunk| @stream.call(chunk) }
|
77
|
-
end
|
78
|
-
|
79
|
-
# @return [Array<Hash>]
|
80
|
-
def messages
|
81
|
-
arrayify(@messages).map do |content|
|
82
|
-
case content
|
83
|
-
when String then { role: OmniAI::Chat::Role::USER, content: }
|
84
|
-
when Hash then content
|
85
|
-
else raise Error, "Unsupported content=#{content.inspect}"
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# @param value [Object, Array<Object>]
|
91
|
-
# @return [Array<Object>]
|
92
|
-
def arrayify(value)
|
93
|
-
value.is_a?(Array) ? value : [value]
|
94
|
-
end
|
95
|
-
|
96
|
-
# @return [HTTP::Response]
|
97
|
-
def request!
|
98
|
-
@client
|
99
|
-
.connection
|
100
|
-
.accept(:json)
|
101
|
-
.post(path, json: payload)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|