llama-swap¶
Das einzige LLM-Backend dieser Maschine. Ein Container trägt alle Modell-Rollen auf der iGPU und lädt sie bei Bedarf um. GitHub
Eckdaten¶
| Image | ghcr.io/mostlygeek/llama-swap:unified-vulkan, per Digest gepinnt |
| Inhalt | llama-swap + llama-server + whisper.cpp |
| Endpunkt | http://10.10.10.7:9292/v1 (OpenAI-kompatibel) |
| Web-UI | http://10.10.10.7:9292/ui |
| Weitere Pfade | /health, /logs, /running, /metrics |
| Konfiguration | /opt/aiserver/llama-swap/config.yaml — zugleich die Rollenkarte |
| Netz | ai (Container-intern lauscht llama-swap auf 8080) |
Modelle kommen aus zwei read-only gemounteten Quellen:
| Mount | Quelle | Zweck |
|---|---|---|
/models |
/opt/ai/models/ollama/models/blobs |
Ollama-Blob-Store — llama.cpp liest dieselben GGUF-Dateien, kein doppelter Download |
/models-hf |
/opt/ai/models/hf |
Offizielle HF-GGUFs, wo der Ollama-Blob nicht taugt |
Gruppen¶
Die Rollen sind in drei Gruppen aufgeteilt. Das ist der Kern des Speicherkonzepts: 96 GB GTT reichen nicht für alle Modelle gleichzeitig, aber der Sprachpfad darf nie warten.
| Gruppe | Verhalten | Mitglieder |
|---|---|---|
resident |
persistent: true, kein Swap |
voice, embed — dauerhaft geladen, vor Verdrängung geschützt |
docs |
kein Swap untereinander | ocr, json — die Paperless-Kette bleibt zusammen geladen |
heavy |
swappt, eins aktiv | brain, coder, translator, vision, allround, cleanup |
Die docs-Gruppe ist kein Detail: Ohne sie würde ein Dokumentenstapel pro
Dokument zweimal swappen (ocr → json → ocr …).
Ein Chat gegen ein heavy-Modell verdrängt die Residenten nicht.
Pflicht-Flags¶
Diese Flags gelten für alle Modelle. Ohne sie gibt es kein Fehlerbild, sondern schlechtes Verhalten.
| Flag | Gilt für | Ohne es |
|---|---|---|
--load-mode none |
alle | ~30 min Seitentabellenaufbau beim Laden (mmap-Falle auf gfx1151 — und mmap ist der llama.cpp-Default) |
-ngl 999 |
alle | Teile des Modells bleiben auf der CPU |
--flash-attn on |
alle | 1–9 % Tempo verschenkt, nie nachteilig |
--jinja |
alle | Die im GGUF eingebetteten Chat-Templates greifen nicht |
--ctx-size explizit |
alle | Der Kontext steht sonst nicht fest |
--spec-type draft-mtp |
brain (Head im GGUF), translator (zusätzlich --spec-draft-model) |
28–63 statt 79–89 Tokens/s |
--image-min-tokens 1024 |
ocr, vision (Qwen-VL-Familie) |
A4-Scans werden so klein skaliert, dass OCR nach zwei Zeilen abbricht |
--reasoning-budget 0 |
cleanup (laguna) |
Thinking frisst das Token-Budget, content bleibt leer |
Speculative Decoding ist verteilungserhaltend — es verändert die Ausgabe nicht, nur das Tempo.
Residenten-Preload¶
Nicht entfernen
Residenten laden sonst lazy — erst beim ersten Request. Der Sprachpfad wäre nach jedem Neustart einen Kaltstart lang taub. Mit Preload steht er nach 2,6 Sekunden.
GPU-Zugriff im Container¶
devices: [/dev/kfd, /dev/dri]
group_add: ["991", "44"] # render, video
security_opt: [seccomp:unconfined]
Die GIDs sind hostspezifisch und gehören gegengeprüft:
Digest-Pflege¶
Die -m-Pfade in config.yaml zeigen bei Ollama-Blobs auf
sha256-…-Dateien. Nach einem ollama pull desselben Tags ändert sich der
Digest, und llama-swap findet die Datei nicht mehr.
docker exec ollama cat /root/.ollama/models/manifests/registry.ollama.ai/library/<modell>/<tag> \
| jq -r '.layers[] | select(.mediaType | contains("model")) | .digest'
Danach den Pfad in config.yaml nachziehen und
docker compose restart llama-swap.
ollama rm kann llama-swap-Modelle zerstören
Vier Rollen lesen ihre Gewichte direkt aus dem Ollama-Blob-Store:
coder, voice, cleanup und json. Vor jedem ollama rm die Digests
gegen config.yaml prüfen — die Blobs sind Dateien, keine
Ollama-Verwaltungsobjekte, und Ollama weiß nichts von ihrem zweiten Nutzer.
Betrieb¶
# Zustand
curl -s localhost:9292/health # erwartet OK
curl -s localhost:9292/v1/models | jq '.data[].id' # Rollenliste mit Ladezustand
# Residenz prüfen (löst zugleich den Lazy-Load aus)
curl -s localhost:9292/v1/chat/completions -H 'Content-Type: application/json' \
-d '{"model":"voice-llamacpp","max_tokens":8,"messages":[{"role":"user","content":"OK?"}]}'
# Neustart nach Config-Änderung
docker compose -f /opt/aiserver/llama-swap/docker-compose.yaml restart
Der erste Aufruf eines kalten heavy-Modells dauert 1,5–24 Sekunden — das ist
der Swap, kein Fehler. brain und coder liegen am unteren Ende, translator
und allround am oberen.
Warum nicht Ollama¶
Ollama war das ursprüngliche Backend und ist seit dem 31.07.2026 gestoppt. Die Gründe, verkürzt:
- Tempo:
brainläuft mit MTP-Speculative-Decoding auf llama-swap mit 89 t/s statt 64 t/s auf Ollama - Kontext-Falle: Ollama lud
german-ocrmit 262k Kontext und belegte 12 statt 4 GB. Auf llama-swap steht der Kontext immer in der Config - Fehlerbilder:
qwen3-vl:4blieferte über Ollama sporadisch leere Antworten (Bug), über das HF-GGUF nicht - Architektur-Inkompatibilitäten: Einige Ollama-Blobs tragen Ollama-eigene
Architekturkennungen, die llama.cpp nicht lädt — dafür gibt es
/models-hf
Der Ollama-Container bleibt reaktivierbar (ollama/, archiviert), etwa um
Modelle zu ziehen. Sein Blob-Store ist weiterhin aktive Dateiquelle.
Details der Umstellung: docs/testrunde-2/z2-migration.md im aiserver-Repo.