intelligence 0.5.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 +7 -0
- data/LICENSE +21 -0
- data/intelligence.gemspec +47 -0
- data/lib/intelligence/adapter/base.rb +7 -0
- data/lib/intelligence/adapter/construction_methods.rb +37 -0
- data/lib/intelligence/adapter.rb +8 -0
- data/lib/intelligence/adapter_error.rb +8 -0
- data/lib/intelligence/adapters/anthropic/adapter.rb +59 -0
- data/lib/intelligence/adapters/anthropic/chat_methods.rb +358 -0
- data/lib/intelligence/adapters/anthropic.rb +2 -0
- data/lib/intelligence/adapters/cerebras.rb +35 -0
- data/lib/intelligence/adapters/generic/adapter.rb +21 -0
- data/lib/intelligence/adapters/generic/chat_methods.rb +331 -0
- data/lib/intelligence/adapters/generic.rb +2 -0
- data/lib/intelligence/adapters/google/adapter.rb +60 -0
- data/lib/intelligence/adapters/google/chat_methods.rb +346 -0
- data/lib/intelligence/adapters/google.rb +2 -0
- data/lib/intelligence/adapters/groq.rb +51 -0
- data/lib/intelligence/adapters/hyperbolic.rb +55 -0
- data/lib/intelligence/adapters/legacy/adapter.rb +13 -0
- data/lib/intelligence/adapters/legacy/chat_methods.rb +37 -0
- data/lib/intelligence/adapters/open_ai/adapter.rb +75 -0
- data/lib/intelligence/adapters/open_ai/chat_methods.rb +314 -0
- data/lib/intelligence/adapters/open_ai.rb +2 -0
- data/lib/intelligence/adapters/samba_nova.rb +64 -0
- data/lib/intelligence/adapters/together_ai.rb +46 -0
- data/lib/intelligence/chat_error_result.rb +11 -0
- data/lib/intelligence/chat_metrics.rb +32 -0
- data/lib/intelligence/chat_request.rb +117 -0
- data/lib/intelligence/chat_result.rb +32 -0
- data/lib/intelligence/chat_result_choice.rb +26 -0
- data/lib/intelligence/conversation.rb +48 -0
- data/lib/intelligence/error.rb +3 -0
- data/lib/intelligence/error_result.rb +24 -0
- data/lib/intelligence/invalid_content_error.rb +3 -0
- data/lib/intelligence/message.rb +53 -0
- data/lib/intelligence/message_content/base.rb +18 -0
- data/lib/intelligence/message_content/binary.rb +24 -0
- data/lib/intelligence/message_content/text.rb +17 -0
- data/lib/intelligence/message_content/tool_call.rb +20 -0
- data/lib/intelligence/message_content/tool_result.rb +20 -0
- data/lib/intelligence/message_content.rb +16 -0
- data/lib/intelligence/unsupported_content_error.rb +3 -0
- data/lib/intelligence/version.rb +3 -0
- data/lib/intelligence.rb +24 -0
- metadata +181 -0
@@ -0,0 +1,346 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Intelligence
|
4
|
+
module Google
|
5
|
+
module ChatMethods
|
6
|
+
|
7
|
+
GENERATIVE_LANGUAGE_URI = "https://generativelanguage.googleapis.com/v1beta/models/"
|
8
|
+
|
9
|
+
def chat_request_uri( options )
|
10
|
+
|
11
|
+
options = options.nil? || options.empty? ? {} : self.class.configure( options )
|
12
|
+
|
13
|
+
key = options[ :key ] || self.key
|
14
|
+
|
15
|
+
gc = options[ :generationConfig ] || {}
|
16
|
+
model = gc[ :model ] || self.model
|
17
|
+
stream = gc.key?( :stream ) ? gc[ :stream ] : self.stream
|
18
|
+
|
19
|
+
raise ArgumentError.new( "A Google API key is required to build a Google chat request." ) \
|
20
|
+
if self.key.nil?
|
21
|
+
raise ArgumentError.new( "A Google model is required to build a Google chat request." ) \
|
22
|
+
if model.nil?
|
23
|
+
|
24
|
+
uri = URI( GENERATIVE_LANGUAGE_URI )
|
25
|
+
path = File.join( uri.path, model )
|
26
|
+
path += stream ? ':streamGenerateContent' : ':generateContent'
|
27
|
+
uri.path = path
|
28
|
+
query = { key: self.key }
|
29
|
+
query[ :alt ] = 'sse' if stream
|
30
|
+
uri.query = URI.encode_www_form( query )
|
31
|
+
|
32
|
+
uri.to_s
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def chat_request_headers( options = {} )
|
37
|
+
{ 'Content-Type' => 'application/json' }
|
38
|
+
end
|
39
|
+
|
40
|
+
def chat_request_body( conversation, options = {} )
|
41
|
+
|
42
|
+
result = {}
|
43
|
+
result[ :generationConfig ] = self.chat_options
|
44
|
+
|
45
|
+
options = options.nil? || options.empty? ? {} : self.class.configure( options )
|
46
|
+
result = result.merge( options )
|
47
|
+
|
48
|
+
# discard properties not part of the google endpoint schema
|
49
|
+
result[ :generationConfig ].delete( :model )
|
50
|
+
result[ :generationConfig ].delete( :stream )
|
51
|
+
|
52
|
+
# construct the system prompt in the form of the google schema
|
53
|
+
system_instructions = translate_system_message( conversation[ :system_message ] )
|
54
|
+
result[ :systemInstruction ] = system_instructions if system_instructions
|
55
|
+
|
56
|
+
result[ :contents ] = []
|
57
|
+
conversation[ :messages ]&.each do | message |
|
58
|
+
|
59
|
+
result_message = { role: message[ :role ] == :user ? 'user' : 'model' }
|
60
|
+
result_message_parts = []
|
61
|
+
|
62
|
+
message[ :contents ]&.each do | content |
|
63
|
+
case content[ :type ]
|
64
|
+
when :text
|
65
|
+
result_message_parts << { text: content[ :text ] }
|
66
|
+
when :binary
|
67
|
+
content_type = content[ :content_type ]
|
68
|
+
bytes = content[ :bytes ]
|
69
|
+
if content_type && bytes
|
70
|
+
unless MIME::Types[ content_type ].empty?
|
71
|
+
# TODO: verify the specific google supported MIME types
|
72
|
+
result_message_parts << {
|
73
|
+
inline_data: {
|
74
|
+
mime_type: content_type,
|
75
|
+
data: Base64.strict_encode64( bytes )
|
76
|
+
}
|
77
|
+
}
|
78
|
+
else
|
79
|
+
raise UnsupportedContentError.new(
|
80
|
+
:google,
|
81
|
+
'only support recognized mime types'
|
82
|
+
)
|
83
|
+
end
|
84
|
+
else
|
85
|
+
raise UnsupportedContentError.new(
|
86
|
+
:google,
|
87
|
+
'requires binary content to include content type and ( packed ) bytes'
|
88
|
+
)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
result_message[ :parts ] = result_message_parts
|
94
|
+
result[ :contents ] << result_message
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
JSON.generate( result )
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
def chat_result_attributes( response )
|
103
|
+
|
104
|
+
return nil unless response.success?
|
105
|
+
|
106
|
+
response_json = JSON.parse( response.body, symbolize_names: true ) rescue nil
|
107
|
+
return nil \
|
108
|
+
if response_json.nil? || response_json[ :candidates ].nil?
|
109
|
+
|
110
|
+
result = {}
|
111
|
+
result[ :choices ] = []
|
112
|
+
|
113
|
+
response_json[ :candidates ]&.each do | response_choice |
|
114
|
+
|
115
|
+
end_reason = translate_finish_reason( response_choice[ :finishReason ] )
|
116
|
+
|
117
|
+
role = nil
|
118
|
+
contents = []
|
119
|
+
|
120
|
+
response_content = response_choice[ :content ]
|
121
|
+
if response_content
|
122
|
+
role = ( response_content[ :role ] == 'model' ) ? 'assistant' : 'user'
|
123
|
+
|
124
|
+
contents = []
|
125
|
+
response_content[ :parts ]&.each do | response_content_part |
|
126
|
+
if response_content_part.key?( :text )
|
127
|
+
contents.push( {
|
128
|
+
type: 'text', text: response_content_part[ :text ]
|
129
|
+
} )
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
result_message = nil
|
135
|
+
if role
|
136
|
+
result_message = { role: role }
|
137
|
+
result_message[ :contents ] = contents
|
138
|
+
end
|
139
|
+
|
140
|
+
result[ :choices ].push( { end_reason: end_reason, message: result_message } )
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
metrics_json = response_json[ :usageMetadata ]
|
145
|
+
unless metrics_json.nil?
|
146
|
+
|
147
|
+
metrics = {}
|
148
|
+
metrics[ :input_tokens ] = metrics_json[ :promptTokenCount ]
|
149
|
+
metrics[ :output_tokens ] = metrics_json[ :candidatesTokenCount ]
|
150
|
+
metrics = metrics.compact
|
151
|
+
|
152
|
+
result[ :metrics ] = metrics unless metrics.empty?
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
result
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
def chat_result_error_attributes( response )
|
161
|
+
|
162
|
+
error_type, error_description = translate_error_response_status( response.status )
|
163
|
+
result = { error_type: error_type.to_s, error_description: error_description }
|
164
|
+
|
165
|
+
response_body = JSON.parse( response.body, symbolize_names: true ) rescue nil
|
166
|
+
if response_body && response_body[ :error ]
|
167
|
+
error_details_reason = response_body[ :error ][ :details ]&.first&.[]( :reason )
|
168
|
+
# a special case for authentication
|
169
|
+
error_type = :authentication_error if error_details_reason == 'API_KEY_INVALID'
|
170
|
+
result = {
|
171
|
+
error_type: error_type.to_s,
|
172
|
+
error: error_details_reason || response_body[ :error ][ :status ] || error_type,
|
173
|
+
error_description: response_body[ :error ][ :message ]
|
174
|
+
}
|
175
|
+
end
|
176
|
+
result
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
def stream_result_chunk_attributes( context, chunk )
|
181
|
+
#---------------------------------------------------
|
182
|
+
|
183
|
+
context ||= {}
|
184
|
+
buffer = context[ :buffer ] || ''
|
185
|
+
metrics = context[ :metrics ] || {
|
186
|
+
input_tokens: 0,
|
187
|
+
output_tokens: 0
|
188
|
+
}
|
189
|
+
choices = context[ :choices ] || Array.new( 1 , { message: {} } )
|
190
|
+
|
191
|
+
choices.each do | choice |
|
192
|
+
choice[ :message ][ :contents ] = choice[ :message ][ :contents ]&.map do | content |
|
193
|
+
case content[ :type ]
|
194
|
+
when :text
|
195
|
+
content[ :text ] = ''
|
196
|
+
else
|
197
|
+
content.clear
|
198
|
+
end
|
199
|
+
content
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
buffer += chunk
|
204
|
+
while ( eol_index = buffer.index( "\n" ) )
|
205
|
+
|
206
|
+
line = buffer.slice!( 0..eol_index )
|
207
|
+
line = line.strip
|
208
|
+
next if line.empty? || !line.start_with?( 'data:' )
|
209
|
+
line = line[ 6..-1 ]
|
210
|
+
|
211
|
+
data = JSON.parse( line, symbolize_names: true )
|
212
|
+
if data.is_a?( Hash )
|
213
|
+
|
214
|
+
data[ :candidates ]&.each do | data_candidate |
|
215
|
+
|
216
|
+
data_candidate_index = data_candidate[ :index ] || 0
|
217
|
+
data_candidate_content = data_candidate[ :content ]
|
218
|
+
data_candidate_finish_reason = data_candidate[ :finishReason ]
|
219
|
+
choices.fill( { message: { role: 'assistant' } }, choices.size, data_candidate_index + 1 ) \
|
220
|
+
if choices.size <= data_candidate_index
|
221
|
+
contents = choices[ data_candidate_index ][ :message ][ :contents ] || []
|
222
|
+
last_content = contents&.last
|
223
|
+
|
224
|
+
if data_candidate_content&.include?( :parts )
|
225
|
+
data_candidate_content_parts = data_candidate_content[ :parts ]
|
226
|
+
data_candidate_content_parts&.each do | data_candidate_content_part |
|
227
|
+
if data_candidate_content_part.key?( :text )
|
228
|
+
if last_content.nil? || last_content[ :type ] != :text
|
229
|
+
contents.push( { type: :text, text: data_candidate_content_part[ :text ] } )
|
230
|
+
else
|
231
|
+
last_content[ :text ] =
|
232
|
+
( last_content[ :text ] || '' ) + data_candidate_content_part[ :text ]
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
choices[ data_candidate_index ][ :message ][ :contents ] = contents
|
238
|
+
choices[ data_candidate_index ][ :end_reason ] =
|
239
|
+
translate_finish_reason( data_candidate_finish_reason )
|
240
|
+
end
|
241
|
+
|
242
|
+
if usage = data[ :usageMetadata ]
|
243
|
+
metrics[ :input_tokens ] = usage[ :promptTokenCount ]
|
244
|
+
metrics[ :output_tokens ] = usage[ :candidatesTokenCount ]
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
context[ :buffer ] = buffer
|
252
|
+
context[ :metrics ] = metrics
|
253
|
+
context[ :choices ] = choices
|
254
|
+
|
255
|
+
[ context, choices.empty? ? nil : { choices: choices.dup } ]
|
256
|
+
|
257
|
+
end
|
258
|
+
|
259
|
+
def stream_result_attributes( context )
|
260
|
+
#--------------------------------------
|
261
|
+
|
262
|
+
choices = context[ :choices ]
|
263
|
+
metrics = context[ :metrics ]
|
264
|
+
|
265
|
+
choices = choices.map do | choice |
|
266
|
+
{ end_reason: choice[ :end_reason ] }
|
267
|
+
end
|
268
|
+
|
269
|
+
{ choices: choices, metrics: context[ :metrics ] }
|
270
|
+
|
271
|
+
end
|
272
|
+
|
273
|
+
alias_method :stream_result_error_attributes, :chat_result_error_attributes
|
274
|
+
|
275
|
+
private; def translate_system_message( system_message )
|
276
|
+
# -----------------------------------------------------
|
277
|
+
|
278
|
+
return nil if system_message.nil?
|
279
|
+
|
280
|
+
text = ''
|
281
|
+
system_message[ :contents ].each do | content |
|
282
|
+
text += content[ :text ] if content[ :type ] == :text
|
283
|
+
end
|
284
|
+
|
285
|
+
return nil if text.empty?
|
286
|
+
|
287
|
+
{
|
288
|
+
role: 'user',
|
289
|
+
parts: [
|
290
|
+
{ text: text }
|
291
|
+
]
|
292
|
+
}
|
293
|
+
|
294
|
+
end
|
295
|
+
|
296
|
+
private; def translate_finish_reason( finish_reason )
|
297
|
+
# ---------------------------------------------------
|
298
|
+
case finish_reason
|
299
|
+
when 'STOP'
|
300
|
+
:ended
|
301
|
+
when 'MAX_TOKENS'
|
302
|
+
:token_limit_exceeded
|
303
|
+
when 'SAFETY', 'RECITATION', 'BLOCKLIST', 'PROHIBITED_CONTENT', 'SPII'
|
304
|
+
:filtered
|
305
|
+
else
|
306
|
+
nil
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
private; def translate_error_response_status( status )
|
311
|
+
case status
|
312
|
+
when 400
|
313
|
+
[ :invalid_request_error,
|
314
|
+
"There was an issue with the format or content of your request." ]
|
315
|
+
when 403
|
316
|
+
[ :permission_error,
|
317
|
+
"Your API key does not have permission to use the specified resource." ]
|
318
|
+
when 404
|
319
|
+
[ :not_found_error,
|
320
|
+
"The requested resource was not found." ]
|
321
|
+
when 413
|
322
|
+
[ :request_too_large,
|
323
|
+
"Request exceeds the maximum allowed number of bytes." ]
|
324
|
+
when 422
|
325
|
+
[ :invalid_request_error,
|
326
|
+
"There was an issue with the format or content of your request." ]
|
327
|
+
when 429
|
328
|
+
[ :rate_limit_error,
|
329
|
+
"Your account has hit a rate limit." ]
|
330
|
+
when 500, 502, 503
|
331
|
+
[ :api_error,
|
332
|
+
"An unexpected error has occurred internal to the providers systems." ]
|
333
|
+
when 529
|
334
|
+
[ :overloaded_error,
|
335
|
+
"The providers server is temporarily overloaded." ]
|
336
|
+
else
|
337
|
+
[ :unknown_error, "
|
338
|
+
An unknown error occurred." ]
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
end
|
343
|
+
|
344
|
+
end
|
345
|
+
|
346
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative 'legacy/adapter'
|
2
|
+
|
3
|
+
module Intelligence
|
4
|
+
module Groq
|
5
|
+
|
6
|
+
class Adapter < Legacy::Adapter
|
7
|
+
|
8
|
+
chat_request_uri 'https://api.groq.com/openai/v1/chat/completions'
|
9
|
+
|
10
|
+
configuration do
|
11
|
+
parameter :key, String, required: true
|
12
|
+
group :chat_options do
|
13
|
+
parameter :frequency_penalty, Float
|
14
|
+
parameter :logit_bias
|
15
|
+
parameter :logprobs, [ TrueClass, FalseClass ]
|
16
|
+
parameter :max_tokens, Integer
|
17
|
+
parameter :model, String
|
18
|
+
parameter :n, Integer
|
19
|
+
# the parallel_tool_calls parameter is only allowed when 'tools' are specified
|
20
|
+
parameter :parallel_tool_calls, [ TrueClass, FalseClass ]
|
21
|
+
parameter :presence_penalty, Float
|
22
|
+
group :response_format do
|
23
|
+
# 'text' and 'json_object' are the only supported types; you must also instruct
|
24
|
+
# the model to output json
|
25
|
+
parameter :type, String
|
26
|
+
end
|
27
|
+
parameter :seed, Integer
|
28
|
+
parameter :stop, String, array: true
|
29
|
+
parameter :stream, [ TrueClass, FalseClass ]
|
30
|
+
group :stream_options do
|
31
|
+
parameter :include_usage, [ TrueClass, FalseClass ]
|
32
|
+
end
|
33
|
+
parameter :temperature, Float
|
34
|
+
group :tool_choice do
|
35
|
+
# one of 'auto', 'none' or 'function'
|
36
|
+
parameter :type, String
|
37
|
+
# the function group is required if you specify a type of 'function'
|
38
|
+
group :function do
|
39
|
+
parameter :name, String
|
40
|
+
end
|
41
|
+
end
|
42
|
+
parameter :top_logprobs, Integer
|
43
|
+
parameter :top_p, Float
|
44
|
+
parameter :user, String
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative 'generic/adapter'
|
2
|
+
|
3
|
+
module Intelligence
|
4
|
+
module Hyperbolic
|
5
|
+
|
6
|
+
class Adapter < Generic::Adapter
|
7
|
+
|
8
|
+
chat_request_uri "https://api.hyperbolic.xyz/v1/chat/completions"
|
9
|
+
|
10
|
+
configuration do
|
11
|
+
parameter :key, String, required: true
|
12
|
+
group :chat_options do
|
13
|
+
parameter :model, String
|
14
|
+
parameter :temperature, Float
|
15
|
+
parameter :top_p, Float
|
16
|
+
parameter :n, Integer
|
17
|
+
parameter :max_tokens, Integer
|
18
|
+
parameter :stop, String, array: true
|
19
|
+
parameter :stream, [ TrueClass, FalseClass ]
|
20
|
+
parameter :frequency_penalty, Float
|
21
|
+
parameter :presence_penalty, Float
|
22
|
+
parameter :user, String
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def chat_result_error_attributes( response )
|
27
|
+
|
28
|
+
error_type, error_description = translate_error_response_status( response.status )
|
29
|
+
result = {
|
30
|
+
error_type: error_type.to_s,
|
31
|
+
error_description: error_description
|
32
|
+
}
|
33
|
+
parsed_body = JSON.parse( response.body, symbolize_names: true ) rescue nil
|
34
|
+
if parsed_body && parsed_body.respond_to?( :include? )
|
35
|
+
if parsed_body.include?( :error )
|
36
|
+
result = {
|
37
|
+
error_type: error_type.to_s,
|
38
|
+
error: parsed_body[ :error ][ :code ] || error_type.to_s,
|
39
|
+
error_description: parsed_body[ :error ][ :message ] || error_description
|
40
|
+
}
|
41
|
+
elsif parsed_body.include?( :detail )
|
42
|
+
result[ :error_description ] = parsed_body[ :detail ]
|
43
|
+
elsif parsed_body[ :object ] == 'error'
|
44
|
+
result[ :error_description ] = parsed_body[ :message ]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
result
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Intelligence
|
2
|
+
module Legacy
|
3
|
+
module ChatMethods
|
4
|
+
|
5
|
+
def chat_request_body( conversation, options = {} )
|
6
|
+
result = self.chat_options.merge( options ).compact
|
7
|
+
result[ :messages ] = []
|
8
|
+
|
9
|
+
system_message = system_message_to_s( conversation[ :system_message ] )
|
10
|
+
result[ :messages ] << { role: 'system', content: system_message } if system_message
|
11
|
+
|
12
|
+
conversation[ :messages ]&.each do | message |
|
13
|
+
result[ :messages ] << chat_request_message_attributes( message )
|
14
|
+
end
|
15
|
+
|
16
|
+
JSON.generate( result )
|
17
|
+
end
|
18
|
+
|
19
|
+
def chat_request_message_attributes( message )
|
20
|
+
result_message = { role: message[ :role ] }
|
21
|
+
result_message_content = ""
|
22
|
+
|
23
|
+
message[ :contents ]&.each do | content |
|
24
|
+
case content[ :type ]
|
25
|
+
when :text
|
26
|
+
result_message_content += content[ :text ]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
result_message[ :content ] = result_message_content
|
31
|
+
result_message
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require_relative 'chat_methods'
|
2
|
+
|
3
|
+
module Intelligence
|
4
|
+
module OpenAi
|
5
|
+
class Adapter < Adapter::Base
|
6
|
+
|
7
|
+
configuration do
|
8
|
+
|
9
|
+
# normalized properties for all endpoints
|
10
|
+
parameter :key, String, required: true
|
11
|
+
|
12
|
+
# openai properties for all endpoints
|
13
|
+
parameter :organization
|
14
|
+
parameter :project
|
15
|
+
|
16
|
+
# properties for generative text endpoints
|
17
|
+
group :chat_options do
|
18
|
+
|
19
|
+
# normalized properties for openai generative text endpoint
|
20
|
+
parameter :model, String, required: true
|
21
|
+
parameter :n, Integer
|
22
|
+
parameter :max_tokens, Integer, as: :max_completion_tokens
|
23
|
+
parameter :temperature, Float
|
24
|
+
parameter :top_p, Float
|
25
|
+
parameter :seed, Integer
|
26
|
+
parameter :stop, String, array: true
|
27
|
+
parameter :stream, [ TrueClass, FalseClass ]
|
28
|
+
|
29
|
+
parameter :frequency_penalty, Float
|
30
|
+
parameter :presence_penalty, Float
|
31
|
+
|
32
|
+
# openai variant of normalized properties for openai generative text endpoints
|
33
|
+
parameter :max_completion_tokens, Integer
|
34
|
+
|
35
|
+
# openai properties for openai generative text endpoint
|
36
|
+
parameter :logit_bias
|
37
|
+
parameter :logprobs, [ TrueClass, FalseClass ]
|
38
|
+
parameter :parallel_tool_calls, [ TrueClass, FalseClass ]
|
39
|
+
group :response_format do
|
40
|
+
# 'text' and 'json_schema' are the only supported types
|
41
|
+
parameter :type, String
|
42
|
+
parameter :json_schema
|
43
|
+
end
|
44
|
+
parameter :service_tier, String
|
45
|
+
group :stream_options do
|
46
|
+
parameter :include_usage, [ TrueClass, FalseClass ]
|
47
|
+
end
|
48
|
+
parameter :tool_choice
|
49
|
+
# the parallel_tool_calls parameter is only allowed when 'tools' are specified
|
50
|
+
parameter :top_logprobs, Integer
|
51
|
+
parameter :user
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_reader :key
|
58
|
+
attr_reader :organization
|
59
|
+
attr_reader :project
|
60
|
+
attr_reader :chat_options
|
61
|
+
|
62
|
+
|
63
|
+
def initialize( attributes = nil, &block )
|
64
|
+
configuration = self.class.configure( attributes, &block )
|
65
|
+
@key = configuration[ :key ]
|
66
|
+
@organization = configuration[ :organization ]
|
67
|
+
@project = configuration[ :project ]
|
68
|
+
@chat_options = configuration[ :chat_options ] || {}
|
69
|
+
end
|
70
|
+
|
71
|
+
include ChatMethods
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|