Class: RubyLLM::Chat

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/ruby_llm/chat.rb

Overview

Represents a conversation with an AI model

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model: nil, provider: nil, assume_model_exists: false, context: nil) ⇒ Chat



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/ruby_llm/chat.rb', line 10

def initialize(model: nil, provider: nil, assume_model_exists: false, context: nil)
  if assume_model_exists && !provider
    raise ArgumentError, 'Provider must be specified if assume_model_exists is true'
  end

  @context = context
  @config = context&.config || RubyLLM.config
  model_id = model || @config.default_model
  with_model(model_id, provider: provider, assume_exists: assume_model_exists)
  @temperature = nil
  @messages = []
  @tools = {}
  @params = {}
  @headers = {}
  @schema = nil
  @thinking = nil
  @on = {
    new_message: nil,
    end_message: nil,
    tool_call: nil,
    tool_result: nil
  }
end

Instance Attribute Details

#headersObject (readonly)

Returns the value of attribute headers.



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

def headers
  @headers
end

#messagesObject (readonly)

Returns the value of attribute messages.



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

def messages
  @messages
end

#modelObject (readonly)

Returns the value of attribute model.



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

def model
  @model
end

#paramsObject (readonly)

Returns the value of attribute params.



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

def params
  @params
end

#schemaObject (readonly)

Returns the value of attribute schema.



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

def schema
  @schema
end

#toolsObject (readonly)

Returns the value of attribute tools.



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

def tools
  @tools
end

Instance Method Details

#add_message(message_or_attributes) ⇒ Object



170
171
172
173
174
# File 'lib/ruby_llm/chat.rb', line 170

def add_message(message_or_attributes)
  message = message_or_attributes.is_a?(Message) ? message_or_attributes : Message.new(message_or_attributes)
  messages << message
  message
end

#ask(message = nil, with: nil) ⇒ Object Also known as: say



34
35
36
37
# File 'lib/ruby_llm/chat.rb', line 34

def ask(message = nil, with: nil, &)
  add_message role: :user, content: build_content(message, with)
  complete(&)
end

#completeObject

rubocop:disable Metrics/PerceivedComplexity



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/ruby_llm/chat.rb', line 137

def complete(&) # rubocop:disable Metrics/PerceivedComplexity
  response = @provider.complete(
    messages,
    tools: @tools,
    temperature: @temperature,
    model: @model,
    params: @params,
    headers: @headers,
    schema: @schema,
    thinking: @thinking,
    &wrap_streaming_block(&)
  )

  @on[:new_message]&.call unless block_given?

  if @schema && response.content.is_a?(String)
    begin
      response.content = JSON.parse(response.content)
    rescue JSON::ParserError
      # If parsing fails, keep content as string
    end
  end

  add_message response
  @on[:end_message]&.call(response)

  if response.tool_call?
    handle_tool_calls(response, &)
  else
    response
  end
end

#eachObject



133
134
135
# File 'lib/ruby_llm/chat.rb', line 133

def each(&)
  messages.each(&)
end

#instance_variablesObject



180
181
182
# File 'lib/ruby_llm/chat.rb', line 180

def instance_variables
  super - %i[@connection @config]
end

#on_end_message(&block) ⇒ Object



118
119
120
121
# File 'lib/ruby_llm/chat.rb', line 118

def on_end_message(&block)
  @on[:end_message] = block
  self
end

#on_new_message(&block) ⇒ Object



113
114
115
116
# File 'lib/ruby_llm/chat.rb', line 113

def on_new_message(&block)
  @on[:new_message] = block
  self
end

#on_tool_call(&block) ⇒ Object



123
124
125
126
# File 'lib/ruby_llm/chat.rb', line 123

def on_tool_call(&block)
  @on[:tool_call] = block
  self
end

#on_tool_result(&block) ⇒ Object



128
129
130
131
# File 'lib/ruby_llm/chat.rb', line 128

def on_tool_result(&block)
  @on[:tool_result] = block
  self
end

#reset_messages!Object



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

def reset_messages!
  @messages.clear
end

#with_context(context) ⇒ Object



83
84
85
86
87
88
# File 'lib/ruby_llm/chat.rb', line 83

def with_context(context)
  @context = context
  @config = context.config
  with_model(@model.id, provider: @provider.slug, assume_exists: true)
  self
end

#with_headers(**headers) ⇒ Object



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

def with_headers(**headers)
  @headers = headers
  self
end

#with_instructions(instructions, append: false, replace: nil) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/ruby_llm/chat.rb', line 41

def with_instructions(instructions, append: false, replace: nil)
  append ||= (replace == false) unless replace.nil?

  if append
    append_system_instruction(instructions)
  else
    replace_system_instruction(instructions)
  end

  self
end

#with_model(model_id, provider: nil, assume_exists: false) ⇒ Object



65
66
67
68
69
# File 'lib/ruby_llm/chat.rb', line 65

def with_model(model_id, provider: nil, assume_exists: false)
  @model, @provider = Models.resolve(model_id, provider:, assume_exists:, config: @config)
  @connection = @provider.connection
  self
end

#with_params(**params) ⇒ Object



90
91
92
93
# File 'lib/ruby_llm/chat.rb', line 90

def with_params(**params)
  @params = params
  self
end

#with_schema(schema) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/ruby_llm/chat.rb', line 100

def with_schema(schema)
  schema_instance = schema.is_a?(Class) ? schema.new : schema

  # Accept both RubyLLM::Schema instances and plain JSON schemas
  @schema = if schema_instance.respond_to?(:to_json_schema)
              schema_instance.to_json_schema[:schema]
            else
              schema_instance
            end

  self
end

#with_temperature(temperature) ⇒ Object



71
72
73
74
# File 'lib/ruby_llm/chat.rb', line 71

def with_temperature(temperature)
  @temperature = temperature
  self
end

#with_thinking(effort: nil, budget: nil) ⇒ Object

Raises:

  • (ArgumentError)


76
77
78
79
80
81
# File 'lib/ruby_llm/chat.rb', line 76

def with_thinking(effort: nil, budget: nil)
  raise ArgumentError, 'with_thinking requires :effort or :budget' if effort.nil? && budget.nil?

  @thinking = Thinking::Config.new(effort: effort, budget: budget)
  self
end

#with_tool(tool) ⇒ Object



53
54
55
56
57
# File 'lib/ruby_llm/chat.rb', line 53

def with_tool(tool)
  tool_instance = tool.is_a?(Class) ? tool.new : tool
  @tools[tool_instance.name.to_sym] = tool_instance
  self
end

#with_tools(*tools, replace: false) ⇒ Object



59
60
61
62
63
# File 'lib/ruby_llm/chat.rb', line 59

def with_tools(*tools, replace: false)
  @tools.clear if replace
  tools.compact.each { |tool| with_tool tool }
  self
end