Class: RLM::Trace

Inherits:
Object
  • Object
show all
Defined in:
lib/rlm/trace.rb

Constant Summary collapse

EVENT_TYPES =
%i[
  run_started
  root_prompt_created
  root_lm_called
  code_generated
  code_executed
  file_read
  tool_called
  sub_lm_called
  output_submitted
  runtime_logged
  validation_attempted
  validation_failed
  budget_checked
  run_completed
  run_failed
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id: SecureRandom.uuid, clock: Time.method(:now)) ⇒ Trace

Returns a new instance of Trace.



29
30
31
32
33
34
# File 'lib/rlm/trace.rb', line 29

def initialize(id: SecureRandom.uuid, clock: Time.method(:now))
  @id = id
  @events = []
  @clock = clock
  @started_at = clock.call
end

Instance Attribute Details

#eventsObject (readonly)

Returns the value of attribute events.



27
28
29
# File 'lib/rlm/trace.rb', line 27

def events
  @events
end

#idObject (readonly)

Returns the value of attribute id.



27
28
29
# File 'lib/rlm/trace.rb', line 27

def id
  @id
end

#started_atObject (readonly)

Returns the value of attribute started_at.



27
28
29
# File 'lib/rlm/trace.rb', line 27

def started_at
  @started_at
end

Instance Method Details

#cost_centsObject



63
64
65
# File 'lib/rlm/trace.rb', line 63

def cost_cents
  llm_calls.sum { |e| e[:payload][:cost_cents].to_i }
end

#duration_msObject



67
68
69
70
71
# File 'lib/rlm/trace.rb', line 67

def duration_ms
  return 0 if events.empty?

  ((@clock.call - @started_at) * 1000).to_i
end

#files_readObject



55
56
57
# File 'lib/rlm/trace.rb', line 55

def files_read
  events.select { |e| e[:type] == :file_read }
end

#llm_callsObject



47
48
49
# File 'lib/rlm/trace.rb', line 47

def llm_calls
  events.select { |e| %i[root_lm_called sub_lm_called].include?(e[:type]) }
end

#record(type, payload = {}) ⇒ Object

Raises:

  • (ArgumentError)


36
37
38
39
40
41
# File 'lib/rlm/trace.rb', line 36

def record(type, payload = {})
  raise ArgumentError, "Unknown trace event type: #{type.inspect}" unless EVENT_TYPES.include?(type)

  events << { type: type, payload: payload, at: @clock.call.iso8601(6) }
  self
end

#stepsObject



43
44
45
# File 'lib/rlm/trace.rb', line 43

def steps
  events.select { |e| %i[code_generated code_executed].include?(e[:type]) }
end

#to_hObject



73
74
75
76
77
78
79
# File 'lib/rlm/trace.rb', line 73

def to_h
  {
    id: id,
    started_at: started_at.iso8601(6),
    events: events
  }
end

#to_jsonObject



81
82
83
# File 'lib/rlm/trace.rb', line 81

def to_json(*)
  JSON.generate(to_h, *)
end

#to_ndjsonObject



85
86
87
# File 'lib/rlm/trace.rb', line 85

def to_ndjson
  events.map { |e| JSON.generate(e) }.join("\n")
end

#tool_callsObject



51
52
53
# File 'lib/rlm/trace.rb', line 51

def tool_calls
  events.select { |e| e[:type] == :tool_called }
end

#validation_errorsObject



59
60
61
# File 'lib/rlm/trace.rb', line 59

def validation_errors
  events.select { |e| e[:type] == :validation_failed }
end