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.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 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
  @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



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

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



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

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

#completeObject

rubocop:disable Metrics/PerceivedComplexity



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/ruby_llm/chat.rb', line 124

def complete(&) # rubocop:disable Metrics/PerceivedComplexity
  response = @provider.complete(
    messages,
    tools: @tools,
    temperature: @temperature,
    model: @model,
    params: @params,
    headers: @headers,
    schema: @schema,
    &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



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

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

#instance_variablesObject



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

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

#on_end_message(&block) ⇒ Object



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

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

#on_new_message(&block) ⇒ Object



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

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

#on_tool_call(&block) ⇒ Object



110
111
112
113
# File 'lib/ruby_llm/chat.rb', line 110

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

#on_tool_result(&block) ⇒ Object



115
116
117
118
# File 'lib/ruby_llm/chat.rb', line 115

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

#reset_messages!Object



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

def reset_messages!
  @messages.clear
end

#with_context(context) ⇒ Object



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

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



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

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

#with_instructions(instructions, replace: false) ⇒ Object



40
41
42
43
44
45
# File 'lib/ruby_llm/chat.rb', line 40

def with_instructions(instructions, replace: false)
  @messages = @messages.reject { |msg| msg.role == :system } if replace

  add_message role: :system, content: instructions
  self
end

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



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

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



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

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

#with_schema(schema) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/ruby_llm/chat.rb', line 87

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



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

def with_temperature(temperature)
  @temperature = temperature
  self
end

#with_tool(tool) ⇒ Object



47
48
49
50
51
# File 'lib/ruby_llm/chat.rb', line 47

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



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

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