#!/usr/bin/env python3 """Prüfstand für Hirn-Kandidaten (17.09.2026), seit 09/2026 eine dünne Hülle um pruefstand.py. Die Messungen selbst (Tempo, 13k-Tiefe, Werkzeuge, Deutsch/JSON, Bild-Probe, Server auf :5899) liegen im Modul — dasselbe nutzt das Modell-Radar nachts. Dieses Skript bleibt der Handbetrieb: Kandidaten mit festen Pfaden gegen die Live-Modelle (llama-swap :8080) messen, optional mit dem Tool-Smoke durch den ECHTEN Hermes-Agenten (`hermes chat --provider pruefstand -m kandidat`; der Provider `pruefstand` -> http://127.0.0.1:5899/v1 muss in `providers:` der Hermes-Config stehen). Aufruf auf der Box: python3 pruefstand-hirn.py [baseline] [nemo] [u38] [u36] (Pfade unten anpassen). Ergebnis: ~/pruefstand-.json + Log auf stdout. """ import json import os import sys import time import pruefstand as ps # liegt daneben; beim Skriptaufruf steht dieser Ordner auf sys.path M = "/srv/models" DFLASH_36 = f"{M}/Qwen3.6-35B-A3B-DFlash-GGUF/giocom-Qwen3.6-35B-A3B-DFlash-Q8_0.gguf" DFLASH2_38 = f"{M}/Qwen3.8-27B-DFlash2-GGUF/Qwen3.8-27B-DFlash2-Q4_K_M.gguf" NEMO = f"{M}/Nemotron-3.5-Lightning-30B-A3B-GGUF/NVIDIA-Nemotron-3.5-Lightning-30B-A3B-Q4_0.gguf" NEMO_MTP = f"{M}/Nemotron-3.5-Lightning-30B-A3B-GGUF/mtp-NVIDIA-Nemotron-3.5-Lightning-30B-A3B-Q8_0.gguf" U38 = f"{M}/Qwen3.8-27B-Uncensored-GGUF/Qwen3.8-27B-Uncensored-Q4_K_M.gguf" U36 = f"{M}/Qwen3.6-35B-A3B-Uncensored-GGUF/Qwen3.6-35B-A3B-Uncensored-HauhauCS-Aggressive-Q4_K_M.gguf" OUT = os.path.expanduser(f"~/pruefstand-{time.strftime('%Y-%m-%d')}.json") RESULTS: list[dict] = [] def save() -> None: with open(OUT, "w", encoding="utf-8") as f: json.dump(RESULTS, f, indent=1, ensure_ascii=False) def probes(basis: str, modell: str, label: str, with_hermes: bool, hermes_args: list[str], bild: bool = False) -> None: werte = {"label": label, **ps.pruefe("hirn", basis, modell, bild=bild)} if with_hermes: werte["hermes"] = ps.hermes_smoke(hermes_args) RESULTS.append(werte) save() def candidate(label: str, model: str, extra: list[str], with_hermes: bool, mmproj: str | None = None) -> None: ps.log(f"\n=== {label}") ps.log(f" {os.path.basename(model)} {' '.join(extra)}") try: server = ps.starte_server(model, mmproj=mmproj, flags=extra, ctx=ps.CTX_STANDARD) except ps.ServerFehler as e: ps.log(f" {e}") RESULTS.append({"label": label, "fehler": str(e)[:300]}) save() return try: probes(ps.KANDIDAT_URL, "kandidat", label, with_hermes, ["--provider", "pruefstand", "-m", "kandidat"], bild=bool(mmproj)) except Exception as e: ps.log(f" FEHLER in Proben: {e}") RESULTS.append({"label": label, "fehler": str(e)[:200]}) save() finally: ps.stoppe_server(server) time.sleep(3) def main() -> None: which = set(sys.argv[1:]) or {"baseline", "nemo", "u38", "u36"} if "baseline" in which: ps.log("\n=== BASELINE fast (live, llama-swap)") probes(ps.SWAP_URL, "fast", "fast-live", True, ["-m", "fast"]) ps.log("\n=== BASELINE coder (live, llama-swap)") probes(ps.SWAP_URL, "coder", "coder-live", True, ["-m", "coder"], bild=True) if "nemo" in which: candidate("Nemotron 3.5 Lightning · MTP n3", NEMO, ps.draft_flags(NEMO_MTP, "draft-mtp", 3), True) candidate("Nemotron 3.5 Lightning · ohne Spec", NEMO, [], False) if "u38" in which: candidate("Qwen3.8-27B · MTP fused n2", U38, ps.draft_flags(None, "draft-mtp", 2), True) candidate("Qwen3.8-27B · DFlash2 (z-lab) n3", U38, ps.draft_flags(DFLASH2_38, "draft-dflash", 3), False) candidate("Qwen3.8-27B · ohne Spec", U38, [], False) if "u36" in which: candidate("Qwen3.6-35B-A3B · DFlash (giocom)", U36, ps.draft_flags(DFLASH_36, "draft-dflash"), True) candidate("Qwen3.6-35B-A3B · ohne Spec", U36, [], False) ps.log("\nPRUEFSTAND_DONE") if __name__ == "__main__": main()