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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35084b4f3df27ee21c0a21a759b74bcca9c05c6b47e0311026d6e6587f8661a3
4
- data.tar.gz: 76afc7ad3e1f2e3637c82e8613b492680be20962ca5daf263d3c457968512c04
3
+ metadata.gz: e92ea1646a9ec5f91a9a8e991c838896c415a94715aeeccd7013363e34009b1b
4
+ data.tar.gz: 67b7fcb6020325d405e463ab2efbc18b44c772e94b76d3ce622fc652de7b4c18
5
5
  SHA512:
6
- metadata.gz: 643f9acfde921655b5861901f5ea11646d00e9673a852e8546ec112a275d9f4e695934c314c577ca5cf44684ee3ce86b57cb5da9100e67b5c016c3bd90672f14
7
- data.tar.gz: 6a9bb70335d3cd9f5b5ef48f1029e8b7997d880a1ebed37168c6d5cae88ec4abb48c2c8ffb95ef63c5b4b82a0e5c00904b0320321c124d8cf24fabb1928e5453
6
+ metadata.gz: 107cb5ddec885d6700b88742474e2948e2abc94da6500b0b1fb39d039c8292fbd648efe4e67b2866d918107759ac111a15de949b3256dc8d2049df52af6cd792
7
+ data.tar.gz: 5052f6057fafd04bd1c310f67de4a89dbbea32f8c279ec5e2bdbd397378629e1cff17ce853774881c0736ee0f9407a5dfd25b63aab9750955737885f8829c489
@@ -104,7 +104,7 @@ module Intelligence
104
104
 
105
105
  tools_attributes = chat_request_tools_attributes( conversation[ :tools ] )
106
106
  result[ :tools ] = tools_attributes if tools_attributes && tools_attributes.length > 0
107
-
107
+
108
108
  JSON.generate( result )
109
109
  end
110
110
 
@@ -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[ :tool_config ] = tool_config if tool_config
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
- tool_choice
56
- top_logprobs Integer
57
- user
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
@@ -1,3 +1,3 @@
1
1
  module Intelligence
2
- VERSION = "0.8.0"
2
+ VERSION = "1.0.0.beta02"
3
3
  end
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.8.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-10-31 00:00:00.000000000 Z
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