Class: LlmCostTracker::Budget

Inherits:
Object
  • Object
show all
Defined in:
lib/llm_cost_tracker/budget.rb

Constant Summary collapse

BUDGET_TYPE_TO_PERIOD =
{ monthly: :month, daily: :day }.freeze

Class Method Summary collapse

Class Method Details

.check!(event) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/llm_cost_tracker/budget.rb', line 36

def check!(event)
  config = LlmCostTracker.configuration
  return unless event.total_cost

  check_per_call_budget(event, config)
  budgets = { daily: config.daily_budget, monthly: config.monthly_budget }.compact
  totals = totals_for(budgets.keys, time: event.tracked_at)

  budgets.each do |budget_type, budget|
    total = totals.fetch(budget_type)

    handle_exceeded(budget_type: budget_type, total: total, budget: budget, last_event: event) if total >= budget
  end
end

.enforce!(provider: nil, model: nil, request: nil) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/llm_cost_tracker/budget.rb', line 14

def enforce!(provider: nil, model: nil, request: nil)
  config = LlmCostTracker.configuration
  return unless config.budget_exceeded_behavior == :block_requests

  estimate = estimate_cost(provider: provider, model: model, request: request)
  raise_per_call_pre_send(estimate, config.per_call_budget) if config.per_call_budget && estimate.positive?

  budgets = { monthly: config.monthly_budget, daily: config.daily_budget }.compact
  return if budgets.empty?

  totals = totals_for(budgets.keys, time: Time.now.utc)

  budgets.each do |budget_type, budget|
    total = totals.fetch(budget_type) + estimate
    next unless total >= budget

    raise BudgetExceededError.new(**budget_payload(
      budget_type: budget_type, total: total, budget: budget, last_event: nil, stage: :pre_send
    ))
  end
end