Class: RubyLLM::Provider

Inherits:
Object
  • Object
show all
Includes:
Streaming
Defined in:
lib/ruby_llm/provider.rb

Overview

Base class for LLM providers.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Streaming

handle_stream, stream_response

Constructor Details

#initialize(config) ⇒ Provider

Returns a new instance of Provider.



10
11
12
13
14
# File 'lib/ruby_llm/provider.rb', line 10

def initialize(config)
  @config = config
  ensure_configured!
  @connection = Connection.new(self, @config)
end

Instance Attribute Details

#config ⇒ Object (readonly)

Returns the value of attribute config.



8
9
10
# File 'lib/ruby_llm/provider.rb', line 8

def config
  @config
end

#connection ⇒ Object (readonly)

Returns the value of attribute connection.



8
9
10
# File 'lib/ruby_llm/provider.rb', line 8

def connection
  @connection
end

Class Method Details

.capabilities ⇒ Object

Raises:

  • (NotImplementedError)


148
149
150
# File 'lib/ruby_llm/provider.rb', line 148

def capabilities
  raise NotImplementedError
end

.configuration_requirements ⇒ Object



152
153
154
# File 'lib/ruby_llm/provider.rb', line 152

def configuration_requirements
  []
end

.configured?(config) ⇒ Boolean

Returns:

  • (Boolean)


164
165
166
# File 'lib/ruby_llm/provider.rb', line 164

def configured?(config)
  configuration_requirements.all? { |req| config.send(req) }
end

.configured_providers(config) ⇒ Object



193
194
195
196
197
# File 'lib/ruby_llm/provider.rb', line 193

def configured_providers(config)
  providers.select do |_slug, provider_class|
    provider_class.configured?(config)
  end.values
end

.configured_remote_providers(config) ⇒ Object



199
200
201
202
203
# File 'lib/ruby_llm/provider.rb', line 199

def configured_remote_providers(config)
  providers.select do |_slug, provider_class|
    provider_class.remote? && provider_class.configured?(config)
  end.values
end

.for(model) ⇒ Object



176
177
178
179
# File 'lib/ruby_llm/provider.rb', line 176

def for(model)
  model_info = Models.find(model)
  resolve model_info.provider
end

.local? ⇒ Boolean

Returns:

  • (Boolean)


156
157
158
# File 'lib/ruby_llm/provider.rb', line 156

def local?
  false
end

.local_providers ⇒ Object



185
186
187
# File 'lib/ruby_llm/provider.rb', line 185

def local_providers
  providers.select { |_slug, provider_class| provider_class.local? }
end

.name ⇒ Object



140
141
142
# File 'lib/ruby_llm/provider.rb', line 140

def name
  to_s.split('::').last
end

.providers ⇒ Object



181
182
183
# File 'lib/ruby_llm/provider.rb', line 181

def providers
  @providers ||= {}
end

.register(name, provider_class) ⇒ Object



168
169
170
# File 'lib/ruby_llm/provider.rb', line 168

def register(name, provider_class)
  providers[name.to_sym] = provider_class
end

.remote? ⇒ Boolean

Returns:

  • (Boolean)


160
161
162
# File 'lib/ruby_llm/provider.rb', line 160

def remote?
  !local?
end

.remote_providers ⇒ Object



189
190
191
# File 'lib/ruby_llm/provider.rb', line 189

def remote_providers
  providers.select { |_slug, provider_class| provider_class.remote? }
end

.resolve(name) ⇒ Object



172
173
174
# File 'lib/ruby_llm/provider.rb', line 172

def resolve(name)
  providers[name.to_sym]
end

.slug ⇒ Object



144
145
146
# File 'lib/ruby_llm/provider.rb', line 144

def slug
  name.downcase
end

Instance Method Details

#api_base ⇒ Object

Raises:

  • (NotImplementedError)


16
17
18
# File 'lib/ruby_llm/provider.rb', line 16

def api_base
  raise NotImplementedError
end

#capabilities ⇒ Object



32
33
34
# File 'lib/ruby_llm/provider.rb', line 32

def capabilities
  self.class.capabilities
end

#complete(messages, tools:, temperature:, model:, params: {}, headers: {}, schema: nil) ⇒ Object

rubocop:disable Metrics/ParameterLists



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/ruby_llm/provider.rb', line 40

def complete(messages, tools:, temperature:, model:, params: {}, headers: {}, schema: nil, &) # rubocop:disable Metrics/ParameterLists
  normalized_temperature = maybe_normalize_temperature(temperature, model)

  payload = Utils.deep_merge(
    render_payload(
      messages,
      tools: tools,
      temperature: normalized_temperature,
      model: model,
      stream: block_given?,
      schema: schema
    ),
    params
  )

  if block_given?
    stream_response @connection, payload, headers, &
  else
    sync_response @connection, payload, headers
  end
end

#configuration_requirements ⇒ Object



36
37
38
# File 'lib/ruby_llm/provider.rb', line 36

def configuration_requirements
  self.class.configuration_requirements
end

#configured? ⇒ Boolean

Returns:

  • (Boolean)


92
93
94
# File 'lib/ruby_llm/provider.rb', line 92

def configured?
  configuration_requirements.all? { |req| @config.send(req) }
end

#embed(text, model:, dimensions:) ⇒ Object



67
68
69
70
71
# File 'lib/ruby_llm/provider.rb', line 67

def embed(text, model:, dimensions:)
  payload = render_embedding_payload(text, model:, dimensions:)
  response = @connection.post(embedding_url(model:), payload)
  parse_embedding_response(response, model:, text:)
end

#format_messages(messages) ⇒ Object



122
123
124
125
126
127
128
129
# File 'lib/ruby_llm/provider.rb', line 122

def format_messages(messages)
  messages.map do |msg|
    {
      role: msg.role.to_s,
      content: msg.content
    }
  end
end

#format_tool_calls(_tool_calls) ⇒ Object



131
132
133
# File 'lib/ruby_llm/provider.rb', line 131

def format_tool_calls(_tool_calls)
  nil
end

#headers ⇒ Object



20
21
22
# File 'lib/ruby_llm/provider.rb', line 20

def headers
  {}
end

#list_models ⇒ Object



62
63
64
65
# File 'lib/ruby_llm/provider.rb', line 62

def list_models
  response = @connection.get models_url
  parse_list_models_response response, slug, capabilities
end

#local? ⇒ Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/ruby_llm/provider.rb', line 96

def local?
  self.class.local?
end

#moderate(input, model:) ⇒ Object



73
74
75
76
77
# File 'lib/ruby_llm/provider.rb', line 73

def moderate(input, model:)
  payload = render_moderation_payload(input, model:)
  response = @connection.post moderation_url, payload
  parse_moderation_response(response, model:)
end

#name ⇒ Object



28
29
30
# File 'lib/ruby_llm/provider.rb', line 28

def name
  self.class.name
end

#paint(prompt, model:, size:) ⇒ Object



79
80
81
82
83
# File 'lib/ruby_llm/provider.rb', line 79

def paint(prompt, model:, size:)
  payload = render_image_payload(prompt, model:, size:)
  response = @connection.post images_url, payload
  parse_image_response(response, model:)
end

#parse_error(response) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/ruby_llm/provider.rb', line 104

def parse_error(response)
  return if response.body.empty?

  body = try_parse_json(response.body)
  case body
  when Hash
    body.dig('error', 'message')
  when Array
    body.map do |part|
      part.dig('error', 'message')
    end.join('. ')
  else
    body
  end
rescue NoMethodError, TypeError
  response.body
end

#parse_tool_calls(_tool_calls) ⇒ Object



135
136
137
# File 'lib/ruby_llm/provider.rb', line 135

def parse_tool_calls(_tool_calls)
  nil
end

#remote? ⇒ Boolean

Returns:

  • (Boolean)


100
101
102
# File 'lib/ruby_llm/provider.rb', line 100

def remote?
  self.class.remote?
end

#slug ⇒ Object



24
25
26
# File 'lib/ruby_llm/provider.rb', line 24

def slug
  self.class.slug
end

#transcribe(audio_file, model:, language:, **options) ⇒ Object



85
86
87
88
89
90
# File 'lib/ruby_llm/provider.rb', line 85

def transcribe(audio_file, model:, language:, **options)
  file_part = build_audio_file_part(audio_file)
  payload = render_transcription_payload(file_part, model:, language:, **options)
  response = @connection.post transcription_url, payload
  parse_transcription_response(response, model:)
end