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,314 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Intelligence
         
     | 
| 
      
 2 
     | 
    
         
            +
              module OpenAi
         
     | 
| 
      
 3 
     | 
    
         
            +
                module ChatMethods
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  CHAT_REQUEST_URI = "https://api.openai.com/v1/chat/completions"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def chat_request_uri( options )
         
     | 
| 
      
 8 
     | 
    
         
            +
                    CHAT_REQUEST_URI
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def chat_request_headers( options = {} )
         
     | 
| 
      
 12 
     | 
    
         
            +
                    result = {}
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    key = options[ :key ] || self.key
         
     | 
| 
      
 15 
     | 
    
         
            +
                    organization = options[ :organization ] || self.organization 
         
     | 
| 
      
 16 
     | 
    
         
            +
                    project = options[ :project ] || self.project 
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    raise ArgumentError.new( "An OpenAI key is required to build an OpenAI chat request." ) \
         
     | 
| 
      
 19 
     | 
    
         
            +
                      if key.nil?
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    result[ 'Content-Type' ] = 'application/json'
         
     | 
| 
      
 22 
     | 
    
         
            +
                    result[ 'Authorization' ] = "Bearer #{key}"
         
     | 
| 
      
 23 
     | 
    
         
            +
                    result[ 'OpenAI-Organization' ] = organization unless organization.nil?
         
     | 
| 
      
 24 
     | 
    
         
            +
                    result[ 'OpenAI-Project' ] = project unless project.nil?
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    result 
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def chat_request_body( conversation, options = {} )
         
     | 
| 
      
 30 
     | 
    
         
            +
                    result = self.chat_options.merge( options ).compact
         
     | 
| 
      
 31 
     | 
    
         
            +
                    result[ :messages ] = []
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    system_message = translate_system_message( conversation[ :system_message ] )
         
     | 
| 
      
 34 
     | 
    
         
            +
                    result[ :messages ] << { role: 'system', content: system_message } if system_message
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    conversation[ :messages ]&.each do | message |
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                      result_message = { role: message[ :role ] }
         
     | 
| 
      
 39 
     | 
    
         
            +
                      result_message_content = []
         
     | 
| 
      
 40 
     | 
    
         
            +
                      
         
     | 
| 
      
 41 
     | 
    
         
            +
                      message[ :contents ]&.each do | content |
         
     | 
| 
      
 42 
     | 
    
         
            +
                        case content[ :type ]
         
     | 
| 
      
 43 
     | 
    
         
            +
                        when :text
         
     | 
| 
      
 44 
     | 
    
         
            +
                          result_message_content << { type: 'text', text: content[ :text ] }
         
     | 
| 
      
 45 
     | 
    
         
            +
                        when :binary
         
     | 
| 
      
 46 
     | 
    
         
            +
                          content_type = content[ :content_type ]
         
     | 
| 
      
 47 
     | 
    
         
            +
                          bytes = content[ :bytes ]
         
     | 
| 
      
 48 
     | 
    
         
            +
                          if content_type && bytes
         
     | 
| 
      
 49 
     | 
    
         
            +
                            mime_type = MIME::Types[ content_type ].first
         
     | 
| 
      
 50 
     | 
    
         
            +
                            if mime_type&.media_type == 'image'
         
     | 
| 
      
 51 
     | 
    
         
            +
                              result_message_content << {
         
     | 
| 
      
 52 
     | 
    
         
            +
                                type: 'image_url',
         
     | 
| 
      
 53 
     | 
    
         
            +
                                image_url: {
         
     | 
| 
      
 54 
     | 
    
         
            +
                                  url: "data:#{content_type};base64,#{Base64.strict_encode64( bytes )}".freeze
         
     | 
| 
      
 55 
     | 
    
         
            +
                                }
         
     | 
| 
      
 56 
     | 
    
         
            +
                              }
         
     | 
| 
      
 57 
     | 
    
         
            +
                            else
         
     | 
| 
      
 58 
     | 
    
         
            +
                              raise UnsupportedContentError.new( 
         
     | 
| 
      
 59 
     | 
    
         
            +
                                :open_ai, 
         
     | 
| 
      
 60 
     | 
    
         
            +
                                'only supports content of type image/*' 
         
     | 
| 
      
 61 
     | 
    
         
            +
                              ) 
         
     | 
| 
      
 62 
     | 
    
         
            +
                            end
         
     | 
| 
      
 63 
     | 
    
         
            +
                          else 
         
     | 
| 
      
 64 
     | 
    
         
            +
                            raise UnsupportedContentError.new(
         
     | 
| 
      
 65 
     | 
    
         
            +
                              :open_ai, 
         
     | 
| 
      
 66 
     | 
    
         
            +
                              'requires binary content to include content type and ( packed ) bytes'  
         
     | 
| 
      
 67 
     | 
    
         
            +
                            )
         
     | 
| 
      
 68 
     | 
    
         
            +
                          end
         
     | 
| 
      
 69 
     | 
    
         
            +
                        end 
         
     | 
| 
      
 70 
     | 
    
         
            +
                      end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                      result_message[ :content ] = result_message_content
         
     | 
| 
      
 73 
     | 
    
         
            +
                      result[ :messages ] << result_message
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                    end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                    JSON.generate( result )
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end 
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  def chat_result_attributes( response )
         
     | 
| 
      
 81 
     | 
    
         
            +
                    return nil unless response.success?
         
     | 
| 
      
 82 
     | 
    
         
            +
                    
         
     | 
| 
      
 83 
     | 
    
         
            +
                    response_json = JSON.parse( response.body, symbolize_names: true ) rescue nil
         
     | 
| 
      
 84 
     | 
    
         
            +
                    return nil \
         
     | 
| 
      
 85 
     | 
    
         
            +
                      if response_json.nil? || response_json[ :choices ].nil?
         
     | 
| 
      
 86 
     | 
    
         
            +
                    
         
     | 
| 
      
 87 
     | 
    
         
            +
                    result = {}
         
     | 
| 
      
 88 
     | 
    
         
            +
                    result[ :choices ] = []
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                    ( response_json[ :choices ] || [] ).each do | json_choice |
         
     | 
| 
      
 91 
     | 
    
         
            +
                      json_message = json_choice[ :message ]
         
     | 
| 
      
 92 
     | 
    
         
            +
                      result[ :choices ].push(
         
     | 
| 
      
 93 
     | 
    
         
            +
                        { 
         
     | 
| 
      
 94 
     | 
    
         
            +
                          end_reason: translate_end_result( json_choice[ :finish_reason ] ), 
         
     | 
| 
      
 95 
     | 
    
         
            +
                          message: { 
         
     | 
| 
      
 96 
     | 
    
         
            +
                            role: json_message[ :role ],
         
     | 
| 
      
 97 
     | 
    
         
            +
                            contents: [ { type: 'text', text: json_message[ :content ] } ]
         
     | 
| 
      
 98 
     | 
    
         
            +
                          } 
         
     | 
| 
      
 99 
     | 
    
         
            +
                        }
         
     | 
| 
      
 100 
     | 
    
         
            +
                      )
         
     | 
| 
      
 101 
     | 
    
         
            +
                    end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                    metrics_json = response_json[ :usage ]
         
     | 
| 
      
 104 
     | 
    
         
            +
                    unless metrics_json.nil?
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                      metrics = {}
         
     | 
| 
      
 107 
     | 
    
         
            +
                      metrics[ :input_tokens ] = metrics_json[ :prompt_tokens ] 
         
     | 
| 
      
 108 
     | 
    
         
            +
                      metrics[ :output_tokens ] = metrics_json[ :completion_tokens ]
         
     | 
| 
      
 109 
     | 
    
         
            +
                      metrics = metrics.compact
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                      result[ :metrics ] = metrics unless metrics.empty?
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                    end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                    result
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                  def chat_result_error_attributes( response )
         
     | 
| 
      
 119 
     | 
    
         
            +
                    error_type, error_description = translate_error_response_status( response.status )
         
     | 
| 
      
 120 
     | 
    
         
            +
                    result = {
         
     | 
| 
      
 121 
     | 
    
         
            +
                      error_type: error_type.to_s,
         
     | 
| 
      
 122 
     | 
    
         
            +
                      error_description: error_description
         
     | 
| 
      
 123 
     | 
    
         
            +
                    }
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                    parsed_body = JSON.parse( response.body, symbolize_names: true ) rescue nil 
         
     | 
| 
      
 126 
     | 
    
         
            +
                    if parsed_body && parsed_body.respond_to?( :include? ) && parsed_body.include?( :error )
         
     | 
| 
      
 127 
     | 
    
         
            +
                      result = {
         
     | 
| 
      
 128 
     | 
    
         
            +
                        error_type: error_type.to_s,
         
     | 
| 
      
 129 
     | 
    
         
            +
                        error: parsed_body[ :error ][ :code ] || error_type.to_s,
         
     | 
| 
      
 130 
     | 
    
         
            +
                        error_description: parsed_body[ :error ][ :message ] || error_description
         
     | 
| 
      
 131 
     | 
    
         
            +
                      }
         
     | 
| 
      
 132 
     | 
    
         
            +
                    end
         
     | 
| 
      
 133 
     | 
    
         
            +
                    
         
     | 
| 
      
 134 
     | 
    
         
            +
                    result
         
     | 
| 
      
 135 
     | 
    
         
            +
                  end
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                  def stream_result_chunk_attributes( context, chunk )
         
     | 
| 
      
 138 
     | 
    
         
            +
                    context ||= {}
         
     | 
| 
      
 139 
     | 
    
         
            +
                    buffer = context[ :buffer ] || ''
         
     | 
| 
      
 140 
     | 
    
         
            +
                    metrics = context[ :metrics ] || {
         
     | 
| 
      
 141 
     | 
    
         
            +
                      input_tokens: 0,
         
     | 
| 
      
 142 
     | 
    
         
            +
                      output_tokens:  0
         
     | 
| 
      
 143 
     | 
    
         
            +
                    }
         
     | 
| 
      
 144 
     | 
    
         
            +
                    choices = context[ :choices ] || Array.new( 1 , { message: {} } )
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                    choices.each do | choice |
         
     | 
| 
      
 147 
     | 
    
         
            +
                      choice[ :message ][ :contents ] = choice[ :message ][ :contents ]&.map do | content |
         
     | 
| 
      
 148 
     | 
    
         
            +
                        case content[ :type ] 
         
     | 
| 
      
 149 
     | 
    
         
            +
                          when :text 
         
     | 
| 
      
 150 
     | 
    
         
            +
                            content[ :text ] = ''
         
     | 
| 
      
 151 
     | 
    
         
            +
                          when :tool_call 
         
     | 
| 
      
 152 
     | 
    
         
            +
                            content[ :tool_parameters ] = ''
         
     | 
| 
      
 153 
     | 
    
         
            +
                          else 
         
     | 
| 
      
 154 
     | 
    
         
            +
                            content.clear 
         
     | 
| 
      
 155 
     | 
    
         
            +
                        end
         
     | 
| 
      
 156 
     | 
    
         
            +
                        content
         
     | 
| 
      
 157 
     | 
    
         
            +
                      end
         
     | 
| 
      
 158 
     | 
    
         
            +
                    end
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                    buffer += chunk
         
     | 
| 
      
 161 
     | 
    
         
            +
                    while ( eol_index = buffer.index( "\n" ) )
         
     | 
| 
      
 162 
     | 
    
         
            +
                      
         
     | 
| 
      
 163 
     | 
    
         
            +
                      line = buffer.slice!( 0..eol_index )        
         
     | 
| 
      
 164 
     | 
    
         
            +
                      line = line.strip 
         
     | 
| 
      
 165 
     | 
    
         
            +
                      next if line.empty? || !line.start_with?( 'data:' )
         
     | 
| 
      
 166 
     | 
    
         
            +
                      line = line[ 6..-1 ]
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                      next if line.end_with?( '[DONE]' )
         
     | 
| 
      
 169 
     | 
    
         
            +
                      data = JSON.parse( line )
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                      if data.is_a?( Hash )
         
     | 
| 
      
 172 
     | 
    
         
            +
                        
         
     | 
| 
      
 173 
     | 
    
         
            +
                        data[ 'choices' ]&.each do | data_choice |
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                          data_choice_index = data_choice[ 'index' ]
         
     | 
| 
      
 176 
     | 
    
         
            +
                          data_choice_delta = data_choice[ 'delta' ]
         
     | 
| 
      
 177 
     | 
    
         
            +
                          data_choice_finish_reason = data_choice[ 'finish_reason' ]
         
     | 
| 
      
 178 
     | 
    
         
            +
                          
         
     | 
| 
      
 179 
     | 
    
         
            +
                          choices.fill( { message: {} }, choices.size, data_choice_index + 1 ) \
         
     | 
| 
      
 180 
     | 
    
         
            +
                            if choices.size <= data_choice_index 
         
     | 
| 
      
 181 
     | 
    
         
            +
                          contents = choices[ data_choice_index ][ :message ][ :contents ] || []
         
     | 
| 
      
 182 
     | 
    
         
            +
                          last_content = contents&.last 
         
     | 
| 
      
 183 
     | 
    
         
            +
                          
         
     | 
| 
      
 184 
     | 
    
         
            +
                          if data_choice_delta.include?( 'content' ) 
         
     | 
| 
      
 185 
     | 
    
         
            +
                            data_choice_content = data_choice_delta[ 'content' ] || ''
         
     | 
| 
      
 186 
     | 
    
         
            +
                            if last_content.nil? || last_content[ :type ] == :tool_call
         
     | 
| 
      
 187 
     | 
    
         
            +
                              contents.push( { type: :text, text: data_choice_content } )
         
     | 
| 
      
 188 
     | 
    
         
            +
                            elsif last_content[ :type ].nil?
         
     | 
| 
      
 189 
     | 
    
         
            +
                              last_content[ :type ] = :text 
         
     | 
| 
      
 190 
     | 
    
         
            +
                              last_content[ :text ] = data_choice_content
         
     | 
| 
      
 191 
     | 
    
         
            +
                            elsif last_content[ :type ] == :text 
         
     | 
| 
      
 192 
     | 
    
         
            +
                              last_content[ :text ] = ( last_content[ :text ] || '' ) + data_choice_content
         
     | 
| 
      
 193 
     | 
    
         
            +
                            end
         
     | 
| 
      
 194 
     | 
    
         
            +
                          elsif data_choice_delta.include?( 'function_call' )
         
     | 
| 
      
 195 
     | 
    
         
            +
                            data_choice_tool_call = data_choice_delta[ 'function_call' ] 
         
     | 
| 
      
 196 
     | 
    
         
            +
                            data_choice_tool_name = data_choice_tool_call[ 'name' ]
         
     | 
| 
      
 197 
     | 
    
         
            +
                            data_choice_tool_parameters = data_choice_tool_call[ 'arguments' ]
         
     | 
| 
      
 198 
     | 
    
         
            +
                            if last_content.nil? || last_content[ :type ] == :text
         
     | 
| 
      
 199 
     | 
    
         
            +
                              contents.push( { 
         
     | 
| 
      
 200 
     | 
    
         
            +
                                type: :tool_call, 
         
     | 
| 
      
 201 
     | 
    
         
            +
                                tool_name: data_choice_tool_name,
         
     | 
| 
      
 202 
     | 
    
         
            +
                                tool_parameters: data_choice_tool_parameters
         
     | 
| 
      
 203 
     | 
    
         
            +
                              } )
         
     | 
| 
      
 204 
     | 
    
         
            +
                            elsif last_content[ :type ].nil?
         
     | 
| 
      
 205 
     | 
    
         
            +
                              last_content[ :type ] = :tool_call 
         
     | 
| 
      
 206 
     | 
    
         
            +
                              last_content[ :tool_name ] = data_choice_tool_name if data_choice_tool_name.present?
         
     | 
| 
      
 207 
     | 
    
         
            +
                              last_content[ :tool_parameters ] = tool_parameters
         
     | 
| 
      
 208 
     | 
    
         
            +
                            elsif last_content[ :type ] == :tool_call 
         
     | 
| 
      
 209 
     | 
    
         
            +
                              last_content[ :tool_parameters ] = 
         
     | 
| 
      
 210 
     | 
    
         
            +
                                ( last_content[ :tool_parameters ] || '' ) + data_choice_tool_parameters
         
     | 
| 
      
 211 
     | 
    
         
            +
                            end
         
     | 
| 
      
 212 
     | 
    
         
            +
                          end
         
     | 
| 
      
 213 
     | 
    
         
            +
                          choices[ data_choice_index ][ :message ][ :contents ] = contents
         
     | 
| 
      
 214 
     | 
    
         
            +
                          choices[ data_choice_index ][ :end_reason ] = 
         
     | 
| 
      
 215 
     | 
    
         
            +
                            translate_end_result( data_choice_finish_reason )
         
     | 
| 
      
 216 
     | 
    
         
            +
                        end
         
     | 
| 
      
 217 
     | 
    
         
            +
              
         
     | 
| 
      
 218 
     | 
    
         
            +
                        if usage = data[ 'usage' ]
         
     | 
| 
      
 219 
     | 
    
         
            +
                          metrics[ :input_tokens ] += usage[ 'prompt_tokens' ]
         
     | 
| 
      
 220 
     | 
    
         
            +
                          metrics[ :output_tokens ] += usage[ 'completion_tokens' ]
         
     | 
| 
      
 221 
     | 
    
         
            +
                        end 
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                      end
         
     | 
| 
      
 224 
     | 
    
         
            +
             
     | 
| 
      
 225 
     | 
    
         
            +
                    end
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
                    context[ :buffer ] = buffer 
         
     | 
| 
      
 228 
     | 
    
         
            +
                    context[ :metrics ] = metrics
         
     | 
| 
      
 229 
     | 
    
         
            +
                    context[ :choices ] = choices
         
     | 
| 
      
 230 
     | 
    
         
            +
                    
         
     | 
| 
      
 231 
     | 
    
         
            +
                    [ context, choices.empty? ? nil : { choices: choices.dup } ]
         
     | 
| 
      
 232 
     | 
    
         
            +
                  end
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
                  def stream_result_attributes( context )
         
     | 
| 
      
 235 
     | 
    
         
            +
                    choices = context[ :choices ]
         
     | 
| 
      
 236 
     | 
    
         
            +
                    metrics = context[ :metrics ]
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                    choices = choices.map do | choice |
         
     | 
| 
      
 239 
     | 
    
         
            +
                      { end_reason: choice[ :end_reason ] }
         
     | 
| 
      
 240 
     | 
    
         
            +
                    end
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
                    { choices: choices, metrics: context[ :metrics ] }
         
     | 
| 
      
 243 
     | 
    
         
            +
                  end
         
     | 
| 
      
 244 
     | 
    
         
            +
             
     | 
| 
      
 245 
     | 
    
         
            +
                  alias_method :stream_result_error_attributes, :chat_result_error_attributes
         
     | 
| 
      
 246 
     | 
    
         
            +
             
     | 
| 
      
 247 
     | 
    
         
            +
                  private; def translate_system_message( system_message )
         
     | 
| 
      
 248 
     | 
    
         
            +
             
     | 
| 
      
 249 
     | 
    
         
            +
                    return nil if system_message.nil?
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
                    result = ''
         
     | 
| 
      
 252 
     | 
    
         
            +
                    system_message[ :contents ].each do | content |
         
     | 
| 
      
 253 
     | 
    
         
            +
                      result += content[ :text ] if content[ :type ] == :text 
         
     | 
| 
      
 254 
     | 
    
         
            +
                    end
         
     | 
| 
      
 255 
     | 
    
         
            +
             
     | 
| 
      
 256 
     | 
    
         
            +
                    result.empty? ? nil : result 
         
     | 
| 
      
 257 
     | 
    
         
            +
             
     | 
| 
      
 258 
     | 
    
         
            +
                  end 
         
     | 
| 
      
 259 
     | 
    
         
            +
             
     | 
| 
      
 260 
     | 
    
         
            +
                  private; def translate_end_result( end_result )
         
     | 
| 
      
 261 
     | 
    
         
            +
                    case end_result
         
     | 
| 
      
 262 
     | 
    
         
            +
                      when 'stop'
         
     | 
| 
      
 263 
     | 
    
         
            +
                        :ended
         
     | 
| 
      
 264 
     | 
    
         
            +
                      when 'length'
         
     | 
| 
      
 265 
     | 
    
         
            +
                        :token_limit_exceeded
         
     | 
| 
      
 266 
     | 
    
         
            +
                      when 'function_call'
         
     | 
| 
      
 267 
     | 
    
         
            +
                        :tool_called
         
     | 
| 
      
 268 
     | 
    
         
            +
                      when 'content_filter'
         
     | 
| 
      
 269 
     | 
    
         
            +
                        :filtered
         
     | 
| 
      
 270 
     | 
    
         
            +
                      else
         
     | 
| 
      
 271 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 272 
     | 
    
         
            +
                    end
         
     | 
| 
      
 273 
     | 
    
         
            +
                  end
         
     | 
| 
      
 274 
     | 
    
         
            +
             
     | 
| 
      
 275 
     | 
    
         
            +
                  def translate_error_response_status( status )
         
     | 
| 
      
 276 
     | 
    
         
            +
                    case status
         
     | 
| 
      
 277 
     | 
    
         
            +
                      when 400
         
     | 
| 
      
 278 
     | 
    
         
            +
                        [ :invalid_request_error, 
         
     | 
| 
      
 279 
     | 
    
         
            +
                          "There was an issue with the format or content of your request." ]
         
     | 
| 
      
 280 
     | 
    
         
            +
                      when 401
         
     | 
| 
      
 281 
     | 
    
         
            +
                        [ :authentication_error, 
         
     | 
| 
      
 282 
     | 
    
         
            +
                          "There's an issue with your API key." ]
         
     | 
| 
      
 283 
     | 
    
         
            +
                      when 403
         
     | 
| 
      
 284 
     | 
    
         
            +
                        [ :permission_error, 
         
     | 
| 
      
 285 
     | 
    
         
            +
                          "Your API key does not have permission to use the specified resource." ]
         
     | 
| 
      
 286 
     | 
    
         
            +
                      when 404
         
     | 
| 
      
 287 
     | 
    
         
            +
                        [ :not_found_error, 
         
     | 
| 
      
 288 
     | 
    
         
            +
                          "The requested resource was not found." ]
         
     | 
| 
      
 289 
     | 
    
         
            +
                      when 413
         
     | 
| 
      
 290 
     | 
    
         
            +
                        [ :request_too_large, 
         
     | 
| 
      
 291 
     | 
    
         
            +
                          "Request exceeds the maximum allowed number of bytes." ]
         
     | 
| 
      
 292 
     | 
    
         
            +
                      when 422
         
     | 
| 
      
 293 
     | 
    
         
            +
                        [ :invalid_request_error, 
         
     | 
| 
      
 294 
     | 
    
         
            +
                          "There was an issue with the format or content of your request." ]
         
     | 
| 
      
 295 
     | 
    
         
            +
                      when 429
         
     | 
| 
      
 296 
     | 
    
         
            +
                        [ :rate_limit_error, 
         
     | 
| 
      
 297 
     | 
    
         
            +
                          "Your account has hit a rate limit." ]
         
     | 
| 
      
 298 
     | 
    
         
            +
                      when 500, 502, 503
         
     | 
| 
      
 299 
     | 
    
         
            +
                        [ :api_error, 
         
     | 
| 
      
 300 
     | 
    
         
            +
                          "An unexpected error has occurred internal to the providers systems." ]
         
     | 
| 
      
 301 
     | 
    
         
            +
                      when 529
         
     | 
| 
      
 302 
     | 
    
         
            +
                        [ :overloaded_error, 
         
     | 
| 
      
 303 
     | 
    
         
            +
                          "The providers server is temporarily overloaded." ]
         
     | 
| 
      
 304 
     | 
    
         
            +
                      else
         
     | 
| 
      
 305 
     | 
    
         
            +
                        [ :unknown_error, "
         
     | 
| 
      
 306 
     | 
    
         
            +
                          An unknown error occurred." ]
         
     | 
| 
      
 307 
     | 
    
         
            +
                      end
         
     | 
| 
      
 308 
     | 
    
         
            +
                  end
         
     | 
| 
      
 309 
     | 
    
         
            +
                
         
     | 
| 
      
 310 
     | 
    
         
            +
                end
         
     | 
| 
      
 311 
     | 
    
         
            +
             
     | 
| 
      
 312 
     | 
    
         
            +
              end
         
     | 
| 
      
 313 
     | 
    
         
            +
             
     | 
| 
      
 314 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,64 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'legacy/adapter'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Intelligence
         
     | 
| 
      
 4 
     | 
    
         
            +
              module SambaNova
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                class Adapter < Legacy::Adapter
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  chat_request_uri "https://api.sambanova.ai/v1/chat/completions"
         
     | 
| 
      
 9 
     | 
    
         
            +
                  
         
     | 
| 
      
 10 
     | 
    
         
            +
                  configuration do 
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    # normalized properties for all endpoints
         
     | 
| 
      
 13 
     | 
    
         
            +
                    parameter :key, String, required: true
         
     | 
| 
      
 14 
     | 
    
         
            +
                    
         
     | 
| 
      
 15 
     | 
    
         
            +
                    # properties for generative text endpoints
         
     | 
| 
      
 16 
     | 
    
         
            +
                    group :chat_options do 
         
     | 
| 
      
 17 
     | 
    
         
            +
                    
         
     | 
| 
      
 18 
     | 
    
         
            +
                      # normalized properties for samba nova generative text endpoint
         
     | 
| 
      
 19 
     | 
    
         
            +
                      parameter :model, String
         
     | 
| 
      
 20 
     | 
    
         
            +
                      parameter :max_tokens, Integer
         
     | 
| 
      
 21 
     | 
    
         
            +
                      parameter :temperature, Float
         
     | 
| 
      
 22 
     | 
    
         
            +
                      parameter :top_p, Float
         
     | 
| 
      
 23 
     | 
    
         
            +
                      parameter :top_k, Float
         
     | 
| 
      
 24 
     | 
    
         
            +
                      parameter :stop, String, array: true
         
     | 
| 
      
 25 
     | 
    
         
            +
                      parameter :stream, [ TrueClass, FalseClass ]
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                      # samba nova properties for samba nova generative text endpoint
         
     | 
| 
      
 28 
     | 
    
         
            +
                      parameter :repetition_penalty, Float
         
     | 
| 
      
 29 
     | 
    
         
            +
                      group :stream_options do
         
     | 
| 
      
 30 
     | 
    
         
            +
                        parameter :include_usage, [ TrueClass, FalseClass ]
         
     | 
| 
      
 31 
     | 
    
         
            +
                      end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def chat_result_error_attributes( response )
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    error_type, error_description = translate_error_response_status( response.status )
         
     | 
| 
      
 40 
     | 
    
         
            +
                    result = {
         
     | 
| 
      
 41 
     | 
    
         
            +
                      error_type: error_type.to_s,
         
     | 
| 
      
 42 
     | 
    
         
            +
                      error_description: error_description
         
     | 
| 
      
 43 
     | 
    
         
            +
                    }
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    parsed_body = JSON.parse( response.body, symbolize_names: true ) rescue nil 
         
     | 
| 
      
 46 
     | 
    
         
            +
                    if parsed_body && parsed_body.respond_to?( :include? ) && parsed_body.include?( :error )
         
     | 
| 
      
 47 
     | 
    
         
            +
                      result = {
         
     | 
| 
      
 48 
     | 
    
         
            +
                        error_type: error_type.to_s,
         
     | 
| 
      
 49 
     | 
    
         
            +
                        error: parsed_body[ :error ][ :code ] || error_type.to_s,
         
     | 
| 
      
 50 
     | 
    
         
            +
                        error_description: parsed_body[ :error ][ :message ] || error_description
         
     | 
| 
      
 51 
     | 
    
         
            +
                      }
         
     | 
| 
      
 52 
     | 
    
         
            +
                    elsif response.headers[ 'content-type' ].start_with?( 'text/plain' ) &&
         
     | 
| 
      
 53 
     | 
    
         
            +
                          response.body && response.body.length > 0
         
     | 
| 
      
 54 
     | 
    
         
            +
                      result[ :error_description ] = response.body
         
     | 
| 
      
 55 
     | 
    
         
            +
                    end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    result
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'legacy/adapter'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Intelligence
         
     | 
| 
      
 4 
     | 
    
         
            +
              module TogetherAi
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                class Adapter < Legacy::Adapter
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  chat_request_uri "https://api.together.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 :top_k, Integer
         
     | 
| 
      
 17 
     | 
    
         
            +
                      parameter :n, Integer
         
     | 
| 
      
 18 
     | 
    
         
            +
                      parameter :max_tokens, Float
         
     | 
| 
      
 19 
     | 
    
         
            +
                      parameter :stop, String, array: true
         
     | 
| 
      
 20 
     | 
    
         
            +
                      parameter :stream, [ TrueClass, FalseClass ]
         
     | 
| 
      
 21 
     | 
    
         
            +
                      parameter :frequency_penalty, Float
         
     | 
| 
      
 22 
     | 
    
         
            +
                      parameter :presence_penalty, Float
         
     | 
| 
      
 23 
     | 
    
         
            +
                      parameter :repetition_penalty, Float
         
     | 
| 
      
 24 
     | 
    
         
            +
                      parameter :user, String
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def translate_end_result( end_result )
         
     | 
| 
      
 29 
     | 
    
         
            +
                    case end_result
         
     | 
| 
      
 30 
     | 
    
         
            +
                      when 'eos'
         
     | 
| 
      
 31 
     | 
    
         
            +
                        :ended
         
     | 
| 
      
 32 
     | 
    
         
            +
                      when 'length'
         
     | 
| 
      
 33 
     | 
    
         
            +
                        :token_limit_exceeded
         
     | 
| 
      
 34 
     | 
    
         
            +
                      when 'stop'
         
     | 
| 
      
 35 
     | 
    
         
            +
                        :end_sequence_encountered
         
     | 
| 
      
 36 
     | 
    
         
            +
                      when 'function_call'
         
     | 
| 
      
 37 
     | 
    
         
            +
                        :tool_called
         
     | 
| 
      
 38 
     | 
    
         
            +
                      else
         
     | 
| 
      
 39 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Intelligence
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              #
         
     | 
| 
      
 4 
     | 
    
         
            +
              # class. ChatMetrics
         
     | 
| 
      
 5 
     | 
    
         
            +
              #
         
     | 
| 
      
 6 
     | 
    
         
            +
              # The ChatMetrics class encapsulates metrics information. These metrics include the number of
         
     | 
| 
      
 7 
     | 
    
         
            +
              # input tokens consumed, the number of output tokens generated, the total number of tokens,
         
     | 
| 
      
 8 
     | 
    
         
            +
              # and the duration of the request in milliseconds.
         
     | 
| 
      
 9 
     | 
    
         
            +
              #
         
     | 
| 
      
 10 
     | 
    
         
            +
              class ChatMetrics 
         
     | 
| 
      
 11 
     | 
    
         
            +
              # ---------------
         
     | 
| 
      
 12 
     | 
    
         
            +
                
         
     | 
| 
      
 13 
     | 
    
         
            +
                attr_reader   :duration
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                attr_reader   :input_tokens
         
     | 
| 
      
 16 
     | 
    
         
            +
                attr_reader   :output_tokens
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def initialize( attributes )
         
     | 
| 
      
 19 
     | 
    
         
            +
                  attributes.each do | key, value |
         
     | 
| 
      
 20 
     | 
    
         
            +
                    instance_variable_set( "@#{key}", value ) if self.respond_to?( "#{key}" )
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def total_tokens
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @total_tokens = @input_tokens + @output_tokens \
         
     | 
| 
      
 26 
     | 
    
         
            +
                    if @total_tokens.nil? && @input_tokens && @output_tokens 
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @total_tokens
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,117 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Intelligence
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              #
         
     | 
| 
      
 4 
     | 
    
         
            +
              # module. ChatRequestMethods
         
     | 
| 
      
 5 
     | 
    
         
            +
              #
         
     | 
| 
      
 6 
     | 
    
         
            +
              # The ChatRequestMethods module extends a Faraday request, adding the +receive_result+ method. 
         
     | 
| 
      
 7 
     | 
    
         
            +
              #
         
     | 
| 
      
 8 
     | 
    
         
            +
              module ChatRequestMethods
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def receive_result( &block )
         
     | 
| 
      
 11 
     | 
    
         
            +
                   @_intelligence_result_callback = block
         
     | 
| 
      
 12 
     | 
    
         
            +
                end 
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              #
         
     | 
| 
      
 17 
     | 
    
         
            +
              # module. ChatResponseMethods
         
     | 
| 
      
 18 
     | 
    
         
            +
              #
         
     | 
| 
      
 19 
     | 
    
         
            +
              # The ChatResponseMethods module extends a Farada reponse, adding the +result+  method. 
         
     | 
| 
      
 20 
     | 
    
         
            +
              #
         
     | 
| 
      
 21 
     | 
    
         
            +
              module ChatResponseMethods
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def result
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @_intelligence_result
         
     | 
| 
      
 25 
     | 
    
         
            +
                end 
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              #
         
     | 
| 
      
 30 
     | 
    
         
            +
              # class. ChatRequest
         
     | 
| 
      
 31 
     | 
    
         
            +
              #
         
     | 
| 
      
 32 
     | 
    
         
            +
              class ChatRequest 
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                DEFAULT_CONNECTION = Faraday.new { | builder | builder.adapter Faraday.default_adapter }
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def initialize( connection: nil, adapter: , **options )
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @connection = connection || DEFAULT_CONNECTION
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @adapter = adapter
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @options = options || {}
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  raise ArgumentError.new( 'An adapter must be configured before a request is constructed.' ) \
         
     | 
| 
      
 42 
     | 
    
         
            +
                    if @adapter.nil?
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def chat( conversation, options = {} )
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  options = @options.merge( options )
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  uri = @adapter.chat_request_uri( options )
         
     | 
| 
      
 50 
     | 
    
         
            +
                  headers = @adapter.chat_request_headers( @options.merge( options ) )
         
     | 
| 
      
 51 
     | 
    
         
            +
                  payload = @adapter.chat_request_body( 
         
     | 
| 
      
 52 
     | 
    
         
            +
                    conversation.to_h, 
         
     | 
| 
      
 53 
     | 
    
         
            +
                    options 
         
     | 
| 
      
 54 
     | 
    
         
            +
                  )
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  result_callback = nil 
         
     | 
| 
      
 57 
     | 
    
         
            +
                  response = @connection.post( uri ) do | request |
         
     | 
| 
      
 58 
     | 
    
         
            +
                    headers.each { | key, value | request.headers[ key ] = value }
         
     | 
| 
      
 59 
     | 
    
         
            +
                    request.body = payload          
         
     | 
| 
      
 60 
     | 
    
         
            +
                    yield request.extend( ChatRequestMethods ) if block_given?
         
     | 
| 
      
 61 
     | 
    
         
            +
                    result_callback = request.instance_variable_get( "@_intelligence_result_callback" )
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  result = nil 
         
     | 
| 
      
 65 
     | 
    
         
            +
                  if response.success?  
         
     | 
| 
      
 66 
     | 
    
         
            +
                    chat_result_attributes = @adapter.chat_result_attributes( response )
         
     | 
| 
      
 67 
     | 
    
         
            +
                    result = ChatResult.new( chat_result_attributes )
         
     | 
| 
      
 68 
     | 
    
         
            +
                  else 
         
     | 
| 
      
 69 
     | 
    
         
            +
                    error_result_attributes = @adapter.chat_result_error_attributes( response )
         
     | 
| 
      
 70 
     | 
    
         
            +
                    result = ChatErrorResult.new( error_result_attributes )
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
                  
         
     | 
| 
      
 73 
     | 
    
         
            +
                  response.instance_variable_set( "@_intelligence_result", result )
         
     | 
| 
      
 74 
     | 
    
         
            +
                  response.extend( ChatResponseMethods ) 
         
     | 
| 
      
 75 
     | 
    
         
            +
                
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                def stream( conversation, options = {} )
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  options = @options.merge( options )
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                  uri = @adapter.chat_request_uri( options )
         
     | 
| 
      
 83 
     | 
    
         
            +
                  headers = @adapter.chat_request_headers( @options.merge( options ) )
         
     | 
| 
      
 84 
     | 
    
         
            +
                  payload = @adapter.chat_request_body( conversation.to_h, options )
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                  context = nil
         
     | 
| 
      
 87 
     | 
    
         
            +
                  response = @connection.post( uri ) do | request |
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                    headers.each { | key, value | request.headers[ key ] = value }
         
     | 
| 
      
 90 
     | 
    
         
            +
                    request.body = payload
         
     | 
| 
      
 91 
     | 
    
         
            +
                    yield request.extend( ChatRequestMethods ) 
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                    result_callback = request.instance_variable_get( "@_intelligence_result_callback" )
         
     | 
| 
      
 94 
     | 
    
         
            +
                    request.options.on_data = Proc.new do | chunk, received_bytes |
         
     | 
| 
      
 95 
     | 
    
         
            +
                      context, attributes = @adapter.stream_result_chunk_attributes( context, chunk )
         
     | 
| 
      
 96 
     | 
    
         
            +
                      result_callback.call( ChatResult.new( attributes ) ) unless attributes.nil?
         
     | 
| 
      
 97 
     | 
    
         
            +
                    end 
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  result = nil 
         
     | 
| 
      
 102 
     | 
    
         
            +
                  if response.success?  
         
     | 
| 
      
 103 
     | 
    
         
            +
                    stream_result_attributes = @adapter.stream_result_attributes( context )
         
     | 
| 
      
 104 
     | 
    
         
            +
                    result = ChatResult.new( stream_result_attributes )
         
     | 
| 
      
 105 
     | 
    
         
            +
                  else 
         
     | 
| 
      
 106 
     | 
    
         
            +
                    error_result_attributes = @adapter.stream_result_error_attributes( response )
         
     | 
| 
      
 107 
     | 
    
         
            +
                    result = ChatErrorResult.new( error_result_attributes )
         
     | 
| 
      
 108 
     | 
    
         
            +
                  end
         
     | 
| 
      
 109 
     | 
    
         
            +
                  
         
     | 
| 
      
 110 
     | 
    
         
            +
                  response.instance_variable_set( "@_intelligence_result", result )
         
     | 
| 
      
 111 
     | 
    
         
            +
                  response.extend( ChatResponseMethods )
         
     | 
| 
      
 112 
     | 
    
         
            +
                
         
     | 
| 
      
 113 
     | 
    
         
            +
                end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
              end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Intelligence
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              #
         
     | 
| 
      
 4 
     | 
    
         
            +
              # class. ChatResult
         
     | 
| 
      
 5 
     | 
    
         
            +
              #
         
     | 
| 
      
 6 
     | 
    
         
            +
              # The ChatResult class encapsulates a successful result to a chat or stream request. A result 
         
     | 
| 
      
 7 
     | 
    
         
            +
              # includes an array of choices ( it is an array even if there is a single choice ) and the 
         
     | 
| 
      
 8 
     | 
    
         
            +
              # metrics associated with the generation of all result choices.
         
     | 
| 
      
 9 
     | 
    
         
            +
              #
         
     | 
| 
      
 10 
     | 
    
         
            +
              class ChatResult
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                attr_reader :choices
         
     | 
| 
      
 13 
     | 
    
         
            +
                attr_reader :metrics
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def initialize( chat_attributes )
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  @choices = []
         
     | 
| 
      
 18 
     | 
    
         
            +
                  chat_attributes[ :choices ]&.each do | json_choice |
         
     | 
| 
      
 19 
     | 
    
         
            +
                    @choices.push( ChatResultChoice.new( json_choice ) )
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @metrics = ChatMetrics.new( chat_attributes[ :metrics ] ) \
         
     | 
| 
      
 22 
     | 
    
         
            +
                    if chat_attributes.key?( :metrics )
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def message 
         
     | 
| 
      
 26 
     | 
    
         
            +
                  return nil if @choices.empty?
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @choices.first.message
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Intelligence
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              class ChatResultChoice 
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :message
         
     | 
| 
      
 6 
     | 
    
         
            +
                attr_reader :end_reason
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :end_sequence
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize( chat_choice_attributes )
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @end_reason = chat_choice_attributes[ :end_reason ]
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @end_sequence = chat_choice_attributes[ :end_sequence ]
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @message = build_message( chat_choice_attributes[ :message ] ) \
         
     | 
| 
      
 13 
     | 
    
         
            +
                    if chat_choice_attributes[ :message ]
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                private; def build_message( json_message )
         
     | 
| 
      
 17 
     | 
    
         
            +
                  message = Message.new( json_message[ :role ]&.to_sym || :assistant )
         
     | 
| 
      
 18 
     | 
    
         
            +
                  json_message[ :contents ]&.each do | json_content |
         
     | 
| 
      
 19 
     | 
    
         
            +
                    message << MessageContent.build( json_content[ :type ], json_content )
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  message 
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,48 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Intelligence
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              #
         
     | 
| 
      
 4 
     | 
    
         
            +
              # class. Conversation
         
     | 
| 
      
 5 
     | 
    
         
            +
              #
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Conversation 
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                attr_reader   :system_message
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_reader   :messages
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_reader   :tools
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def initialize( attributes = {} )
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @system_message = attributes[ :system_message ]&.dup
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @messages = attributes[ :messages ]&.dup || []
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @tools = attributes[ :tools ]&.dup || [] 
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def has_system_message?
         
     | 
| 
      
 19 
     | 
    
         
            +
                  ( @system_message || false ) && !@system_message.empty?
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def has_messages?
         
     | 
| 
      
 23 
     | 
    
         
            +
                  !@messages.empty?
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def has_tools?
         
     | 
| 
      
 27 
     | 
    
         
            +
                  !@tools.empty?
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def system_message=( message )
         
     | 
| 
      
 31 
     | 
    
         
            +
                  raise ArgumentError, "The system message must be a Intelligence::Message." \
         
     | 
| 
      
 32 
     | 
    
         
            +
                    unless message.is_a?( Intelligence::Message )
         
     | 
| 
      
 33 
     | 
    
         
            +
                  raise ArgumentError, "The system message MUST have a role of 'system'." \
         
     | 
| 
      
 34 
     | 
    
         
            +
                    unless message.role == :system
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @system_message = message
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def to_h
         
     | 
| 
      
 39 
     | 
    
         
            +
                  result = {}
         
     | 
| 
      
 40 
     | 
    
         
            +
                  result[ :system_message ] = @system_message.to_h if @system_message
         
     | 
| 
      
 41 
     | 
    
         
            +
                  result[ :messages ] = @messages.map { | m | m.to_h } 
         
     | 
| 
      
 42 
     | 
    
         
            +
                  result[ :tools ] = @tools.map { | t | t.to_h } 
         
     | 
| 
      
 43 
     | 
    
         
            +
                  result
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            end
         
     |