Class: RubyLLM::Cost
- Inherits:
-
Object
- Object
- RubyLLM::Cost
- Includes:
- Support::Inspectable
- Defined in:
- lib/ruby_llm/cost.rb
Overview
A Cost prices token usage in US dollars using pricing from the model registry. Usage entries own accounting events; Message and Chat aggregate calls, and Model#cost_for prices any token usage against a specific model.
response = chat.ask "Summarize Ruby's object model."
response.cost.total
cost = model.cost_for(response.tokens)
cost.input
cost.output
The components are RubyLLM's normalized token buckets: #input, #output,
#cache_read, #cache_write, and #thinking. When the registry lacks
pricing for tokens that were used, the affected component and #total
return nil instead of a false zero.
When the provider reports the exact cost of a call, #total returns the reported amount instead of a registry-price estimate, even when registry pricing is missing.
Costs are computed when the object is built. Readers do not recalculate them when registry prices change. ::aggregate and ::from_h return the same class, so a single call, a whole chat, and a stored breakdown all read the same way.
Constant Summary collapse
- COMPONENTS =
:nodoc:
%i[input output cache_read cache_write thinking].freeze
- PER_MILLION =
:nodoc:
1_000_000.0
Constants included from Support::Inspectable
Support::Inspectable::TRUNCATE_AT
Class Method Summary collapse
-
.aggregate(costs, complete: true) ⇒ Object
Combines several costs into one Cost that sums each component.
-
.from_h(hash, tokens: nil) ⇒ Object
Rebuilds a cost from a stored breakdown Hash, as produced by #to_h and persisted alongside a usage entry.
Instance Method Summary collapse
-
#cache_read ⇒ Object
Returns the cost of cache-read input tokens in US dollars, or
nilwhen the token count or its pricing is unavailable. -
#cache_write ⇒ Object
Returns the cost of cache-write input tokens in US dollars, or
nilwhen the token count or its pricing is unavailable. -
#initialize(tokens: nil, model: nil, category: :text_tokens, input_details: nil, tier: :standard, amounts: nil, missing: nil, reported: nil, complete: true, total: nil) ⇒ Cost
constructor
:nodoc:.
-
#input ⇒ Object
Returns the cost of input tokens in US dollars, or
nilwhen the token count or its pricing is unavailable. -
#missing?(component) ⇒ Boolean
:nodoc:.
-
#output ⇒ Object
Returns the cost of billable output tokens in US dollars, or
nilwhen the token count or its pricing is unavailable. -
#thinking ⇒ Object
Returns the cost of thinking tokens in US dollars, or
nilwhen the model does not price reasoning output separately from regular output or the token count is unavailable. -
#to_h ⇒ Object
Returns a hash of component costs in US dollars, plus
:total, omittingnilvalues. -
#tokens? ⇒ Boolean
:nodoc:.
-
#total ⇒ Object
Returns the sum of all components in US dollars, or the exact amount the provider reported when it reported one.
Methods included from Support::Inspectable
#full_inspect, #inspect, #pretty_print
Constructor Details
#initialize(tokens: nil, model: nil, category: :text_tokens, input_details: nil, tier: :standard, amounts: nil, missing: nil, reported: nil, complete: true, total: nil) ⇒ Cost
:nodoc:
99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/ruby_llm/cost.rb', line 99 def initialize(tokens: nil, model: nil, category: :text_tokens, input_details: nil, tier: :standard, # :nodoc: amounts: nil, missing: nil, reported: nil, complete: true, total: nil) if amounts @amounts = amounts @missing = missing || [] @reported = reported else price_tokens(tokens, model, category, input_details, tier) total = reported_total if total.nil? @reported ||= !total.nil? end @complete = complete @total = total end |
Class Method Details
.aggregate(costs, complete: true) ⇒ Object
Combines several costs into one Cost that sums each component.
Ignores nil entries. A component returns nil when pricing was
missing for one of the calls, or when no call has a cost for that
component. Pass complete: false when some requests are still
running or their costs are unknown; #total then remains nil.
cost = RubyLLM::Cost.aggregate(.map(&:cost))
cost.total
44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/ruby_llm/cost.rb', line 44 def aggregate(costs, complete: true) costs = costs.compact.select(&:tokens?) missing = COMPONENTS.select do |component| costs.any? { |cost| cost.missing?(component) } end amounts = COMPONENTS.to_h do |component| values = costs.filter_map { |cost| cost.public_send(component) } [component, missing.include?(component) || values.empty? ? nil : values.sum] end new(amounts:, missing:, reported: costs.any?, complete:, total: aggregate_total(costs)) end |
.from_h(hash, tokens: nil) ⇒ Object
66 67 68 69 70 71 72 73 |
# File 'lib/ruby_llm/cost.rb', line 66 def from_h(hash, tokens: nil) amounts = COMPONENTS.to_h { |component| [component, hash[component] || hash[component.to_s]] } total_recorded = hash.key?(:total) || hash.key?('total') total = hash[:total] || hash['total'] if total_recorded missing = missing_recorded_components(amounts, tokens, total_recorded) new(amounts:, missing:, reported: recorded_tokens?(amounts, tokens, total_recorded), total:) end |
Instance Method Details
#cache_read ⇒ Object
Returns the cost of cache-read input tokens in US dollars, or nil
when the token count or its pricing is unavailable.
128 129 130 |
# File 'lib/ruby_llm/cost.rb', line 128 def cache_read @amounts[:cache_read] end |
#cache_write ⇒ Object
Returns the cost of cache-write input tokens in US dollars, or nil
when the token count or its pricing is unavailable.
134 135 136 |
# File 'lib/ruby_llm/cost.rb', line 134 def cache_write @amounts[:cache_write] end |
#input ⇒ Object
Returns the cost of input tokens in US dollars, or nil when the
token count or its pricing is unavailable.
116 117 118 |
# File 'lib/ruby_llm/cost.rb', line 116 def input @amounts[:input] end |
#missing?(component) ⇒ Boolean
:nodoc:
179 180 181 |
# File 'lib/ruby_llm/cost.rb', line 179 def missing?(component) # :nodoc: @missing.include?(component) end |
#output ⇒ Object
Returns the cost of billable output tokens in US dollars, or nil
when the token count or its pricing is unavailable.
122 123 124 |
# File 'lib/ruby_llm/cost.rb', line 122 def output @amounts[:output] end |
#thinking ⇒ Object
Returns the cost of thinking tokens in US dollars, or nil when
the model does not price reasoning output separately from regular
output or the token count is unavailable. When not priced
separately, thinking tokens are part of #output.
142 143 144 |
# File 'lib/ruby_llm/cost.rb', line 142 def thinking @amounts[:thinking] end |
#to_h ⇒ Object
Returns a hash of component costs in US dollars, plus :total,
omitting nil values.
164 165 166 167 168 169 170 171 172 173 |
# File 'lib/ruby_llm/cost.rb', line 164 def to_h { input: input, output: output, cache_read: cache_read, cache_write: cache_write, thinking: thinking, total: total }.compact end |
#tokens? ⇒ Boolean
:nodoc:
175 176 177 |
# File 'lib/ruby_llm/cost.rb', line 175 def tokens? # :nodoc: @reported end |
#total ⇒ Object
Returns the sum of all components in US dollars, or the exact amount
the provider reported when it reported one. Returns nil when there
is no token usage, or when pricing is missing for tokens that were
used and the provider reported no cost.
150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/ruby_llm/cost.rb', line 150 def total return nil unless @complete return nil unless tokens? return @total unless @total.nil? return nil if @missing.any? amounts = @amounts.values.compact return nil if amounts.empty? amounts.sum end |