Add price mode: emit computed dollar cost instead of token counts#8
Open
anassg-lago wants to merge 1 commit into
Open
Add price mode: emit computed dollar cost instead of token counts#8anassg-lago wants to merge 1 commit into
anassg-lago wants to merge 1 commit into
Conversation
New optional pricing_mode ("tokens" default | "price"). In price mode the SDK
emits one llm_cost event per call whose value is Σ(unit_price × tokens) × markup,
with a full per-field breakdown (tokens, unit_price, cost, base_cost, markup,
price_source) in properties.
Pricing sources (public, no API keys):
- OpenRouter /api/v1/models for native anthropic/openai/mistral/gemini (USD/token)
- AWS Bedrock Price List Bulk API (per-region offer files) for Bedrock
Design:
- pricing.py: PricingProvider with a TTL cache + injectable fetcher; lookup()
is pure in-memory and never blocks the call; maybe_refresh() does the HTTP on
the queue's background thread. Fork-safe via a PID self-heal (no
register_at_fork — that tripped macOS's objc fork-safety abort).
- Conservative, vendor-gated model matching; Bedrock parser keys on
inferenceType and rejects priority/flex/batch tiers, scales per-1K units.
- Money in Decimal floored to 12 dp; identical output to the JS BigInt impl
(locked by a cross-repo golden fixture).
- Fallback: unavailable price -> emit token events + on_error (never under-bill).
- mode + markup overridable per-call via extra_lago; global via LagoConfig.
Default mode is "tokens" -> zero behavior change. New config: pricing_mode,
markup, cost_metric_code, pricing_ttl_seconds, bedrock_default_region,
pricing_provider. 28 new pricing unit tests + env-gated live test.
Gate: ruff + format + mypy clean; 346 unit tests; coverage 88.27%.
Contributor
|
@anassg-lago do we only compute this in dollars? Is there any plan to do other currencies? Seems like if there is room for that we should do it in this PR. |
vladmarascu
requested changes
Jun 12, 2026
| "timestamp": int(time.time()), | ||
| # Top-level amount (in cents) for Lago's dynamic charge model — | ||
| # the charge sums these into a single fee. | ||
| "precise_total_amount_cents": breakdown.total_cents, |
Contributor
There was a problem hiding this comment.
is this sent as string? Worth checking if we accept this as str in the Lago model
| self._queue.push(event) | ||
| price = self._pricing.lookup(usage.provider, usage.model, usage.api) | ||
| if price is None: | ||
| # Don't silently under-bill: fall back to token events + report. |
Contributor
There was a problem hiding this comment.
Here it could be worth adding a more clear fall-back?
Add a price_fallback config with three modes, and — this is the important part — pick a default that matches the setup the README tells people to create (a single llm_cost dynamic charge).
# config.py
# What to emit in price mode when a unit price can't be resolved.
PriceFallback = Literal["zero_cost_event", "token_events", "drop"]
price_fallback: PriceFallback = "zero_cost_event"
# sdk.py — the price-None branch
price = self._pricing.lookup(usage.provider, usage.model, usage.api)
if price is None:
self._report_error(PricingUnavailableError(usage.provider, usage.model, usage.api), "pricing")
self._handle_price_unavailable(usage, sub, dimensions) # switches on config.price_fallback
return
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
New optional pricing_mode ("tokens" default | "price"). In price mode the SDK emits one llm_cost event per call whose value is Σ(unit_price × tokens) × markup, with a full per-field breakdown (tokens, unit_price, cost, base_cost, markup, price_source) in properties.
Pricing sources (public, no API keys):
Design:
Default mode is "tokens" -> zero behavior change. New config: pricing_mode, markup, cost_metric_code, pricing_ttl_seconds, bedrock_default_region, pricing_provider. 28 new pricing unit tests + env-gated live test.