intelligence 1.0.0.beta01 → 1.0.0.beta03

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: 02df79612b47068ee3792e78566e94160741db46f22c5ff8a97947a09872fe5f
4
- data.tar.gz: e2bf793c4bf2feb17798e0a59bdc2272cdac9e95b9cd2c31b386d973601bfcdf
3
+ metadata.gz: 77033342b73065a73acde0156a288f66fb0ef7413a939292d23886b353397fd3
4
+ data.tar.gz: 6a8c7131991c0af60d9e30c000048ae9cb7e562e7c7dbb9ca519febe486d8491
5
5
  SHA512:
6
- metadata.gz: 12bf185efa0bbd063699fc25cd33ada8729a6a95fda62ec4535319dc88b92764fb43677421cfb714f02aa766ec3e52740f018241f1632f0ea938c08543f0e62b
7
- data.tar.gz: 221871ceb024b137d2e77810ea4ef840bbe161248a72dd69c8d184af4ce176664993dbb6d3d36bc91bbb89b3c2ed8515a2692f681d7e82894c147d83e7e2bda3
6
+ metadata.gz: 65050bd8d219f8348a0fe6c5b6cbc951a8de190572c01ecdc7e947aa2fa207f4fb65ae0e6afc2658ecf1fbe50ca0fd5b58c5fcf2651cc416fb9e6aeff73c97df
7
+ data.tar.gz: 17ef75ad141fc8f25f0a62a32c1b677785340b0bd15c8f907c455a10b5d7e35532728e7f36cb62b3ccb3ebe0c835b8facd6777832dda955bb09aabae1802975b
@@ -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
 
@@ -57,7 +57,7 @@ module Intelligence
57
57
  def chat_request_body( conversation, options = {} )
58
58
  options = @options.merge( build_options( options ) )
59
59
 
60
- gc = options[ :generationConfig ]
60
+ gc = options[ :generationConfig ]&.dup || {}
61
61
  # discard properties not part of the google generationConfig schema
62
62
  gc.delete( :model )
63
63
  gc.delete( :stream )
@@ -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 = "1.0.0.beta01"
2
+ VERSION = "1.0.0.beta03"
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: 1.0.0.beta01
4
+ version: 1.0.0.beta03
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-01 00:00:00.000000000 Z
11
+ date: 2024-11-12 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