Class: Llmemory::LLM::UsageLedger

Inherits:
Object
  • Object
show all
Defined in:
lib/llmemory/llm/usage_ledger.rb

Overview

Cumulative LLM token usage per user, persisted in the short-term store under a pseudo-session key (same pattern as ForgetLog).

Constant Summary collapse

SESSION_KEY =
"__llm_usage__"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(store: nil) ⇒ UsageLedger

Returns a new instance of UsageLedger.



13
14
15
# File 'lib/llmemory/llm/usage_ledger.rb', line 13

def initialize(store: nil)
  @store = store || ShortTerm::Stores.build
end

Class Method Details

.format_text(totals) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/llmemory/llm/usage_ledger.rb', line 57

def self.format_text(totals)
  inv = totals[:invoke]
  emb = totals[:embed]
  lines = [
    "LLM TOKEN USAGE:",
    "  Chat/completions: #{inv[:total_tokens]} total (#{inv[:input_tokens]} in, #{inv[:output_tokens]} out, #{inv[:calls]} calls)",
    "  Embeddings: #{emb[:total_tokens]} total (#{emb[:calls]} calls)"
  ]
  lines << "  Last updated: #{totals[:updated_at]}" if totals[:updated_at]
  lines.join("\n")
end

Instance Method Details

#record(user_id, usage, operation:) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/llmemory/llm/usage_ledger.rb', line 17

def record(user_id, usage, operation:)
  @store.update(user_id, SESSION_KEY) do |state|
    state = normalize(state || default_state)
    case operation.to_sym
    when :invoke
      bucket = state[:invoke]
      state = state.merge(
        invoke: {
          input_tokens: bucket[:input_tokens] + usage.input_tokens,
          output_tokens: bucket[:output_tokens] + usage.output_tokens,
          total_tokens: bucket[:total_tokens] + usage.total_tokens,
          calls: bucket[:calls] + 1
        }
      )
    when :embed
      bucket = state[:embed]
      state = state.merge(
        embed: {
          total_tokens: bucket[:total_tokens] + usage.total_tokens,
          calls: bucket[:calls] + 1
        }
      )
    else
      next state
    end
    state.merge(updated_at: Time.now.iso8601)
  end
  totals(user_id)
end

#reset!(user_id) ⇒ Object



51
52
53
54
55
# File 'lib/llmemory/llm/usage_ledger.rb', line 51

def reset!(user_id)
  empty = default_state
  @store.save(user_id, SESSION_KEY, stringify(empty))
  empty
end

#totals(user_id) ⇒ Object



47
48
49
# File 'lib/llmemory/llm/usage_ledger.rb', line 47

def totals(user_id)
  normalize(load_raw(user_id))
end