Class: TurnKit::Cost
- Inherits:
-
Object
- Object
- TurnKit::Cost
- Defined in:
- lib/turnkit/cost.rb
Constant Summary collapse
- COMPONENTS =
%i[input output cache_read cache_write].freeze
- PER_MILLION =
1_000_000.0
Instance Attribute Summary collapse
-
#cache_read ⇒ Object
readonly
Returns the value of attribute cache_read.
-
#cache_write ⇒ Object
readonly
Returns the value of attribute cache_write.
-
#input ⇒ Object
readonly
Returns the value of attribute input.
-
#output ⇒ Object
readonly
Returns the value of attribute output.
Class Method Summary collapse
- .aggregate(costs) ⇒ Object
- .amount(tokens, price) ⇒ Object
- .custom_cost(usage, model) ⇒ Object
- .from_hash(hash) ⇒ Object
- .from_rates(usage, rates) ⇒ Object
- .from_record(record) ⇒ Object
- .from_records(records) ⇒ Object
- .from_ruby_llm(usage, model) ⇒ Object
- .from_usage(usage, model: nil) ⇒ Object
Instance Method Summary collapse
-
#initialize(input: nil, output: nil, cache_read: nil, cache_write: nil, total: nil, strict: false) ⇒ Cost
constructor
A new instance of Cost.
- #to_h ⇒ Object
- #total ⇒ Object
Constructor Details
#initialize(input: nil, output: nil, cache_read: nil, cache_write: nil, total: nil, strict: false) ⇒ Cost
Returns a new instance of Cost.
122 123 124 125 126 127 128 129 |
# File 'lib/turnkit/cost.rb', line 122 def initialize(input: nil, output: nil, cache_read: nil, cache_write: nil, total: nil, strict: false) @input = number(input) @output = number(output) @cache_read = number(cache_read) @cache_write = number(cache_write) @total = number(total) @strict = strict end |
Instance Attribute Details
#cache_read ⇒ Object (readonly)
Returns the value of attribute cache_read.
8 9 10 |
# File 'lib/turnkit/cost.rb', line 8 def cache_read @cache_read end |
#cache_write ⇒ Object (readonly)
Returns the value of attribute cache_write.
8 9 10 |
# File 'lib/turnkit/cost.rb', line 8 def cache_write @cache_write end |
#input ⇒ Object (readonly)
Returns the value of attribute input.
8 9 10 |
# File 'lib/turnkit/cost.rb', line 8 def input @input end |
#output ⇒ Object (readonly)
Returns the value of attribute output.
8 9 10 |
# File 'lib/turnkit/cost.rb', line 8 def output @output end |
Class Method Details
.aggregate(costs) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/turnkit/cost.rb', line 10 def self.aggregate(costs) costs = costs.compact return new unless costs.any? if costs.any? { |cost| COMPONENTS.any? { |component| !cost.public_send(component).nil? } } values = COMPONENTS.to_h do |component| amounts = costs.filter_map { |cost| cost.public_send(component) } [ component, amounts.any? ? amounts.sum : nil ] end return new(**values) end totals = costs.map(&:total) return new(total: totals.sum) if totals.none?(&:nil?) new end |
.amount(tokens, price) ⇒ Object
115 116 117 118 119 120 |
# File 'lib/turnkit/cost.rb', line 115 def self.amount(tokens, price) return nil if tokens.to_i.positive? && price.nil? return 0.0 if tokens.to_i.zero? tokens.to_i * price.to_f / PER_MILLION end |
.custom_cost(usage, model) ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/turnkit/cost.rb', line 99 def self.custom_cost(usage, model) return unless TurnKit.cost_calculator value = TurnKit.cost_calculator.call(usage, model) case value when nil nil when Cost value when Hash from_hash(value) else new(total: value) end end |
.from_hash(hash) ⇒ Object
88 89 90 91 92 93 94 95 96 97 |
# File 'lib/turnkit/cost.rb', line 88 def self.from_hash(hash) hash = hash.transform_keys(&:to_sym) new( input: hash[:input], output: hash[:output], cache_read: hash[:cache_read] || hash[:cached_input], cache_write: hash[:cache_write] || hash[:cache_creation], total: hash[:total] ) end |
.from_rates(usage, rates) ⇒ Object
51 52 53 54 55 56 57 58 59 60 |
# File 'lib/turnkit/cost.rb', line 51 def self.from_rates(usage, rates) rates = rates.transform_keys(&:to_sym) new( input: amount(usage.input_tokens, rates[:input] || rates[:input_per_million]), output: amount(usage.output_tokens, rates[:output] || rates[:output_per_million]), cache_read: amount(usage.cached_tokens, rates[:cache_read] || rates[:cached_input] || rates[:cache_read_input_per_million] || rates[:cached_input_per_million]), cache_write: amount(usage.cache_write_tokens, rates[:cache_write] || rates[:cache_creation] || rates[:cache_write_input_per_million] || rates[:cache_creation_input_per_million]), strict: true ) end |
.from_record(record) ⇒ Object
42 43 44 45 46 47 48 49 |
# File 'lib/turnkit/cost.rb', line 42 def self.from_record(record) attrs = record.transform_keys(&:to_s) usage = attrs["usage"] || {} return from_hash(usage["cost_details"] || usage[:cost_details]) if usage["cost_details"] || usage[:cost_details] return new(total: attrs["cost"]) if attrs["cost"] from_usage(Usage.from_h(usage), model: attrs["model"]) end |
.from_records(records) ⇒ Object
38 39 40 |
# File 'lib/turnkit/cost.rb', line 38 def self.from_records(records) aggregate(records.map { |record| from_record(record) }) end |
.from_ruby_llm(usage, model) ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/turnkit/cost.rb', line 62 def self.from_ruby_llm(usage, model) require "ruby_llm" model_info = ::RubyLLM.models.find(model) if model return new unless model_info if defined?(::RubyLLM::Cost) tokens = ::RubyLLM::Tokens.new( input: usage.input_tokens, output: usage.output_tokens, cached: usage.cached_tokens, cache_creation: usage.cache_write_tokens ) from_hash(::RubyLLM::Cost.new(tokens: tokens, model: model_info).to_h) else from_rates( usage, input: model_info.input_price_per_million, output: model_info.output_price_per_million, cached_input: model_info.pricing&.text_tokens&.cached_input ) end rescue LoadError, StandardError new end |
.from_usage(usage, model: nil) ⇒ Object
28 29 30 31 32 33 34 35 36 |
# File 'lib/turnkit/cost.rb', line 28 def self.from_usage(usage, model: nil) return new(total: usage.cost) if usage.cost custom = custom_cost(usage, model) return custom if custom rates = TurnKit.cost_rates[model.to_s] || TurnKit.cost_rates[model&.to_sym] rates ? from_rates(usage, rates) : from_ruby_llm(usage, model) end |
Instance Method Details
#to_h ⇒ Object
139 140 141 142 143 144 145 146 147 |
# File 'lib/turnkit/cost.rb', line 139 def to_h { "input" => input, "output" => output, "cache_read" => cache_read, "cache_write" => cache_write, "total" => total }.compact end |
#total ⇒ Object
131 132 133 134 135 136 137 |
# File 'lib/turnkit/cost.rb', line 131 def total return @total if @total return nil if @strict && COMPONENTS.any? { |component| public_send(component).nil? } values = COMPONENTS.filter_map { |component| public_send(component) } values.empty? ? nil : values.sum end |