"""Modelle-Endpoints: Liste (mit Caps), Discover, Fit, Register, Groups.""" import psutil from fastapi import APIRouter, HTTPException from pydantic import BaseModel from services import discover, llamaswap from services.fit import evaluate_fit, max_ctx_for router = APIRouter(prefix="/api") def _ram_gb() -> float: return psutil.virtual_memory().total / (1024 ** 3) @router.get("/models") def models() -> dict: items = llamaswap.list_models() return {"models": items, "count": len(items)} @router.get("/discover") def discover_models(force: bool = False) -> dict: ram = _ram_gb() data = discover.refresh_discover(ram) if force else discover.safe_discover(ram) if not data: raise HTTPException(502, "Modell-Quellen gerade nicht erreichbar — später erneut.") return {**data, "sys_ram_gb": round(ram, 1)} @router.get("/fit") def fit(params_b: float, quant: str = "Q4_K_M", ctx: int = 8192, name: str = "") -> dict: ram = _ram_gb() return { "fit": evaluate_fit(params_b, quant, ctx, ram, name=name), "optimal_ctx": max_ctx_for(params_b, quant, ram), "sys_ram_gb": round(ram, 1), } class RegisterReq(BaseModel): model_path: str role: str | None = None ctx: int = 8192 ttl: int | None = None mmproj_path: str | None = None jinja: bool = False @router.post("/models/register") def register(req: RegisterReq) -> dict: try: model_id = llamaswap.register_model( req.model_path, role=req.role, ctx=req.ctx, ttl=req.ttl, mmproj_path=req.mmproj_path, jinja=req.jinja, ) except PermissionError as exc: raise HTTPException(500, str(exc)) return {"ok": True, "model_id": model_id} @router.get("/groups") def groups() -> dict: return {"groups": llamaswap.list_groups()} class GroupReq(BaseModel): group: str members: list[str] swap: bool = False persist: bool = False @router.put("/groups") def set_group(req: GroupReq) -> dict: try: llamaswap.set_group(req.group, req.members, swap=req.swap, persist=req.persist) except PermissionError as exc: raise HTTPException(500, str(exc)) return {"ok": True}