llamacppctl/BEDIENUNGSANLEITUNG.md
dschlueter b8ea6545f8 docs: add BEDIENUNGSANLEITUNG.md and INSTALL_FROM_ARCHIVE.md
Vollständige deutschsprachige Bedienungsanleitung (Installation, Konfiguration,
alle fünf Aktionen, Prompt-Quellen, Antwort-/Reasoning-Steuerung, Netzwerk/
Sicherheit, GPU/Kontext, Exit-Codes, Fehlersuche, Tests) sowie eine Anleitung
zur Installation aus dem .tar.gz-Archiv.

build_archive.py: beide Anleitungen in INCLUDE_FILES + REQUIRED_FILES (werden
gepackt und verifiziert).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 17:48:39 +02:00

283 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Bedienungsanleitung — llamacppctl
`llamacppctl` startet, prüft, stoppt, wechselt und promptet einen
**llama.cpp-Server, der als Docker-Container** läuft — über **eine** CLI statt
mehrerer Shell-Skripte. Die OpenAI-kompatible API des Servers ist standardmäßig
nur auf `127.0.0.1` erreichbar.
Diese Anleitung deckt **Installation** und **Benutzung** vollständig ab. Zur
Installation aus dem fertigen Archiv siehe zusätzlich
[`INSTALL_FROM_ARCHIVE.md`](INSTALL_FROM_ARCHIVE.md). Details zum Sicherheits-
und Betriebsmodell stehen in [`docs/SECURITY_AND_OPERATIONS.md`](docs/SECURITY_AND_OPERATIONS.md);
die vollständige Optionsreferenz in der Manpage (`man/llamacppctl.1`).
---
## 1. Voraussetzungen
- **Docker** (Daemon läuft, Nutzer in der `docker`-Gruppe): `docker version` muss funktionieren.
- **NVIDIA-GPU** + Treiber + **NVIDIA Container Toolkit** (damit `--gpus` im Container greift): `nvidia-smi` funktioniert, und `docker run --rm --gpus all <cuda-image> nvidia-smi` zeigt die GPU.
- **Python ≥ 3.10**.
- Ein **GGUF-Modell** auf dem Host, das read-only in den Container gemountet wird.
- Das Docker-Image, z. B. `ghcr.io/ggml-org/llama.cpp:server-cuda` (wird beim ersten Start automatisch gezogen).
---
## 2. Installation
### 2.1 Aus dem Quellcode (empfohlen für Entwicklung)
```bash
cd llamacppctl
python3 -m venv .venv
source .venv/bin/activate
pip install -e . # editable: CLI == Quellcode in src/
# optional für Tests:
pip install -e ".[dev]"
```
> **Wichtig:** Bei `pip install .` (ohne `-e`) läuft das CLI aus einer Kopie in
> `site-packages` — Änderungen an `src/` wirken dann NICHT. Für Entwicklung immer
> `-e` verwenden. Kontrolle: `python -c "import llamacppctl.actions as a; print(a.__file__)"`
> muss auf `src/` zeigen.
### 2.2 Aus dem Archiv
Siehe [`INSTALL_FROM_ARCHIVE.md`](INSTALL_FROM_ARCHIVE.md).
### 2.3 Installation prüfen (ohne Docker)
```bash
llamacppctl --help
llamacppctl --print-effective-config --config llama.cpp.config --start --dry-run
```
---
## 3. Konfiguration
### 3.1 Datei anlegen
```bash
cp llama.cpp.config.example llama.cpp.config
# llama.cpp.config an den Host anpassen (Pfade, GPU, Ports)
```
Der Standard-Pfad ist `llama.cpp.config` im aktuellen Verzeichnis, überschreibbar
mit `--config <pfad>`.
### 3.2 Aufbau (INI)
- `[default]` — globale Werte, überschreiben die eingebauten Defaults.
- `[model.<name>]` — ein Modell-Profil, gewählt mit `--profile <name>`.
- `[prompt.<name>]` — ein *Fallback*-Systemprompt, gewählt mit `--system-prompt-profile <name>` (ein explizites `-s`/`--system-file`/`--system-url` gewinnt immer).
**Auflösungsreihenfolge** (niedrig → hoch): eingebaute Defaults → `[default]`
`[model.<profile>]` → CLI-Overrides.
### 3.3 Wichtige Felder
| Feld / CLI | Bedeutung |
|---|---|
| `image` / `--image` | Docker-Image (z. B. `ghcr.io/ggml-org/llama.cpp:server-cuda`) |
| `hf_home` / `--hf-home` | Host-Verzeichnis, read-only gemountet. **Env-Variablen erlaubt**, z. B. `hf_home = ${HF_HOME}` |
| `model_path` / `--model-path` | Modellpfad, relativ zu `hf_home` (oder absolut) |
| `container_name` / `--container-name` | **Pflicht**, eindeutig pro parallel laufendem Profil (Identitätsanker für Naming/Lock/Stop/Check) |
| `host_port` / `--host-port` | Host-Port (165535) |
| `container_port` / `--container-port` | Container-interner Port |
| `model_alias` / `--model-alias` | Modell-Alias in der API |
| `gpu_device` / `--gpu` | GPU-Device für `--gpus device=<id>` (auch mehrere: `1,2`) |
| `ctx_size` / `--ctx-size` | Kontextfenster (KV-Cache wächst damit) |
| `n_predict` / `--n-predict` | Server-seitige max. Vorhersage-Tokens |
| `temp`, `top_p`, `top_k`, `min_p`, `repeat_penalty` | Sampling (beim Start in den Container gebacken) |
| `expose` / `--expose` / `--no-expose` | Port auf allen Interfaces (LAN) statt nur `127.0.0.1`. **Default: aus** |
| `api_key` / `--api-key` | API-Key: Server verlangt ihn, Tool sendet ihn als Bearer-Token |
| `max_tokens` / `--max-tokens` | Antwortbudget für `--chat`/`--start`-Antwort (Default 2048) |
| `chat_temperature` / `--chat-temp` | Temperatur des Chat-Requests (leer = Server-`temp`) |
| `timeout` / `--timeout` | Readiness-Timeout in Sekunden |
| `reasoning` / `--reasoning {on,off}` | Reasoning-Modus |
Boolean-Schalter mit Paar-Form: `--jinja/--no-jinja`, `--fa/--no-fa`,
`--kv-unified/--no-kv-unified`, `--cont-batching/--no-cont-batching`,
`--no-context-shift/--context-shift`.
### 3.4 Beispiel
```ini
[default]
image = ghcr.io/ggml-org/llama.cpp:server-cuda
hf_home = ${HF_HOME}
model_path = models/qwen3/mein-modell-Q4_K_M.gguf
model_alias = mein_llm
container_name = llama_cpp_server
host_port = 8001
gpu_device = 1
ctx_size = 65536
max_tokens = 8192
[prompt.knapp]
system_prompt = Antworte kurz, präzise und technisch.
[model.zweitmodell]
model_path = models/qwen3/anderes-modell.gguf
model_alias = zweit_llm
container_name = llama_cpp_zweit
host_port = 8002
gpu_device = 2
```
---
## 4. Die fünf Aktionen
Genau **eine** Aktion pro Aufruf ist erforderlich.
### `--start` — Server starten
Entfernt einen vorhandenen Container gleichen Namens, startet neu, wartet per
echter Chat-Completion auf Readiness (nicht nur offener Port). Läuft unter Lock.
```bash
llamacppctl --start
llamacppctl --start --profile zweitmodell
llamacppctl --start -p "Sag kurz Hallo." # + Testantwort nach dem Start
llamacppctl --start --dry-run # nur das docker-run-Kommando zeigen
```
### `--check` — Status prüfen
Zeigt Container-/HTTP-Status; mit User-Prompt zusätzlich eine echte Chat-Probe.
**Scriptbar:** Exit 0 = läuft & erreichbar, sonst 5.
```bash
llamacppctl --check
llamacppctl --check -p "ping" && echo "OK" || echo "nicht bereit"
```
### `--stop` — Container stoppen und entfernen
```bash
llamacppctl --stop
llamacppctl --stop --force # auch bei Inkonsistenzen entfernen
```
### `--change` — Modell/Config wechseln
Stoppt, konfiguriert neu, startet — unter Lock. **Validiert den Modellpfad,
bevor** der laufende Container entfernt wird (kein unnötiger Ausfall).
```bash
llamacppctl --change --profile zweitmodell
llamacppctl --change --model-path models/qwen3/neues-modell.gguf --ctx-size 32768
```
### `--chat` — an laufenden Server prompten
```bash
llamacppctl --chat -p "Was ist 2+2?"
llamacppctl --chat -s "Du antwortest nur mit Zahlen." -p "Wie viel ist 6*7?"
llamacppctl --chat --stream -p "Schreibe eine kurze Geschichte."
```
---
## 5. Prompts (System & User)
Pro Feld genau **eine** Quelle:
| System-Prompt | User-Prompt | Quelle |
|---|---|---|
| `-s`, `--system` | `-p`, `--prompt` | Literaler Text |
| `--system-file` | `--prompt-file` | Lokale Datei (nur reguläre Dateien, UTF-8, Größenlimit) |
| `--system-url` | `--prompt-url` | HTTPS-URL (SSRF-gehärtet) |
```bash
llamacppctl --chat --system-file ./prompts/reviewer.md --prompt-file ./frage.txt
llamacppctl --start --system-prompt-profile knapp -p "Erkläre Backups."
```
URL-Quellen sind standardmäßig HTTPS-only, blockieren private/loopback/metadata-
IPs und Redirects; Details in `docs/SECURITY_AND_OPERATIONS.md`.
---
## 6. Antwortsteuerung & Reasoning
- `--max-tokens N` — Budget der Antwort (Default 2048).
- `--chat-temp F` — Temperatur des Requests (sonst gilt die Server-`temp`).
- `--stream` — Tokens live auf stdout, während sie generiert werden.
> **Reasoning-Modelle** (z. B. Qwen3.x mit `reasoning = on`) „denken" erst
> intern (oft mehrere tausend Tokens) und geben **dann** die eigentliche
> Antwort. Ist `--max-tokens` zu klein, endet die Generierung im Denken und der
> sichtbare `content` bleibt **leer** — das Tool warnt dann
> (`finish_reason=length`). Für lange Texte großzügig setzen (z. B. `--max-tokens 8000`).
---
## 7. Netzwerk & Sicherheit (Kurz)
- Der Port wird per Default nur auf **`127.0.0.1`** veröffentlicht — die
unauthentifizierte API ist **nicht** im LAN erreichbar.
- Für LAN-Zugriff: `--expose`/`expose = true`. **Dann unbedingt** `--api-key`/`api_key` setzen.
- Mit Key schützt llama.cpp `/v1/chat/completions` (ohne Key → 401); `/health`
und `/v1/models` bleiben bewusst offen (für Health-Checks).
- `hf_home` wird **read-only** gemountet; alle Docker-Aufrufe nutzen
Argumentlisten (keine Shell-Injection).
---
## 8. GPU & Kontextgröße
- Ein Modell muss samt KV-Cache in den GPU-Speicher passen. Der KV-Cache wächst
linear mit `ctx_size` und wird beim Laden komplett allokiert.
- Mehrere GPUs: `gpu_device = 1,2` (bzw. `--gpu 1,2`) verteilt das Modell.
- Vor einer Änderung mit `--dry-run` das Kommando prüfen, mit
`--print-effective-config` die aufgelösten Werte kontrollieren.
---
## 9. Exit-Codes
| Code | Bedeutung |
|---|---|
| 0 | Erfolg (bzw. `--check`: läuft & erreichbar) |
| 1 | Allgemeiner Fehler / leere Antwort trotz Budget |
| 2 | CLI-/Argument-Fehler |
| 3 | Modelldatei nicht gefunden |
| 4 | Docker-Fehler |
| 5 | HTTP/Readiness nicht bereit (auch `--check`, wenn nicht erreichbar) |
| 6 | Lock belegt (anderer `--start`/`--change` läuft; ggf. `--force`) |
---
## 10. Fehlersuche
| Symptom | Ursache | Lösung |
|---|---|---|
| `docker is not available on PATH` | Docker-CLI/-Daemon fehlt | Docker installieren/starten, Nutzer in `docker`-Gruppe |
| `model file not found: …` | `model_path`/`hf_home` falsch | Pfade prüfen; `${HF_HOME}` gesetzt? |
| `Server did not become ready within <n>s` | Modell lädt langsam / OOM | `--timeout` erhöhen, `--logs` für Log-Tail, ggf. `ctx_size` senken |
| Leere Antwort + Hinweis `finish_reason=length` | Reasoning verbraucht das Budget | `--max-tokens` erhöhen |
| `HTTP 401: Invalid API Key` | Server verlangt Key | `--api-key`/`api_key` passend setzen |
| `lock busy: …` | Paralleler `--start`/`--change` | warten oder `--force` (hängender Lock) |
| `--check` zeigt `health=unhealthy`, Server antwortet aber | bildeigener Docker-Healthcheck ≠ HTTP-Probe | unkritisch: `HTTP: OK` + Exit 0 zählt |
---
## 11. Tests
```bash
pip install -e ".[dev]"
pytest -q # Unit-Tests (kein Docker nötig)
```
End-to-End gegen einen echten Server (opt-in, braucht Docker + GPU + Modell):
```bash
SMOKE_GPU=1 scripts/smoke.sh
```
---
## 12. Weiterführend
- `man/llamacppctl.1` — vollständige Optionsreferenz (`man ./man/llamacppctl.1`).
- `docs/SECURITY_AND_OPERATIONS.md` — Architektur, Sicherheits- und Betriebsmodell.
- `README.md` — Kurzüberblick.
- `INSTALL_FROM_ARCHIVE.md` — Installation aus dem `.tar.gz`-Archiv.