SPB Git forge

spb/ai-atlas

Public
41commits 1branches 0releases
4.6 MBsize
maindefault branch
12 days agolast push
HTML 77.2% TypeScript 10.5% Python 9.6% JavaScript 2.5%
3.5 KB · 76 lines python
Raw Blame History
1"""Cost arithmetic for API deployments (pure, deterministic). Prices are USD per 1M tokens; nothing is assumed when a price is missing —2the affected component is `null` and a `note` says why.34    per_request = input_tokens × effective_input / 1e6 + output_tokens × effective_output / 1e6 (+ per_request fee when published)5    effective_input  = (1 − cached_share) × input + cached_share × cached_input        (cached_input falls back to input with a note)6    batch            = batch_input / batch_output when published (else the standard prices, with a note)7    daily = per_request × requests_per_day · monthly = daily × 30 · annual = daily × 3658"""9from __future__ import annotations1011from typing import Any1213DAYS_PER_MONTH = 3014DAYS_PER_YEAR = 365151617def _f(v: Any) -> float | None:18    if v is None or isinstance(v, bool):19        return None20    try:21        return float(v)22    except (TypeError, ValueError):23        return None242526def compute_cost(prices: dict[str, Any], *, input_tokens: int, output_tokens: int, requests_per_day: float = 1.0, cached_share: float = 0.0,27                 batch: bool = False) -> dict[str, Any]:28    """`prices` uses the Deployment `prices` keys (input, output, cached_input, batch_input, batch_output, per_request)."""29    notes: list[str] = []30    cached_share = min(1.0, max(0.0, float(cached_share or 0.0)))31    inp, outp = _f(prices.get("input")), _f(prices.get("output"))32    if batch:33        bi, bo = _f(prices.get("batch_input")), _f(prices.get("batch_output"))34        if bi is None or bo is None:35            notes.append("batch prices not published for this deployment; standard prices used")36        inp = bi if bi is not None else inp37        outp = bo if bo is not None else outp38    eff_input = inp39    if cached_share > 0 and inp is not None:40        cached = _f(prices.get("cached_input"))41        if cached is None:42            notes.append("cached input price not published; cached share billed at the standard input price")43            cached = inp44        eff_input = (1 - cached_share) * inp + cached_share * cached45    fee = _f(prices.get("per_request")) or 0.046    if inp is None:47        notes.append("input price unavailable")48    if outp is None:49        notes.append("output price unavailable")50    if eff_input is None or outp is None:51        per_request = None52    else:53        per_request = input_tokens * eff_input / 1e6 + output_tokens * outp / 1e6 + fee54    daily = per_request * requests_per_day if per_request is not None else None55    return {56        "per_request": _round(per_request, 8), "daily": _round(daily, 6),57        "monthly": _round(daily * DAYS_PER_MONTH, 4) if daily is not None else None,58        "annual": _round(daily * DAYS_PER_YEAR, 4) if daily is not None else None,59        "effective_input_per_mtok": _round(eff_input, 6), "effective_output_per_mtok": _round(outp, 6), "per_request_fee": fee or None,60        "inputs": {"input_tokens": input_tokens, "output_tokens": output_tokens, "requests_per_day": requests_per_day, "cached_share": cached_share, "batch": batch},61        "notes": notes,62    }636465def context_fill_cost(input_per_mtok: Any, tokens: int) -> float | None:66    """Cost of one fully populated context of `tokens` input tokens."""67    p = _f(input_per_mtok)68    return _round(p * tokens / 1e6, 6) if p is not None else None697071def _round(v: float | None, nd: int) -> float | None:72    return round(v, nd) if v is not None else None737475__all__ = ["DAYS_PER_MONTH", "DAYS_PER_YEAR", "compute_cost", "context_fill_cost"]76