docs: add model profiles, evaluation rubric, and CLAUDE.md

KI_TOOLS_PROFILES.md records what each local GGUF is actually for, based on
the model cards: ornith is a purpose-built agentic coding model, Carnice targets
agent runtimes, Qwopus is reasoning plus vision, and the two HauhauCS models are
abliterated — an axis about refusals, not literary quality. It also maps which
models the local mmproj.gguf fits (the Qwen3.6-35B-A3B based ones, not ornith).
Capability and benchmark claims are attributed to their authors, not asserted.

EVAL_RUBRIC.md separates what a script can measure from what needs reading, and
warns that a passing test suite only proves the code satisfies its own tests.

CHANGELOG covers the mmproj feature, the --print-effective-config fix, and the
new tooling.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-07-10 16:25:26 +02:00
commit bee6a71de0
4 changed files with 406 additions and 0 deletions

108
docs/EVAL_RUBRIC.md Normal file
View file

@ -0,0 +1,108 @@
# Bewertungsrubrik für Modell-Prompt-Tests
Zweck: Modellwechsel (anderes Modell, andere Quantisierung, `Balanced` statt
`Aggressive`, MTP, KV-Cache-Einstellungen) sollen an **Zahlen** entschieden
werden, nicht an Bauchgefühl. Ohne Vorher-Nachher-Messung ist nicht feststellbar,
ob eine Änderung verbessert oder verschlechtert hat.
Grundlage sind die Läufe unter `~/llamacppctl_prompt_tests/` gegen die Prompts in
`example_user_prompts/`. Modelleignung siehe [`KI_TOOLS_PROFILES.md`](KI_TOOLS_PROFILES.md).
## Zwei Ebenen
**Objektiv** — von `scripts/eval_prompt_tests.py` automatisch gemessen, keine
Meinung nötig:
| Metrik | Domäne | Bedeutung |
|---|---|---|
| Wortzahl, Abweichung vom Ziel | prosa, reden | Der Prompt nennt ein Ziel („etwa 1200 Wörtern"). |
| Trunkierungsverdacht | alle | Text endet ohne Satzzeichen → Budget zu klein. |
| Tests laufen durch | coding | Der generierte Code wird **wirklich ausgeführt**. |
| Anteil bestandener Tests | coding | `passed / (passed + failed)`. |
**Subjektiv** — von Hand oder per LLM-Judge, Skala 15. Die Anker unten sind
bewusst so formuliert, dass 3 „brauchbar, aber mit Mängeln" bedeutet; ein
durchschnittlich guter Text landet nicht automatisch bei 4.
## Skala
| Punkte | Bedeutung |
|---|---|
| 5 | Kriterium durchgängig erfüllt; kein Eingriff nötig. |
| 4 | Erfüllt, mit einzelnen Schwächen, die den Gesamteindruck nicht tragen. |
| 3 | Brauchbar, aber erkennbare Mängel; Überarbeitung nötig. |
| 2 | Kriterium überwiegend verfehlt; Grundgerüst vorhanden. |
| 1 | Verfehlt. |
## Prosa
1. **Show, don't tell** — Innenleben ausschließlich über Handlung, Gegenstand,
Wahrnehmung. *1 = benannte Gefühle („sie war traurig"); 5 = kein einziges
benanntes Gefühl, Zustand trotzdem eindeutig.*
2. **Schlussbild** — konkretes, bedeutungstragendes Bild statt Moral oder
Zusammenfassung. *1 = explizite Lehre; 5 = Bild, das die Geschichte trägt.*
3. **Ton- und Registertreue** — hält die geforderte Tonlage (z. B. „nüchtern,
ohne Pathos") über den gesamten Text.
4. **Sprachliche Präzision** — konkrete Substantive, keine Füllattribute, keine
Klischees.
5. **Komposition** — Aufbau trägt; kein Leerlauf, kein abrupter Abbruch.
6. **Sprachrichtigkeit (Deutsch)** — Grammatik, Kasus, Idiomatik. *Eigener
Punkt, weil abliterierte, primär englisch trainierte Modelle hier auffällig
sind.*
## Reden
1. **Argumentative Substanz** — trägt der Gedankengang, oder reiht er Behauptungen?
2. **Vorweggenommene Einwände** — wird der stärkste Gegeneinwand benannt und
beantwortet, nicht der schwächste?
3. **Benannte Zielkonflikte** — werden echte Interessengegensätze offen
ausgesprochen statt harmonisiert?
4. **Rhetorische Mittel** — bewusst und sparsam eingesetzt (Trikolon, Anapher,
Antithese), nicht dekorativ.
5. **Adressatenbezug** — Sprache, Beispiele und Anrede passen zum Publikum.
6. **Sprachrichtigkeit (Deutsch)** — siehe oben.
## Coding
1. **Korrektheit***primär aus dem automatischen Testlauf.* Ein Modul, dessen
eigene Tests durchfallen, kann in diesem Kriterium nicht über 2 kommen.
2. **Anforderungsabdeckung** — sind alle Punkte des Prompts umgesetzt?
3. **Fehlerbehandlung** — die im Prompt geforderten Fehlerfälle, sauber getrennt.
4. **Testqualität** — decken die Tests die genannten Fälle ab, und sind sie
konsistent zum eigenen Code (richtiger Exception-Typ, Fixtures erfüllen das
Schema)?
5. **Keine Halluzinationen** — keine erfundenen APIs, Signaturen,
Framework-Aussagen oder Benchmark-Messwerte. *Automatisch nicht prüfbar;
erfundene Messwerte sind in den bisherigen Läufen wiederholt aufgetreten.*
6. **Lesbarkeit** — Benennung, Struktur, Kommentardichte.
## Durchführung
- **Blind bewerten.** Die Modellzuordnung steckt im Dateinamen; beim Scoren
ausblenden (`scripts/eval_prompt_tests.py --anonymize` schreibt anonymisierte
Kopien mit Zufalls-IDs und eine Auflösungstabelle).
- **Ein Kriterium über alle Texte**, nicht ein Text über alle Kriterien. Das
hält den Maßstab konstant.
- **LLM-Judge:** möglich gegen den lokalen Server, aber der Judge darf **nicht**
das bewertete Modell sein. Ein Modell bewertet seine eigenen Texte zu gut.
Der Judge ersetzt die menschliche Stichprobe nicht — mindestens 20 % der Texte
gegenlesen und die Übereinstimmung prüfen.
- **Mindestens zwei Läufe pro Zelle**, weil bei `temp > 0` ein Einzellauf wenig
aussagt. Für Coding-Vergleiche `--seed` fixieren.
## Was die Zahlen nicht sagen
Ein bestandener Testlauf beweist, dass der Code *seine eigenen* Tests besteht —
nicht, dass er korrekt ist. Wenn Modell und Test aus derselben Halluzination
stammen, sind beide konsistent falsch. Kriterium 4 (Testqualität) ist deshalb
nicht redundant zu Kriterium 1, sondern dessen Korrektiv.
## Sicherheitshinweis
`scripts/eval_prompt_tests.py` führt **modellgenerierten Code aus**. Das ist der
Sinn der Übung, aber es ist Codeausführung aus einer nicht vertrauenswürdigen
Quelle. Der Runner arbeitet in einem temporären Verzeichnis, erzwingt ein
Zeitlimit und verweigert den Start als `root`. Er bietet **keine** Netz- oder
Dateisystem-Isolation. Wer die Läufe auf einem Rechner mit Produktionsdaten
auswertet, sollte `--no-exec` verwenden oder das Skript in einem Container
starten.

169
docs/KI_TOOLS_PROFILES.md Normal file
View file

@ -0,0 +1,169 @@
# Modellprofile — Eignung der lokalen GGUF-Modelle
Dieses Dokument beschreibt, **wofür** sich die Modelle unter
`$HF_HOME/models/qwen3/` jeweils eignen, unabhängig von den Beispiel-Prompts in
`example_system_prompts/`. Grundlage sind die Modellkarten auf Hugging Face
(Stand Juli 2026) sowie die eigenen Testläufe unter `~/llamacppctl_prompt_tests/`.
> Die Angaben zu Fähigkeiten und Benchmarks stammen, wo nicht anders vermerkt,
> **von den Modellautoren selbst** und sind nicht unabhängig verifiziert.
## Übersicht
| Datei | Profil | Basis | Primäre Eignung |
|---|---|---|---|
| `ornith-1.0-35b-Q4_K_M.gguf` | `ornith35b` | Qwen3.5-MoE | Agentisches Coding |
| `Carnice-Qwen3.6-MoE-35B-A3B-Q4_K_M.gguf` | `carnice` | Qwen3.6-35B-A3B | Agenten-/Tool-Calling-Workflows |
| `Qwopus3.6-35B-A3B-v1-Q4_K_M.gguf` | `qwopus` | Qwen3.6-35B-A3B | Reasoning, Vision, Tool-Calling |
| `Qwen3.6-35B-A3B-Uncensored-HauhauCS-Aggressive-Q4_K_M.gguf` | `[default]` | Qwen3.6-35B-A3B | Kreatives Schreiben ohne Verweigerungen |
| `Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS.gguf` | `qwen27b` | Qwen3.6-27B (dense) | Wie oben, kleinerer VRAM-Bedarf |
| `mmproj.gguf` | — | Qwen3.6-35B-A3B | Vision-Projektor (kein eigenständiges Modell) |
Alle 35B-A3B-Modelle sind MoE mit **3 B aktiven Parametern** pro Token: hoher
Durchsatz bei 21 GB VRAM-Bedarf. Das 27B ist dense — langsamer pro Token, aber
nur ~15 GB.
## Ornith-1.0-35B — agentisches Coding
Quelle: [`deepreinforce-ai/Ornith-1.0-35B-GGUF`](https://huggingface.co/deepreinforce-ai/Ornith-1.0-35B-GGUF) (MIT)
Ein dediziertes Coding-Modell aus einer selbstverbessernden Modellfamilie. Das
Trainings-Framework erzeugt per RL nicht nur Lösungs-Rollouts, sondern optimiert
auch das treibende Scaffold gemeinsam mit ihnen. Beworben mit SOTA unter
vergleichbar großen Open-Source-Modellen auf Terminal-Bench 2.1, SWE-Bench,
NL2Repo und OpenClaw. Reasoning-Modell: die Assistant-Antwort beginnt mit einem
`<think>`-Block.
**Einsetzen für:** Code-Generierung, Refactoring, Repo-weite Aufgaben,
Agenten-Loops mit Tool-Calls.
**Nicht einsetzen für:** Prosa und Reden — dafür ist das Sampling im Profil
(`temp = 0.20`) bewusst deterministisch gewählt.
Beachte: Basis ist **Qwen3.5**-MoE (`qwen3_5_moe`), nicht 3.6. Die lokale
`mmproj.gguf` passt deshalb *nicht* zu diesem Modell.
## Carnice-Qwen3.6-MoE-35B-A3B — Agenten-Workflows
Quelle: [`samuelcardillo/Carnice-Qwen3.6-MoE-35B-A3B`](https://huggingface.co/samuelcardillo/Carnice-Qwen3.6-MoE-35B-A3B)
QLoRA-Finetune von Qwen3.6-35B-A3B, trainiert auf echten Execution-Traces der
Hermes-Agent-Runtime. Das erklärte Ziel ist, dem Modell die konkreten
Konversationsmuster beizubringen, die ein Agenten-Runtime erwartet — nicht
generisches Reasoning.
**Einsetzen für:** Tool-Calling-Pipelines, Agenten-Orchestrierung (z. B. n8n),
strukturierte Mehrschritt-Abläufe.
## Qwopus3.6-35B-A3B-v1 — Reasoning + Vision
Quelle: [`Jackrong/Qwopus3.6-35B-A3B-v1`](https://huggingface.co/Jackrong/Qwopus3.6-35B-A3B-v1)
Reasoning-verstärkter Finetune, dreistufiges SFT mit progressiv steigender
Reasoning-Komplexität. Unterstützt Vision und Tool-Calling.
**Einsetzen für:** Aufgaben mit langer Gedankenkette, multimodale Eingaben.
**Vorbehalt:** Der Autor kennzeichnet das Modell ausdrücklich als experimentell,
ohne vollständige Performance- oder Sicherheitsevaluation.
Für reines Coding gibt es die separate Variante
[`Qwopus3.6-35B-A3B-Coder-MTP`](https://huggingface.co/Jackrong/Qwopus3.6-35B-A3B-Coder-MTP-GGUF)
(thinking-off, 62,4 % auf einem 300-Fall-SWE-Bench-Lauf) — lokal nicht vorhanden.
## HauhauCS Uncensored (35B-A3B und 27B) — kreatives Schreiben
Quellen: [35B-A3B](https://huggingface.co/HauhauCS/Qwen3.6-35B-A3B-Uncensored-HauhauCS-Aggressive),
[27B](https://huggingface.co/HauhauCS/Qwen3.6-27B-Uncensored-HauhauCS-Aggressive)
**Abliterierte** Modelle: keine neuen Fähigkeiten, entfernte Verweigerungen
(Modellkarte: „0/465 Refusals"). Alle Quants mit imatrix erzeugt. Beide sind
multimodal.
**Einsetzen für:** Prosa, Reden, Dialog, Rollenspiel — Themen, bei denen ein
aligntes Modell abbricht.
**Nicht einsetzen für:** Coding. Eigene Testläufe zeigen wiederkehrend Tests, die
inkonsistent zum selbst erzeugten Schema sind, erfundene Framework-Aussagen und
Benchmarks mit erfundenen Messwerten.
Zwei Punkte, die in der aktuellen Konfiguration relevant sind:
1. Die Karte des 27B empfiehlt selbst, dass **99,9 % der Nutzer die
`Balanced`-Variante** nehmen sollten statt `Aggressive`. Beide erreichen
dieselbe Refusal-Rate; `Balanced` bietet zusätzlich stabileres Sampling für
agentic coding, Tool-Use und Reasoning. `Aggressive` spart lediglich
Vorreden. Aktuell sind beide lokalen HauhauCS-Modelle `Aggressive`.
2. Die Behauptungen „lossless" und „zero capability loss" stammen vom Autor der
Modellkarte. Abliteration kostet in aller Regel *etwas* Fähigkeit.
## Empirische Befunde (eigene Läufe)
Getestet gegen das Default-Modell (HauhauCS 35B-A3B), Reasoning aktiv, ctx 262144:
- **Längenvorgaben werden nicht präzise getroffen** (27 % bis +26 % über sechs
Läufe). Länge als Spanne vorgeben oder im zweiten Turn nachjustieren.
- **Reasoning frisst das Antwortbudget.** Bei `--max-tokens 10000` endeten
schwere Aufgaben in `finish_reason=length`. Für Prosa/Reden/Dialog
`--max-tokens` ≥ 16000 wählen.
- **`--chat` ohne `--stream`** läuft bei langem Output in den Read-Timeout.
Immer `--stream` verwenden (jeder Token setzt den Timeout zurück).
- **Coding: Struktur gut, Korrektheit unzuverlässig.** Generierten Code und
generierte Tests immer wirklich ausführen.
Rohdaten: `~/llamacppctl_prompt_tests/`.
## Vision (mmproj)
Die lokale `mmproj.gguf` (902 MB) ist der Vision-Encoder des **Basismodells
Qwen3.6-35B-A3B** (aus dem unsloth-Repo). GGUF-Metadaten:
```
general.architecture = clip
general.name = Qwen3.6 35B A3B
clip.projector_type = qwen3vl_merger
clip.has_vision_encoder
```
Ein mmproj ist kein eigenständiges Modell, sondern projiziert Bild-Embeddings in
den Textmodell-Raum. Er muss zum Vision-Tower der jeweiligen Basis passen.
| Modell | mmproj.gguf passt? |
|---|---|
| HauhauCS 35B-A3B | ja (Basis Qwen3.6-35B-A3B) |
| Qwopus3.6-35B-A3B | ja (dieselbe Basis) |
| Carnice-Qwen3.6-MoE-35B-A3B | ja (dieselbe Basis) |
| `ornith-1.0-35b` | **nein** — Basis Qwen3.5-MoE, eigener Projektor nötig |
| HauhauCS 27B (dense) | **nein** — anderer Vision-Encoder |
Verwendung über `llamacppctl` (siehe `[model.vision]` in `llama.cpp.config`):
```bash
llamacppctl --start --config llama.cpp.config --profile vision
```
Das Profil setzt `mmproj = models/qwen3/mmproj.gguf`; der Pfad wird — wie
`model_path` — relativ zu `hf_home` aufgelöst und als `--mmproj` an den
llama.cpp-Server durchgereicht. Der Projektor wird standardmäßig auf die GPU
ausgelagert; `mmproj_offload = false` bzw. `--no-mmproj-offload` verhindert das,
wenn der VRAM knapp ist.
Bilder gehen anschließend über den OpenAI-kompatiblen Endpunkt
`/v1/chat/completions` als `image_url`-Content-Part. `llamacppctl --chat` sendet
derzeit nur Text; für Bild-Requests den Endpunkt direkt ansprechen.
## MTP / Speculative Decoding (nicht lokal vorhanden)
Für Ornith, Carnice und Qwopus existieren **MTP-Quants** mit eingebettetem
Multi-Token-Prediction-Head. Mit hinreichend aktuellem llama.cpp erlauben sie
self-speculative Decoding ohne separates Draft-Modell (`--draft-mtp`);
Community-Berichte nennen etwa doppelten Decode-Durchsatz bei ~2,5 % größerer
Datei. Die im pyproject gepinnte Image-Version muss das unterstützen.
## Quellen
- <https://huggingface.co/deepreinforce-ai/Ornith-1.0-35B-GGUF>
- <https://huggingface.co/SC117/Ornith-1.0-35B-MTP-APEX-GGUF>
- <https://huggingface.co/samuelcardillo/Carnice-Qwen3.6-MoE-35B-A3B>
- <https://huggingface.co/Jackrong/Qwopus3.6-35B-A3B-v1>
- <https://huggingface.co/Jackrong/Qwopus3.6-35B-A3B-Coder-MTP-GGUF>
- <https://huggingface.co/HauhauCS/Qwen3.6-35B-A3B-Uncensored-HauhauCS-Aggressive>
- <https://huggingface.co/HauhauCS/Qwen3.6-27B-Uncensored-HauhauCS-Aggressive>
- <https://github.com/ggml-org/llama.cpp/blob/master/docs/multimodal.md>