intelligence 0.5.0 → 0.6.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/intelligence.gemspec +1 -1
- data/lib/intelligence/adapter/base.rb +15 -2
- data/lib/intelligence/adapter/class_methods/construction.rb +17 -0
- data/lib/intelligence/adapter/module_methods/construction.rb +43 -0
- data/lib/intelligence/adapter.rb +2 -2
- data/lib/intelligence/adapters/anthropic/adapter.rb +4 -15
- data/lib/intelligence/adapters/anthropic/chat_methods.rb +9 -8
- data/lib/intelligence/adapters/cerebras.rb +3 -3
- data/lib/intelligence/adapters/generic/adapter.rb +1 -12
- data/lib/intelligence/adapters/generic/chat_methods.rb +34 -10
- data/lib/intelligence/adapters/google/adapter.rb +2 -15
- data/lib/intelligence/adapters/google/chat_methods.rb +68 -21
- data/lib/intelligence/adapters/groq.rb +20 -1
- data/lib/intelligence/adapters/hyperbolic.rb +1 -1
- data/lib/intelligence/adapters/legacy/adapter.rb +0 -2
- data/lib/intelligence/adapters/legacy/chat_methods.rb +23 -6
- data/lib/intelligence/adapters/mistral.rb +57 -0
- data/lib/intelligence/adapters/open_ai/adapter.rb +2 -16
- data/lib/intelligence/adapters/open_ai/chat_methods.rb +39 -8
- data/lib/intelligence/adapters/open_router.rb +62 -0
- data/lib/intelligence/adapters/samba_nova.rb +1 -1
- data/lib/intelligence/adapters/together_ai.rb +1 -1
- data/lib/intelligence/chat_request.rb +57 -7
- data/lib/intelligence/chat_result.rb +4 -0
- data/lib/intelligence/chat_result_choice.rb +4 -2
- data/lib/intelligence/conversation.rb +37 -9
- data/lib/intelligence/message.rb +90 -23
- data/lib/intelligence/message_content/base.rb +10 -0
- data/lib/intelligence/message_content/binary.rb +6 -0
- data/lib/intelligence/message_content/file.rb +35 -0
- data/lib/intelligence/message_content/text.rb +5 -0
- data/lib/intelligence/message_content/tool_call.rb +8 -1
- data/lib/intelligence/message_content/tool_result.rb +8 -1
- data/lib/intelligence/message_content.rb +12 -3
- data/lib/intelligence/version.rb +1 -1
- data/lib/intelligence.rb +4 -3
- metadata +9 -5
- data/lib/intelligence/adapter/construction_methods.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 754f9f4fd414c8bee3fd90ea14aeae011e21f3312e483096f5a50b41698dfef5
|
4
|
+
data.tar.gz: 7ba7e4cb7cd172e152f8ab6c886255a13d0bbf26b6c6e0f674b71765ed03cf67
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db69984a0028e297a30346406f351388caca294094fabe00d30c8598f038db8731acfbf1ded26c6fa8f653bf388826ec6fa07327c5868bec40ba6686a7f38182
|
7
|
+
data.tar.gz: f1a21376458d278c46828c564951a945bc7c896951946911e06fe73c04204dad2147ce91ba83434161d55e0c0c1a7132d1d9f7006ea9f2ef3fbe59bcf24bc87d
|
data/intelligence.gemspec
CHANGED
@@ -37,7 +37,7 @@ Gem::Specification.new do | spec |
|
|
37
37
|
spec.require_paths = [ "lib" ]
|
38
38
|
|
39
39
|
spec.add_runtime_dependency 'faraday', '~> 2.7'
|
40
|
-
spec.add_runtime_dependency 'adaptiveconfiguration', '~> 1.0.0.
|
40
|
+
spec.add_runtime_dependency 'adaptiveconfiguration', '~> 1.0.0.beta08'
|
41
41
|
spec.add_runtime_dependency 'mime-types', '~> 3.6'
|
42
42
|
|
43
43
|
spec.add_development_dependency 'rspec', '~> 3.4'
|
@@ -1,7 +1,20 @@
|
|
1
|
+
require_relative 'class_methods/construction'
|
2
|
+
|
1
3
|
module Intelligence
|
2
4
|
module Adapter
|
3
5
|
class Base
|
4
6
|
extend AdaptiveConfiguration::Configurable
|
5
|
-
|
7
|
+
extend ClassMethods::Construction
|
8
|
+
|
9
|
+
def initialize( options = nil, configuration: nil )
|
10
|
+
@options = options ? self.class.configure( options ) : {}
|
11
|
+
@options = configuration.merge( @options ) if configuration
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
attr_reader :options
|
16
|
+
|
17
|
+
end
|
6
18
|
end
|
7
|
-
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Intelligence
|
2
|
+
module Adapter
|
3
|
+
module ClassMethods
|
4
|
+
module Construction
|
5
|
+
|
6
|
+
def build( options = nil, &block )
|
7
|
+
self.new( configuration: self.configure( options, &block ) )
|
8
|
+
end
|
9
|
+
|
10
|
+
def build!( options = nil, &block )
|
11
|
+
self.new( configuration: self.configure!( options, &block ) )
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Intelligence
|
2
|
+
module Adapter
|
3
|
+
module ModuleMethods
|
4
|
+
module Construction
|
5
|
+
|
6
|
+
def []( adapter_type )
|
7
|
+
|
8
|
+
raise ArgumentError.new( "An adapter type is required but nil was given." ) \
|
9
|
+
if adapter_type.nil?
|
10
|
+
|
11
|
+
class_name = adapter_type.to_s.split( '_' ).map( &:capitalize ).join
|
12
|
+
class_name += "::Adapter"
|
13
|
+
|
14
|
+
adapter_class = Intelligence.const_get( class_name ) rescue nil
|
15
|
+
if adapter_class.nil?
|
16
|
+
adapter_file = File.expand_path( "../../../adapters/#{adapter_type}", __FILE__ )
|
17
|
+
unless require adapter_file
|
18
|
+
raise ArgumentError.new(
|
19
|
+
"The Intelligence adapter file #{adapter_file} is missing or does not define #{class_name}."
|
20
|
+
)
|
21
|
+
end
|
22
|
+
adapter_class = Intelligence.const_get( class_name ) rescue nil
|
23
|
+
end
|
24
|
+
|
25
|
+
raise ArgumentError.new( "An unknown Intelligence adapter #{adapter_type} was requested." ) \
|
26
|
+
if adapter_class.nil?
|
27
|
+
|
28
|
+
adapter_class
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
def build( adapter_type, attributes = nil, &block )
|
33
|
+
self.[]( adapter_type ).build( attributes, &block )
|
34
|
+
end
|
35
|
+
|
36
|
+
def build!( adapter_type, attributes = nil, &block )
|
37
|
+
self.[]( adapter_type ).build!( attributes, &block )
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/intelligence/adapter.rb
CHANGED
@@ -7,16 +7,16 @@ module Intelligence
|
|
7
7
|
configuration do
|
8
8
|
|
9
9
|
# normalized properties for all endpoints
|
10
|
-
parameter :key
|
10
|
+
parameter :key
|
11
11
|
|
12
12
|
# anthropic specific properties for all endpoints
|
13
|
-
parameter :version, String,
|
13
|
+
parameter :version, String, default: '2023-06-01'
|
14
14
|
|
15
15
|
group :chat_options do
|
16
16
|
|
17
17
|
# normalized properties for anthropic generative text endpoint
|
18
|
-
parameter :model, String
|
19
|
-
parameter :max_tokens, Integer
|
18
|
+
parameter :model, String
|
19
|
+
parameter :max_tokens, Integer
|
20
20
|
parameter :temperature, Float
|
21
21
|
parameter :top_k, Integer
|
22
22
|
parameter :top_p, Float
|
@@ -40,17 +40,6 @@ module Intelligence
|
|
40
40
|
|
41
41
|
end
|
42
42
|
|
43
|
-
attr_reader :key
|
44
|
-
attr_reader :version
|
45
|
-
attr_reader :chat_options
|
46
|
-
|
47
|
-
def initialize( attributes = nil, &block )
|
48
|
-
configuration = self.class.configure( attributes, &block )
|
49
|
-
@key = configuration[ :key ]
|
50
|
-
@version = configuration[ :version ]
|
51
|
-
@chat_options = configuration[ :chat_options ] || {}
|
52
|
-
end
|
53
|
-
|
54
43
|
include ChatMethods
|
55
44
|
|
56
45
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'base64'
|
2
|
-
|
3
1
|
module Intelligence
|
4
2
|
module Anthropic
|
5
3
|
module ChatMethods
|
@@ -10,11 +8,13 @@ module Intelligence
|
|
10
8
|
CHAT_REQUEST_URI
|
11
9
|
end
|
12
10
|
|
13
|
-
def chat_request_headers( options =
|
11
|
+
def chat_request_headers( options = nil )
|
12
|
+
options = options ? self.class.configure( options ) : {}
|
13
|
+
options = @options.merge( options )
|
14
14
|
result = {}
|
15
15
|
|
16
|
-
key = options[ :key ]
|
17
|
-
version = options[ :version ] ||
|
16
|
+
key = options[ :key ]
|
17
|
+
version = options[ :version ] || "2023-06-01"
|
18
18
|
|
19
19
|
raise ArgumentError.new(
|
20
20
|
"An Anthropic key is required to build an Anthropic chat request."
|
@@ -27,9 +27,10 @@ module Intelligence
|
|
27
27
|
result
|
28
28
|
end
|
29
29
|
|
30
|
-
def chat_request_body( conversation, options =
|
31
|
-
options = self.class.configure( options )
|
32
|
-
|
30
|
+
def chat_request_body( conversation, options = nil )
|
31
|
+
options = options ? self.class.configure( options ) : {}
|
32
|
+
options = @options.merge( options )
|
33
|
+
result = options[ :chat_options ]&.compact || {}
|
33
34
|
|
34
35
|
system_message = translate_system_message( conversation[ :system_message ] )
|
35
36
|
result[ :system ] = system_message unless system_message.nil?
|
@@ -8,10 +8,10 @@ module Intelligence
|
|
8
8
|
chat_request_uri "https://api.cerebras.ai/v1/chat/completions"
|
9
9
|
|
10
10
|
configuration do
|
11
|
-
parameter :key
|
11
|
+
parameter :key
|
12
12
|
group :chat_options do
|
13
|
-
parameter :model, String
|
14
|
-
parameter :max_tokens, Integer
|
13
|
+
parameter :model, String
|
14
|
+
parameter :max_tokens, Integer
|
15
15
|
parameter :response_format do
|
16
16
|
parameter :type, String, default: 'json_schema'
|
17
17
|
parameter :json_schema
|
@@ -4,18 +4,7 @@ require_relative 'chat_methods'
|
|
4
4
|
module Intelligence
|
5
5
|
module Generic
|
6
6
|
class Adapter < Adapter::Base
|
7
|
-
|
8
|
-
attr_reader :key
|
9
|
-
attr_reader :chat_options
|
10
|
-
|
11
|
-
def initialize( attributes = nil, &block )
|
12
|
-
configuration = self.class.configure( attributes, &block )
|
13
|
-
@key = configuration[ :key ]
|
14
|
-
@chat_options = configuration[ :chat_options ] || {}
|
15
|
-
end
|
16
|
-
|
17
7
|
include ChatMethods
|
18
|
-
|
19
8
|
end
|
20
9
|
end
|
21
|
-
end
|
10
|
+
end
|
@@ -20,10 +20,12 @@ module Intelligence
|
|
20
20
|
self.class.chat_request_uri
|
21
21
|
end
|
22
22
|
|
23
|
-
def chat_request_headers( options =
|
23
|
+
def chat_request_headers( options = nil )
|
24
|
+
options = options ? self.class.configure( options ) : {}
|
25
|
+
options = @options.merge( options )
|
24
26
|
result = {}
|
25
27
|
|
26
|
-
key = options[ :key ]
|
28
|
+
key = options[ :key ]
|
27
29
|
|
28
30
|
raise ArgumentError.new( "An API key is required to build a chat request." ) \
|
29
31
|
if key.nil?
|
@@ -34,8 +36,11 @@ module Intelligence
|
|
34
36
|
result
|
35
37
|
end
|
36
38
|
|
37
|
-
def chat_request_body( conversation, options =
|
38
|
-
|
39
|
+
def chat_request_body( conversation, options = nil )
|
40
|
+
options = options ? self.class.configure( options ) : {}
|
41
|
+
options = @options.merge( options )
|
42
|
+
|
43
|
+
result = options[ :chat_options ]
|
39
44
|
result[ :messages ] = []
|
40
45
|
|
41
46
|
system_message = system_message_to_s( conversation[ :system_message ] )
|
@@ -79,6 +84,28 @@ module Intelligence
|
|
79
84
|
'requires binary content to include content type and ( packed ) bytes'
|
80
85
|
)
|
81
86
|
end
|
87
|
+
when :file
|
88
|
+
content_type = content[ :content_type ]
|
89
|
+
uri = content[ :uri ]
|
90
|
+
if content_type && uri
|
91
|
+
mime_type = MIME::Types[ content_type ].first
|
92
|
+
if mime_type&.media_type == 'image'
|
93
|
+
result_message_content << {
|
94
|
+
type: 'image_url',
|
95
|
+
image_url: { url: uri }
|
96
|
+
}
|
97
|
+
else
|
98
|
+
raise UnsupportedContentError.new(
|
99
|
+
:generic,
|
100
|
+
'only support content of type image/*'
|
101
|
+
)
|
102
|
+
end
|
103
|
+
else
|
104
|
+
raise UnsupportedContentError.new(
|
105
|
+
:generic,
|
106
|
+
'requires binary content to include content type and ( packed ) bytes'
|
107
|
+
)
|
108
|
+
end
|
82
109
|
end
|
83
110
|
end
|
84
111
|
result_message[ :content ] = result_message_content
|
@@ -124,7 +151,7 @@ module Intelligence
|
|
124
151
|
end
|
125
152
|
|
126
153
|
def chat_result_error_attributes( response )
|
127
|
-
|
154
|
+
|
128
155
|
error_type, error_description = translate_error_response_status( response.status )
|
129
156
|
result = {
|
130
157
|
error_type: error_type.to_s,
|
@@ -178,7 +205,6 @@ module Intelligence
|
|
178
205
|
|
179
206
|
next if line.end_with?( '[DONE]' )
|
180
207
|
data = JSON.parse( line )
|
181
|
-
|
182
208
|
if data.is_a?( Hash )
|
183
209
|
|
184
210
|
data[ 'choices' ]&.each do | data_choice |
|
@@ -196,10 +222,8 @@ module Intelligence
|
|
196
222
|
data_choice_content = data_choice_delta[ 'content' ] || ''
|
197
223
|
if last_content.nil? || last_content[ :type ] == :tool_call
|
198
224
|
contents.push( { type: :text, text: data_choice_content } )
|
199
|
-
elsif last_content[ :type ].nil?
|
225
|
+
elsif last_content[ :type ] == :text || last_content[ :type ].nil?
|
200
226
|
last_content[ :type ] = :text
|
201
|
-
last_content[ :text ] = data_choice_content
|
202
|
-
elsif last_content[ :type ] == :text
|
203
227
|
last_content[ :text ] = ( last_content[ :text ] || '' ) + data_choice_content
|
204
228
|
end
|
205
229
|
elsif data_choice_delta.include?( 'function_call' )
|
@@ -223,7 +247,7 @@ module Intelligence
|
|
223
247
|
end
|
224
248
|
end
|
225
249
|
choices[ data_choice_index ][ :message ][ :contents ] = contents
|
226
|
-
choices[ data_choice_index ][ :end_reason ]
|
250
|
+
choices[ data_choice_index ][ :end_reason ] ||=
|
227
251
|
translate_end_result( data_choice_finish_reason )
|
228
252
|
end
|
229
253
|
|
@@ -7,12 +7,12 @@ module Intelligence
|
|
7
7
|
configuration do
|
8
8
|
|
9
9
|
# normalized properties for all endpoints
|
10
|
-
parameter :key, String
|
10
|
+
parameter :key, String
|
11
11
|
|
12
12
|
group :chat_options, as: :generationConfig do
|
13
13
|
|
14
14
|
# normalized properties for google generative text endpoint
|
15
|
-
parameter :model, String
|
15
|
+
parameter :model, String
|
16
16
|
parameter :max_tokens, Integer, as: :maxOutputTokens
|
17
17
|
parameter :n, Integer, as: :candidateCount
|
18
18
|
parameter :temperature, Float
|
@@ -38,19 +38,6 @@ module Intelligence
|
|
38
38
|
|
39
39
|
end
|
40
40
|
|
41
|
-
attr_reader :key
|
42
|
-
attr_reader :model
|
43
|
-
attr_reader :stream
|
44
|
-
attr_reader :chat_options
|
45
|
-
|
46
|
-
def initialize( attributes = nil, &block )
|
47
|
-
configuration = self.class.configure( attributes, &block ).to_h
|
48
|
-
@key = configuration.delete( :key )
|
49
|
-
@model = configuration[ :generationConfig ]&.delete( :model )
|
50
|
-
@stream = configuration[ :generationConfig ]&.delete( :stream ) || false
|
51
|
-
@chat_options = configuration[ :generationConfig ] || {}
|
52
|
-
end
|
53
|
-
|
54
41
|
include ChatMethods
|
55
42
|
|
56
43
|
end
|
@@ -6,18 +6,37 @@ module Intelligence
|
|
6
6
|
|
7
7
|
GENERATIVE_LANGUAGE_URI = "https://generativelanguage.googleapis.com/v1beta/models/"
|
8
8
|
|
9
|
-
|
9
|
+
SUPPORTED_BINARY_MEDIA_TYPES = %w[ text ]
|
10
|
+
|
11
|
+
SUPPORTED_BINARY_CONTENT_TYPES = %w[
|
12
|
+
image/png image/jpeg image/webp image/heic image/heif
|
13
|
+
audio/aac audio/flac audio/mp3 audio/m4a audio/mpeg audio/mpga audio/mp4 audio/opus
|
14
|
+
audio/pcm audio/wav audio/webm
|
15
|
+
application/pdf
|
16
|
+
]
|
17
|
+
|
18
|
+
SUPPORTED_FILE_MEDIA_TYPES = %w[ text ]
|
19
|
+
|
20
|
+
SUPPORTED_CONTENT_TYPES = %w[
|
21
|
+
image/png image/jpeg image/webp image/heic image/heif
|
22
|
+
video/x-flv video/quicktime video/mpeg video/mpegps video/mpg video/mp4 video/webm
|
23
|
+
video/wmv video/3gpp
|
24
|
+
audio/aac audio/flac audio/mp3 audio/m4a audio/mpeg audio/mpga audio/mp4 audio/opus
|
25
|
+
audio/pcm audio/wav audio/webm
|
26
|
+
application/pdf
|
27
|
+
]
|
10
28
|
|
11
|
-
|
29
|
+
def chat_request_uri( options )
|
30
|
+
options = options ? self.class.configure( options ) : {}
|
31
|
+
options = @options.merge( options )
|
12
32
|
|
13
|
-
key = options[ :key ]
|
14
|
-
|
33
|
+
key = options[ :key ]
|
15
34
|
gc = options[ :generationConfig ] || {}
|
16
|
-
model = gc[ :model ]
|
17
|
-
stream = gc.key?( :stream ) ? gc[ :stream ] :
|
35
|
+
model = gc[ :model ]
|
36
|
+
stream = gc.key?( :stream ) ? gc[ :stream ] : false
|
18
37
|
|
19
38
|
raise ArgumentError.new( "A Google API key is required to build a Google chat request." ) \
|
20
|
-
if
|
39
|
+
if key.nil?
|
21
40
|
raise ArgumentError.new( "A Google model is required to build a Google chat request." ) \
|
22
41
|
if model.nil?
|
23
42
|
|
@@ -25,12 +44,11 @@ module Intelligence
|
|
25
44
|
path = File.join( uri.path, model )
|
26
45
|
path += stream ? ':streamGenerateContent' : ':generateContent'
|
27
46
|
uri.path = path
|
28
|
-
query = { key:
|
47
|
+
query = { key: key }
|
29
48
|
query[ :alt ] = 'sse' if stream
|
30
49
|
uri.query = URI.encode_www_form( query )
|
31
50
|
|
32
51
|
uri.to_s
|
33
|
-
|
34
52
|
end
|
35
53
|
|
36
54
|
def chat_request_headers( options = {} )
|
@@ -38,16 +56,16 @@ module Intelligence
|
|
38
56
|
end
|
39
57
|
|
40
58
|
def chat_request_body( conversation, options = {} )
|
59
|
+
options = options ? self.class.configure( options ) : {}
|
60
|
+
options = @options.merge( options )
|
41
61
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
result = result.merge( options )
|
62
|
+
gc = options[ :generationConfig ]
|
63
|
+
# discard properties not part of the google generationConfig schema
|
64
|
+
gc.delete( :model )
|
65
|
+
gc.delete( :stream )
|
47
66
|
|
48
|
-
|
49
|
-
result[ :generationConfig ]
|
50
|
-
result[ :generationConfig ].delete( :stream )
|
67
|
+
result = {}
|
68
|
+
result[ :generationConfig ] = gc
|
51
69
|
|
52
70
|
# construct the system prompt in the form of the google schema
|
53
71
|
system_instructions = translate_system_message( conversation[ :system_message ] )
|
@@ -67,8 +85,9 @@ module Intelligence
|
|
67
85
|
content_type = content[ :content_type ]
|
68
86
|
bytes = content[ :bytes ]
|
69
87
|
if content_type && bytes
|
70
|
-
|
71
|
-
|
88
|
+
mime_type = MIME::Types[ content_type ].first
|
89
|
+
if SUPPORTED_BINARY_MEDIA_TYPES.include?( mime_type&.media_type ) ||
|
90
|
+
SUPPORTED_BINARY_CONTENT_TYPES.include?( content_type )
|
72
91
|
result_message_parts << {
|
73
92
|
inline_data: {
|
74
93
|
mime_type: content_type,
|
@@ -78,7 +97,7 @@ module Intelligence
|
|
78
97
|
else
|
79
98
|
raise UnsupportedContentError.new(
|
80
99
|
:google,
|
81
|
-
|
100
|
+
"does not support #{content_type} content type"
|
82
101
|
)
|
83
102
|
end
|
84
103
|
else
|
@@ -86,7 +105,35 @@ module Intelligence
|
|
86
105
|
:google,
|
87
106
|
'requires binary content to include content type and ( packed ) bytes'
|
88
107
|
)
|
89
|
-
end
|
108
|
+
end
|
109
|
+
when :file
|
110
|
+
content_type = content[ :content_type ]
|
111
|
+
uri = content[ :uri ]
|
112
|
+
if content_type && uri
|
113
|
+
mime_type = MIME::Types[ content_type ].first
|
114
|
+
if SUPPORTED_FILE_MEDIA_TYPES.include?( mime_type&.media_type ) ||
|
115
|
+
SUPPORTED_FILE_CONTENT_TYPES.include?( content_type )
|
116
|
+
result_message_parts << {
|
117
|
+
file_data: {
|
118
|
+
mime_type: content_type,
|
119
|
+
file_uri: uri
|
120
|
+
}
|
121
|
+
}
|
122
|
+
else
|
123
|
+
raise UnsupportedContentError.new(
|
124
|
+
:google,
|
125
|
+
"does not support #{content_type} content type"
|
126
|
+
)
|
127
|
+
end
|
128
|
+
else
|
129
|
+
raise UnsupportedContentError.new(
|
130
|
+
:google,
|
131
|
+
'requires file content to include content type and uri'
|
132
|
+
)
|
133
|
+
end
|
134
|
+
|
135
|
+
else
|
136
|
+
raise InvalidContentError.new( :google )
|
90
137
|
end
|
91
138
|
end
|
92
139
|
|
@@ -8,7 +8,7 @@ module Intelligence
|
|
8
8
|
chat_request_uri 'https://api.groq.com/openai/v1/chat/completions'
|
9
9
|
|
10
10
|
configuration do
|
11
|
-
parameter :key, String
|
11
|
+
parameter :key, String
|
12
12
|
group :chat_options do
|
13
13
|
parameter :frequency_penalty, Float
|
14
14
|
parameter :logit_bias
|
@@ -45,6 +45,25 @@ module Intelligence
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
alias chat_request_generic_message_attributes chat_request_message_attributes
|
49
|
+
|
50
|
+
# groq models only support the legacy Open AI message schema for the assistant
|
51
|
+
# messages while supporting the modern message schema for user messages
|
52
|
+
def chat_request_message_attributes( message )
|
53
|
+
role = message[ :role ]&.to_sym
|
54
|
+
case role
|
55
|
+
when :user
|
56
|
+
chat_request_generic_message_attributes( message )
|
57
|
+
when :assistant
|
58
|
+
chat_request_legacy_message_attributes( message )
|
59
|
+
else
|
60
|
+
raise UnsupportedContentError.new(
|
61
|
+
:mistral,
|
62
|
+
'only supports user and assistant message roles'
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
48
67
|
end
|
49
68
|
|
50
69
|
end
|
@@ -8,7 +8,7 @@ module Intelligence
|
|
8
8
|
chat_request_uri "https://api.hyperbolic.xyz/v1/chat/completions"
|
9
9
|
|
10
10
|
configuration do
|
11
|
-
parameter :key, String
|
11
|
+
parameter :key, String
|
12
12
|
group :chat_options do
|
13
13
|
parameter :model, String
|
14
14
|
parameter :temperature, Float
|
@@ -3,20 +3,37 @@ module Intelligence
|
|
3
3
|
module ChatMethods
|
4
4
|
|
5
5
|
def chat_request_body( conversation, options = {} )
|
6
|
-
|
6
|
+
options = options ? self.class.configure( options ) : {}
|
7
|
+
options = @options.merge( options )
|
8
|
+
|
9
|
+
result = options[ :chat_options ]&.compact || {}
|
7
10
|
result[ :messages ] = []
|
8
11
|
|
9
12
|
system_message = system_message_to_s( conversation[ :system_message ] )
|
10
13
|
result[ :messages ] << { role: 'system', content: system_message } if system_message
|
11
|
-
|
12
|
-
conversation
|
13
|
-
|
14
|
+
|
15
|
+
# detect if the conversation has any non-text content; this handles the sittuation
|
16
|
+
# where non-vision models only support the legacy message schema while the vision
|
17
|
+
# models only support the modern message schema
|
18
|
+
has_non_text_content = conversation[ :messages ]&.find do | message |
|
19
|
+
message[ :contents ]&.find do | content |
|
20
|
+
content[ :type ] != nil && content[ :type ] != :text
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
if has_non_text_content
|
25
|
+
conversation[ :messages ]&.each do | message |
|
26
|
+
result[ :messages ] << chat_request_message_attributes( message )
|
27
|
+
end
|
28
|
+
else
|
29
|
+
conversation[ :messages ]&.each do | message |
|
30
|
+
result[ :messages ] << chat_request_legacy_message_attributes( message )
|
31
|
+
end
|
14
32
|
end
|
15
|
-
|
16
33
|
JSON.generate( result )
|
17
34
|
end
|
18
35
|
|
19
|
-
def
|
36
|
+
def chat_request_legacy_message_attributes( message )
|
20
37
|
result_message = { role: message[ :role ] }
|
21
38
|
result_message_content = ""
|
22
39
|
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative 'legacy/adapter'
|
2
|
+
|
3
|
+
module Intelligence
|
4
|
+
module Mistral
|
5
|
+
|
6
|
+
class Adapter < Legacy::Adapter
|
7
|
+
|
8
|
+
chat_request_uri "https://api.mistral.ai/v1/chat/completions"
|
9
|
+
|
10
|
+
configuration do
|
11
|
+
parameter :key, String
|
12
|
+
group :chat_options do
|
13
|
+
parameter :model, String
|
14
|
+
parameter :temperature, Float
|
15
|
+
parameter :top_p, Float
|
16
|
+
parameter :max_tokens, Integer
|
17
|
+
parameter :min_tokens, Integer
|
18
|
+
parameter :seed, Integer, as: :random_seed
|
19
|
+
parameter :stop, String, array: true
|
20
|
+
parameter :stream, [ TrueClass, FalseClass ]
|
21
|
+
|
22
|
+
parameter :random_seed, Integer
|
23
|
+
group :response_format do
|
24
|
+
parameter :type, String
|
25
|
+
end
|
26
|
+
group :tool_choice do
|
27
|
+
parameter :type, String
|
28
|
+
group :function do
|
29
|
+
parameter :name, String
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
alias chat_request_generic_message_attributes chat_request_message_attributes
|
36
|
+
|
37
|
+
# mistral vision models only support the legacy Open AI message schema for the assistant
|
38
|
+
# messages while supporting the modern message schema for user messages :facepalm:
|
39
|
+
def chat_request_message_attributes( message )
|
40
|
+
role = message[ :role ]&.to_sym
|
41
|
+
case role
|
42
|
+
when :user
|
43
|
+
chat_request_generic_message_attributes( message )
|
44
|
+
when :assistant
|
45
|
+
chat_request_legacy_message_attributes( message )
|
46
|
+
else
|
47
|
+
raise UnsupportedContentError.new(
|
48
|
+
:mistral,
|
49
|
+
'only supports user and assistant message roles'
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|