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

Returns a new instance of 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

Parameters:

  • prompt (String)

    The prompt to generate the object from

  • schema (Dry::Schema::Params)

    The schema to validate against

  • options (Hash) (defaults to: {})

    Generation options

Options Hash (options):

  • :model (String)

    The model to use

  • :temperature (Float) — default: 0.7

    The temperature to use

Returns:

  • (Hash)

    The generated object

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

Parameters:

  • prompt (String)

    The prompt to generate text from

  • options (Hash) (defaults to: {})

    Generation options

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

Returns:

  • (String)

    The generated text

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

Parameters:

  • error (StandardError)

    The error to handle

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

Parameters:

  • response (HTTParty::Response)

    The response to parse

Returns:

  • (Hash)

    The parsed 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