Class: LastLLM::Provider

Inherits:
Object
  • Object
show all
Defined in:
lib/last_llm/provider.rb

Overview

Base class for all LLM providers Implements common functionality and defines the interface that all providers must implement

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, config = {}) ⇒ Provider



14
15
16
17
18
19
20
21
22
23
24
# File 'lib/last_llm/provider.rb', line 14

def initialize(name, config = {})
  @name = name
  @config = config
  @logger = setup_logger(config[:logger])

  if instance_of?(Provider)
    raise NotImplementedError, "#{self.class} is an abstract class and cannot be instantiated directly"
  end

  validate_config! unless config[:skip_validation]
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



12
13
14
# File 'lib/last_llm/provider.rb', line 12

def config
  @config
end

#nameObject (readonly)

Returns the value of attribute name.



12
13
14
# File 'lib/last_llm/provider.rb', line 12

def name
  @name
end

Instance Method Details

#generate_object(prompt, schema, options = {}) ⇒ Hash

Generate a structured object from a prompt

Options Hash (options):

  • :model (String)

    The model to use

  • :temperature (Float) — default: 0.7

    The temperature to use

Raises:

  • (NotImplementedError)

    If not implemented by subclass



46
47
48
# File 'lib/last_llm/provider.rb', line 46

def generate_object(prompt, schema, options = {})
  raise NotImplementedError, "#{self.class}##{__method__} must be implemented by subclass"
end

#generate_text(prompt, options = {}) ⇒ String

Generate text from a prompt

Options Hash (options):

  • :model (String)

    The model to use

  • :temperature (Float) — default: 0.7

    The temperature to use

  • :max_tokens (Integer)

    The maximum number of tokens to generate

Raises:

  • (NotImplementedError)

    If not implemented by subclass



34
35
36
# File 'lib/last_llm/provider.rb', line 34

def generate_text(prompt, options = {})
  raise NotImplementedError, "#{self.class}##{__method__} must be implemented by subclass"
end

#handle_request_error(error) ⇒ Object

Handle request errors

Raises:

  • (ApiError)

    A standardized API error



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/last_llm/provider.rb', line 53

def handle_request_error(error)
  status = nil
  message = "API request failed: #{error.message}"

  case error
  when Faraday::ResourceNotFound
    status = 404
  when Faraday::ConnectionFailed
    status = 503
  when Faraday::TimeoutError
    status = 504
  when Faraday::Error
    if error.respond_to?(:response) && error.response.is_a?(Hash)
      status = error.response[:status]
      body = error.response[:body]

      # Try to extract a more helpful message from the response body
      if body.is_a?(String) && !body.empty?
        begin
          parsed_body = JSON.parse(body)
          message = "API error: #{parsed_body['error']['message'] || parsed_body['error']}" if parsed_body['error']
        rescue JSON::ParserError
          # Use default message if we can't parse the body
        end
      end
    end
  end

  raise LastLLM::ApiError.new(message, status)
end

#parse_response(response) ⇒ Hash

Parse API response

Raises:

  • (ApiError)

    If the response is invalid



88
89
90
91
92
93
94
95
96
# File 'lib/last_llm/provider.rb', line 88

def parse_response(response)
  return {} if response.body.nil? || response.body.empty?

  begin
    response.body.deep_symbolize_keys
  rescue JSON::ParserError
    raise LastLLM::ApiError, "Invalid JSON response: #{response.body}"
  end
end