Module: LlmCostTracker::Billing::Components

Defined in:
lib/llm_cost_tracker/billing/components.rb

Defined Under Namespace

Classes: Component

Constant Summary collapse

REQUIRED_FIELDS =
%i[key kind direction modality cache_state unit category].freeze
DEFINITIONS_PATH =
File.expand_path("components.yml", __dir__)
REGISTRY =
load_registry
BY_KEY =
REGISTRY.to_h { |component| [component.key, component] }.freeze
TOKEN_PRICED =
REGISTRY.select { |component| component.token_key && component.cost_key }.freeze

Class Method Summary collapse

Class Method Details

.build(attributes) ⇒ Object

Raises:



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/llm_cost_tracker/billing/components.rb', line 63

def self.build(attributes)
  missing = REQUIRED_FIELDS - attributes.keys
  raise Error, "components.yml entry missing #{missing.join(', ')}: #{attributes.inspect}" if missing.any?

  unit = attributes.fetch(:unit).to_sym
  rate_basis = attributes[:rate_basis]&.to_sym || Billing::DEFAULT_RATE_BASIS_BY_UNIT[unit]
  if rate_basis.nil?
    raise Error, "components.yml entry needs rate_basis for unit #{unit.inspect}: #{attributes.inspect}"
  end
  unless Billing::RATE_BASES.include?(rate_basis)
    raise Error, "components.yml entry has unknown rate_basis #{rate_basis.inspect}: #{attributes.inspect}"
  end

  Component.new(
    key: attributes.fetch(:key).to_sym,
    kind: attributes.fetch(:kind).to_sym,
    direction: attributes.fetch(:direction).to_sym,
    modality: attributes.fetch(:modality).to_sym,
    cache_state: attributes.fetch(:cache_state).to_sym,
    unit: unit,
    category: attributes.fetch(:category).to_sym,
    token_key: attributes[:token_key]&.to_sym,
    cost_key: attributes[:cost_key]&.to_sym,
    rate_basis: rate_basis
  )
end

.load_registryObject



57
58
59
60
61
# File 'lib/llm_cost_tracker/billing/components.rb', line 57

def self.load_registry
  Psych.safe_load_file(DEFINITIONS_PATH, permitted_classes: [], symbolize_names: true)
       .map { |attributes| build(attributes) }
       .freeze
end