Module: LlmCostTracker::Pricing::Registry
- Defined in:
- lib/llm_cost_tracker/pricing/registry.rb
Constant Summary collapse
- DEFAULT_PRICES_PATH =
File.("../prices.json", __dir__)
- CONTEXT_THRESHOLD_KEY =
"_context_price_threshold_tokens"- PRICE_KEYS =
Usage::Catalog.token_priced.map(&:key).freeze
- METADATA_KEYS =
["_source", CONTEXT_THRESHOLD_KEY].freeze
Class Method Summary collapse
- .builtin_prices ⇒ Object
- .builtin_rates ⇒ Object
- .file_metadata(path) ⇒ Object
- .file_prices(path) ⇒ Object
- .file_rates(path) ⇒ Object
- .metadata ⇒ Object
- .normalize_price_entries(table, context:) ⇒ Object
- .prices_file_mtime_iso ⇒ Object
- .rates_from_registry(registry, context:) ⇒ Object
- .raw_file_registry(path) ⇒ Object
- .raw_registry ⇒ Object
- .reset! ⇒ Object
- .sorted_price_keys(table) ⇒ Object
- .sources ⇒ Object
Class Method Details
.builtin_prices ⇒ Object
36 37 38 39 40 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 36 def builtin_prices @builtin_prices ||= normalize_price_entries( raw_registry.fetch("models", {}), context: "bundled prices" ).freeze end |
.builtin_rates ⇒ Object
81 82 83 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 81 def builtin_rates @builtin_rates ||= rates_from_registry(raw_registry, context: DEFAULT_PRICES_PATH).freeze end |
.file_metadata(path) ⇒ Object
46 47 48 49 50 51 52 53 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 46 def (path) return {} unless path = raw_file_registry(path).fetch("metadata", {}) return if .is_a?(Hash) raise Error, "Unable to load prices_file #{path.inspect}: prices_file metadata must be a hash" end |
.file_prices(path) ⇒ Object
55 56 57 58 59 60 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 55 def file_prices(path) return {} unless path prices, @file_prices = memoize_in(@file_prices, path) { load_file_prices(path) } prices end |
.file_rates(path) ⇒ Object
85 86 87 88 89 90 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 85 def file_rates(path) return {} unless path rates, @file_rates = memoize_in(@file_rates, path) { load_file_rates(path) } rates end |
.metadata ⇒ Object
42 43 44 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 42 def @metadata ||= raw_registry.fetch("metadata", {}).freeze end |
.normalize_price_entries(table, context:) ⇒ Object
62 63 64 65 66 67 68 69 70 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 62 def normalize_price_entries(table, context:) table = {} if table.nil? raise ArgumentError, "#{context} must be a hash of models" unless table.is_a?(Hash) table.each_with_object({}) do |(model, price), normalized| price = validate_price_entry(price, model: model, context: context) normalized[model.to_s] = normalize_price_entry(model, price, context) end end |
.prices_file_mtime_iso ⇒ Object
103 104 105 106 107 108 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 103 def prices_file_mtime_iso path = LlmCostTracker.configuration.prices_file return nil unless path && File.exist?(path) @prices_file_mtime_iso ||= File.mtime(path).utc.iso8601 end |
.rates_from_registry(registry, context:) ⇒ Object
92 93 94 95 96 97 98 99 100 101 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 92 def rates_from_registry(registry, context:) data = registry.fetch("service_charges", {}) raise ArgumentError, "#{context} service_charges must be a hash" unless data.is_a?(Hash) currency = upcased_currency(registry.dig("metadata", "currency")) data.each_with_object({}) do |(provider, entries), rates| section_context = "#{context} service_charges.#{provider}" rates[provider] = rates_from_section(entries, currency: currency, context: section_context) end end |
.raw_file_registry(path) ⇒ Object
76 77 78 79 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 76 def raw_file_registry(path) registry, @raw_file_registries = memoize_in(@raw_file_registries, path) { load_raw_file_registry(path) } registry end |
.raw_registry ⇒ Object
72 73 74 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 72 def raw_registry @raw_registry ||= YAML.safe_load_file(DEFAULT_PRICES_PATH, aliases: false).freeze end |
.reset! ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 23 def reset! @builtin_prices = nil @metadata = nil @raw_registry = nil @raw_file_registries = nil @file_prices = nil @builtin_rates = nil @file_rates = nil @sources = nil @sorted_price_keys_cache = nil @prices_file_mtime_iso = nil end |
.sorted_price_keys(table) ⇒ Object
139 140 141 142 143 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 139 def sorted_price_keys(table) keys, @sorted_price_keys_cache = memoize_in(@sorted_price_keys_cache, table, identity: true) { table.keys.sort_by { |key| -key.length } } keys end |
.sources ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/llm_cost_tracker/pricing/registry.rb', line 110 def sources @sources ||= begin config = LlmCostTracker.configuration [ Source.new( name: "pricing_overrides", prices: config.pricing_overrides, rates: {}, currency: upcased_currency(nil), version: "configuration" ), Source.new( name: "prices_file", prices: file_prices(config.prices_file), rates: file_rates(config.prices_file), currency: upcased_currency((config.prices_file)["currency"]), version: prices_file_mtime_iso ), Source.new( name: "bundled", prices: builtin_prices, rates: builtin_rates, currency: upcased_currency(["currency"]), version: LlmCostTracker::VERSION ) ].freeze end end |