intelligence 0.8.0 → 1.0.0.beta02
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/lib/intelligence/adapters/generic/chat_request_methods.rb +1 -1
- data/lib/intelligence/adapters/google/adapter.rb +13 -0
- data/lib/intelligence/adapters/google/chat_request_methods.rb +20 -7
- data/lib/intelligence/adapters/open_ai/adapter.rb +29 -5
- data/lib/intelligence/adapters/x_ai.rb +196 -0
- data/lib/intelligence/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e92ea1646a9ec5f91a9a8e991c838896c415a94715aeeccd7013363e34009b1b
|
4
|
+
data.tar.gz: 67b7fcb6020325d405e463ab2efbc18b44c772e94b76d3ce622fc652de7b4c18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 107cb5ddec885d6700b88742474e2948e2abc94da6500b0b1fb39d039c8292fbd648efe4e67b2866d918107759ac111a15de949b3256dc8d2049df52af6cd792
|
7
|
+
data.tar.gz: 5052f6057fafd04bd1c310f67de4a89dbbea32f8c279ec5e2bdbd397378629e1cff17ce853774881c0736ee0f9407a5dfd25b63aab9750955737885f8829c489
|
@@ -35,6 +35,19 @@ module Intelligence
|
|
35
35
|
response_mime_type String, as: :responseMimeType
|
36
36
|
response_schema as: :responseSchema
|
37
37
|
|
38
|
+
# google tools setup
|
39
|
+
tools do
|
40
|
+
google_search as: :google_search_retrieval do
|
41
|
+
dynamic_retrieval as: :dynamic_retrieval_config, default: {} do
|
42
|
+
mode String, default: 'MODE_DYNAMIC'
|
43
|
+
threshold Float, as: :dynamic_threshold, in: 0..1, default: 0.3
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
code_execution do
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
38
51
|
# google specific tool configuration
|
39
52
|
tool_configuration as: :tool_config do
|
40
53
|
function_calling as: :function_calling_config do
|
@@ -61,16 +61,33 @@ module Intelligence
|
|
61
61
|
# discard properties not part of the google generationConfig schema
|
62
62
|
gc.delete( :model )
|
63
63
|
gc.delete( :stream )
|
64
|
-
|
64
|
+
|
65
|
+
# googlify tools
|
66
|
+
tools = gc.delete( :tools )
|
67
|
+
if tools&.any?
|
68
|
+
tools = tools.then do | tools_object |
|
69
|
+
tools_array ||= []
|
70
|
+
tools_object.each { | key, value | tools_array << { key => value } }
|
71
|
+
tools_array
|
72
|
+
end
|
73
|
+
end
|
74
|
+
tool_functions = to_google_tools( conversation[ :tools ] )
|
75
|
+
if tool_functions&.any?
|
76
|
+
tools ||= {}
|
77
|
+
tools[ :function_declarations ] ||= []
|
78
|
+
tools[ :function_declarations ].concat( tool_functions )
|
79
|
+
end
|
80
|
+
|
65
81
|
# googlify tool configuration
|
66
82
|
if tool_config = gc.delete( :tool_config )
|
67
83
|
mode = tool_config[ :function_calling_config ]&.[]( :mode )
|
68
84
|
tool_config[ :function_calling_config ][ :mode ] = mode.to_s.upcase if mode
|
69
85
|
end
|
70
|
-
|
86
|
+
|
71
87
|
result = {}
|
72
88
|
result[ :generationConfig ] = gc
|
73
|
-
result[ :
|
89
|
+
result[ :tools ] = tools if tools
|
90
|
+
result[ :tool_config ] = tool_config if tools && tool_config
|
74
91
|
|
75
92
|
# construct the system prompt in the form of the google schema
|
76
93
|
system_instructions = to_google_system_message( conversation[ :system_message ] )
|
@@ -163,10 +180,6 @@ module Intelligence
|
|
163
180
|
|
164
181
|
end
|
165
182
|
|
166
|
-
tools_attributes = to_google_tools( conversation[ :tools ] )
|
167
|
-
result[ :tools ] = [ { function_declarations: tools_attributes } ] \
|
168
|
-
if tools_attributes&.any?
|
169
|
-
|
170
183
|
JSON.generate( result )
|
171
184
|
end
|
172
185
|
|
@@ -40,9 +40,8 @@ module Intelligence
|
|
40
40
|
end
|
41
41
|
logit_bias
|
42
42
|
logprobs [ TrueClass, FalseClass ]
|
43
|
+
top_logprobs Integer
|
43
44
|
modalities String, array: true
|
44
|
-
# the parallel_tool_calls parameter is only allowed when 'tools' are specified
|
45
|
-
parallel_tool_calls [ TrueClass, FalseClass ]
|
46
45
|
response_format do
|
47
46
|
# 'text' and 'json_schema' are the only supported types
|
48
47
|
type Symbol, in: [ :text, :json_schema ]
|
@@ -52,9 +51,34 @@ module Intelligence
|
|
52
51
|
stream_options do
|
53
52
|
include_usage [ TrueClass, FalseClass ]
|
54
53
|
end
|
55
|
-
|
56
|
-
|
57
|
-
|
54
|
+
user
|
55
|
+
|
56
|
+
# open ai tool configuration; this allows you to enable build in tools ( currently
|
57
|
+
# that's just 'code_interpreter' )
|
58
|
+
#
|
59
|
+
# tool :code_interpreter
|
60
|
+
#
|
61
|
+
#tool array: true, as: :tools, arguments: :type
|
62
|
+
# type Symbol
|
63
|
+
#end
|
64
|
+
|
65
|
+
# open ai tool choice configuration
|
66
|
+
#
|
67
|
+
# `tool_choice :none`
|
68
|
+
# or
|
69
|
+
# ```
|
70
|
+
# tool_choice :function do
|
71
|
+
# function :my_function
|
72
|
+
# end
|
73
|
+
# ```
|
74
|
+
tool_choice arguments: :type do
|
75
|
+
type Symbol, in: [ :none, :auto, :required ]
|
76
|
+
function arguments: :name do
|
77
|
+
name Symbol
|
78
|
+
end
|
79
|
+
end
|
80
|
+
# the parallel_tool_calls parameter is only allowed when 'tools' are specified
|
81
|
+
parallel_tool_calls [ TrueClass, FalseClass ]
|
58
82
|
|
59
83
|
end
|
60
84
|
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require_relative 'generic/adapter'
|
2
|
+
|
3
|
+
module Intelligence
|
4
|
+
module XAi
|
5
|
+
|
6
|
+
class Adapter < Generic::Adapter
|
7
|
+
|
8
|
+
chat_request_uri "https://api.x.ai/v1/chat/completions"
|
9
|
+
|
10
|
+
schema do
|
11
|
+
key String
|
12
|
+
chat_options do
|
13
|
+
model String
|
14
|
+
frequency_penalty Float, in: -2..2
|
15
|
+
logit_bias Hash
|
16
|
+
logprobs [ TrueClass, FalseClass ]
|
17
|
+
max_tokens Integer
|
18
|
+
n Integer
|
19
|
+
presence_penalty Float, in: -2..2
|
20
|
+
response_format
|
21
|
+
seed Integer
|
22
|
+
stop String, array: true
|
23
|
+
stream [ TrueClass, FalseClass ]
|
24
|
+
stream_options
|
25
|
+
temperature Float, in: 0..2
|
26
|
+
tool_choice
|
27
|
+
top_logprobs Integer, in: 0..20
|
28
|
+
top_p Float
|
29
|
+
user String
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def chat_result_attributes( response )
|
34
|
+
return nil unless response.success?
|
35
|
+
response_json = JSON.parse( response.body, symbolize_names: true ) rescue nil
|
36
|
+
return nil if response_json.nil? || response_json[ :choices ].nil?
|
37
|
+
|
38
|
+
result = {}
|
39
|
+
result[ :choices ] = []
|
40
|
+
|
41
|
+
( response_json[ :choices ] || [] ).each do | json_choice |
|
42
|
+
end_reason = to_end_reason( json_choice[ :finish_reason ] )
|
43
|
+
if ( json_message = json_choice[ :message ] )
|
44
|
+
result_message = { role: json_message[ :role ] }
|
45
|
+
if json_message[ :content ]
|
46
|
+
result_message[ :contents ] = [ { type: :text, text: json_message[ :content ] } ]
|
47
|
+
end
|
48
|
+
if json_message[ :tool_calls ] && !json_message[ :tool_calls ].empty?
|
49
|
+
result_message[ :contents ] ||= []
|
50
|
+
end_reason = :tool_called if end_reason == :ended
|
51
|
+
json_message[ :tool_calls ].each do | json_message_tool_call |
|
52
|
+
result_message_tool_call_parameters =
|
53
|
+
JSON.parse( json_message_tool_call[ :function ][ :arguments ], symbolize_names: true ) \
|
54
|
+
rescue json_message_tool_call[ :function ][ :arguments ]
|
55
|
+
result_message[ :contents ] << {
|
56
|
+
type: :tool_call,
|
57
|
+
tool_call_id: json_message_tool_call[ :id ],
|
58
|
+
tool_name: json_message_tool_call[ :function ][ :name ],
|
59
|
+
tool_parameters: result_message_tool_call_parameters
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
result[ :choices ].push( { end_reason: end_reason, message: result_message } )
|
65
|
+
end
|
66
|
+
|
67
|
+
metrics_json = response_json[ :usage ]
|
68
|
+
unless metrics_json.nil?
|
69
|
+
|
70
|
+
metrics = {}
|
71
|
+
metrics[ :input_tokens ] = metrics_json[ :prompt_tokens ]
|
72
|
+
metrics[ :output_tokens ] = metrics_json[ :completion_tokens ]
|
73
|
+
metrics = metrics.compact
|
74
|
+
|
75
|
+
result[ :metrics ] = metrics unless metrics.empty?
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
result
|
80
|
+
end
|
81
|
+
|
82
|
+
def stream_result_chunk_attributes( context, chunk )
|
83
|
+
context ||= {}
|
84
|
+
buffer = context[ :buffer ] || ''
|
85
|
+
metrics = context[ :metrics ] || {
|
86
|
+
input_tokens: 0,
|
87
|
+
output_tokens: 0
|
88
|
+
}
|
89
|
+
choices = context[ :choices ] || Array.new( 1 , { message: {} } )
|
90
|
+
|
91
|
+
choices.each do | choice |
|
92
|
+
choice[ :message ][ :contents ] = choice[ :message ][ :contents ]&.map do | content |
|
93
|
+
{ type: content[ :type ] }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
buffer += chunk
|
98
|
+
while ( eol_index = buffer.index( "\n" ) )
|
99
|
+
line = buffer.slice!( 0..eol_index )
|
100
|
+
line = line.strip
|
101
|
+
next if line.empty? || !line.start_with?( 'data:' )
|
102
|
+
line = line[ 6..-1 ]
|
103
|
+
next if line.end_with?( '[DONE]' )
|
104
|
+
|
105
|
+
data = JSON.parse( line ) rescue nil
|
106
|
+
if data.is_a?( Hash )
|
107
|
+
data[ 'choices' ]&.each do | data_choice |
|
108
|
+
|
109
|
+
data_choice_index = data_choice[ 'index' ]
|
110
|
+
data_choice_delta = data_choice[ 'delta' ]
|
111
|
+
end_reason = to_end_reason( data_choice[ 'finish_reason' ] )
|
112
|
+
|
113
|
+
choices.fill( { message: {} }, choices.size, data_choice_index + 1 ) \
|
114
|
+
if choices.size <= data_choice_index
|
115
|
+
contents = choices[ data_choice_index ][ :message ][ :contents ] || []
|
116
|
+
|
117
|
+
text_content = contents.first&.[]( :type ) == :text ? contents.first : nil
|
118
|
+
if data_choice_content = data_choice_delta[ 'content' ]
|
119
|
+
if text_content.nil?
|
120
|
+
contents.unshift( text_content = { type: :text, text: data_choice_content } )
|
121
|
+
else
|
122
|
+
text_content[ :text ] = ( text_content[ :text ] || '' ) + data_choice_content
|
123
|
+
end
|
124
|
+
end
|
125
|
+
if data_choice_tool_calls = data_choice_delta[ 'tool_calls' ]
|
126
|
+
end_reason = :tool_called
|
127
|
+
data_choice_tool_calls.each_with_index do | data_choice_tool_call, data_choice_tool_call_index |
|
128
|
+
if data_choice_tool_call_function = data_choice_tool_call[ 'function' ]
|
129
|
+
data_choice_tool_index = data_choice_tool_call[ 'index' ] || data_choice_tool_call_index
|
130
|
+
data_choice_tool_id = data_choice_tool_call[ 'id' ]
|
131
|
+
data_choice_tool_name = data_choice_tool_call_function[ 'name' ]
|
132
|
+
data_choice_tool_parameters = data_choice_tool_call_function[ 'arguments' ]
|
133
|
+
|
134
|
+
tool_call_content_index = ( text_content.nil? ? 0 : 1 ) + data_choice_tool_index
|
135
|
+
if tool_call_content_index >= contents.length
|
136
|
+
contents.push( {
|
137
|
+
type: :tool_call,
|
138
|
+
tool_call_id: data_choice_tool_id,
|
139
|
+
tool_name: data_choice_tool_name,
|
140
|
+
tool_parameters: data_choice_tool_parameters
|
141
|
+
} )
|
142
|
+
else
|
143
|
+
tool_call = contents[ tool_call_content_index ]
|
144
|
+
tool_call[ :tool_call_id ] = ( tool_call[ :tool_call_id ] || '' ) + data_choice_tool_id \
|
145
|
+
if data_choice_tool_id
|
146
|
+
tool_call[ :tool_name ] = ( tool_call[ :tool_name ] || '' ) + data_choice_tool_name \
|
147
|
+
if data_choice_tool_name
|
148
|
+
tool_call[ :tool_parameters ] = ( tool_call[ :tool_parameters ] || '' ) + data_choice_tool_parameters \
|
149
|
+
if data_choice_tool_parameters
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
choices[ data_choice_index ][ :message ][ :contents ] = contents
|
155
|
+
choices[ data_choice_index ][ :end_reason ] ||= end_reason
|
156
|
+
end
|
157
|
+
|
158
|
+
if usage = data[ 'usage' ]
|
159
|
+
# note: A number of providers will resend the input tokens as part of their usage
|
160
|
+
# payload.
|
161
|
+
metrics[ :input_tokens ] = usage[ 'prompt_tokens' ] \
|
162
|
+
if usage.include?( 'prompt_tokens' )
|
163
|
+
metrics[ :output_tokens ] += usage[ 'completion_tokens' ] \
|
164
|
+
if usage.include?( 'completion_tokens' )
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
context[ :buffer ] = buffer
|
172
|
+
context[ :metrics ] = metrics
|
173
|
+
context[ :choices ] = choices
|
174
|
+
|
175
|
+
[ context, choices.empty? ? nil : { choices: choices.dup } ]
|
176
|
+
end
|
177
|
+
|
178
|
+
def chat_result_error_attributes( response )
|
179
|
+
error_type, error_description = to_error_response( response.status )
|
180
|
+
error = error_type
|
181
|
+
|
182
|
+
parsed_body = JSON.parse( response.body, symbolize_names: true ) rescue nil
|
183
|
+
if parsed_body && parsed_body.respond_to?( :[] )
|
184
|
+
error = parsed_body[ :code ] || error_type
|
185
|
+
error_description = parsed_body[ :error ] || error_description
|
186
|
+
end
|
187
|
+
|
188
|
+
{ error_type: error_type.to_s, error: error.to_s, error_description: error_description }
|
189
|
+
end
|
190
|
+
|
191
|
+
alias_method :stream_result_error_attributes, :chat_result_error_attributes
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
data/lib/intelligence/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: intelligence
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.beta02
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kristoph Cichocki-Romanov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -153,6 +153,7 @@ files:
|
|
153
153
|
- lib/intelligence/adapters/open_router.rb
|
154
154
|
- lib/intelligence/adapters/samba_nova.rb
|
155
155
|
- lib/intelligence/adapters/together_ai.rb
|
156
|
+
- lib/intelligence/adapters/x_ai.rb
|
156
157
|
- lib/intelligence/chat_error_result.rb
|
157
158
|
- lib/intelligence/chat_metrics.rb
|
158
159
|
- lib/intelligence/chat_request.rb
|