Add owned OpenAI endpoint and coordinated native model switching

This commit is contained in:
Mikei386
2026-09-28 20:24:12 +02:00
parent 8d03a9a979
commit ff5d36252a
25 changed files with 952 additions and 177 deletions
+131
View File
@@ -0,0 +1,131 @@
# Eigener OpenAI-kompatibler Endpunkt
Die Übersicht steuert den API-Listener: Start, Stopp, Erreichbarkeit, Port,
aktivierte/ausführbare Profile pro Kategorie und tatsächlich geladener Worker.
Die Demo-API wurde entfernt. Einstellungen → **Endpunkt & Profile** konfiguriert
Port und Veröffentlichungen. Alternativ kann jedes ausführbare Profil direkt
im Profileditor am Endpunkt aktiviert werden. Neue Profile sind standardmäßig
nicht veröffentlicht. Profilfreigabe lädt noch keine Gewichte.
## Zugriff und Port
UI und Inferenz-API sind getrennte Listener. Standard für Inferenz: **8120**.
Der vorhandene Deck-API-Token gilt für alle Inferenzrouten; Kennwort/Cookie gelten
nur für die Verwaltung. Tokenrotation wirkt sofort auf neue Anfragen. Keine
Token, Prompts oder Antworten werden in Zugriffslogs geschrieben. Intern erhält
llama.cpp einen unabhängigen kurzlebigen Schlüssel in einer Datei mit Modus 0600.
Die aktuelle Docker-Testinstallation veröffentlicht ausschließlich Host-Loopback
**8120–8124**. Innerhalb dieses Bereichs ist der Port bei gestopptem Endpunkt
in der GUI frei wählbar. Der Installer prüft neue Ports vor dem Ersetzen des
eigenen Containers; vorhandene fremde Dienste werden nie gestoppt.
Anderer Bereich: `./install.sh --update --api-ports 8130-8134 --directory <Installation>`.
Danach gegebenenfalls den gespeicherten API-Port in der GUI korrigieren.
Bei nativem Betrieb ist jeder freie Port 1024–65535 möglich; standardmäßig wird
nur an 127.0.0.1 gebunden. Kein automatischer Firewall-, WireGuard- oder DNS-Umbau.
Auf dem Arbeitsplatz für API-Zugriff, zusätzlich zum bestehenden UI-Tunnel:
```sh
ssh -i /Users/mike_i386/.ssh/athena_key -o BatchMode=yes \
-o ExitOnForwardFailure=yes -o ServerAliveInterval=30 \
-N -L 8120:127.0.0.1:8120 root@192.168.1.212
```
Client-Basisadresse: `http://127.0.0.1:8120/v1`. Bei Portänderung den Tunnel
entsprechend anpassen. Der Endpunkt merkt sich Start/Stopp; nach regulärem
Deck-Neustart startet nur der Listener automatisch, kein Modell.
## Routen
Alle Inferenzrouten benötigen `Authorization: Bearer <Deck-API-Token>`.
| Methode | Pfad | Verhalten |
|---|---|---|
| GET | `/v1/models` | Nur freigegebene, ausführbare Profilnamen; kein Modellstart |
| GET | `/health` | Listener-Health, ebenfalls authentifiziert |
| POST | `/v1/chat/completions` | Textchat, JSON und SSE-Streaming, Sampling-Defaults aus dem Profil |
| POST | `/v1/images/generations` | Qwen-Image-2.1-Rezept, n=1, `b64_json` |
| POST | `/v1/audio/speech` | 501: noch kein eigener TTS-Worker |
| POST | `/v1/audio/transcriptions` | 501: noch kein eigener STT-Worker |
`model` ist immer der **API-Profilname**, nicht der GGUF-Dateiname. Bildaufträge
verwenden die gespeicherte Auflösung, Schritte, Guidance und Seed; eine explizite
`size` muss der Profilauflösung entsprechen. Das Bild liegt wie beim GUI-Test im
eigenen Jobverzeichnis. Kein Bildprompt wird persistiert; PNG-Metadaten sind
deaktiviert. n=1; Ausgabe zunächst als Base64, keine öffentlich abrufbaren Bild-URLs.
Die API ist bewusst ein Teilumfang: noch keine `/v1/responses`, Embeddings,
Vision-Eingaben, Bildbearbeitung, Video oder Audio-Worker. TTS/STT benötigen keinen
eigenen Port, sondern eigene Routen und Worker hinter demselben Listener.
Chat akzeptiert übliche Nachrichten, Tools, response_format, Sampling-Overrides
und Streaming-Optionen; unbekannte Erweiterungsfelder werden abgelehnt. Maximal
1 MiB JSON pro Anfrage, 16 MiB gepufferte Chatantwort. Keine Chunked-Uploads oder
Cross-Origin-Browserfreigabe. Internes llama.cpp-HTTP-Zeitlimit: 120 Sekunden ohne
Antwortdaten, maximal 600 Sekunden für laufende SSE-Ausgabe.
## Prozesssteuerung und Speicher
- Eigener nativer llama-server aus dem gewählten, geprüften CUDA-Build. Kein
produktiver Container wird gestartet, gestoppt oder umkonfiguriert.
- Start erfolgt nach Anfrage. Mehrere Profile dürfen dieselbe Modelldatei nutzen.
Ein anderes Profil bzw. eine neue Profilrevision entlädt zunächst den eigenen
Worker und startet ihn mit den gespeicherten Parametern neu.
- FIFO-Warteschlange (maximal 16 wartende Aufträge, 600 Sekunden Wartezeit).
Gleiches Chatprofil darf bis zur konfigurierten Slotzahl parallel antworten.
Ein wartender Wechsel verhindert, dass neue Chats ihn dauerhaft überholen.
Streaming hält die Modellreservierung bis zum Ende der Ausgabe.
- Bildaufträge benötigen beide freien GPUs. GUI-Bildtests und API nutzen dieselbe
Reservierung. GUI meldet bei belegter Reservierung einen Konflikt; API wartet.
Das Sprachmodell wird vor Bildgenerierung entladen. ComfyUI wird nach jedem Bild
vollständig beendet; die nächste Textanfrage lädt ihr Profil erneut.
- Stoppen nimmt keine neuen Anfragen an, verwirft wartende Anfragen und lässt
bereits laufende Antworten/Generierungen fertig werden, dann wird entladen.
SIGTERM beendet eigene Worker. Keine Garantie für SIGKILL bei nativem Betrieb;
das spätere systemd-Paket muss Prozesse über seine Cgroup vollständig aufräumen.
- GPU-Auswahl über UUID-Reihenfolge; busy GPUs werden abgewiesen. Speicherprüfung
vor jedem Start: reale freie GPU-/RAM-Kapazität, Cgroup-Limit, Reserven. Inaktiver,
reclaimbarer Dateicache wird vom Cgroup-Verbrauch abgezogen, anonyme Belegung nicht.
Ein zusätzlicher GPU-Prozess während des Betriebs beendet nur den Deck-Worker.
- llama.cpp: Gesamtkontext und Slots bleiben unverändert. Shared KV (`--kv-unified`),
K/V q4_0, Flash Attention on, load-mode none; derzeit diese festen Backend-Defaults.
Fit ist eine **Prognose**, kein OOM-Test. Feste Tensor-Splits werden separat per
`--fit-print` geprüft; falls nötig wird in höchstens zehn Schritten eine passende
GPU-Layerzahl gesucht. Verhältnisse und Kontext werden dabei nicht umgeschrieben.
Ohne feste Verteilung verwendet Deck die geprüften Fit-Parameter des Builds.
Aktive Modellstarts bleiben an freie Ressourcen gebunden. Der alte Router kann
weiterlaufen; fordert er dieselben GPUs an, beendet Deck bei erkanntem Konflikt
seinen eigenen Worker. Das ersetzt keine serverweite Ressourcenkoordination.
## Interne Verwaltungs-API
Nur angemeldete Oberflächensitzungen plus `X-Athena-Deck: 1`, kein API-Token:
| Methode | Route | JSON |
|---|---|---|
| GET | `/api/v1/endpoint` | Status, Port, Zähler, Worker, Warteschlange, Profile |
| POST | `/api/v1/endpoint/start` | `{}` |
| POST | `/api/v1/endpoint/stop` | `{}` |
| POST | `/api/v1/endpoint/config` | `{"port":8120}`; nur gestoppt |
| POST | `/api/v1/endpoint/profile` | `{"id":"<Profil-ID>","enabled":true}` |
Persistenz: `endpoint.json` im Deck-Zustandsverzeichnis. Aktivierte, später
unvollständige/gelöschte Profile verschwinden aus `/v1/models`; bestehende Requests
nutzen ihren konsistenten Profilsnapshot. Wartende Requests eines geänderten oder
deaktivierten Profils werden abgewiesen. Aktive Buildänderungen gelten nach dem
nächsten Entladen; Modellprofile selbst werden nicht automatisch verändert.
## Verifiziert am 28.09.2026
Isolierte HTTP-/Scheduler-Tests: Tokenrotation, Adminschutz, explizite Freigabe,
Profilwechsel, Streaming-Leases, ungültige Anfragen, Warteschlange und Portkonflikte.
GUI: Freigabe, Start/Stopp, Status und Portformular.
Echter Test auf Athena mit separaten Testprofilen und synthetischen Eingaben:
Qwen IQ4_XS Pure, Medium 160000/2 Slots/85:15 → zweites Profil 4096/1 Slot mit SSE
→ Qwen-Image-Rezept (512×512, 4 Schritte) → LLM. PNG geprüft; anschließend eigener
Listener gestoppt und Modell entladen. Keine vorhandenen Nutzerprompts oder
Anwendungslogs gelesen. Testprofile und Testzugang gehören nicht zur normalen
Deck-Konfiguration. Der Test weist keine vollständige OpenAI-Kompatibilität oder
Langzeitstabilität nach.