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
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 694776aeafc7552879d8b9d5358907e62c90a6fc5a1219081ee1d1a4cb5ddeef
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 380f5cd13200750f65938fd4e92c21218af8c2b57af0614bfe16f714ba296e68
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: f2ca65b2a4e3a202bc1b331f7965da9e76a8ccd2ec83f7c5c273c94137fb1e0131226ecf3bf2aed6d50e262933d26c0024b3a5052edda28c39768c766b508e29
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: c6694ffa62ddd9eb766f42fb9cc073195a01e11e0d34cd346588b3923266c14f794d1711e1766888369874e27ce4ac696de0513055af8e27149a778611ce0cb2
         
     | 
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            MIT License
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Copyright (c) 2024 Endless International
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy
         
     | 
| 
      
 6 
     | 
    
         
            +
            of this software and associated documentation files (the "Software"), to deal
         
     | 
| 
      
 7 
     | 
    
         
            +
            in the Software without restriction, including without limitation the rights
         
     | 
| 
      
 8 
     | 
    
         
            +
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         
     | 
| 
      
 9 
     | 
    
         
            +
            copies of the Software, and to permit persons to whom the Software is
         
     | 
| 
      
 10 
     | 
    
         
            +
            furnished to do so, subject to the following conditions:
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in all
         
     | 
| 
      
 13 
     | 
    
         
            +
            copies or substantial portions of the Software.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 16 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 17 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 18 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 19 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 20 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         
     | 
| 
      
 21 
     | 
    
         
            +
            SOFTWARE.
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'lib/intelligence/version'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Gem::Specification.new do | spec |
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              spec.name          = 'intelligence'
         
     | 
| 
      
 6 
     | 
    
         
            +
              spec.version       = Intelligence::VERSION
         
     | 
| 
      
 7 
     | 
    
         
            +
              spec.authors       = [ 'Kristoph Cichocki-Romanov' ]
         
     | 
| 
      
 8 
     | 
    
         
            +
              spec.email         = [ 'rubygems.org@kristoph.net' ]
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              spec.summary       = <<~TEXT.gsub( "\n", " " ).strip
         
     | 
| 
      
 11 
     | 
    
         
            +
                A Ruby gem for seamlessly and uniformly interacting with large languge and vision model (LLM) 
         
     | 
| 
      
 12 
     | 
    
         
            +
                API's served by numerous services, including those of OpenAI, Anthropic, Google and others. 
         
     | 
| 
      
 13 
     | 
    
         
            +
              TEXT
         
     | 
| 
      
 14 
     | 
    
         
            +
              spec.description   = <<~TEXT.gsub( "\n", " " ).strip
         
     | 
| 
      
 15 
     | 
    
         
            +
                Intelligence is a lightweight yet powerful Ruby gem that allows you to seamlessly and uniformly 
         
     | 
| 
      
 16 
     | 
    
         
            +
                interact with large language and vision models (LLM) API's of numerous vendors, including 
         
     | 
| 
      
 17 
     | 
    
         
            +
                OpenAI, Anthropic, Google, Cerebras, Groq, Hyperbolic, Samba Nova and Together AI. It can be 
         
     | 
| 
      
 18 
     | 
    
         
            +
                trivially expanded to other OpenAI conformant API providers as well as self hosted models.
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                Intelligence supports text models in streaming and non-streaming mode, vision models, and 
         
     | 
| 
      
 21 
     | 
    
         
            +
                tool use.  
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                Intelligence has minimal dependencies and does not require the vendors ( often bloated )
         
     | 
| 
      
 24 
     | 
    
         
            +
                SDK's. 
         
     | 
| 
      
 25 
     | 
    
         
            +
              TEXT
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              spec.license       = 'MIT'
         
     | 
| 
      
 28 
     | 
    
         
            +
              spec.homepage      = 'https://github.com/EndlessInternational/intelligence'
         
     | 
| 
      
 29 
     | 
    
         
            +
              spec.metadata = {
         
     | 
| 
      
 30 
     | 
    
         
            +
                'source_code_uri'   => 'https://github.com/EndlessInternational/intelligence',
         
     | 
| 
      
 31 
     | 
    
         
            +
                'bug_tracker_uri'   => 'https://github.com/EndlessInternational/intelligence/issues',
         
     | 
| 
      
 32 
     | 
    
         
            +
            #    'documentation_uri' => 'https://github.com/EndlessInternational/intelligence/wiki'
         
     | 
| 
      
 33 
     | 
    
         
            +
              }
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              spec.required_ruby_version = '>= 3.0'
         
     | 
| 
      
 36 
     | 
    
         
            +
              spec.files         = Dir[ "lib/**/*.rb", "LICENSE", "README.md", "intelligence.gemspec" ]
         
     | 
| 
      
 37 
     | 
    
         
            +
              spec.require_paths = [ "lib" ]
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              spec.add_runtime_dependency 'faraday', '~> 2.7'
         
     | 
| 
      
 40 
     | 
    
         
            +
              spec.add_runtime_dependency 'adaptiveconfiguration', '~> 1.0.0.beta01'
         
     | 
| 
      
 41 
     | 
    
         
            +
              spec.add_runtime_dependency 'mime-types', '~> 3.6'
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              spec.add_development_dependency 'rspec', '~> 3.4'
         
     | 
| 
      
 44 
     | 
    
         
            +
              spec.add_development_dependency 'debug', '~> 1.9'
         
     | 
| 
      
 45 
     | 
    
         
            +
              spec.add_development_dependency 'vcr', '~> 6.3'
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Intelligence
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Adapter
         
     | 
| 
      
 3 
     | 
    
         
            +
                module ConstructionMethods
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  def []( adapter_type )
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    raise ArgumentError.new( "An adapter type is required but nil was given." ) \
         
     | 
| 
      
 8 
     | 
    
         
            +
                      if adapter_type.nil?
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    class_name = adapter_type.to_s.split( '_' ).map( &:capitalize ).join
         
     | 
| 
      
 11 
     | 
    
         
            +
                    class_name += "::Adapter"
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    adapter_class = Intelligence.const_get( class_name ) rescue nil
         
     | 
| 
      
 14 
     | 
    
         
            +
                    if adapter_class.nil?
         
     | 
| 
      
 15 
     | 
    
         
            +
                      adapter_file = File.expand_path( "../../adapters/#{adapter_type}", __FILE__ )
         
     | 
| 
      
 16 
     | 
    
         
            +
                      unless require adapter_file
         
     | 
| 
      
 17 
     | 
    
         
            +
                        raise ArgumentError.new( 
         
     | 
| 
      
 18 
     | 
    
         
            +
                          "The Intelligence adapter file #{adapter_file} is missing or does not define #{class_name}." 
         
     | 
| 
      
 19 
     | 
    
         
            +
                        )
         
     | 
| 
      
 20 
     | 
    
         
            +
                      end
         
     | 
| 
      
 21 
     | 
    
         
            +
                      adapter_class = Intelligence.const_get( class_name ) rescue nil
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    raise ArgumentError.new( "An unknown Intelligence adapter #{adapter_type} was configured." ) \
         
     | 
| 
      
 25 
     | 
    
         
            +
                      if adapter_class.nil? 
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    adapter_class
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def build( adapter_type, attributes, &block )
         
     | 
| 
      
 32 
     | 
    
         
            +
                    self.[]( adapter_type ).new( attributes, &block )
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end  
         
     | 
| 
         @@ -0,0 +1,59 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'chat_methods'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Intelligence
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Anthropic
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Adapter < Adapter::Base
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  configuration do 
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    # normalized properties for all endpoints
         
     | 
| 
      
 10 
     | 
    
         
            +
                    parameter :key, required: true 
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    # anthropic specific properties for all endpoints
         
     | 
| 
      
 13 
     | 
    
         
            +
                    parameter :version, String, required: true, default: '2023-06-01'
         
     | 
| 
      
 14 
     | 
    
         
            +
             
         
     | 
| 
      
 15 
     | 
    
         
            +
                    group :chat_options do 
         
     | 
| 
      
 16 
     | 
    
         
            +
              
         
     | 
| 
      
 17 
     | 
    
         
            +
                      # normalized properties for anthropic generative text endpoint
         
     | 
| 
      
 18 
     | 
    
         
            +
                      parameter :model, String, required: true
         
     | 
| 
      
 19 
     | 
    
         
            +
                      parameter :max_tokens, Integer, required: true
         
     | 
| 
      
 20 
     | 
    
         
            +
                      parameter :temperature, Float
         
     | 
| 
      
 21 
     | 
    
         
            +
                      parameter :top_k, Integer
         
     | 
| 
      
 22 
     | 
    
         
            +
                      parameter :top_p, Float
         
     | 
| 
      
 23 
     | 
    
         
            +
                      parameter :stop, String, array: true, as: :stop_sequences
         
     | 
| 
      
 24 
     | 
    
         
            +
                      parameter :stream, [ TrueClass, FalseClass ]
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                      # anthropic variant of normalized properties for anthropic generative text endpoints
         
     | 
| 
      
 27 
     | 
    
         
            +
                      parameter :stop_sequences, String, array: true
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                      # anthropic specific properties for anthropic generative text endpoints
         
     | 
| 
      
 30 
     | 
    
         
            +
                      parameter :tool_choice do 
         
     | 
| 
      
 31 
     | 
    
         
            +
                        parameter :type, String  
         
     | 
| 
      
 32 
     | 
    
         
            +
                        # the name parameter should only be set if type = 'tool'
         
     | 
| 
      
 33 
     | 
    
         
            +
                        parameter :name, String
         
     | 
| 
      
 34 
     | 
    
         
            +
                      end
         
     | 
| 
      
 35 
     | 
    
         
            +
                      group :metadata do
         
     | 
| 
      
 36 
     | 
    
         
            +
                        parameter :user_id, String
         
     | 
| 
      
 37 
     | 
    
         
            +
                      end 
         
     | 
| 
      
 38 
     | 
    
         
            +
                      
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
                    
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 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 
     | 
    
         
            +
                  include ChatMethods
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                end 
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
            end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,358 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'base64'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Intelligence
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Anthropic
         
     | 
| 
      
 5 
     | 
    
         
            +
                module ChatMethods
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  CHAT_REQUEST_URI = "https://api.anthropic.com/v1/messages"
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def chat_request_uri( options )
         
     | 
| 
      
 10 
     | 
    
         
            +
                    CHAT_REQUEST_URI
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def chat_request_headers( options = {} )
         
     | 
| 
      
 14 
     | 
    
         
            +
                    result = {}
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    key = options[ :key ] || self.key
         
     | 
| 
      
 17 
     | 
    
         
            +
                    version = options[ :version ] || self.version || "2023-06-01" 
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    raise ArgumentError.new( 
         
     | 
| 
      
 20 
     | 
    
         
            +
                      "An Anthropic key is required to build an Anthropic chat request." 
         
     | 
| 
      
 21 
     | 
    
         
            +
                    ) if key.nil?
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    result[ 'content-type' ] = 'application/json'
         
     | 
| 
      
 24 
     | 
    
         
            +
                    result[ 'x-api-key' ] = "#{key}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                    result[ 'anthropic-version' ] = version unless version.nil?
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    result 
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def chat_request_body( conversation, options = {} )
         
     | 
| 
      
 31 
     | 
    
         
            +
                    options = self.class.configure( options ) unless options.empty?
         
     | 
| 
      
 32 
     | 
    
         
            +
                    result = self.chat_options.merge( options ).compact
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    system_message = translate_system_message( conversation[ :system_message ] )
         
     | 
| 
      
 35 
     | 
    
         
            +
                    result[ :system ] = system_message unless system_message.nil?
         
     | 
| 
      
 36 
     | 
    
         
            +
                    result[ :messages ] = []
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    messages = conversation[ :messages ] 
         
     | 
| 
      
 39 
     | 
    
         
            +
                    length = messages&.length || 0
         
     | 
| 
      
 40 
     | 
    
         
            +
                    index = 0; while index < length 
         
     | 
| 
      
 41 
     | 
    
         
            +
                      
         
     | 
| 
      
 42 
     | 
    
         
            +
                      message = messages[ index ]
         
     | 
| 
      
 43 
     | 
    
         
            +
                      unless message.nil?
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                        # The Anthropic API will not accept a sequence of messages where the role of two 
         
     | 
| 
      
 46 
     | 
    
         
            +
                        # sequentian messages is the same.
         
     | 
| 
      
 47 
     | 
    
         
            +
                        #
         
     | 
| 
      
 48 
     | 
    
         
            +
                        # The purpose of this code is to identify such occurences and coalece them such 
         
     | 
| 
      
 49 
     | 
    
         
            +
                        # that the first message in the sequence aggregates the contents of all subsequent
         
     | 
| 
      
 50 
     | 
    
         
            +
                        # messages with the same role.
         
     | 
| 
      
 51 
     | 
    
         
            +
                        look_ahead_index = index + 1; while look_ahead_index < length
         
     | 
| 
      
 52 
     | 
    
         
            +
                          ahead_message = messages[ look_ahead_index ]
         
     | 
| 
      
 53 
     | 
    
         
            +
                          unless ahead_message.nil?
         
     | 
| 
      
 54 
     | 
    
         
            +
                            if ahead_message[ :role ] == message[ :role ]
         
     | 
| 
      
 55 
     | 
    
         
            +
                              message[ :contents ] = 
         
     | 
| 
      
 56 
     | 
    
         
            +
                                ( message[ :contents ] || [] ) + 
         
     | 
| 
      
 57 
     | 
    
         
            +
                                ( ahead_message[ :contents ] || [] )
         
     | 
| 
      
 58 
     | 
    
         
            +
                              messages[ look_ahead_index ] = nil 
         
     | 
| 
      
 59 
     | 
    
         
            +
                              look_ahead_index += 1
         
     | 
| 
      
 60 
     | 
    
         
            +
                            else 
         
     | 
| 
      
 61 
     | 
    
         
            +
                              break
         
     | 
| 
      
 62 
     | 
    
         
            +
                            end
         
     | 
| 
      
 63 
     | 
    
         
            +
                          end
         
     | 
| 
      
 64 
     | 
    
         
            +
                        end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                        result_message = { role: message[ :role ] }
         
     | 
| 
      
 67 
     | 
    
         
            +
                        result_message_content = []
         
     | 
| 
      
 68 
     | 
    
         
            +
                        
         
     | 
| 
      
 69 
     | 
    
         
            +
                        message[ :contents ]&.each do | content |
         
     | 
| 
      
 70 
     | 
    
         
            +
                          case content[ :type ]
         
     | 
| 
      
 71 
     | 
    
         
            +
                          when :text
         
     | 
| 
      
 72 
     | 
    
         
            +
                            result_message_content << { type: 'text', text: content[ :text ] }
         
     | 
| 
      
 73 
     | 
    
         
            +
                          when :binary
         
     | 
| 
      
 74 
     | 
    
         
            +
                            content_type = content[ :content_type ]
         
     | 
| 
      
 75 
     | 
    
         
            +
                            bytes = content[ :bytes ]
         
     | 
| 
      
 76 
     | 
    
         
            +
                            if content_type && bytes
         
     | 
| 
      
 77 
     | 
    
         
            +
                              mime_type = MIME::Types[ content_type ].first
         
     | 
| 
      
 78 
     | 
    
         
            +
                              if mime_type&.media_type == 'image'
         
     | 
| 
      
 79 
     | 
    
         
            +
                                result_message_content << {
         
     | 
| 
      
 80 
     | 
    
         
            +
                                  type: 'image',
         
     | 
| 
      
 81 
     | 
    
         
            +
                                  source: {
         
     | 
| 
      
 82 
     | 
    
         
            +
                                    type: 'base64',
         
     | 
| 
      
 83 
     | 
    
         
            +
                                    media_type: content_type,
         
     | 
| 
      
 84 
     | 
    
         
            +
                                    data: Base64.strict_encode64( bytes )
         
     | 
| 
      
 85 
     | 
    
         
            +
                                  }
         
     | 
| 
      
 86 
     | 
    
         
            +
                                }
         
     | 
| 
      
 87 
     | 
    
         
            +
                              else
         
     | 
| 
      
 88 
     | 
    
         
            +
                                raise UnsupportedContentError.new( 
         
     | 
| 
      
 89 
     | 
    
         
            +
                                  :anthropic, 
         
     | 
| 
      
 90 
     | 
    
         
            +
                                  'only support content of type image/*' 
         
     | 
| 
      
 91 
     | 
    
         
            +
                                ) 
         
     | 
| 
      
 92 
     | 
    
         
            +
                              end
         
     | 
| 
      
 93 
     | 
    
         
            +
                            else 
         
     | 
| 
      
 94 
     | 
    
         
            +
                              raise InvalidContentError.new( :anthropic ) 
         
     | 
| 
      
 95 
     | 
    
         
            +
                            end
         
     | 
| 
      
 96 
     | 
    
         
            +
                          end 
         
     | 
| 
      
 97 
     | 
    
         
            +
                        end
         
     | 
| 
      
 98 
     | 
    
         
            +
                        
         
     | 
| 
      
 99 
     | 
    
         
            +
                        result_message[ :content ] = result_message_content
         
     | 
| 
      
 100 
     | 
    
         
            +
                        result[ :messages ] << result_message
         
     | 
| 
      
 101 
     | 
    
         
            +
                      
         
     | 
| 
      
 102 
     | 
    
         
            +
                      end
         
     | 
| 
      
 103 
     | 
    
         
            +
                    
         
     | 
| 
      
 104 
     | 
    
         
            +
                      index += 1
         
     | 
| 
      
 105 
     | 
    
         
            +
                    
         
     | 
| 
      
 106 
     | 
    
         
            +
                    end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                    JSON.generate( result )
         
     | 
| 
      
 109 
     | 
    
         
            +
                  end 
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                  def chat_result_attributes( response )
         
     | 
| 
      
 112 
     | 
    
         
            +
                    return nil unless response.success?
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                    response_json = JSON.parse( response.body, symbolize_names: true ) rescue nil
         
     | 
| 
      
 115 
     | 
    
         
            +
                    return nil if response_json.nil? 
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                    result = {}
         
     | 
| 
      
 118 
     | 
    
         
            +
                    
         
     | 
| 
      
 119 
     | 
    
         
            +
                    result_choice = { 
         
     | 
| 
      
 120 
     | 
    
         
            +
                      end_reason: translate_end_result( response_json[ :stop_reason ] ),
         
     | 
| 
      
 121 
     | 
    
         
            +
                      end_sequence: response_json[ :stop_sequence ], 
         
     | 
| 
      
 122 
     | 
    
         
            +
                    }
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                    if response_json[ :content ] && 
         
     | 
| 
      
 125 
     | 
    
         
            +
                       response_json[ :content ].is_a?( Array ) &&
         
     | 
| 
      
 126 
     | 
    
         
            +
                       !response_json[ :content ].empty?
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                      result_content = []
         
     | 
| 
      
 129 
     | 
    
         
            +
                      response_json[ :content ].each do | content |
         
     | 
| 
      
 130 
     | 
    
         
            +
                        if content[ :type ] == 'text'
         
     | 
| 
      
 131 
     | 
    
         
            +
                          result_content.push( { type: 'text', text: content[ :text ] } )
         
     | 
| 
      
 132 
     | 
    
         
            +
                        end
         
     | 
| 
      
 133 
     | 
    
         
            +
                      end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                      unless result_content.empty?
         
     | 
| 
      
 136 
     | 
    
         
            +
                        result_choice[ :message ] = {
         
     | 
| 
      
 137 
     | 
    
         
            +
                          role: response_json[ :role ] || 'assistant',
         
     | 
| 
      
 138 
     | 
    
         
            +
                          contents: result_content
         
     | 
| 
      
 139 
     | 
    
         
            +
                        }
         
     | 
| 
      
 140 
     | 
    
         
            +
                      end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                    end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                    result[ :choices ] = [ result_choice ]
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                    metrics_json = response_json[ :usage ]
         
     | 
| 
      
 147 
     | 
    
         
            +
                    unless metrics_json.nil?
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                      result_metrics = {}
         
     | 
| 
      
 150 
     | 
    
         
            +
                      result_metrics[ :input_tokens ] = metrics_json[ :input_tokens ] 
         
     | 
| 
      
 151 
     | 
    
         
            +
                      result_metrics[ :output_tokens ] = metrics_json[ :output_tokens ]
         
     | 
| 
      
 152 
     | 
    
         
            +
                      result_metrics = result_metrics.compact
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
                      result[ :metrics ] = result_metrics unless result_metrics.empty?
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                    end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                    result 
         
     | 
| 
      
 159 
     | 
    
         
            +
                  end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                  def chat_result_error_attributes( response )
         
     | 
| 
      
 162 
     | 
    
         
            +
                    error_type, error_description = translate_response_status( response.status )
         
     | 
| 
      
 163 
     | 
    
         
            +
                    parsed_body = JSON.parse( response.body, symbolize_names: true ) rescue nil 
         
     | 
| 
      
 164 
     | 
    
         
            +
                    if parsed_body && parsed_body.respond_to?( :include? ) && parsed_body.include?( :error )
         
     | 
| 
      
 165 
     | 
    
         
            +
                      result = {
         
     | 
| 
      
 166 
     | 
    
         
            +
                        error_type: error_type.to_s,
         
     | 
| 
      
 167 
     | 
    
         
            +
                        error: parsed_body[ :error ][ :type ],
         
     | 
| 
      
 168 
     | 
    
         
            +
                        error_description: parsed_body[ :error ][ :message ] || error_description
         
     | 
| 
      
 169 
     | 
    
         
            +
                      }
         
     | 
| 
      
 170 
     | 
    
         
            +
                    elsif 
         
     | 
| 
      
 171 
     | 
    
         
            +
                      result = {
         
     | 
| 
      
 172 
     | 
    
         
            +
                        error_type: error_type.to_s,
         
     | 
| 
      
 173 
     | 
    
         
            +
                        error_description: error_description
         
     | 
| 
      
 174 
     | 
    
         
            +
                      } 
         
     | 
| 
      
 175 
     | 
    
         
            +
                    end
         
     | 
| 
      
 176 
     | 
    
         
            +
                    result 
         
     | 
| 
      
 177 
     | 
    
         
            +
                  end
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
                  def stream_result_chunk_attributes( context, chunk )
         
     | 
| 
      
 180 
     | 
    
         
            +
                    context ||= {}
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                    buffer = context[ :buffer ] || ''
         
     | 
| 
      
 183 
     | 
    
         
            +
                    contents = context[ :contents ] || []    
         
     | 
| 
      
 184 
     | 
    
         
            +
                    end_reason = context[ :end_reason ]
         
     | 
| 
      
 185 
     | 
    
         
            +
                    end_sequence = context[ :end_sequence ]
         
     | 
| 
      
 186 
     | 
    
         
            +
                    metrics = context[ :metrics ] || {
         
     | 
| 
      
 187 
     | 
    
         
            +
                      input_tokens: 0,
         
     | 
| 
      
 188 
     | 
    
         
            +
                      output_tokens:  0
         
     | 
| 
      
 189 
     | 
    
         
            +
                    }
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
                    contents.each do | content |
         
     | 
| 
      
 192 
     | 
    
         
            +
                      case content[ :type ] 
         
     | 
| 
      
 193 
     | 
    
         
            +
                        when :text 
         
     | 
| 
      
 194 
     | 
    
         
            +
                          content[ :text ] = ''
         
     | 
| 
      
 195 
     | 
    
         
            +
                        when :tool_call 
         
     | 
| 
      
 196 
     | 
    
         
            +
                          content[ :tool_parameters ] = ''
         
     | 
| 
      
 197 
     | 
    
         
            +
                        else 
         
     | 
| 
      
 198 
     | 
    
         
            +
                          content.clear 
         
     | 
| 
      
 199 
     | 
    
         
            +
                      end
         
     | 
| 
      
 200 
     | 
    
         
            +
                    end
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
                    buffer += chunk
         
     | 
| 
      
 203 
     | 
    
         
            +
                    while ( eol_index = buffer.index( "\n" ) )
         
     | 
| 
      
 204 
     | 
    
         
            +
                      
         
     | 
| 
      
 205 
     | 
    
         
            +
                      line = buffer.slice!( 0..eol_index )
         
     | 
| 
      
 206 
     | 
    
         
            +
                      line = line.strip 
         
     | 
| 
      
 207 
     | 
    
         
            +
                      next if line.empty? || !line.start_with?( 'data:' )
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
                      line = line[ 6..-1 ]
         
     | 
| 
      
 210 
     | 
    
         
            +
                      data = JSON.parse( line )
         
     | 
| 
      
 211 
     | 
    
         
            +
                      
         
     | 
| 
      
 212 
     | 
    
         
            +
                      case data[ 'type' ]
         
     | 
| 
      
 213 
     | 
    
         
            +
                        when 'message_start'
         
     | 
| 
      
 214 
     | 
    
         
            +
                          metrics[ :input_tokens ] += data[ 'message' ]&.[]( 'usage' )&.[]( 'input_tokens' ) || 0
         
     | 
| 
      
 215 
     | 
    
         
            +
                          metrics[ :output_tokens ] += data[ 'message' ]&.[]( 'usage' )&.[]( 'output_tokens' ) || 0
         
     | 
| 
      
 216 
     | 
    
         
            +
                        when 'content_block_start'
         
     | 
| 
      
 217 
     | 
    
         
            +
                          index = data[ 'index' ]
         
     | 
| 
      
 218 
     | 
    
         
            +
                          contents.fill( {}, contents.size, index + 1 ) if contents.size <= index
         
     | 
| 
      
 219 
     | 
    
         
            +
                          if content_block = data[ 'content_block' ]
         
     | 
| 
      
 220 
     | 
    
         
            +
                            if content_block[ 'type' ] == 'text'
         
     | 
| 
      
 221 
     | 
    
         
            +
                              contents[ index ] = {
         
     | 
| 
      
 222 
     | 
    
         
            +
                                type: :text,
         
     | 
| 
      
 223 
     | 
    
         
            +
                                text: content_block[ 'text' ] || '' 
         
     | 
| 
      
 224 
     | 
    
         
            +
                              }
         
     | 
| 
      
 225 
     | 
    
         
            +
                            elsif content_block[ 'type' ] == 'tool_use'
         
     | 
| 
      
 226 
     | 
    
         
            +
                              contents[ index ] = {
         
     | 
| 
      
 227 
     | 
    
         
            +
                                type: :tool_call,
         
     | 
| 
      
 228 
     | 
    
         
            +
                                tool_name: content_block[ 'name' ],
         
     | 
| 
      
 229 
     | 
    
         
            +
                                tool_call_id: content_block[ 'id' ],
         
     | 
| 
      
 230 
     | 
    
         
            +
                                tool_parameters: ''
         
     | 
| 
      
 231 
     | 
    
         
            +
                              }
         
     | 
| 
      
 232 
     | 
    
         
            +
                            end
         
     | 
| 
      
 233 
     | 
    
         
            +
                          end
         
     | 
| 
      
 234 
     | 
    
         
            +
                        when 'content_block_delta'
         
     | 
| 
      
 235 
     | 
    
         
            +
                          index = data[ 'index' ]
         
     | 
| 
      
 236 
     | 
    
         
            +
                          contents.fill( {}, contents.size, index + 1 ) if contents.size <= index
         
     | 
| 
      
 237 
     | 
    
         
            +
                          if delta = data[ 'delta' ]
         
     | 
| 
      
 238 
     | 
    
         
            +
                            if delta[ 'type' ] == 'text_delta'
         
     | 
| 
      
 239 
     | 
    
         
            +
                              contents[ index ][ :type ] = :text 
         
     | 
| 
      
 240 
     | 
    
         
            +
                              contents[ index ][ :text ] = ( contents[ index ][ :text ] || '' ) + delta[ 'text' ]
         
     | 
| 
      
 241 
     | 
    
         
            +
                            elsif delta[ 'type' ] == 'input_json_delta'
         
     | 
| 
      
 242 
     | 
    
         
            +
                              contents[ index ][ :type ] = :tool_call 
         
     | 
| 
      
 243 
     | 
    
         
            +
                              contents[ index ][ :tool_parameters ] = 
         
     | 
| 
      
 244 
     | 
    
         
            +
                                ( contents[ index ][ :tool_parameters ] || '' ) + delta[ 'input_json_delta' ]                
         
     | 
| 
      
 245 
     | 
    
         
            +
                            end
         
     | 
| 
      
 246 
     | 
    
         
            +
                          end
         
     | 
| 
      
 247 
     | 
    
         
            +
                        when 'message_delta'
         
     | 
| 
      
 248 
     | 
    
         
            +
                          if delta = data[ 'delta' ]
         
     | 
| 
      
 249 
     | 
    
         
            +
                            end_reason = delta[ 'stop_reason' ]
         
     | 
| 
      
 250 
     | 
    
         
            +
                            end_sequence = delta[ 'stop_sequence' ]
         
     | 
| 
      
 251 
     | 
    
         
            +
                          end
         
     | 
| 
      
 252 
     | 
    
         
            +
                          metrics[ :output_tokens ] += data[ 'usage' ]&.[]( 'output_tokens' ) || 0
         
     | 
| 
      
 253 
     | 
    
         
            +
                        when 'message_stop'
         
     | 
| 
      
 254 
     | 
    
         
            +
                          
         
     | 
| 
      
 255 
     | 
    
         
            +
                      end 
         
     | 
| 
      
 256 
     | 
    
         
            +
                    end
         
     | 
| 
      
 257 
     | 
    
         
            +
             
     | 
| 
      
 258 
     | 
    
         
            +
                    context = {
         
     | 
| 
      
 259 
     | 
    
         
            +
                      buffer: buffer,
         
     | 
| 
      
 260 
     | 
    
         
            +
                      contents: contents,
         
     | 
| 
      
 261 
     | 
    
         
            +
                      end_reason: end_reason,
         
     | 
| 
      
 262 
     | 
    
         
            +
                      end_sequence: end_sequence,
         
     | 
| 
      
 263 
     | 
    
         
            +
                      metrics: metrics
         
     | 
| 
      
 264 
     | 
    
         
            +
                    }
         
     | 
| 
      
 265 
     | 
    
         
            +
                    choices = [ {
         
     | 
| 
      
 266 
     | 
    
         
            +
                        end_reason: translate_end_result( end_reason ),
         
     | 
| 
      
 267 
     | 
    
         
            +
                        end_sequence: end_sequence,
         
     | 
| 
      
 268 
     | 
    
         
            +
                        message: {
         
     | 
| 
      
 269 
     | 
    
         
            +
                          contents: contents.dup
         
     | 
| 
      
 270 
     | 
    
         
            +
                        }
         
     | 
| 
      
 271 
     | 
    
         
            +
                      }
         
     | 
| 
      
 272 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 273 
     | 
    
         
            +
             
     | 
| 
      
 274 
     | 
    
         
            +
                    [ context, ( choices.empty? ? nil : { choices: choices } ) ]
         
     | 
| 
      
 275 
     | 
    
         
            +
                  end
         
     | 
| 
      
 276 
     | 
    
         
            +
             
     | 
| 
      
 277 
     | 
    
         
            +
                  def stream_result_attributes( context )
         
     | 
| 
      
 278 
     | 
    
         
            +
                    {
         
     | 
| 
      
 279 
     | 
    
         
            +
                      choices: [ { 
         
     | 
| 
      
 280 
     | 
    
         
            +
                        end_reason: translate_end_result( context[ :end_reason ] ),
         
     | 
| 
      
 281 
     | 
    
         
            +
                        end_sequence: context[ :end_sequence ], 
         
     | 
| 
      
 282 
     | 
    
         
            +
                      } ],
         
     | 
| 
      
 283 
     | 
    
         
            +
                      metrics: context[ :metrics ]
         
     | 
| 
      
 284 
     | 
    
         
            +
                    }
         
     | 
| 
      
 285 
     | 
    
         
            +
                  end
         
     | 
| 
      
 286 
     | 
    
         
            +
             
     | 
| 
      
 287 
     | 
    
         
            +
                  alias_method :stream_result_error_attributes, :chat_result_error_attributes 
         
     | 
| 
      
 288 
     | 
    
         
            +
             
     | 
| 
      
 289 
     | 
    
         
            +
                private 
         
     | 
| 
      
 290 
     | 
    
         
            +
             
     | 
| 
      
 291 
     | 
    
         
            +
                  def translate_system_message( system_message )
         
     | 
| 
      
 292 
     | 
    
         
            +
             
     | 
| 
      
 293 
     | 
    
         
            +
                    return nil if system_message.nil?
         
     | 
| 
      
 294 
     | 
    
         
            +
             
     | 
| 
      
 295 
     | 
    
         
            +
                    # note: the current version of the anthropic api simply takes a string as the 
         
     | 
| 
      
 296 
     | 
    
         
            +
                    #       system message but the beta version requires an array of objects akin
         
     | 
| 
      
 297 
     | 
    
         
            +
                    #       to message contents.
         
     | 
| 
      
 298 
     | 
    
         
            +
             
     | 
| 
      
 299 
     | 
    
         
            +
                    result = ''
         
     | 
| 
      
 300 
     | 
    
         
            +
                    system_message[ :contents ].each do | content |
         
     | 
| 
      
 301 
     | 
    
         
            +
                      result += content[ :text ] if content[ :type ] == :text 
         
     | 
| 
      
 302 
     | 
    
         
            +
                    end
         
     | 
| 
      
 303 
     | 
    
         
            +
             
     | 
| 
      
 304 
     | 
    
         
            +
                    result.empty? ? nil : result 
         
     | 
| 
      
 305 
     | 
    
         
            +
             
     | 
| 
      
 306 
     | 
    
         
            +
                  end 
         
     | 
| 
      
 307 
     | 
    
         
            +
             
     | 
| 
      
 308 
     | 
    
         
            +
                  def translate_end_result( end_result )
         
     | 
| 
      
 309 
     | 
    
         
            +
                    case end_result
         
     | 
| 
      
 310 
     | 
    
         
            +
                      when 'end_turn'
         
     | 
| 
      
 311 
     | 
    
         
            +
                        :ended
         
     | 
| 
      
 312 
     | 
    
         
            +
                      when 'max_tokens'
         
     | 
| 
      
 313 
     | 
    
         
            +
                        :token_limit_exceeded
         
     | 
| 
      
 314 
     | 
    
         
            +
                      when 'stop_sequence'
         
     | 
| 
      
 315 
     | 
    
         
            +
                        :end_sequence_encountered
         
     | 
| 
      
 316 
     | 
    
         
            +
                      when 'tool_use'
         
     | 
| 
      
 317 
     | 
    
         
            +
                        :tool_called
         
     | 
| 
      
 318 
     | 
    
         
            +
                      else
         
     | 
| 
      
 319 
     | 
    
         
            +
                        # if the result has already been translated, this simply returns it
         
     | 
| 
      
 320 
     | 
    
         
            +
                        end_result
         
     | 
| 
      
 321 
     | 
    
         
            +
                    end
         
     | 
| 
      
 322 
     | 
    
         
            +
                  end
         
     | 
| 
      
 323 
     | 
    
         
            +
             
     | 
| 
      
 324 
     | 
    
         
            +
                  def translate_response_status( status )
         
     | 
| 
      
 325 
     | 
    
         
            +
                    case status
         
     | 
| 
      
 326 
     | 
    
         
            +
                      when 400
         
     | 
| 
      
 327 
     | 
    
         
            +
                        [ :invalid_request_error, 
         
     | 
| 
      
 328 
     | 
    
         
            +
                          "There was an issue with the format or content of your request." ]
         
     | 
| 
      
 329 
     | 
    
         
            +
                      when 401
         
     | 
| 
      
 330 
     | 
    
         
            +
                        [ :authentication_error, 
         
     | 
| 
      
 331 
     | 
    
         
            +
                          "There's an issue with your API key." ]
         
     | 
| 
      
 332 
     | 
    
         
            +
                      when 403
         
     | 
| 
      
 333 
     | 
    
         
            +
                        [ :permission_error, 
         
     | 
| 
      
 334 
     | 
    
         
            +
                          "Your API key does not have permission to use the specified resource." ]
         
     | 
| 
      
 335 
     | 
    
         
            +
                      when 404
         
     | 
| 
      
 336 
     | 
    
         
            +
                        [ :not_found_error, 
         
     | 
| 
      
 337 
     | 
    
         
            +
                          "The requested resource was not found." ]
         
     | 
| 
      
 338 
     | 
    
         
            +
                      when 413
         
     | 
| 
      
 339 
     | 
    
         
            +
                        [ :request_too_large, 
         
     | 
| 
      
 340 
     | 
    
         
            +
                          "Request exceeds the maximum allowed number of bytes." ]
         
     | 
| 
      
 341 
     | 
    
         
            +
                      when 429
         
     | 
| 
      
 342 
     | 
    
         
            +
                        [ :rate_limit_error, 
         
     | 
| 
      
 343 
     | 
    
         
            +
                          "Your account has hit a rate limit." ]
         
     | 
| 
      
 344 
     | 
    
         
            +
                      when 500
         
     | 
| 
      
 345 
     | 
    
         
            +
                        [ :api_error, 
         
     | 
| 
      
 346 
     | 
    
         
            +
                          "An unexpected error has occurred internal to Anthropic's systems." ]
         
     | 
| 
      
 347 
     | 
    
         
            +
                      when 529
         
     | 
| 
      
 348 
     | 
    
         
            +
                        [ :overloaded_error, 
         
     | 
| 
      
 349 
     | 
    
         
            +
                          "Anthropic's API is temporarily overloaded." ]
         
     | 
| 
      
 350 
     | 
    
         
            +
                      else
         
     | 
| 
      
 351 
     | 
    
         
            +
                        [ :unknown_error, "
         
     | 
| 
      
 352 
     | 
    
         
            +
                          An unknown error occurred." ]
         
     | 
| 
      
 353 
     | 
    
         
            +
                      end
         
     | 
| 
      
 354 
     | 
    
         
            +
                  end
         
     | 
| 
      
 355 
     | 
    
         
            +
                
         
     | 
| 
      
 356 
     | 
    
         
            +
                end
         
     | 
| 
      
 357 
     | 
    
         
            +
              end
         
     | 
| 
      
 358 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'legacy/adapter'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Intelligence
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Cerebras
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                class Adapter < Legacy::Adapter
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  chat_request_uri "https://api.cerebras.ai/v1/chat/completions"
         
     | 
| 
      
 9 
     | 
    
         
            +
                  
         
     | 
| 
      
 10 
     | 
    
         
            +
                  configuration do 
         
     | 
| 
      
 11 
     | 
    
         
            +
                    parameter :key, required: true 
         
     | 
| 
      
 12 
     | 
    
         
            +
                    group :chat_options do 
         
     | 
| 
      
 13 
     | 
    
         
            +
                      parameter :model, String, required: true
         
     | 
| 
      
 14 
     | 
    
         
            +
                      parameter :max_tokens, Integer, required: true
         
     | 
| 
      
 15 
     | 
    
         
            +
                      parameter :response_format do 
         
     | 
| 
      
 16 
     | 
    
         
            +
                        parameter :type, String, default: 'json_schema'
         
     | 
| 
      
 17 
     | 
    
         
            +
                        parameter :json_schema
         
     | 
| 
      
 18 
     | 
    
         
            +
                      end
         
     | 
| 
      
 19 
     | 
    
         
            +
                      parameter :seed, Integer
         
     | 
| 
      
 20 
     | 
    
         
            +
                      parameter :stop, array: true
         
     | 
| 
      
 21 
     | 
    
         
            +
                      parameter :stream, [ TrueClass, FalseClass ]
         
     | 
| 
      
 22 
     | 
    
         
            +
                      parameter :temperature, Float
         
     | 
| 
      
 23 
     | 
    
         
            +
                      parameter :top_p, Float
         
     | 
| 
      
 24 
     | 
    
         
            +
                      parameter :tool_choice do 
         
     | 
| 
      
 25 
     | 
    
         
            +
                        parameter :type, String 
         
     | 
| 
      
 26 
     | 
    
         
            +
                        parameter :mame, String
         
     | 
| 
      
 27 
     | 
    
         
            +
                      end
         
     | 
| 
      
 28 
     | 
    
         
            +
                      parameter :user
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative '../../adapter'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative 'chat_methods'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Intelligence
         
     | 
| 
      
 5 
     | 
    
         
            +
              module Generic
         
     | 
| 
      
 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 
     | 
    
         
            +
                  include ChatMethods
         
     | 
| 
      
 18 
     | 
    
         
            +
                
         
     | 
| 
      
 19 
     | 
    
         
            +
                end 
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     |