omniai 1.7.0 → 1.8.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 +4 -4
- data/Gemfile +2 -0
- data/README.md +3 -10
- data/lib/omniai/chat/choice.rb +68 -0
- data/lib/omniai/chat/content.rb +10 -2
- data/lib/omniai/chat/file.rb +3 -3
- data/lib/omniai/chat/function.rb +57 -0
- data/lib/omniai/chat/message/builder.rb +67 -0
- data/lib/omniai/chat/message.rb +64 -45
- data/lib/omniai/chat/payload.rb +85 -0
- data/lib/omniai/chat/prompt.rb +30 -16
- data/lib/omniai/chat/response.rb +70 -0
- data/lib/omniai/chat/stream.rb +61 -0
- data/lib/omniai/chat/text.rb +2 -2
- data/lib/omniai/chat/tool_call.rb +54 -0
- data/lib/omniai/chat/tool_call_message.rb +61 -0
- data/lib/omniai/chat/tool_call_result.rb +51 -0
- data/lib/omniai/chat/url.rb +2 -2
- data/lib/omniai/chat/usage.rb +60 -0
- data/lib/omniai/chat.rb +61 -34
- data/lib/omniai/context.rb +12 -0
- data/lib/omniai/embed/response.rb +2 -2
- data/lib/omniai/tool.rb +6 -2
- data/lib/omniai/version.rb +1 -1
- metadata +12 -16
- data/lib/omniai/chat/response/choice.rb +0 -35
- data/lib/omniai/chat/response/chunk.rb +0 -15
- data/lib/omniai/chat/response/completion.rb +0 -15
- data/lib/omniai/chat/response/delta.rb +0 -11
- data/lib/omniai/chat/response/delta_choice.rb +0 -25
- data/lib/omniai/chat/response/function.rb +0 -25
- data/lib/omniai/chat/response/message.rb +0 -11
- data/lib/omniai/chat/response/message_choice.rb +0 -25
- data/lib/omniai/chat/response/part.rb +0 -38
- data/lib/omniai/chat/response/payload.rb +0 -72
- data/lib/omniai/chat/response/resource.rb +0 -22
- data/lib/omniai/chat/response/stream.rb +0 -27
- data/lib/omniai/chat/response/tool_call.rb +0 -30
- data/lib/omniai/chat/response/usage.rb +0 -35
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OmniAI
|
4
|
+
class Chat
|
5
|
+
# Used when processing everything at once.
|
6
|
+
class Response
|
7
|
+
# @return [Hash]
|
8
|
+
attr_accessor :data
|
9
|
+
|
10
|
+
# @param data [Hash]
|
11
|
+
# @param context [Context, nil]
|
12
|
+
def initialize(data:, context: nil)
|
13
|
+
@data = data
|
14
|
+
@context = context
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Payload]
|
18
|
+
def completion
|
19
|
+
@completion ||= Payload.deserialize(@data, context: @context)
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [Usage, nil]
|
23
|
+
def usage
|
24
|
+
completion.usage
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Array<Choice>]
|
28
|
+
def choices
|
29
|
+
completion.choices
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Array<Message>]
|
33
|
+
def messages
|
34
|
+
completion.messages
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param index [Integer]
|
38
|
+
# @return [Choice]
|
39
|
+
def choice(index: 0)
|
40
|
+
completion.choice(index:)
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param index [Integer]
|
44
|
+
# @return [Message]
|
45
|
+
def message(index: 0)
|
46
|
+
completion.message(index:)
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [String]
|
50
|
+
def text
|
51
|
+
message.text
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [Boolean]
|
55
|
+
def text?
|
56
|
+
message.text?
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [Array<ToolCall>]
|
60
|
+
def tool_call_list
|
61
|
+
choice.tool_call_list
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [Boolean]
|
65
|
+
def tool_call_list?
|
66
|
+
tool_call_list&.any?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OmniAI
|
4
|
+
class Chat
|
5
|
+
# Used when streaming to process chunks of data.
|
6
|
+
class Stream
|
7
|
+
# @param logger [OmniAI::Client]
|
8
|
+
# @param body [HTTP::Response::Body]
|
9
|
+
# @param context [Context, nil]
|
10
|
+
def initialize(body:, logger: nil, context: nil)
|
11
|
+
@body = body
|
12
|
+
@logger = logger
|
13
|
+
@context = context
|
14
|
+
end
|
15
|
+
|
16
|
+
# @yield [payload]
|
17
|
+
# @yieldparam payload [OmniAI::Chat::Payload]
|
18
|
+
def stream!(&)
|
19
|
+
@body.each do |chunk|
|
20
|
+
parser.feed(chunk) do |type, data, id|
|
21
|
+
process!(type, data, id, &)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
# @param type [String]
|
29
|
+
# @param data [String]
|
30
|
+
# @param id [String]
|
31
|
+
def log(type, data, id)
|
32
|
+
arguments = [
|
33
|
+
("type=#{type.inspect}" if type),
|
34
|
+
("data=#{data.inspect}" if data),
|
35
|
+
("id=#{id.inspect}" if id),
|
36
|
+
].compact
|
37
|
+
|
38
|
+
@logger&.debug("Stream#process! #{arguments.join(' ')}")
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param type [String]
|
42
|
+
# @param data [String]
|
43
|
+
# @param id [String]
|
44
|
+
#
|
45
|
+
# @yield [payload]
|
46
|
+
# @yieldparam payload [OmniAI::Chat::Payload]
|
47
|
+
def process!(type, data, id, &block)
|
48
|
+
log(type, data, id)
|
49
|
+
|
50
|
+
return if data.eql?('[DONE]')
|
51
|
+
|
52
|
+
block.call(Payload.deserialize(JSON.parse(data), context: @context))
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [EventStreamParser::Parser]
|
56
|
+
def parser
|
57
|
+
@parser ||= EventStreamParser::Parser.new
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/omniai/chat/text.rb
CHANGED
@@ -25,7 +25,7 @@ module OmniAI
|
|
25
25
|
|
26
26
|
# @param data [Hash]
|
27
27
|
def self.deserialize(data, context: nil)
|
28
|
-
deserialize = context&.
|
28
|
+
deserialize = context&.deserializer(:text)
|
29
29
|
return deserialize.call(data, context:) if deserialize
|
30
30
|
|
31
31
|
new(data['text'])
|
@@ -35,7 +35,7 @@ module OmniAI
|
|
35
35
|
#
|
36
36
|
# @return [Hash]
|
37
37
|
def serialize(context: nil)
|
38
|
-
serializer = context&.
|
38
|
+
serializer = context&.serializer(:text)
|
39
39
|
return serializer.call(self, context:) if serializer
|
40
40
|
|
41
41
|
{ type: 'text', text: @text }
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OmniAI
|
4
|
+
class Chat
|
5
|
+
# A tool-call that includes an ID / function.
|
6
|
+
class ToolCall
|
7
|
+
# @return [String]
|
8
|
+
attr_accessor :id
|
9
|
+
|
10
|
+
# @return [Function]
|
11
|
+
attr_accessor :function
|
12
|
+
|
13
|
+
# @param id [String]
|
14
|
+
# @param function [Function]
|
15
|
+
def initialize(id:, function:)
|
16
|
+
@id = id
|
17
|
+
@function = function
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [String]
|
21
|
+
def inspect
|
22
|
+
"#<#{self.class.name} id=#{id.inspect} function=#{function.inspect}>"
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param data [Hash]
|
26
|
+
# @param context [Context] optional
|
27
|
+
#
|
28
|
+
# @return [Function]
|
29
|
+
def self.deserialize(data, context: nil)
|
30
|
+
deserialize = context&.deserializer(:tool_call)
|
31
|
+
return deserialize.call(data, context:) if deserialize
|
32
|
+
|
33
|
+
id = data['id']
|
34
|
+
function = Function.deserialize(data['function'], context:)
|
35
|
+
|
36
|
+
new(id:, function:)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param context [Context] optional
|
40
|
+
#
|
41
|
+
# @return [Hash]
|
42
|
+
def serialize(context: nil)
|
43
|
+
serializer = context&.serializer(:tool_call)
|
44
|
+
return serializer.call(self, context:) if serializer
|
45
|
+
|
46
|
+
{
|
47
|
+
id: @id,
|
48
|
+
type: 'function',
|
49
|
+
function: @function.serialize(context:),
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OmniAI
|
4
|
+
class Chat
|
5
|
+
# A specific message that contains the result of a tool call.
|
6
|
+
class ToolCallMessage < Message
|
7
|
+
# @return [String]
|
8
|
+
attr_accessor :tool_call_id
|
9
|
+
|
10
|
+
# @param content [String]
|
11
|
+
# @param tool_call_id [String]
|
12
|
+
def initialize(content:, tool_call_id:, role: OmniAI::Chat::Role::TOOL)
|
13
|
+
super(content:, role:)
|
14
|
+
@tool_call_id = tool_call_id
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [String]
|
18
|
+
def inspect
|
19
|
+
"#<#{self.class.name} content=#{content.inspect} tool_call_id=#{tool_call_id.inspect}>"
|
20
|
+
end
|
21
|
+
|
22
|
+
# Usage:
|
23
|
+
#
|
24
|
+
# ToolCall.deserialize({ 'role' => 'tool', content: '{ 'temperature': 0 }' }) # => #<ToolCall ...>
|
25
|
+
#
|
26
|
+
# @param data [Hash]
|
27
|
+
# @param context [Context] optional
|
28
|
+
#
|
29
|
+
# @return [ToolMessage]
|
30
|
+
def self.deserialize(data, context: nil)
|
31
|
+
deserialize = context&.deserializer(:tool_message)
|
32
|
+
return deserialize.call(data, context:) if deserialize
|
33
|
+
|
34
|
+
role = data['role']
|
35
|
+
content = JSON.parse(data['content'])
|
36
|
+
tool_call_id = data['tool_call_id']
|
37
|
+
|
38
|
+
new(role:, content:, tool_call_id:)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Usage:
|
42
|
+
#
|
43
|
+
# message.serialize # => { role: :user, content: 'Hello!' }
|
44
|
+
# message.serialize # => { role: :user, content: [{ type: 'text', text: 'Hello!' }] }
|
45
|
+
#
|
46
|
+
# @param context [Context] optional
|
47
|
+
#
|
48
|
+
# @return [Hash]
|
49
|
+
def serialize(context: nil)
|
50
|
+
serializer = context&.serializer(:tool_message)
|
51
|
+
return serializer.call(self, context:) if serializer
|
52
|
+
|
53
|
+
role = @role
|
54
|
+
content = JSON.generate(@content)
|
55
|
+
tool_call_id = @tool_call_id
|
56
|
+
|
57
|
+
{ role:, content:, tool_call_id: }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OmniAI
|
4
|
+
class Chat
|
5
|
+
# The result of a tool call.
|
6
|
+
class ToolCallResult
|
7
|
+
# @return [Object]
|
8
|
+
attr_accessor :content
|
9
|
+
|
10
|
+
# @return [ToolCall]
|
11
|
+
attr_accessor :tool_call_id
|
12
|
+
|
13
|
+
# @param content [Object]
|
14
|
+
# @param tool_call [ToolCall]
|
15
|
+
def initialize(content:, tool_call_id:)
|
16
|
+
@content = content
|
17
|
+
@tool_call_id = tool_call_id
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [String]
|
21
|
+
def inspect
|
22
|
+
"#<#{self.class.name} content=#{content.inspect} tool_call_id=#{tool_call_id.inspect}>"
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param context [Context] optional
|
26
|
+
# @return [Hash]
|
27
|
+
def serialize(context: nil)
|
28
|
+
serializer = context&.serializer(:tool_call_result)
|
29
|
+
return serializer.call(self, context:) if serializer
|
30
|
+
|
31
|
+
content = JSON.generate(@content)
|
32
|
+
tool_call_id = @tool_call_id
|
33
|
+
|
34
|
+
{ content:, tool_call_id: }
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param data [Hash]
|
38
|
+
# @param context [Context] optional
|
39
|
+
# @return [ToolCallResult]
|
40
|
+
def self.deserialize(data, context: nil)
|
41
|
+
deserialize = context&.deserializer(:tool_call_result)
|
42
|
+
return deserialize.call(data, context:) if deserialize
|
43
|
+
|
44
|
+
content = JSON.parse(data['content'])
|
45
|
+
tool_call_id = data['tool_call_id']
|
46
|
+
|
47
|
+
new(content:, tool_call_id:)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/omniai/chat/url.rb
CHANGED
@@ -28,7 +28,7 @@ module OmniAI
|
|
28
28
|
|
29
29
|
# @param data [Hash]
|
30
30
|
def self.deserialize(data, context: nil)
|
31
|
-
deserialize = context&.
|
31
|
+
deserialize = context&.deserializer(:url)
|
32
32
|
return deserialize.call(data, context:) if deserialize
|
33
33
|
|
34
34
|
type = /(?<type>\w+)_url/.match(data['type'])[:type]
|
@@ -45,7 +45,7 @@ module OmniAI
|
|
45
45
|
content = fetch!
|
46
46
|
Text.new("<file>#{filename}: #{content}</file>").serialize(context:)
|
47
47
|
else
|
48
|
-
serializer = context&.
|
48
|
+
serializer = context&.serializer(:url)
|
49
49
|
return serializer.call(self, context:) if serializer
|
50
50
|
|
51
51
|
{
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OmniAI
|
4
|
+
class Chat
|
5
|
+
# The usage of a chat in terms of tokens (input / output / total).
|
6
|
+
class Usage
|
7
|
+
# @return [Integer]
|
8
|
+
attr_accessor :input_tokens
|
9
|
+
|
10
|
+
# @return [Integer]
|
11
|
+
attr_accessor :output_tokens
|
12
|
+
|
13
|
+
# @return [Integer]
|
14
|
+
attr_accessor :total_tokens
|
15
|
+
|
16
|
+
# @param input_tokens [Integer]
|
17
|
+
# @param output_tokens [Integer]
|
18
|
+
# @param total_tokens [Integer]
|
19
|
+
def initialize(input_tokens:, output_tokens:, total_tokens:)
|
20
|
+
@input_tokens = input_tokens
|
21
|
+
@output_tokens = output_tokens
|
22
|
+
@total_tokens = total_tokens
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [String]
|
26
|
+
def inspect
|
27
|
+
"#<#{self.class.name} input_tokens=#{input_tokens} output_tokens=#{output_tokens} total_tokens=#{total_tokens}>"
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param data [Hash]
|
31
|
+
# @param context [OmniAI::Context] optional
|
32
|
+
#
|
33
|
+
# @return [OmniAI::Chat::Usage]
|
34
|
+
def self.deserialize(data, context: nil)
|
35
|
+
deserialize = context&.deserializer(:usage)
|
36
|
+
return deserialize.call(data, context:) if deserialize
|
37
|
+
|
38
|
+
input_tokens = data['input_tokens']
|
39
|
+
output_tokens = data['output_tokens']
|
40
|
+
total_tokens = data['total_tokens']
|
41
|
+
|
42
|
+
new(input_tokens:, output_tokens:, total_tokens:)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param context [OmniAI::Context] optional
|
46
|
+
#
|
47
|
+
# @return [Hash]
|
48
|
+
def serialize(context: nil)
|
49
|
+
serialize = context&.serializer(:usage)
|
50
|
+
return serialize.call(self, context:) if serialize
|
51
|
+
|
52
|
+
{
|
53
|
+
input_tokens:,
|
54
|
+
output_tokens:,
|
55
|
+
total_tokens:,
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/omniai/chat.rb
CHANGED
@@ -27,14 +27,23 @@ module OmniAI
|
|
27
27
|
class Chat
|
28
28
|
JSON_PROMPT = 'Respond with valid JSON. Do not include any non-JSON in the response.'
|
29
29
|
|
30
|
-
# An error raised
|
31
|
-
class
|
32
|
-
|
33
|
-
|
30
|
+
# An error raised for tool-call issues.
|
31
|
+
class ToolCallError < Error
|
32
|
+
# @param tool_call [OmniAI::Chat::ToolCall]
|
33
|
+
# @param message [String]
|
34
|
+
def initialize(tool_call:, message:)
|
35
|
+
super(message)
|
34
36
|
@tool_call = tool_call
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
40
|
+
# An error raised when a tool-call is missing.
|
41
|
+
class ToolCallMissingError < ToolCallError
|
42
|
+
def initialize(tool_call:)
|
43
|
+
super(tool_call:, message: "missing tool for tool_call=#{tool_call.inspect}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
38
47
|
module Role
|
39
48
|
ASSISTANT = 'assistant'
|
40
49
|
USER = 'user'
|
@@ -87,10 +96,22 @@ module OmniAI
|
|
87
96
|
|
88
97
|
protected
|
89
98
|
|
99
|
+
# Override to provide an context for serializers / deserializes for a provider.
|
100
|
+
#
|
101
|
+
# @return [Context, nil]
|
102
|
+
def context
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
|
106
|
+
# @return [Logger, nil]
|
107
|
+
def logger
|
108
|
+
@client.logger
|
109
|
+
end
|
110
|
+
|
90
111
|
# Used to spawn another chat with the same configuration using different messages.
|
91
112
|
#
|
92
113
|
# @param prompt [OmniAI::Chat::Prompt]
|
93
|
-
# @return [OmniAI::Chat
|
114
|
+
# @return [OmniAI::Chat]
|
94
115
|
def spawn!(prompt)
|
95
116
|
self.class.new(
|
96
117
|
prompt,
|
@@ -100,7 +121,7 @@ module OmniAI
|
|
100
121
|
stream: @stream,
|
101
122
|
tools: @tools,
|
102
123
|
format: @format
|
103
|
-
)
|
124
|
+
)
|
104
125
|
end
|
105
126
|
|
106
127
|
# @return [Hash]
|
@@ -114,7 +135,7 @@ module OmniAI
|
|
114
135
|
end
|
115
136
|
|
116
137
|
# @param response [HTTP::Response]
|
117
|
-
# @return [OmniAI::Chat::Response
|
138
|
+
# @return [OmniAI::Chat::Response]
|
118
139
|
def parse!(response:)
|
119
140
|
if @stream
|
120
141
|
stream!(response:)
|
@@ -124,31 +145,32 @@ module OmniAI
|
|
124
145
|
end
|
125
146
|
|
126
147
|
# @param response [HTTP::Response]
|
127
|
-
# @return [OmniAI::Chat::Response
|
148
|
+
# @return [OmniAI::Chat::Response]
|
128
149
|
def complete!(response:)
|
129
|
-
completion = self.class::Response
|
130
|
-
|
131
|
-
if @tools && completion.tool_call_list
|
132
|
-
spawn!(
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
150
|
+
completion = self.class::Response.new(data: response.parse, context:)
|
151
|
+
|
152
|
+
if @tools && completion.tool_call_list?
|
153
|
+
spawn!(
|
154
|
+
@prompt.dup.tap do |prompt|
|
155
|
+
prompt.messages += completion.messages
|
156
|
+
prompt.messages += build_tool_call_messages(completion.tool_call_list)
|
157
|
+
end
|
158
|
+
).process!
|
137
159
|
else
|
138
160
|
completion
|
139
161
|
end
|
140
162
|
end
|
141
163
|
|
142
164
|
# @param response [HTTP::Response]
|
143
|
-
# @return [OmniAI::Chat::
|
165
|
+
# @return [OmniAI::Chat::Stream]
|
144
166
|
def stream!(response:)
|
145
167
|
raise Error, "#{self.class.name}#stream! unstreamable" unless @stream
|
146
168
|
|
147
|
-
self.class::
|
169
|
+
self.class::Stream.new(body: response.body, logger:, context:).stream! do |chunk|
|
148
170
|
case @stream
|
149
171
|
when IO, StringIO
|
150
|
-
if chunk.
|
151
|
-
@stream << chunk.
|
172
|
+
if chunk.text
|
173
|
+
@stream << chunk.text
|
152
174
|
@stream.flush
|
153
175
|
end
|
154
176
|
else @stream.call(chunk)
|
@@ -160,31 +182,36 @@ module OmniAI
|
|
160
182
|
|
161
183
|
# @return [HTTP::Response]
|
162
184
|
def request!
|
185
|
+
logger&.debug("Chat#request! payload=#{payload.inspect}")
|
186
|
+
|
163
187
|
@client
|
164
188
|
.connection
|
165
189
|
.accept(:json)
|
166
190
|
.post(path, json: payload)
|
167
191
|
end
|
168
192
|
|
193
|
+
# @param tool_call_list [Array<OmniAI::Chat::ToolCall>]
|
194
|
+
# @return [Array<Message>]
|
195
|
+
def build_tool_call_messages(tool_call_list)
|
196
|
+
tool_call_list.map do |tool_call|
|
197
|
+
content = execute_tool_call(tool_call)
|
198
|
+
ToolCallMessage.new(content:, tool_call_id: tool_call.id)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# @raise [ToolCallError]
|
169
203
|
# @param tool_call [OmniAI::Chat::ToolCall]
|
204
|
+
# @return [ToolCallResult]
|
170
205
|
def execute_tool_call(tool_call)
|
171
|
-
|
206
|
+
logger&.debug("Chat#execute_tool_call tool_call=#{tool_call.inspect}")
|
172
207
|
|
173
|
-
|
174
|
-
|
208
|
+
function = tool_call.function
|
209
|
+
tool = @tools.find { |entry| function.name == entry.name } || raise(ToolCallMissingError, tool_call)
|
210
|
+
content = tool.call(function.arguments)
|
175
211
|
|
176
|
-
|
177
|
-
end
|
212
|
+
logger&.debug("Chat#execute_tool_call content=#{content.inspect}")
|
178
213
|
|
179
|
-
|
180
|
-
# @param content [String]
|
181
|
-
def prepare_tool_call_message(tool_call:, content:)
|
182
|
-
{
|
183
|
-
role: Role::TOOL,
|
184
|
-
name: tool_call.function.name,
|
185
|
-
tool_call_id: tool_call.id,
|
186
|
-
content:,
|
187
|
-
}
|
214
|
+
content
|
188
215
|
end
|
189
216
|
end
|
190
217
|
end
|
data/lib/omniai/context.rb
CHANGED
@@ -39,5 +39,17 @@ module OmniAI
|
|
39
39
|
@serializers = {}
|
40
40
|
@deserializers = {}
|
41
41
|
end
|
42
|
+
|
43
|
+
# @param name [Symbol]
|
44
|
+
# @return [Proc, nil]
|
45
|
+
def serializer(name)
|
46
|
+
@serializers[name]
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param name [Symbol]
|
50
|
+
# @return [Proc, nil]
|
51
|
+
def deserializer(name)
|
52
|
+
@deserializers[name]
|
53
|
+
end
|
42
54
|
end
|
43
55
|
end
|
@@ -22,7 +22,7 @@ module OmniAI
|
|
22
22
|
# @return [Usage]
|
23
23
|
def usage
|
24
24
|
@usage ||= begin
|
25
|
-
deserializer = @context&.
|
25
|
+
deserializer = @context&.deserializer(:usage)
|
26
26
|
|
27
27
|
if deserializer
|
28
28
|
deserializer.call(@data, context: @context)
|
@@ -45,7 +45,7 @@ module OmniAI
|
|
45
45
|
# @return [Array<Array<Float>>]
|
46
46
|
def embeddings
|
47
47
|
@embeddings ||= begin
|
48
|
-
deserializer = @context&.
|
48
|
+
deserializer = @context&.deserializer(:embeddings)
|
49
49
|
|
50
50
|
if deserializer
|
51
51
|
deserializer.call(@data, context: @context)
|
data/lib/omniai/tool.rb
CHANGED
@@ -44,7 +44,7 @@ module OmniAI
|
|
44
44
|
end
|
45
45
|
|
46
46
|
# @example
|
47
|
-
# tool.
|
47
|
+
# tool.serialize
|
48
48
|
# # {
|
49
49
|
# # type: 'function',
|
50
50
|
# # function: {
|
@@ -60,8 +60,12 @@ module OmniAI
|
|
60
60
|
# # }
|
61
61
|
# # }
|
62
62
|
#
|
63
|
+
# @param context [Context] optional
|
63
64
|
# @return [Hash]
|
64
|
-
def
|
65
|
+
def serialize(context: nil)
|
66
|
+
serialize = context&.serializer(:tool)
|
67
|
+
return serialize.call(self, context:) if serialize
|
68
|
+
|
65
69
|
{
|
66
70
|
type: 'function',
|
67
71
|
function: {
|
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.
|
4
|
+
version: 1.8.0
|
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-08-
|
11
|
+
date: 2024-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: event_stream_parser
|
@@ -68,27 +68,23 @@ files:
|
|
68
68
|
- exe/omniai
|
69
69
|
- lib/omniai.rb
|
70
70
|
- lib/omniai/chat.rb
|
71
|
+
- lib/omniai/chat/choice.rb
|
71
72
|
- lib/omniai/chat/content.rb
|
72
73
|
- lib/omniai/chat/file.rb
|
74
|
+
- lib/omniai/chat/function.rb
|
73
75
|
- lib/omniai/chat/media.rb
|
74
76
|
- lib/omniai/chat/message.rb
|
77
|
+
- lib/omniai/chat/message/builder.rb
|
78
|
+
- lib/omniai/chat/payload.rb
|
75
79
|
- lib/omniai/chat/prompt.rb
|
76
|
-
- lib/omniai/chat/response
|
77
|
-
- lib/omniai/chat/
|
78
|
-
- lib/omniai/chat/response/completion.rb
|
79
|
-
- lib/omniai/chat/response/delta.rb
|
80
|
-
- lib/omniai/chat/response/delta_choice.rb
|
81
|
-
- lib/omniai/chat/response/function.rb
|
82
|
-
- lib/omniai/chat/response/message.rb
|
83
|
-
- lib/omniai/chat/response/message_choice.rb
|
84
|
-
- lib/omniai/chat/response/part.rb
|
85
|
-
- lib/omniai/chat/response/payload.rb
|
86
|
-
- lib/omniai/chat/response/resource.rb
|
87
|
-
- lib/omniai/chat/response/stream.rb
|
88
|
-
- lib/omniai/chat/response/tool_call.rb
|
89
|
-
- lib/omniai/chat/response/usage.rb
|
80
|
+
- lib/omniai/chat/response.rb
|
81
|
+
- lib/omniai/chat/stream.rb
|
90
82
|
- lib/omniai/chat/text.rb
|
83
|
+
- lib/omniai/chat/tool_call.rb
|
84
|
+
- lib/omniai/chat/tool_call_message.rb
|
85
|
+
- lib/omniai/chat/tool_call_result.rb
|
91
86
|
- lib/omniai/chat/url.rb
|
87
|
+
- lib/omniai/chat/usage.rb
|
92
88
|
- lib/omniai/cli.rb
|
93
89
|
- lib/omniai/cli/base_handler.rb
|
94
90
|
- lib/omniai/cli/chat_handler.rb
|