This commit is contained in:
team3
2026-07-23 16:07:36 +02:00
commit cb68cd671b
88 changed files with 10029 additions and 0 deletions

52
backend/ledger.py Normal file
View File

@@ -0,0 +1,52 @@
"""Event-Ledger: eine Zeile je LLM-Versuch (im finally — jeder Ausgang zählt,
auch Hedge-Verlierer). Budget = harte Grenze, geprüft VOR und NACH jedem Call."""
from . import config, db
class BudgetErschoepft(Exception):
pass
def log_call(run_id: int, *, stufe: str = "", knoten: str = "", item: str = "",
skills_liste: list | None = None, skill_hash: str = "",
model: str = "", role: str = "", status: str = "",
dur_ms: int = 0, wait_ms: int = 0,
tokens: dict | None = None, meta: dict | None = None,
prompt: str = "", antwort: str = "") -> int | None:
t = tokens or {}
event_id = db.insert(
"events", run_id=run_id, ts=db.now(), stufe=stufe, knoten=knoten,
item=item, skills=db.j(skills_liste or []), skill_hash=skill_hash,
model=model, role=role, status=status, dur_ms=dur_ms,
wait_ms=wait_ms, tok_in=t.get("input", 0), tok_out=t.get("output", 0),
tok_cache_read=t.get("cache_read", 0),
tok_cache_write=t.get("cache_write", 0), meta=db.j(meta or {}))
if config.LLM_LOG and event_id and (prompt or antwort):
db.insert("call_texte", event_id=event_id, prompt=prompt, antwort=antwort)
return event_id
def verbraucht(run_id: int) -> int:
r = db.one("SELECT COALESCE(SUM(tok_in + tok_out), 0) s FROM events "
"WHERE run_id=?", run_id)
return r["s"]
def budget_pruefen(run_id: int) -> None:
run = db.one("SELECT budget_tokens FROM runs WHERE id=?", run_id)
limit = (run or {}).get("budget_tokens") or 0
if limit > 0 and verbraucht(run_id) >= limit:
raise BudgetErschoepft(f"Budget {limit} Tokens erreicht")
def kennzahlen(run_id: int) -> dict:
zeilen = db.query(
"SELECT stufe, knoten, COUNT(*) calls, SUM(tok_in) tok_in, "
"SUM(tok_out) tok_out, SUM(tok_cache_read) cache_read, "
"SUM(dur_ms) dur_ms, SUM(wait_ms) wait_ms, "
"SUM(status='ok') ok, SUM(status IN ('error','infra','parse','cap')) fehler "
"FROM events WHERE run_id=? GROUP BY stufe, knoten ORDER BY MIN(id)", run_id)
gesamt = verbraucht(run_id)
kosten = sum(z["tok_in"] or 0 for z in zeilen) / 1e6 * config.PREIS_IN + \
sum(z["tok_out"] or 0 for z in zeilen) / 1e6 * config.PREIS_OUT
return {"zeilen": zeilen, "verbraucht": gesamt, "kosten_usd": round(kosten, 2)}