foley.cost#
Cost: what a call will cost before it is made, and a cumulative cap on a run (#57).
Three pieces, each small:
Pricing as data. Each source declares
SOURCE_CONFIG['pricing']— the falaw convention (unit,amount_usd, plus thesourceandseendate the price was read from).estimate_call()turns it into dollars for one call, and returnsNone— never0.0— when the cost cannot be known (no pricing, or a per-second price with no duration and no maximum).A run-scoped budget.
spend_scope()makes aBudgetthe active one for afind/score/generaterun;authorize()is called before every paid call and refuses the first one that would take the run pastmax_usd(defaultdefault_max_usd():DEFAULT_MAX_USD, $1 — maintainer decision on #57 — or, when the caller chosea paid LLM for the SELECT rungs,
DEFAULT_MAX_USD_BY_LLM, #88), or whose cost is unknown unless the budget approves unknown costs.
Two errors.
BudgetExceededand its subclassCostApprovalRequired.
Stdlib-only.
Module Attributes
The default cumulative cap for one run (a |
|
The default cap of a |
|
Set to 1 to approve calls whose cost is unknown, for every run that does not say. |
Functions
|
The USD cost of one call to the source |
|
Put |
|
Iterate |
The innermost |
|
|
Raise unless every budget in force can afford |
|
Admit a paid call: every budget in force must afford it, and each reserves it. |
|
Replace each budget's reservation with the actual cost ( |
|
Undo a reservation for a call that was never sent. |
|
The cap of a run given no budget: higher when the caller chose a paid LLM. |
|
Record |
Exceptions
Raised before a paid call that would take the run past its |
|
Raised before a call whose cost is unknown, when the budget has not approved that. |
- foley.cost.APPROVE_UNKNOWN_COST_ENV = 'FOLEY_APPROVE_UNKNOWN_COST'#
Set to 1 to approve calls whose cost is unknown, for every run that does not say.
- exception foley.cost.BudgetExceeded[source]#
Bases:
RuntimeErrorRaised before a paid call that would take the run past its
max_usdcap.
- exception foley.cost.CostApprovalRequired[source]#
Bases:
BudgetExceededRaised before a call whose cost is unknown, when the budget has not approved that.
- foley.cost.DEFAULT_MAX_USD: float = 1.0#
The default cumulative cap for one run (a
find/score/generatecall).
- foley.cost.DEFAULT_MAX_USD_BY_LLM: dict[str, float] = {'anthropic': 3.0}#
The default cap of a
foley.find()run whose LLM rungs the caller chose to pay for (llm=or$FOLEY_LLM), keyed by provider. With the defaults (6 events,k=10,verify='listen') Claude’s upper bound is about $2.52, so the $1 cap would refuse every such run before its first call; $3 lets it run and still caps it. A run usually spends far less than its bound (#88).Budget(max_usd=...)overrides it.
- foley.cost.authorize(estimate_usd, *, what)[source]#
Admit a paid call: every budget in force must afford it, and each reserves it.
The reservation is atomic per budget, so concurrent calls cannot all pass before any is counted. Call
settle()afterwards with the actual cost when known; a call that fails after being sent keeps its reservation (it may have been billed); one refused before sending is released withrelease().- Raises:
CostApprovalRequired – If
estimate_usdisNoneand a budget in force has not approved unknown costs (Budget.approve_unknown_cost/$FOLEY_APPROVE_UNKNOWN_COST).BudgetExceeded – If a budget’s spend plus
estimate_usdexceeds itsmax_usd.
- Return type:
- foley.cost.charge(usd)[source]#
Record
usdagainst every budget in force (a no-op outside any run).- Return type:
- foley.cost.check(estimate_usd, *, what)[source]#
Raise unless every budget in force can afford
estimate_usd(reserves nothing).For a whole-run upper bound (
find’s pre-flight).- Return type:
- foley.cost.default_max_usd(llm=None)[source]#
The cap of a run given no budget: higher when the caller chose a paid LLM.
The provider is the one named by
llmor, failing that,$FOLEY_LLM(the free default never resolves to a paid one); seeDEFAULT_MAX_USD_BY_LLM.- Return type:
>>> default_max_usd("fake") 1.0 >>> default_max_usd("anthropic") 3.0
- foley.cost.estimate_call(config, **affordances)[source]#
The USD cost of one call to the source
configdeclares, orNoneif unknown.config['pricing']units:'free'(local inference, a free API tier) →0.0;'per_call'→amount_usd;'per_second'→amount_usd× the requestedduration, or × the backend’snative_defaults['duration_max_s']when the duration is left to the backend (an upper bound), elseNone.
- foley.cost.release(reserved_usd)[source]#
Undo a reservation for a call that was never sent.
- Return type:
- foley.cost.scoped_iter(iterator_factory, budget=None)[source]#
Iterate
iterator_factory()withbudgetin force only while it runs.A generator that holds a
spend_scope()acrossyieldwould leave its budget active in the caller’s context between items (so the caller’s own calls, or another interleaved stream, would charge it). This re-enters the scope for each step and leaves it before handing the item out; closing the stream closes the inner iterator inside the scope too.
- foley.cost.settle(reserved_usd, actual_usd)[source]#
Replace each budget’s reservation with the actual cost (
None: keep it).- Return type:
- foley.cost.spend_scope(budget=None)[source]#
Put
budgetin force for the block; every enclosing budget stays in force too.Budgets stack: a paid call must fit every budget in force (so an explicit, stricter
budgetinside afind/scorerun still applies) and is charged to each of them once. With nobudget: inside a run, nothing changes; outside one, a fresh defaultBudgetis used ($1).- Yields:
The innermost budget in force.