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

Returns a new instance of Chat.



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

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 = {}
  @tool_prefs = { choice: nil, calls: nil }
  @concurrency = normalize_tool_concurrency(@config.tool_concurrency)
  @params = {}
  @headers = {}
  @schema = nil
  @thinking = nil
  @on = {
    new_message: nil,
    end_message: nil,
    tool_call: nil,
    tool_result: nil
  }
  @callbacks = Hash.new { |callbacks, name| callbacks[name] = [] }
end

Instance Attribute Details

#concurrencyObject (readonly)

Returns the value of attribute concurrency.



10
11
12
# File 'lib/ruby_llm/chat.rb', line 10

def concurrency
  @concurrency
end

#headersObject (readonly)

Returns the value of attribute headers.



10
11
12
# File 'lib/ruby_llm/chat.rb', line 10

def headers
  @headers
end

#messagesObject (readonly)

Returns the value of attribute messages.



10
11
12
# File 'lib/ruby_llm/chat.rb', line 10

def messages
  @messages
end

#modelObject (readonly)

Returns the value of attribute model.



10
11
12
# File 'lib/ruby_llm/chat.rb', line 10

def model
  @model
end

#paramsObject (readonly)

Returns the value of attribute params.



10
11
12
# File 'lib/ruby_llm/chat.rb', line 10

def params
  @params
end

#schemaObject (readonly)

Returns the value of attribute schema.



10
11
12
# File 'lib/ruby_llm/chat.rb', line 10

def schema
  @schema
end

#tool_prefsObject (readonly)

Returns the value of attribute tool_prefs.



10
11
12
# File 'lib/ruby_llm/chat.rb', line 10

def tool_prefs
  @tool_prefs
end

#toolsObject (readonly)

Returns the value of attribute tools.



10
11
12
# File 'lib/ruby_llm/chat.rb', line 10

def tools
  @tools
end

Instance Method Details

#add_message(message_or_attributes) ⇒ Object



165
166
167
168
169
# File 'lib/ruby_llm/chat.rb', line 165

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

#after_messageObject



141
142
143
# File 'lib/ruby_llm/chat.rb', line 141

def after_message(&)
  add_callback(:after_message, &)
end

#after_tool_resultObject



149
150
151
# File 'lib/ruby_llm/chat.rb', line 149

def after_tool_result(&)
  add_callback(:after_tool_result, &)
end

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



39
40
41
42
# File 'lib/ruby_llm/chat.rb', line 39

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

#before_messageObject



137
138
139
# File 'lib/ruby_llm/chat.rb', line 137

def before_message(&)
  add_callback(:before_message, &)
end

#before_tool_callObject



145
146
147
# File 'lib/ruby_llm/chat.rb', line 145

def before_tool_call(&)
  add_callback(:before_tool_call, &)
end

#completeObject



161
162
163
# File 'lib/ruby_llm/chat.rb', line 161

def complete(&)
  instrument_completion(&)
end

#costObject



157
158
159
# File 'lib/ruby_llm/chat.rb', line 157

def cost
  Cost.aggregate(messages.map { |message| message.cost(model: message.model_info || model) })
end

#eachObject



153
154
155
# File 'lib/ruby_llm/chat.rb', line 153

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

#instance_variablesObject



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

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

#on_end_messageObject



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

def on_end_message(&)
  set_legacy_callback(:end_message, :on_end_message, :after_message, &)
end

#on_new_messageObject



121
122
123
# File 'lib/ruby_llm/chat.rb', line 121

def on_new_message(&)
  set_legacy_callback(:new_message, :on_new_message, :before_message, &)
end

#on_tool_callObject



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

def on_tool_call(&)
  set_legacy_callback(:tool_call, :on_tool_call, :before_tool_call, &)
end

#on_tool_resultObject



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

def on_tool_result(&)
  set_legacy_callback(:tool_result, :on_tool_result, :after_tool_result, &)
end

#reset_messages!Object

Mutates this chat by removing all in-memory messages.



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

def reset_messages!
  @messages.clear
end

#with_context(context) ⇒ Object



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

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



106
107
108
109
# File 'lib/ruby_llm/chat.rb', line 106

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

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



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/ruby_llm/chat.rb', line 46

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



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

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



101
102
103
104
# File 'lib/ruby_llm/chat.rb', line 101

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

#with_schema(schema) ⇒ Object



111
112
113
114
115
116
117
118
119
# File 'lib/ruby_llm/chat.rb', line 111

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

  @schema = normalize_schema_payload(
    schema_instance.respond_to?(:to_json_schema) ? schema_instance.to_json_schema : schema_instance
  )

  self
end

#with_temperature(temperature) ⇒ Object



82
83
84
85
# File 'lib/ruby_llm/chat.rb', line 82

def with_temperature(temperature)
  @temperature = temperature
  self
end

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

Raises:

  • (ArgumentError)


87
88
89
90
91
92
# File 'lib/ruby_llm/chat.rb', line 87

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, choice: nil, calls: nil, concurrency: @concurrency) ⇒ Object



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

def with_tool(tool, choice: nil, calls: nil, concurrency: @concurrency)
  unless tool.nil?
    tool_instance = tool.is_a?(Class) ? tool.new : tool
    @tools[tool_instance.name.to_sym] = tool_instance
  end
  update_tool_options(choice:, calls:)
  update_tool_concurrency(concurrency)
  self
end

#with_tools(*tools, replace: false, choice: nil, calls: nil, concurrency: @concurrency) ⇒ Object



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

def with_tools(*tools, replace: false, choice: nil, calls: nil, concurrency: @concurrency)
  @tools.clear if replace
  tools.compact.each { |tool| with_tool tool }
  update_tool_options(choice:, calls:)
  update_tool_concurrency(concurrency)
  self
end