Class: Omakase::Agent

Inherits:
Object
  • Object
show all
Defined in:
lib/omakase/agent.rb

Overview

Fields are state, methods are what the model can call, generates declares the methods the model implements.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(chat: nil) ⇒ Agent

chat: injects a prepared RubyLLM::Chat — the seam for tests.



77
78
79
# File 'lib/omakase/agent.rb', line 77

def initialize(chat: nil)
  @chat = chat
end

Class Method Details

.chat_optionsObject



51
# File 'lib/omakase/agent.rb', line 51

def chat_options = @chat_options ||= {}

.describe(text) ⇒ Object

Documents the method defined next — the docstring Ruby does not have.



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

def describe(text)
  @pending_description = text
end

.descriptionsObject



49
# File 'lib/omakase/agent.rb', line 49

def descriptions = @descriptions ||= {}

.generates(name, prompt = nil, returns: nil, strategy: nil, &schema) ⇒ Object

Without a prompt, the method name is the prompt.



36
37
38
39
40
41
42
43
44
45
# File 'lib/omakase/agent.rb', line 36

def generates(name, prompt = nil, returns: nil, strategy: nil, &schema)
  generations[name] = Generation.new(
    name:,
    prompt: prompt || humanize(name),
    schema: Schema.define(returns:, &schema),
    strategy: Strategies.fetch(strategy || self.strategy)
  )
  define_method(name) { |**inputs| generate(name, inputs) }
  define_singleton_method(name) { |**inputs| new.public_send(name, **inputs) }
end

.generationsObject



47
# File 'lib/omakase/agent.rb', line 47

def generations = @generations ||= {}

.instructions(text = nil) ⇒ Object



18
19
20
21
22
# File 'lib/omakase/agent.rb', line 18

def instructions(text = nil)
  return @instructions.to_s if text.nil?

  @instructions = text
end

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

The model and any RubyLLM chat option. Naming a provider takes the model id on trust, since providers like OpenRouter or Ollama serve ids that are not in RubyLLM's registry.



11
12
13
14
15
16
# File 'lib/omakase/agent.rb', line 11

def model(id = nil, **options)
  return chat_options if id.nil? && options.empty?

  options = {assume_model_exists: true, **options} if options[:provider]
  @chat_options = {model: id, **options}.compact
end

.strategy(name = nil) ⇒ Object



24
25
26
27
28
# File 'lib/omakase/agent.rb', line 24

def strategy(name = nil)
  return @strategy || :code_act if name.nil?

  @strategy = name
end

Instance Method Details

#chatObject

A fresh conversation per call.



82
# File 'lib/omakase/agent.rb', line 82

def chat = @chat || RubyLLM.chat(**self.class.chat_options)

#doc(object) ⇒ Object

For generated code meeting an object whose type it does not know.



85
# File 'lib/omakase/agent.rb', line 85

def doc(object) = puts(Doc.of(object))

#finish(value) ⇒ Object

How generated code answers: with the value itself.



88
# File 'lib/omakase/agent.rb', line 88

def finish(value) = throw(Executor::RESULT, value)

#p(*args) ⇒ Object Also known as: pp



96
97
98
99
# File 'lib/omakase/agent.rb', line 96

def p(*args)
  args.each { |arg| omakase_output.puts(arg.inspect) }
  args.size <= 1 ? args.first : args
end


94
# File 'lib/omakase/agent.rb', line 94

def print(*args) = omakase_output.print(*args)

#puts(*args) ⇒ Object

Printing from generated code goes to the observation, not to the process's stdout — and the buffer is per thread, so concurrent agents stay separate.



92
# File 'lib/omakase/agent.rb', line 92

def puts(*args) = omakase_output.puts(*args)