Class: Rubyagents::Memory

Inherits:
Object
  • Object
show all
Defined in:
lib/rubyagents/memory.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(system_prompt:, task:) ⇒ Memory



38
39
40
41
42
43
44
# File 'lib/rubyagents/memory.rb', line 38

def initialize(system_prompt:, task:)
  @system_prompt = system_prompt
  @task = task
  @steps = []
  @total_tokens = TokenUsage.new(input_tokens: 0, output_tokens: 0)
  @total_duration = 0.0
end

Instance Attribute Details

#steps ⇒ Object (readonly)

Returns the value of attribute steps.



36
37
38
# File 'lib/rubyagents/memory.rb', line 36

def steps
  @steps
end

#system_prompt ⇒ Object (readonly)

Returns the value of attribute system_prompt.



36
37
38
# File 'lib/rubyagents/memory.rb', line 36

def system_prompt
  @system_prompt
end

#task ⇒ Object (readonly)

Returns the value of attribute task.



36
37
38
# File 'lib/rubyagents/memory.rb', line 36

def task
  @task
end

#total_duration ⇒ Object (readonly)

Returns the value of attribute total_duration.



36
37
38
# File 'lib/rubyagents/memory.rb', line 36

def total_duration
  @total_duration
end

#total_tokens ⇒ Object (readonly)

Returns the value of attribute total_tokens.



36
37
38
# File 'lib/rubyagents/memory.rb', line 36

def total_tokens
  @total_tokens
end

Instance Method Details

#action_steps ⇒ Object



70
71
72
# File 'lib/rubyagents/memory.rb', line 70

def action_steps
  @steps.select { |s| s.is_a?(ActionStep) }
end

#add_plan(plan:, duration: 0.0, token_usage: nil) ⇒ Object



61
62
63
64
# File 'lib/rubyagents/memory.rb', line 61

def add_plan(plan:, duration: 0.0, token_usage: nil)
  step = PlanningStep.new(plan: plan, duration: duration, token_usage: token_usage)
  record_step(step, duration, token_usage)
end

#add_step(thought:, code: nil, tool_calls: nil, observation: nil, error: nil, duration: 0.0, token_usage: nil) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/rubyagents/memory.rb', line 46

def add_step(thought:, code: nil, tool_calls: nil, observation: nil, error: nil,
             duration: 0.0, token_usage: nil)
  step = ActionStep.new(
    step_number: action_steps.size + 1,
    thought: thought,
    code: code,
    tool_calls: tool_calls,
    observation: observation,
    error: error,
    duration: duration,
    token_usage: token_usage
  )
  record_step(step, duration, token_usage)
end

#add_user_message(message) ⇒ Object



66
67
68
# File 'lib/rubyagents/memory.rb', line 66

def add_user_message(message)
  @steps << UserMessage.new(content: message)
end

#last_step ⇒ Object



119
120
121
# File 'lib/rubyagents/memory.rb', line 119

def last_step
  @steps.last
end

#progress_summary ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/rubyagents/memory.rb', line 74

def progress_summary
  completed = action_steps
  return "No steps completed yet." if completed.empty?

  lines = ["Steps completed so far:"]
  completed.each do |step|
    status = step.error ? "failed" : "done"
    summary = step.thought || step.observation || "no details"
    lines << "  #{step.step_number}. [#{status}] #{summary.to_s[0, 100]}"
  end
  lines.join("\n")
end

#replay(io: $stdout) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/rubyagents/memory.rb', line 142

def replay(io: $stdout)
  io.puts UI::Styles.final_answer.render("Task: ") + task.to_s
  io.puts

  steps.each do |step|
    case step
    when ActionStep
      replay_action_step(step, io)
    when PlanningStep
      io.puts UI::Styles.plan_label.render(" Plan ")
      io.puts UI::Styles.plan_box.render(step.plan)
      replay_metrics(step, io)
    when UserMessage
      io.puts UI::Styles.label.render("User: ") + step.content.to_s
      io.puts
    end
  end

  parts = ["#{action_steps.size} steps", format("%.1fs total", total_duration)]
  parts << total_tokens.to_s if total_tokens.total_tokens > 0
  io.puts UI::Styles.dim.render(parts.join(" | "))
end

#return_full_code ⇒ Object



123
124
125
# File 'lib/rubyagents/memory.rb', line 123

def return_full_code
  action_steps.filter_map(&:code).join("\n\n")
end

#to_h ⇒ Object



127
128
129
130
131
132
133
134
135
# File 'lib/rubyagents/memory.rb', line 127

def to_h
  {
    system_prompt: system_prompt,
    task: task,
    steps: steps.map(&:to_h),
    total_tokens: total_tokens.to_h,
    total_duration: total_duration
  }
end

#to_json(*args) ⇒ Object



137
138
139
140
# File 'lib/rubyagents/memory.rb', line 137

def to_json(*args)
  require "json"
  to_h.to_json(*args)
end

#to_messages ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/rubyagents/memory.rb', line 87

def to_messages
  messages = [
    { role: "system", content: system_prompt },
    { role: "user", content: task }
  ]

  steps.each do |step|
    case step
    when UserMessage
      messages << { role: "user", content: step.content }
    when PlanningStep
      messages << { role: "assistant", content: "Plan:\n#{step.plan}" }
      messages << { role: "user", content: "Now proceed and carry out this plan." }
    when ActionStep
      assistant_msg = build_assistant_message(step)
      messages << assistant_msg if assistant_msg

      if step.observation
        messages << { role: "user", content: "Observation: #{step.observation}" }
      elsif step.error
        messages << {
          role: "user",
          content: "Error: #{step.error}\nNow let's retry: take care not to repeat previous errors! " \
                   "If you have retried several times, try a completely different approach."
        }
      end
    end
  end

  messages.each { |m| m[:content] = sanitize_utf8(m[:content]) if m[:content] }
end