Module: Legion::LLM::CostTracker

Extended by:
Legion::Logging::Helper
Defined in:
lib/legion/llm/cost_tracker.rb

Constant Summary collapse

DEFAULT_PRICING =

Default per-1M-token pricing in USD (input / output). Overridable via Legion::Settings[:pricing].

{
  'claude-sonnet-4-6' => { input: 3.0,  output: 15.0 },
  'claude-haiku-4-5'  => { input: 0.80, output: 4.0  },
  'claude-opus-4-6'   => { input: 15.0, output: 75.0 },
  'gpt-4o'            => { input: 2.50, output: 10.0 },
  'gpt-4o-mini'       => { input: 0.15, output: 0.60 }
}.freeze

Class Method Summary collapse

Class Method Details

.clearObject

Clears all recorded entries.



68
69
70
# File 'lib/legion/llm/cost_tracker.rb', line 68

def clear
  @records = []
end

.pricing_for(model) ⇒ Hash

Returns pricing for a model, preferring settings-defined overrides.

Parameters:

  • model (String)

    model identifier

Returns:

  • (Hash)

    with :input and :output keys (per-1M-token USD)



76
77
78
79
# File 'lib/legion/llm/cost_tracker.rb', line 76

def pricing_for(model)
  custom = settings_pricing
  custom[model.to_s] || DEFAULT_PRICING[model.to_s] || { input: 5.0, output: 15.0 }
end

.record(model:, input_tokens:, output_tokens:, provider: nil) ⇒ Hash

Records a completed LLM request and calculates its cost.

Parameters:

  • model (String)

    model identifier

  • input_tokens (Integer)

    number of input tokens consumed

  • output_tokens (Integer)

    number of output tokens produced

  • provider (Symbol, nil) (defaults to: nil)

    provider (informational)

Returns:

  • (Hash)

    the recorded entry



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/legion/llm/cost_tracker.rb', line 27

def record(model:, input_tokens:, output_tokens:, provider: nil)
  pricing = pricing_for(model)
  cost    = (input_tokens * pricing[:input] / 1_000_000.0) +
            (output_tokens * pricing[:output] / 1_000_000.0)

  entry = {
    model:         model,
    provider:      provider,
    input_tokens:  input_tokens,
    output_tokens: output_tokens,
    cost_usd:      cost.round(6),
    recorded_at:   Time.now
  }

  records << entry
  log.debug "[LLM::CostTracker] #{model}: #{input_tokens}+#{output_tokens} tokens = $#{cost.round(6)}"
  entry
end

.summary(since: nil) ⇒ Hash

Returns a cost summary, optionally filtered by a start time.

Parameters:

  • since (Time, nil) (defaults to: nil)

    include only records on or after this time

Returns:

  • (Hash)

    with :total_cost_usd, :total_requests, token totals, and :by_model breakdown



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/legion/llm/cost_tracker.rb', line 50

def summary(since: nil)
  subset = since ? records.select { |r| r[:recorded_at] >= since } : records.dup

  {
    total_cost_usd:      subset.sum { |r| r[:cost_usd] }.round(6),
    total_requests:      subset.size,
    total_input_tokens:  subset.sum { |r| r[:input_tokens] },
    total_output_tokens: subset.sum { |r| r[:output_tokens] },
    by_model:            subset.group_by { |r| r[:model] }.transform_values do |rs|
      {
        cost_usd: rs.sum { |r| r[:cost_usd] }.round(6),
        requests: rs.size
      }
    end
  }
end