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%
7.8 KB · 119 lines python
Raw Blame History
1"""/deployments (cursor page of `Deployment` rows) · /cost (per request / day / month / year for every current deployment) ·2/cost/context (cost of one fully populated context)."""3from __future__ import annotations45from typing import Any67from fastapi import APIRouter, Query, Request89from aiatlas.api.common import (10    PRICE_COLS,11    PRICE_FROM,12    ApiError,13    cached,14    deployment_row,15    parse_ts,16    resolve_entity,17    resolve_id,18)19from aiatlas.db import connection, fetch_all, fetch_val20from aiatlas.services.cost import compute_cost, context_fill_cost2122router = APIRouter(prefix="/api/v1", tags=["deployments"])23TOTAL_CAP = 10_000242526@router.get("/deployments")27@cached(300)28async def list_deployments(request: Request, model: str | None = None, provider: str | None = None, current: int = Query(1, ge=0, le=1), limit: int = Query(50, ge=1, le=200),29                           offset: int = Query(0, ge=0, le=10000), before: str | None = Query(None, description="cursor: valid_from of the last item"),30                           org: str | None = None, sort: str = Query("valid_from", pattern="^(valid_from|output|input|model|provider)$"),31                           status: str | None = Query(None, pattern="^(active|delisted|all)$", description="active = current rows (default when current=1), delisted = closed rows only, all = both")) -> dict[str, Any]:32    where = ["m.entity_type in ('model','artifact')"]33    params: dict[str, Any] = {"lim": limit, "off": offset}34    status = status or ("active" if current else "all")35    if status == "active":36        where.append("p.valid_to is null")37        where.append("m.merged_into is null")38    elif status == "delisted":39        where.append("p.valid_to is not null")40    else:41        where.append("(p.valid_to is not null or m.merged_into is null)")  # closed rows of since-merged models stay visible as history42    before_ts = parse_ts(before, "before")43    if before_ts is not None:44        where.append("p.valid_from < :before")45        params["before"] = before_ts46    async with connection() as conn:47        if model:48            where.append("p.model_id = :model")49            params["model"] = await resolve_id(conn, model)50        if provider:51            where.append("p.provider_id = :provider")52            params["provider"] = await resolve_id(conn, provider)53        if org:54            where.append("(mo.slug = :org or mo.id = :org or mo.canonical_name ilike :org)")55            params["org"] = org56        order = {"valid_from": ("p.valid_to desc nulls last, p.id desc" if status == "delisted" else "p.valid_from desc, p.id desc"), "output": "p.output_per_mtok asc nulls last, p.id",57                 "input": "p.input_per_mtok asc nulls last, p.id", "model": "m.canonical_name asc, pv.canonical_name asc, p.id", "provider": "pv.canonical_name asc, m.canonical_name asc, p.id"}[sort]58        where_sql = " and ".join(where)59        rows = await fetch_all(conn, f"select {PRICE_COLS} from {PRICE_FROM} where {where_sql} order by {order} limit :lim offset :off", **params)60        total = await fetch_val(conn, f"select count(*) from (select 1 from {PRICE_FROM} where {where_sql} limit {TOTAL_CAP}) t", **{k: v for k, v in params.items() if k not in ('lim', 'off')})61    items = [deployment_row(r) for r in rows]62    return {"items": items, "total": int(total or 0), "limit": limit, "offset": offset,63            "next_before": items[-1]["valid_from"] if len(items) == limit and sort == "valid_from" and status != "delisted" else None, "current": bool(current), "status": status}646566@router.get("/cost")67@cached(300)68async def cost(request: Request, model: str = Query(..., description="model slug or id"), provider: str | None = None, input_tokens: int = Query(1000, ge=0, le=100_000_000),69               output_tokens: int = Query(500, ge=0, le=100_000_000), requests_per_day: float = Query(1000, ge=0, le=1e9), cached_share: float = Query(0.0, ge=0, le=1),70               batch: int = Query(0, ge=0, le=1)) -> dict[str, Any]:71    async with connection() as conn:72        m = await resolve_entity(conn, model, ("model", "artifact"))73        where = ["p.model_id = :mid", "p.valid_to is null"]74        params: dict[str, Any] = {"mid": m["id"]}75        if provider:76            where.append("p.provider_id = :pid")77            params["pid"] = await resolve_id(conn, provider, ("provider",))78        rows = await fetch_all(conn, f"select {PRICE_COLS} from {PRICE_FROM} where {' and '.join(where)} order by p.output_per_mtok asc nulls last, pv.canonical_name limit 200", **params)79    items = []80    for r in rows:81        d = deployment_row(r)82        c = compute_cost(d["prices"], input_tokens=input_tokens, output_tokens=output_tokens, requests_per_day=requests_per_day, cached_share=cached_share, batch=bool(batch))83        items.append({"deployment": d, "cost": c})84    items.sort(key=lambda x: (x["cost"]["per_request"] is None, x["cost"]["per_request"] or 0))85    return {"model": {"id": m["id"], "slug": m["slug"], "name": m["canonical_name"]}, "inputs": {"input_tokens": input_tokens, "output_tokens": output_tokens, "requests_per_day": requests_per_day,86                                                                                               "cached_share": cached_share, "batch": bool(batch)},87            "items": items, "total": len(items), "currency": "USD",88            "methodology": "per_request = input_tokens × effective input price / 1e6 + output_tokens × output price / 1e6 (+ per-request fee when published); "89                           "effective input = (1 − cached_share) × input + cached_share × cached input (falls back to the standard price with a note); "90                           "batch uses batch prices when published; daily = per_request × requests_per_day; monthly = daily × 30; annual = daily × 365. Only current offers.",91            "note": None if items else "no current deployment for this model"}929394@router.get("/cost/context")95@cached(300)96async def cost_context(request: Request, tokens: int = Query(1_000_000, ge=1, le=100_000_000), limit: int = Query(50, ge=1, le=500), model: str | None = None,97                       org: str | None = None) -> dict[str, Any]:98    """Cost of ONE fully populated context of `tokens` input tokens per current deployment whose context window is ≥ tokens, cheapest first."""99    where = ["p.valid_to is null", "p.input_per_mtok > 0", "m.entity_type in ('model','artifact')", "m.merged_into is null",100             "coalesce(p.context_length, case when m.attributes->>'context_length' ~ '^[0-9]+$' then (m.attributes->>'context_length')::bigint end) >= :tokens"]101    params: dict[str, Any] = {"tokens": tokens, "lim": limit}102    async with connection() as conn:103        if model:104            where.append("p.model_id = :mid")105            params["mid"] = await resolve_id(conn, model)106        if org:107            where.append("(mo.slug = :org or mo.id = :org or mo.canonical_name ilike :org)")108            params["org"] = org109        rows = await fetch_all(conn, f"""select {PRICE_COLS}, coalesce(p.context_length, case when m.attributes->>'context_length' ~ '^[0-9]+$' then (m.attributes->>'context_length')::bigint end) as ctx110                                         from {PRICE_FROM} where {' and '.join(where)} order by p.input_per_mtok asc, m.canonical_name limit :lim""", **params)111    items = [{"deployment": deployment_row(r), "context_length": r["ctx"], "context_source": "offer" if r.get("context_length") else "model attribute",112              "cost_usd": context_fill_cost(r["input_per_mtok"], tokens)} for r in rows]113    return {"tokens": tokens, "items": items, "total": len(items), "currency": "USD",114            "methodology": "cost = input price (USD per 1M tokens) × tokens / 1e6 for every current offer whose context window (offer's, else the model's attribute) is at least `tokens`. "115                           "Long-context surcharges published as native units are not applied."}116117118__all__ = ["ApiError", "router"]119