Class: Mistri::Usage
- Inherits:
-
Object
- Object
- Mistri::Usage
- Defined in:
- lib/mistri/usage.rb
Overview
Token accounting for an assistant turn, and the dollar cost of those tokens.
input counts only prompt tokens billed at the full rate: cache reads and
writes are separate fields, so a cached token is never double-billed.
reasoning is the thinking slice of output. cache_write_1h is the slice
of cache_write held for an hour, which bills at twice the input rate.
Defined Under Namespace
Classes: Cost
Class Method Summary collapse
Instance Method Summary collapse
- #+(other) ⇒ Object
-
#initialize(input: 0, output: 0, cache_read: 0, cache_write: 0, cache_write_1h: 0, reasoning: 0, cost: Cost.unknown) ⇒ Usage
constructor
A new instance of Usage.
- #prompt_tokens ⇒ Object
- #to_h ⇒ Object
- #total_tokens ⇒ Object
-
#with_cost(rates) ⇒ Object
A copy with cost computed from per-million-token rates.
Constructor Details
#initialize(input: 0, output: 0, cache_read: 0, cache_write: 0, cache_write_1h: 0, reasoning: 0, cost: Cost.unknown) ⇒ Usage
Returns a new instance of Usage.
59 60 61 62 |
# File 'lib/mistri/usage.rb', line 59 def initialize(input: 0, output: 0, cache_read: 0, cache_write: 0, cache_write_1h: 0, reasoning: 0, cost: Cost.unknown) super end |
Class Method Details
.from_h(hash) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/mistri/usage.rb', line 66 def self.from_h(hash) h = (hash || {}).transform_keys(&:to_s) c = (h["cost"] || {}).transform_keys(&:to_s) counts = { input: h.fetch("input", 0).to_i, output: h.fetch("output", 0).to_i, cache_read: h.fetch("cache_read", 0).to_i, cache_write: h.fetch("cache_write", 0).to_i, cache_write_1h: h.fetch("cache_write_1h", 0).to_i, reasoning: h.fetch("reasoning", 0).to_i } amounts = { input: c.fetch("input", 0).to_f, output: c.fetch("output", 0).to_f, cache_read: c.fetch("cache_read", 0).to_f, cache_write: c.fetch("cache_write", 0).to_f, total: c.fetch("total", 0).to_f } known = c.fetch("known", false) == true known ||= !c.key?("known") && counts.values.all?(&:zero?) && amounts.values.all?(&:zero?) new(**counts, cost: Cost.new(**amounts, known:)) end |
Instance Method Details
#+(other) ⇒ Object
104 105 106 107 108 109 110 111 |
# File 'lib/mistri/usage.rb', line 104 def +(other) self.class.new(input: input + other.input, output: output + other.output, cache_read: cache_read + other.cache_read, cache_write: cache_write + other.cache_write, cache_write_1h: cache_write_1h + other.cache_write_1h, reasoning: reasoning + other.reasoning, cost: cost + other.cost) end |
#prompt_tokens ⇒ Object
83 |
# File 'lib/mistri/usage.rb', line 83 def prompt_tokens = input + cache_read + cache_write |
#to_h ⇒ Object
113 |
# File 'lib/mistri/usage.rb', line 113 def to_h = super.merge(cost: cost.to_h) |
#total_tokens ⇒ Object
85 |
# File 'lib/mistri/usage.rb', line 85 def total_tokens = input + output + cache_read + cache_write |
#with_cost(rates) ⇒ Object
A copy with cost computed from per-million-token rates. The 1h cache-write slice bills at the :cache_write_1h rate when given, else at twice the input rate, matching extended-retention pricing.
90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/mistri/usage.rb', line 90 def with_cost(rates) long = [cache_write_1h, cache_write].min short = cache_write - long computed = { input: rate(rates, :input) * input, output: rate(rates, :output) * output, cache_read: rate(rates, :cache_read) * cache_read, cache_write: (rate(rates, :cache_write) * short) + (long_write_rate(rates) * long) } with(cost: Cost.new(**computed, total: computed.values.sum, known: rates_cover?(rates, short, long))) end |