mirror of
https://github.com/Jeuners/Logpy-AgentOne.git
synced 2026-09-09 15:02:33 +02:00
feat: OpenRouter-Backend + Modell-Dropdown im Leitstand, Live-Log fuer Dauer/Tokens/Kosten
Zweites Kategorisierungs-Backend neben Ollama (pipe/categorize.py), fuer Vergleichstests mit staerkeren Cloud-Modellen. Umschaltbar per Dropdown oben rechts im Leitstand (pipe/modellwahl.py, geteilte telefon/modell.json) - der laufende Watcher braucht dafuer keinen Neustart, die Auswahl wird bei jedem Anruf frisch gelesen. Jede Kategorisierung loggt jetzt Backend/Modell/Dauer/Tokens/Kosten mit ins Leitstand-Verlauf (protokoll.schreibe), nicht nur versteckt in meta.json. Testergebnis (Nemotron ueber OpenRouter, :free-Tier): stark schwankende Latenz (8,5s bis 80s je nach Modell/Auslastung), einmal 502 "temporarily overloaded" - :free-Modelle sind fuer spaeter geplanten Echtzeit-Dialog ungeeignet, dafuer braucht es ein bezahltes/dediziertes Tier. telefon/modell.json ist Laufzeit-Zustand, kein Quellcode - neu ignoriert. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vtvcyNkapuDh583643hNs
This commit is contained in:
parent
4109aee1bb
commit
3e2d829542
7 changed files with 230 additions and 18 deletions
|
|
@ -23,7 +23,7 @@ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|||
from pathlib import Path
|
||||
from urllib.parse import unquote, urlparse
|
||||
|
||||
from . import config, dashboard, protokoll, stapel, store
|
||||
from . import config, dashboard, modellwahl, protokoll, stapel, store
|
||||
|
||||
# Statusabfragen sind teuer (Netz, Unterprozesse) - kurz zwischenspeichern,
|
||||
# damit haeufiges Nachfragen den Rechner nicht belastet.
|
||||
|
|
@ -277,6 +277,8 @@ class Handler(BaseHTTPRequestHandler):
|
|||
self._json({"stapel": stapel.erlaubt(), "anrufe": anrufe()})
|
||||
elif pfad == "/api/verlauf":
|
||||
self._json(verlauf(150))
|
||||
elif pfad == "/api/modell":
|
||||
self._json({"aktuell": modellwahl.aktuelle_id(), "optionen": modellwahl.AUSWAHL})
|
||||
elif pfad.startswith("/audio/"):
|
||||
self._audio(pfad[len("/audio/"):])
|
||||
else:
|
||||
|
|
@ -292,6 +294,19 @@ class Handler(BaseHTTPRequestHandler):
|
|||
protokoll.schreibe("archiv", f"{anzahl} Anruf(e) archiviert (simuliert)", anzahl=anzahl)
|
||||
self._json({"ok": True, "anzahl": anzahl, "simuliert": True})
|
||||
return
|
||||
if pfad == "/api/modell":
|
||||
try:
|
||||
laenge = int(self.headers.get("Content-Length") or 0)
|
||||
kennung = json.loads(self.rfile.read(min(laenge, 10_000)).decode("utf-8"))["id"]
|
||||
except Exception:
|
||||
self._json({"ok": False, "fehler": "ungültige Anfrage"})
|
||||
return
|
||||
if not modellwahl.setze(kennung):
|
||||
self._json({"ok": False, "fehler": f"unbekanntes Modell: {kennung}"})
|
||||
return
|
||||
protokoll.schreibe("system", f"Kategorisierungs-Modell → {kennung}")
|
||||
self._json({"ok": True})
|
||||
return
|
||||
if pfad != "/api/stapel":
|
||||
self._sende(b"nicht gefunden", "text/plain; charset=utf-8", 404)
|
||||
return
|
||||
|
|
@ -386,6 +401,8 @@ font:15px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif}
|
|||
header{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:12px}
|
||||
h1{font-size:19px;margin:0}
|
||||
.stand{color:var(--muted);font-size:13px;font-variant-numeric:tabular-nums;margin-left:auto}
|
||||
.modell-select{background:var(--karte);border:1px solid var(--rand);color:var(--fg);border-radius:8px;
|
||||
padding:6px 10px;font-size:13px;font-family:inherit;cursor:pointer;max-width:280px}
|
||||
.dienste{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:9px}
|
||||
.dienst{background:var(--karte);border:1px solid var(--rand);border-radius:9px;padding:9px 11px;
|
||||
display:flex;align-items:center;gap:9px}
|
||||
|
|
@ -471,7 +488,9 @@ color:var(--gut);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:
|
|||
<header><h1>Anruf-Leitstand</h1>
|
||||
<button class="sicher-btn" id="sicherBtn" title="Namen, Nummern, Anliegen und Transkripte unscharf - fuer Bildschirmaufnahmen/Screenshots">🙈 Sicher-Modus</button>
|
||||
<button class="archiv-btn" id="archivBtn" title="Erledigte Anrufe vom Board raeumen (simuliert - nichts wird geloescht oder exportiert)">🗄️ Tag archivieren</button>
|
||||
<span class="stand" id="stand">…</span></header>
|
||||
<span class="stand" id="stand">…</span>
|
||||
<select class="modell-select" id="modellSelect" title="Kategorisierungs-Modell fuer neue Anrufe - Aenderung greift sofort, kein Neustart noetig"></select>
|
||||
</header>
|
||||
<div id="verlauf"></div>
|
||||
<div id="hinweise"></div>
|
||||
<div class="notfall-banner" id="notfallBanner">🚨 <span id="notfallText"></span></div>
|
||||
|
|
@ -665,6 +684,24 @@ function sicherSetzen(an){
|
|||
try{sicherSetzen(localStorage.getItem('sicherModus')==='1')}catch(e){}
|
||||
sicherBtn.onclick=()=>sicherSetzen(!document.body.classList.contains('sicher'));
|
||||
|
||||
// Kategorisierungs-Modell (Dropdown oben rechts) - Wechsel greift sofort
|
||||
// beim naechsten Anruf, kein Neustart des Watchers noetig (siehe
|
||||
// pipe/modellwahl.py, geteilte Zustandsdatei).
|
||||
async function modellLaden(){
|
||||
const d=await hole('/api/modell'); if(!d)return;
|
||||
const sel=document.getElementById('modellSelect');
|
||||
sel.innerHTML=d.optionen.map(o=>
|
||||
`<option value="${esc(o.id)}"${o.id===d.aktuell?' selected':''}>${esc(o.label)}</option>`).join('');
|
||||
}
|
||||
document.getElementById('modellSelect').onchange=async e=>{
|
||||
const label=e.target.selectedOptions[0].textContent;
|
||||
const r=await fetch('/api/modell',{method:'POST',headers:{'Content-Type':'application/json'},
|
||||
body:JSON.stringify({id:e.target.value})});
|
||||
const d=await r.json().catch(()=>null);
|
||||
toast(d&&d.ok?`Modell gewechselt: ${label}`:'Umschalten fehlgeschlagen');
|
||||
};
|
||||
modellLaden();
|
||||
|
||||
document.getElementById('archivBtn').onclick=async()=>{
|
||||
const btn=document.getElementById('archivBtn');
|
||||
const letzter=STAPEL[STAPEL.length-1];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue