- templates/web/pricing.py: pricing table with source and as-of date; cost_for_call
(input rate + (output + thinking) at output rate, long-context above threshold;
unknown model raises naming the known models).
- Cost tab: coverage pill, total/this-month/tokens tiles, month-by-month table,
per-run tokens and cost ("not priced", never $0), by-hand panel with editable
assumptions labelled as such.
- Contract: RoiRun and GET /roi; optional GET /models and POST /runs/{id}/retry.
- SKILL.md: cost page wiring, model picker and retry-on-other-model as optional sections.
- Tests: test_pricing.py self-check, page_check_ai/test_ai_cost.py.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
33 lines
1.5 KiB
Python
33 lines
1.5 KiB
Python
"""Pricing table and cost per call for the cost page. The backend imports it.
|
|
|
|
Rates are USD per million tokens. Thinking tokens bill at the output rate. A model
|
|
with "long_threshold" switches both rates to its *_long rates when a call's input
|
|
tokens go above that threshold.
|
|
|
|
Replace the table with the rates of the provider and models the project really uses,
|
|
copied from the provider's pricing page, and update PRICING_SOURCE and PRICING_AS_OF.
|
|
Never guess a rate: a model missing here is an error, never a cost of zero.
|
|
"""
|
|
|
|
PRICING_SOURCE = "https://ai.google.dev/gemini-api/docs/pricing"
|
|
PRICING_AS_OF = "2026-08-11"
|
|
|
|
PRICING = {
|
|
"gemini-2.5-pro": {"input": 1.25, "output": 10.00,
|
|
"long_threshold": 200_000, "input_long": 2.50, "output_long": 15.00},
|
|
"gemini-2.5-flash": {"input": 0.30, "output": 2.50},
|
|
"gemini-2.5-flash-lite": {"input": 0.10, "output": 0.40},
|
|
}
|
|
|
|
|
|
def cost_for_call(model, input_tokens, output_tokens, thinking_tokens=0):
|
|
"""USD for one call. Raises ValueError, naming the known models, for a model not in PRICING."""
|
|
if model not in PRICING:
|
|
raise ValueError(f"No pricing for model '{model}'. Add it to PRICING from {PRICING_SOURCE}. "
|
|
f"Known models: {', '.join(PRICING)}")
|
|
p = PRICING[model]
|
|
in_rate, out_rate = p["input"], p["output"]
|
|
if "long_threshold" in p and input_tokens > p["long_threshold"]:
|
|
in_rate, out_rate = p["input_long"], p["output_long"]
|
|
return (input_tokens * in_rate + (output_tokens + thinking_tokens) * out_rate) / 1_000_000
|