from __future__ import annotations import math, time from sqlalchemy import select, func from app.models.request_log import RequestLog from app.models.model_catalog import ModelCatalog def estimate_tokens(text: str) -> int: words = len(text.split()) chars = len(text) return int(words * 1.35 + chars / 4) async def estimate_cost(session, model: str, tokens_in: int, tokens_out: int) -> float: result = await session.execute( select(ModelCatalog).where(ModelCatalog.id == model) ) row = result.scalar_one_or_none() if not row: return 0.0 cost_in = (tokens_in / 1_000_000) * row.input_price cost_out = (tokens_out / 1_000_000) * row.output_price return round(cost_in + cost_out, 6) async def get_latency_leaderboard(session, hours: int = 24) -> list: cutoff = time.time() - (hours * 3600) result = await session.execute( select( RequestLog.model, func.avg(RequestLog.latency_ms).label("avg_latency"), func.count(RequestLog.id).label("request_count"), ) .where( RequestLog.latency_ms > 0, RequestLog.model.isnot(None), ) .group_by(RequestLog.model) .order_by(func.avg(RequestLog.latency_ms).asc()) .limit(20) ) return [ { "model": row[0], "avg_latency_ms": round(row[1], 1), "request_count": row[2], } for row in result.all() if row[0] ]