Class: Lemans::CLI::Report::Aggregate

Inherits:
Object
  • Object
show all
Defined in:
lib/lemans/cli/report/aggregate.rb

Overview

Rolls trials up the way a leaderboard quotes them: solved out of attempts, median time, mean spend per run. Groups by any 1-3 of task, agent, model — "task-model" reads as two columns.

Constant Summary collapse

KEYS =
%i[task agent model].freeze
METRICS =
%i[score time cost steps tokens].freeze
METRIC_SOURCES =
{ time: :duration, cost: :cost_usd, steps: :steps, tokens: :tokens }.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(report, keys:) ⇒ Aggregate

Returns a new instance of Aggregate.



25
26
27
28
29
30
31
32
33
# File 'lib/lemans/cli/report/aggregate.rb', line 25

def initialize(report, keys:)
  @report = report
  @keys = keys

  @groups = report.rows
                  .group_by { |row| keys.map { row[it] } }
                  .map { |values, group| build(values, group) }
                  .sort_by { |group| keys.map { group[it].to_s } }
end

Instance Attribute Details

#keysObject (readonly)

Returns the value of attribute keys.



16
17
18
# File 'lib/lemans/cli/report/aggregate.rb', line 16

def keys
  @keys
end

#reportObject (readonly)

Returns the value of attribute report.



16
17
18
# File 'lib/lemans/cli/report/aggregate.rb', line 16

def report
  @report
end

Class Method Details

.keys(spec) ⇒ Object

Raises:



18
19
20
21
22
23
# File 'lib/lemans/cli/report/aggregate.rb', line 18

def self.keys(spec)
  keys = spec.to_s.split("-").map(&:to_sym)
  return keys if keys.size.between?(1, 3) && keys.uniq == keys && (keys - KEYS).empty?

  raise ConfigError, "--aggregate: expected 1-3 of #{KEYS.join(", ")} joined by dashes (got #{spec.inspect})"
end

Instance Method Details

#order_by!(column) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/lemans/cli/report/aggregate.rb', line 35

def order_by!(column)
  column = Report.sort_column(column, allowed: keys + METRICS)
  @groups =
    if keys.include?(column)
      Report.sort_rows(@groups) { it[column].to_s }
    elsif column == :score
      Report.sort_rows(@groups, descending: true) { [ Rational(it[:solved], it[:attempts]), it[:attempts] ] }
    else
      Report.sort_rows(@groups, descending: true) { it[METRIC_SOURCES.fetch(column)] }
    end
  self
end

#summaryObject



69
# File 'lib/lemans/cli/report/aggregate.rb', line 69

def summary = report.summary

#summary_linesObject



71
# File 'lib/lemans/cli/report/aggregate.rb', line 71

def summary_lines = report.summary_lines

#to_csvObject



61
62
63
64
65
66
67
# File 'lib/lemans/cli/report/aggregate.rb', line 61

def to_csv
  columns = keys + %i[solved attempts duration cost_usd steps tokens]
  CSV.generate do |csv|
    csv << columns
    @groups.each { |group| csv << columns.map { group[it] } }
  end
end

#to_rowsObject



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/lemans/cli/report/aggregate.rb', line 48

def to_rows
  [ keys.map(&:to_s) + METRICS.map(&:to_s) ] +
    @groups.map do |group|
      keys.map { |key| display_key(key, group[key]) } + [
        "#{group[:solved]}/#{group[:attempts]}",
        time(group[:duration]),
        cost(group[:cost_usd]),
        mean_display(group[:steps], 1),
        mean_display(group[:tokens], 0)
      ]
    end
end