diff --git a/docs/GSQ_RCO_BETA1_20260904.md b/docs/GSQ_RCO_BETA1_20260904.md index a45aee6..e9824eb 100644 --- a/docs/GSQ_RCO_BETA1_20260904.md +++ b/docs/GSQ_RCO_BETA1_20260904.md @@ -63,3 +63,48 @@ frei. Ein realer Bildtest beschrieb Motiv und sichtbaren Text korrekt. Das Profil war anschließend gesund. Die frühere IQ3_XXS-GGUF wurde erst nach diesen Prüfungen entfernt; die JSON-Ergebnisse liegen auf Athena unter `/data/model-benchmarks/gsq-rco-iq3s-ab-20260908/`. + +## Profilweiter A/B-Härtetest am 08.09.2026 + +Ein zweiter Test verglich GSQ-RCO IQ3_S mit den jeweils heute verwendeten +Q4-Modellen unter den echten Kontext-, GPU-, MTP- und Batch-Einstellungen der +Profile. Medium und Large luden dabei auch den Vision-Projektor auf der RTX +3060; der dort bereits laufende TTS-Dienst blieb unangetastet. Alle acht +Varianten fanden drei synthetische Nadeln bei 70 Prozent des jeweiligen +Kontextfensters. + +| Profil | Q4 kurzer Prefill | IQ3_S kurzer Prefill | Delta | Q4 Decode | IQ3_S Decode | Delta | Q4 Lang-Prefill | IQ3_S Lang-Prefill | Delta | Q4 Lang-Decode | IQ3_S Lang-Decode | Delta | +|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:| +| Fast 76,8K | 938,2 | 860,5 | -8,3 % | 115,3 | 109,2 | -5,2 % | 816,7 | 757,4 | -7,3 % | 74,7 | 76,4 | +2,3 % | +| Medium 160K | 1.449,7 | 1.342,3 | -7,4 % | 104,0 | 86,9 | -16,5 % | 948,3 | 897,3 | -5,4 % | 56,3 | 48,9 | -13,1 % | +| Large 192K | 1.456,5 | 1.342,6 | -7,8 % | 104,3 | 86,9 | -16,7 % | 849,5 | 808,9 | -4,8 % | 52,2 | 45,5 | -12,8 % | +| Ultra 262K | 1.728,3 | 1.288,2 | -25,5 % | 83,8 | 73,5 | -12,3 % | 808,2 | 677,8 | -16,1 % | 33,3 | 32,0 | -4,0 % | + +Alle Geschwindigkeiten sind Token/s. `Fast` vergleicht das produktive +IQ4-MIX mit IQ3_S; die übrigen Profile vergleichen IQ4_XS Pure mit IQ3_S. +Die langen Prompts enthielten rund 53,8K, 112K, 134,5K beziehungsweise 183,6K +synthetische Token. + +Der komplexere Qualitätstest bestand aus neun deutschsprachigen Aufgaben zu +Logik, evidenzgebundener Diagnose, nebenläufigem Python, Kapazitätsplanung, +Prompt-Injection, Laufzeit- gegenüber Konfigurationszustand und sicherem +Adminverhalten sowie einem nativen Tool-Call. Acht Aufgaben waren inhaltlich +gleichwertig; beide Modelle hatten beim nebenläufigen Python-Code denselben +subtilen Restfehler. Bei der Kapazitätsplanung ermittelten beide intern korrekt, +dass die Migration unmöglich ist. Beide erreichten jedoch das 4K-Ausgabelimit: +Q4 gab die Schlussfolgerung und fast den ganzen Beweis sichtbar aus, IQ3_S +verbrauchte das Limit vollständig im Reasoning und lieferte keinen sichtbaren +Antworttext. Beide nativen Tool-Calls waren korrekt. + +Über alle neun Aufgaben benötigte Q4 223,0 Sekunden und IQ3_S 278,9 Sekunden; +IQ3_S war damit 25,0 Prozent länger beschäftigt. Zusammen mit der überwiegend +niedrigeren Inferenzgeschwindigkeit ist kein profilweiter Vorteil belegt. + +Entscheidung: Die produktiven Q4-Profile werden nicht durch IQ3_S ersetzt und +es werden keine vollständigen Q3-Doppelprofile angelegt. `beta1` bleibt als +gezielter 112K-Versuch erhalten: Dort passt das gesamte Textmodell auf die RTX +5080, während der Projektor auf der RTX 3060 liegt. Dieser besondere +Platzierungsvorteil gilt nicht automatisch für die größeren Profile. + +Die vollständigen JSON-Ergebnisse liegen auf Athena unter +`/data/model-benchmarks/gsq-rco-iq3s-ab-v2-20260908/`. diff --git a/experiments/gsq-rco-iq3s-ab-v2/README.md b/experiments/gsq-rco-iq3s-ab-v2/README.md new file mode 100644 index 0000000..fd73d9b --- /dev/null +++ b/experiments/gsq-rco-iq3s-ab-v2/README.md @@ -0,0 +1,18 @@ +# GSQ-RCO IQ3_S profile A/B test + +`run-case.sh` starts one isolated llama.cpp test container for either the +current Q4 reference or GSQ-RCO IQ3_S. It refuses to start while a production +LLM container is running. Context, GPU split, vision projector, MTP depth and +batch sizes are explicit command-line arguments so every candidate can use the +same settings as its corresponding production profile. + +The 2026-09-08 run used the existing dependency-free benchmark programs: + +- `experiments/dirk-qwen38/bench-case.py` +- `experiments/dirk-qwen38/quality-ab.py` +- `dev/QWEN38-FINAL-ACCEPTANCE-v1.json` + +Results are retained on Athena in +`/data/model-benchmarks/gsq-rco-iq3s-ab-v2-20260908/`. The conclusions and +aggregate measurements are documented in +`docs/GSQ_RCO_BETA1_20260904.md`. diff --git a/experiments/gsq-rco-iq3s-ab-v2/run-case.sh b/experiments/gsq-rco-iq3s-ab-v2/run-case.sh new file mode 100755 index 0000000..be93bf9 --- /dev/null +++ b/experiments/gsq-rco-iq3s-ab-v2/run-case.sh @@ -0,0 +1,130 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +MODEL=${1:-} +CONTEXT=${2:-} +SPLIT=${3:-} +VISION=${4:-no} +MTP=${5:-3} +BATCH=${6:-2048} +UBATCH=${7:-128} + +case "$MODEL" in + q4-pure) + MODEL_FILE=/models/qwen3.8-27b-iq4-xs-pure/qwen3.8-27b-IQ4_XS-pure.gguf + ;; + q4-mix) + MODEL_FILE=/models/qwen3.8-27b-iq4-mix/Qwen3.8-27B-IQ4-MIX.gguf + ;; + iq3s) + MODEL_FILE=/models/qwen3.8-27b-gsq-rco-iq3s/Qwen3.8-27B-GSQ-RCO-IQ3_S-mtp.gguf + ;; + *) + echo "Usage: $0 {q4-pure|q4-mix|iq3s} CONTEXT {none|PERCENT,PERCENT} {yes|no}" >&2 + exit 2 + ;; +esac + +[[ $CONTEXT =~ ^[0-9]+$ ]] || { echo "Invalid context" >&2; exit 2; } +[[ $SPLIT == none || $SPLIT =~ ^[0-9]+,[0-9]+$ ]] || { echo "Invalid split" >&2; exit 2; } +[[ $VISION == yes || $VISION == no ]] || { echo "Invalid vision setting" >&2; exit 2; } +[[ $MTP =~ ^[0-9]+$ ]] || { echo "Invalid MTP setting" >&2; exit 2; } +[[ $BATCH =~ ^[0-9]+$ ]] || { echo "Invalid batch setting" >&2; exit 2; } +[[ $UBATCH =~ ^[0-9]+$ ]] || { echo "Invalid ubatch setting" >&2; exit 2; } + +NAME=mike-ai-llama-gsq-v2 +IMAGE=${LLAMA_IMAGE:-mike-ai/llama.cpp:local} + +if docker ps --format '{{.Names}}' | grep -qx "$NAME"; then + echo "A/B container already running" >&2 + exit 1 +fi + +mapfile -t blockers < <( + docker ps --format '{{.Names}}' | + grep -E '^mike-ai-llama-' | + grep -vE '^mike-ai-llama-dashboard$' || true +) +if ((${#blockers[@]})); then + printf 'Production model still running: %s\n' "${blockers[*]}" >&2 + exit 1 +fi + +args=( + --model "$MODEL_FILE" + --alias benchmark + --ctx-size "$CONTEXT" + --flash-attn on + --cache-type-k q4_0 + --cache-type-v q4_0 + --cache-prompt + --cache-reuse 256 + --cache-ram 8192 + --threads 6 + --threads-batch 6 + --batch-size "$BATCH" + --ubatch-size "$UBATCH" + --parallel 1 + --kv-unified + --jinja + --reasoning auto + --reasoning-preserve + --host 127.0.0.1 + --port 5005 + --metrics + --fit off + --n-gpu-layers all + --no-mmap + --no-ui + --temperature 0.2 + --top-p 0.8 + --top-k 20 + --spec-type draft-mtp + --spec-draft-n-max "$MTP" + --spec-draft-type-k f16 + --spec-draft-type-v f16 +) + +env_args=() +if [[ $VISION == yes ]]; then + env_args=(-e MTMD_BACKEND_DEVICE=CUDA1) + args+=(--mmproj /models/qwen/mmproj-BF16.gguf --mmproj-device CUDA1) +fi + +if [[ $SPLIT == none ]]; then + args+=(--device CUDA0 --main-gpu 0 --split-mode none) +else + args+=(--device CUDA0,CUDA1 --main-gpu 0 --split-mode layer --tensor-split "$SPLIT") +fi + +docker run -d \ + --name "$NAME" \ + --gpus all \ + --network host \ + --read-only \ + --tmpfs /tmp:rw,noexec,nosuid,nodev,size=256m \ + --security-opt no-new-privileges:true \ + --cap-drop ALL \ + --pids-limit 1024 \ + --log-opt max-size=20m \ + --log-opt max-file=2 \ + -v /data/models:/models:ro \ + "${env_args[@]}" \ + --label mike-ai.experiment=gsq-rco-iq3s-ab-v2 \ + "$IMAGE" "${args[@]}" + +deadline=$((SECONDS + 900)) +until curl -fsS --max-time 3 http://127.0.0.1:5005/health >/dev/null; do + if [[ $(docker inspect -f '{{.State.Running}}' "$NAME" 2>/dev/null || true) != true ]]; then + docker logs --tail 100 "$NAME" >&2 || true + exit 1 + fi + if ((SECONDS >= deadline)); then + docker logs --tail 100 "$NAME" >&2 || true + exit 1 + fi + sleep 2 +done + +curl -fsS http://127.0.0.1:5005/props +printf '\nReady: %s, context %s, split %s, vision %s\n' "$MODEL" "$CONTEXT" "$SPLIT" "$VISION"