Class: RubyLLM::Agent

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable
Defined in:
lib/ruby_llm/agent.rb

Overview

Base class for simple, class-configured agents.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(chat: nil, inputs: nil, persist_instructions: true, **kwargs) ⇒ Agent

Returns a new instance of Agent.



351
352
353
354
355
356
# File 'lib/ruby_llm/agent.rb', line 351

def initialize(chat: nil, inputs: nil, persist_instructions: true, **kwargs)
  input_values, chat_options = self.class.send(:partition_inputs, kwargs)
  @chat = chat || RubyLLM.chat(**self.class.chat_kwargs, **chat_options)
  self.class.send(:apply_configuration, @chat, input_values: input_values.merge(inputs || {}),
                                               persist_instructions:)
end

Instance Attribute Details

#chatObject (readonly)

Returns the value of attribute chat.



358
359
360
# File 'lib/ruby_llm/agent.rb', line 358

def chat
  @chat
end

Class Method Details

.chat(**kwargs) ⇒ Object



103
104
105
106
107
108
# File 'lib/ruby_llm/agent.rb', line 103

def chat(**kwargs)
  input_values, chat_options = partition_inputs(kwargs)
  chat = RubyLLM.chat(**chat_kwargs, **chat_options)
  apply_configuration(chat, input_values:, persist_instructions: true)
  chat
end

.chat_kwargsObject



99
100
101
# File 'lib/ruby_llm/agent.rb', line 99

def chat_kwargs
  @chat_kwargs || {}
end

.chat_model(value = nil) ⇒ Object



86
87
88
89
90
91
# File 'lib/ruby_llm/agent.rb', line 86

def chat_model(value = nil)
  return @chat_model if value.nil?

  @chat_model = value
  remove_instance_variable(:@resolved_chat_model) if instance_variable_defined?(:@resolved_chat_model)
end

.context(value = nil) ⇒ Object



80
81
82
83
84
# File 'lib/ruby_llm/agent.rb', line 80

def context(value = nil)
  return @context if value.nil?

  @context = value
end

.create(**kwargs) ⇒ Object



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

def create(**kwargs)
  with_rails_chat_record(:create, **kwargs)
end

.create!(**kwargs) ⇒ Object



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

def create!(**kwargs)
  with_rails_chat_record(:create!, **kwargs)
end

.find(id, **kwargs) ⇒ Object

Raises:

  • (ArgumentError)


118
119
120
121
122
123
124
125
126
# File 'lib/ruby_llm/agent.rb', line 118

def find(id, **kwargs)
  raise ArgumentError, 'chat_model must be configured to use find' unless resolved_chat_model

  input_values, = partition_inputs(kwargs)
  record = resolved_chat_model.find(id)
  apply_configuration(record, input_values:, persist_instructions: false)

  record
end

.headers(**headers, &block) ⇒ Object



68
69
70
71
72
# File 'lib/ruby_llm/agent.rb', line 68

def headers(**headers, &block)
  return @headers || {} if headers.empty? && !block_given?

  @headers = block_given? ? block : headers
end

.inherited(subclass) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/ruby_llm/agent.rb', line 15

def inherited(subclass)
  super
  subclass.instance_variable_set(:@chat_kwargs, (@chat_kwargs || {}).dup)
  subclass.instance_variable_set(:@tools, (@tools || []).dup)
  subclass.instance_variable_set(:@instructions, @instructions)
  subclass.instance_variable_set(:@temperature, @temperature)
  subclass.instance_variable_set(:@thinking, @thinking)
  subclass.instance_variable_set(:@params, (@params || {}).dup)
  subclass.instance_variable_set(:@headers, (@headers || {}).dup)
  subclass.instance_variable_set(:@schema, @schema)
  subclass.instance_variable_set(:@context, @context)
  subclass.instance_variable_set(:@chat_model, @chat_model)
  subclass.instance_variable_set(:@input_names, (@input_names || []).dup)
end

.inputs(*names) ⇒ Object



93
94
95
96
97
# File 'lib/ruby_llm/agent.rb', line 93

def inputs(*names)
  return @input_names || [] if names.empty?

  @input_names = names.flatten.map(&:to_sym)
end

.instructions(text = nil, **prompt_locals, &block) ⇒ Object



41
42
43
44
45
46
47
48
# File 'lib/ruby_llm/agent.rb', line 41

def instructions(text = nil, **prompt_locals, &block)
  if text.nil? && prompt_locals.empty? && !block_given?
    @instructions ||= { prompt: 'instructions', locals: {} }
    return @instructions
  end

  @instructions = block || text || { prompt: 'instructions', locals: prompt_locals }
end

.model(model_id = nil, **options) ⇒ Object



30
31
32
33
# File 'lib/ruby_llm/agent.rb', line 30

def model(model_id = nil, **options)
  options[:model] = model_id unless model_id.nil?
  @chat_kwargs = options
end

.params(**params, &block) ⇒ Object



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

def params(**params, &block)
  return @params || {} if params.empty? && !block_given?

  @params = block_given? ? block : params
end

.render_prompt(name, chat:, inputs:, locals:) ⇒ Object



142
143
144
145
146
147
148
149
150
151
# File 'lib/ruby_llm/agent.rb', line 142

def render_prompt(name, chat:, inputs:, locals:)
  path = prompt_path_for(name)
  unless File.exist?(path)
    raise RubyLLM::PromptNotFoundError,
          "Prompt file not found for #{self}: #{path}. Create the file or use inline instructions."
  end

  resolved_locals = resolve_prompt_locals(locals, runtime: runtime_context(chat:, inputs:), chat:, inputs:)
  ERB.new(File.read(path)).result_with_hash(resolved_locals)
end

.schema(value = nil, &block) ⇒ Object



74
75
76
77
78
# File 'lib/ruby_llm/agent.rb', line 74

def schema(value = nil, &block)
  return @schema if value.nil? && !block_given?

  @schema = block_given? ? block : value
end

.sync_instructions!(chat_or_id, **kwargs) ⇒ Object

Raises:

  • (ArgumentError)


128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/ruby_llm/agent.rb', line 128

def sync_instructions!(chat_or_id, **kwargs)
  raise ArgumentError, 'chat_model must be configured to use sync_instructions!' unless resolved_chat_model

  input_values, = partition_inputs(kwargs)
  record = chat_or_id.is_a?(resolved_chat_model) ? chat_or_id : resolved_chat_model.find(chat_or_id)
  apply_assume_model_exists(record)
  runtime = runtime_context(chat: record, inputs: input_values)
  instructions_value = resolved_instructions_value(record, runtime, inputs: input_values)
  return record if instructions_value.nil?

  record.with_instructions(instructions_value)
  record
end

.temperature(value = nil) ⇒ Object



50
51
52
53
54
# File 'lib/ruby_llm/agent.rb', line 50

def temperature(value = nil)
  return @temperature if value.nil?

  @temperature = value
end

.thinking(effort: nil, budget: nil) ⇒ Object



56
57
58
59
60
# File 'lib/ruby_llm/agent.rb', line 56

def thinking(effort: nil, budget: nil)
  return @thinking if effort.nil? && budget.nil?

  @thinking = { effort: effort, budget: budget }
end

.tools(*tools, &block) ⇒ Object



35
36
37
38
39
# File 'lib/ruby_llm/agent.rb', line 35

def tools(*tools, &block)
  return @tools || [] if tools.empty? && !block_given?

  @tools = block_given? ? block : tools.flatten
end