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%
9.9 KB · 125 lines python
Raw Blame History
1"""/diff?a=&b=&scope= — what changed between two dates: new / gone entities, property, price and benchmark changes, new benchmark leaders,2provider listings, hardware, context changes, retired models. API 1.1: events use `occurred_at` and `is_backfill = false`; `new_entities`3excludes artifacts unless `include=artifacts`."""4from __future__ import annotations56from datetime import UTC, datetime7from datetime import time as dtime8from typing import Any910from fastapi import APIRouter, Query, Request1112from aiatlas.api.common import (13    ENTITY_COLS,14    ENTITY_FROM,15    EVENT_COLS,16    EVENT_FROM,17    ApiError,18    cached,19    change_event,20    entity_summary,21    parse_date,22)23from aiatlas.db import connection, fetch_all, fetch_one, fetch_val24from aiatlas.services.frontier import benchmark_meta, leader_at, load_results2526router = APIRouter(prefix="/api/v1/diff", tags=["diff"])27GONE_TYPES = ("RETIREMENT_ANNOUNCED", "DEPRECATION_ANNOUNCED", "STATUS_CHANGED", "ENTITY_MERGED", "MODEL_RETIRED", "MODEL_DEPRECATED")28RETIRED_PRED = "(ev.event_type in ('RETIREMENT_ANNOUNCED','DEPRECATION_ANNOUNCED','MODEL_RETIRED','MODEL_DEPRECATED') or (ev.event_type = 'STATUS_CHANGED' and ev.new_value::text ~* 'retired|deprecated'))"29_leaders_at = leader_at303132async def _scope(conn: Any, scope: str) -> tuple[str, str, dict[str, Any], dict[str, Any]]:33    """Returns (entity where-fragment on alias e, event where-fragment on alias e, params, scope description)."""34    s = (scope or "all").strip()35    if s == "all":36        return "true", "true", {}, {"kind": "all"}37    if s == "models":38        return "e.entity_type = 'model'", "e.entity_type = 'model'", {}, {"kind": "models"}39    if s.startswith("org:"):40        key = s[4:]41        org = await fetch_one(conn, "select id, slug, canonical_name from entities where slug = :k or id = :k limit 1", k=key)42        if not org:43            raise ApiError(404, f"organization {key!r} not found")44        frag = "(e.organization_id = :org or e.id = :org)"45        return frag, frag, {"org": org["id"]}, {"kind": "org", "organization": {"id": org["id"], "slug": org["slug"], "name": org["canonical_name"]}}46    if s.startswith("family:"):47        frag = "(e.attributes->>'family' ilike :family or exists (select 1 from entities f where f.id = e.family_id and (f.slug = :family or f.canonical_name ilike :family)))"48        return frag, frag, {"family": s[7:]}, {"kind": "family", "family": s[7:]}49    raise ApiError(400, "scope must be all | models | org:<slug> | family:<name>")505152@router.get("")53@cached(300)54async def diff(request: Request, a: str = Query(..., description="YYYY-MM-DD"), b: str = Query(..., description="YYYY-MM-DD"), scope: str = "all",55               limit: int = Query(200, ge=1, le=1000), include: str | None = None, include_backfill: int = Query(0, ge=0, le=1)) -> dict[str, Any]:56    da, db = parse_date(a, "a"), parse_date(b, "b")57    assert da is not None and db is not None58    if da > db:59        da, db = db, da60    start, end = datetime.combine(da, dtime.max, UTC), datetime.combine(db, dtime.max, UTC)61    include_artifacts = "artifacts" in {x.strip() for x in (include or "").split(",")}62    bf = "" if include_backfill else " and ev.is_backfill = false"63    win = f"ev.occurred_at > :s and ev.occurred_at <= :e{bf}"64    async with connection() as conn:65        ent_frag, ev_frag, params, scope_desc = await _scope(conn, scope)66        art = "" if include_artifacts else " and e.entity_type <> 'artifact'"67        new_entities = await fetch_all(conn, f"select {ENTITY_COLS} from {ENTITY_FROM} where e.merged_into is null and {ent_frag}{art} and e.first_seen_at > :s and e.first_seen_at <= :e "68                                             f"order by e.first_seen_at desc limit :lim", s=start, e=end, lim=limit, **params)69        gone = await fetch_all(conn, f"""select distinct on (e.id) {ENTITY_COLS} from change_events ev join entities e on e.id = ev.entity_id left join entities eo on eo.id = e.organization_id70                                         where {ev_frag} and {win} and (ev.event_type = any(cast(:gt as text[])) or e.merged_into is not null)71                                         and (e.status in ('retired','deprecated','merged') or ev.event_type in ('RETIREMENT_ANNOUNCED','DEPRECATION_ANNOUNCED'))72                                         order by e.id limit :lim""", s=start, e=end, gt=list(GONE_TYPES), lim=limit, **params)7374        async def events(cond: str) -> list[dict[str, Any]]:75            rows = await fetch_all(conn, f"select {EVENT_COLS}, ev.occurred_at, ev.is_backfill from {EVENT_FROM} where {ev_frag} and {win} and {cond} "76                                         f"order by ev.importance desc, ev.occurred_at desc limit :lim", s=start, e=end, lim=limit, **params)77            out = []78            for r in rows:79                ev = change_event(r)80                ev["occurred_at"] = r.get("occurred_at")81                out.append(ev)82            return out8384        prop_changes = await events("ev.property is not null and ev.category not in ('price','benchmark') and ev.event_type <> 'DOCUMENT_CHANGED'")85        price_changes = await events("ev.category = 'price'")86        bench_changes = await events("ev.category = 'benchmark'")87        provider_changes = await events("ev.event_type in ('PROVIDER_LISTED','PROVIDER_DELISTED','NEW_PROVIDER')")88        hardware_changes = await events("(ev.category = 'hardware' or ev.event_type = 'NEW_HARDWARE')")89        context_changes = await events("ev.event_type in ('CONTEXT_CHANGED','MAX_OUTPUT_CHANGED')")90        retired = await events(RETIRED_PRED)91        counts = await fetch_one(conn, f"""select (select count(*) from entities e where e.merged_into is null and {ent_frag}{art} and e.first_seen_at > :s and e.first_seen_at <= :e) as new_entities,92                                           (select count(*) from change_events ev left join entities e on e.id = ev.entity_id where {ev_frag} and {win} and ev.event_type <> 'DOCUMENT_CHANGED') as events,93                                           (select count(*) from change_events ev left join entities e on e.id = ev.entity_id where {ev_frag} and {win} and ev.category = 'price') as price_changes,94                                           (select count(*) from change_events ev left join entities e on e.id = ev.entity_id where {ev_frag} and {win} and ev.category = 'benchmark') as benchmark_changes,95                                           (select count(*) from change_events ev left join entities e on e.id = ev.entity_id where {ev_frag} and {win} and ev.event_type in ('PROVIDER_LISTED','PROVIDER_DELISTED','NEW_PROVIDER')) as provider_changes,96                                           (select count(*) from change_events ev left join entities e on e.id = ev.entity_id where {ev_frag} and {win} and ev.event_type in ('CONTEXT_CHANGED','MAX_OUTPUT_CHANGED')) as context_changes,97                                           (select count(*) from change_events ev left join entities e on e.id = ev.entity_id where {ev_frag} and {win} and {RETIRED_PRED}) as retired_models,98                                           (select count(*) from prices p join entities e on e.id = p.model_id where {ent_frag} and p.valid_from > :s and p.valid_from <= :e) as price_rows_opened,99                                           (select count(*) from prices p join entities e on e.id = p.model_id where {ent_frag} and p.valid_to > :s and p.valid_to <= :e) as price_rows_closed,100                                           (select count(*) from claims c join entities e on e.id = c.entity_id where {ent_frag} and c.valid_to > :s and c.valid_to <= :e) as claims_superseded""",101                                 s=start, e=end, **params)102        entities_at_a = await fetch_val(conn, f"select count(*) from entities e where e.merged_into is null and {ent_frag}{art} and e.first_seen_at <= :s", s=start, **params)103        entities_at_b = await fetch_val(conn, f"select count(*) from entities e where e.merged_into is null and {ent_frag}{art} and e.first_seen_at <= :e", e=end, **params)104        # new benchmark leaders: leader of each benchmark's primary group at a vs at b (from results observed by each date)105        meta = await benchmark_meta(conn)106        all_rows = await load_results(conn, current_only=False)107    by_bench: dict[str, list[dict[str, Any]]] = {}108    for r in all_rows:109        by_bench.setdefault(r["benchmark_id"], []).append(r)110    new_leaders = []111    for bid, rows in by_bench.items():112        m = meta.get(bid, {})113        la, lb = _leaders_at(rows, start, m.get("attributes")), _leaders_at(rows, end, m.get("attributes"))114        if lb and (la is None or la["model"]["id"] != lb["model"]["id"]):115            new_leaders.append({"benchmark": {"id": bid, "slug": m.get("slug"), "name": m.get("name"), "category": m.get("category")}, "at_a": la, "at_b": lb})116    new_leaders.sort(key=lambda x: x["benchmark"]["name"] or "")117    return {"a": da.isoformat(), "b": db.isoformat(), "scope": scope_desc, "new_entities": [entity_summary(r) for r in new_entities], "gone_entities": [entity_summary(r) for r in gone],118            "property_changes": prop_changes, "price_changes": price_changes, "benchmark_changes": bench_changes, "new_benchmark_leaders": new_leaders,119            "provider_changes": provider_changes, "hardware_changes": hardware_changes, "context_changes": context_changes, "retired_models": retired,120            "counts": {**{k: int(v or 0) for k, v in (counts or {}).items()}, "gone_entities": len(gone), "new_benchmark_leaders": len(new_leaders),121                       "entities_at_a": int(entities_at_a or 0), "entities_at_b": int(entities_at_b or 0)},122            "include_artifacts": include_artifacts, "include_backfill": bool(include_backfill),123            "note": "Events are keyed on occurred_at (effective date when known) and exclude back-filled history unless include_backfill=1; new_entities uses first_seen_at. "124                    "new_benchmark_leaders compares the primary-group leader computed from results observed by each date."}125