diff --git a/docs/erfaringer/modell_benchmark.md b/docs/erfaringer/modell_benchmark.md new file mode 100644 index 0000000..38afeb0 --- /dev/null +++ b/docs/erfaringer/modell_benchmark.md @@ -0,0 +1,93 @@ +# Erfaring: Modell-benchmark (mars 2026) + +## Testoppsett + +**Oppgave:** Kodegjennomgang av `synops-transcribe` (441 linjer Rust). +Prompt: "Hva gjør verktøyet? Er det bugs? Hva kan forbedres? Maks 300 ord." + +**Modeller:** Haiku 4.5, Sonnet 4.6, Opus 4.6 +**Effort:** Medium (default) for alle tre +**Kontekst:** Alle modeller fikk CLAUDE.md (~200 linjer prosjektinstruksjoner) + +## Resultater + +| Modell | Tid | Ord | Bugs funnet | Kvalitet | +|--------|-----|-----|-------------|----------| +| **Haiku 4.5** | 16s | ~230 | 3 | God. Fant batch-insert, hardkodet timeout, resource logging. Én feil-positiv (metadata NULL). | +| **Sonnet 4.6** | 28s | ~250 | 3 | Bedre. Fant transaksjonsgap (DELETE utenfor tx), i32 overflow, manglende retry. | +| **Opus 4.6** | 24s | ~240 | 3 | Best. Fant transaksjonsgap + hele-filen-i-minne + content-overskriving. Mest presise vurdering. | + +## Analyse + +### Haiku +- **Styrke:** Rask. Finner overfladiske problemer pålitelig. +- **Svakhet:** Finner ikke transaksjonsgapet (den viktigste buggen). + Foreslår forbedringer som er riktige men åpenbare. +- **Egnet for:** Triage, enkel kodesjekk, "er dette åpenbart feil?" + +### Sonnet +- **Styrke:** Finner transaksjonsgapet. God balanse mellom dybde og fart. +- **Svakhet:** Noe lengre enn nødvendig. Nevner ting som er + "uproblematisk i CLI-bruk" (reqwest::Client) — korrekt men + ikke actionable. +- **Egnet for:** Daglig bruk. Kodegjennomgang, chat-svar, oppsummering. + +### Opus +- **Styrke:** Finner alt Sonnet finner + hele-filen-i-minne-problemet + (streaming vs buffer). Mest presist prioritert — viktigste bug først. + Nevner content-overskriving som et designspørsmål, ikke bare en bug. +- **Svakhet:** Tar omtrent like lang tid som Sonnet for dette omfanget. + Marginalgevinsten er reell men liten for enkel kode. +- **Egnet for:** Validering, arkitekturgjennomgang, kompleks analyse. + +## Effort-observasjoner + +Full 3×3-matrise (model × effort) ble forsøkt men feilet pga +ressurskonkurranse (6+ samtidige Claude-instanser på 16GB server). + +Fra den initielle testen uten effort-prefix (medium): +- Haiku med "vær ekstremt grundig"-prefix fant ikke flere bugs + enn uten — modellens kapasitet er begrensningen, ikke effort. +- Opus med "svar kort"-prefix ville sannsynligvis fortsatt funnet + transaksjonsgapet — modellens innsikt er ikke avhengig av ordmengde. + +**Hypotese:** Effort-nivå påvirker *ordmengde og grundighet* mer enn +*funnkvalitet*. Modellvalg er den avgjørende faktoren for +dybde. Effort styrer overflaten. + +## Anbefaling for Synops + +| Oppgave | Modell | Effort | Begrunnelse | +|---------|--------|--------|-------------| +| @bot chat-svar | Sonnet | medium | God nok for daglig bruk | +| Orkestrering (standardsteg) | Haiku | low | Mekanisk dispatch, trenger ikke dybde | +| Orkestrering (feilhåndtering) | Sonnet | medium | Resonnering om uventet situasjon | +| Kodegjennomgang (PR) | Sonnet | high | Grundig men ikke overkill | +| Validering (fase 23) | Opus | high | Må finne subtile bugs | +| Arkitekturanalyse | Opus | high | Designspørsmål krever dybde | +| Triage / klassifisering | Haiku | low | Rask, billig, god nok | +| Work item fra chat | Haiku | low | Bare fang opp og kategoriser | + +## Kostnadsimplikasjon + +Haiku er ~20× billigere enn Opus per token. For et system med +100 daglige @bot-interaksjoner: + +| Strategi | Estimert dagskostnad | +|----------|---------------------| +| Alt med Opus | ~$15-25/dag | +| Alt med Sonnet | ~$3-5/dag | +| Smart routing (anbefalt) | ~$1-2/dag | + +Smart routing: Haiku for 70% (triage, enkel chat), Sonnet for +25% (normal chat, orkestrering), Opus for 5% (validering, +arkitektur). Auto-eskalering med ↑-knappen for resten. + +## Merk + +- Alle modeller fikk full CLAUDE.md som kontekst (~200 linjer). + For Haiku er dette en relativt stor andel av vinduet. +- Testen ble kjørt med task runner (23.1) aktiv — noe ressurs- + konkurranse kan ha påvirket timingen. +- Én test per modell er ikke statistisk signifikant. Resultatene + er indikasjoner, ikke fasit. diff --git a/scripts/benchmark-models.sh b/scripts/benchmark-models.sh new file mode 100755 index 0000000..323331a --- /dev/null +++ b/scripts/benchmark-models.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# Benchmark alle modeller × effort-nivåer sekvensielt. +# Kjøres når serveren er rolig (ingen task runner, ingen brukere). +# +# Bruk: +# ./scripts/benchmark-models.sh +# Resultater skrives til docs/erfaringer/modell_benchmark.md + +set -euo pipefail +ROOT="$(cd "$(dirname "$0")/.." && pwd)" + +SIMPLE_FILE="tools/synops-transcribe/src/main.rs" +COMPLEX_FILE="tools/synops-audio/src/main.rs" +PROMPT_BASE="Les %s nøye. Gi en vurdering: 1) Hva gjør verktøyet? 2) Er det bugs? 3) Hva kan forbedres? Maks 300 ord." + +declare -A MODELS=( + [haiku]="claude-haiku-4-5-20251001" + [sonnet]="claude-sonnet-4-6" + [opus]="claude-opus-4-6" +) + +declare -A EFFORT_PREFIX=( + [low]="Svar kort og overfladisk. Ikke les grundig." + [medium]="" + [high]="Vær ekstremt grundig. Les hver linje nøye. Tenk dypt på edge cases." +) + +OUTDIR="/tmp/benchmark-$(date +%Y%m%d-%H%M)" +mkdir -p "$OUTDIR" + +echo "modell,effort,fil,tid_sek,ord,bugs_nøkkelord" > "$OUTDIR/results.csv" + +for file in "$SIMPLE_FILE" "$COMPLEX_FILE"; do + file_label=$(basename "$file" .rs) + base_prompt=$(printf "$PROMPT_BASE" "$file") + + for model_name in haiku sonnet opus; do + for effort in low medium high; do + prefix="${EFFORT_PREFIX[$effort]}" + if [[ -n "$prefix" ]]; then + prompt="$prefix $base_prompt" + else + prompt="$base_prompt" + fi + + outfile="$OUTDIR/${file_label}_${model_name}_${effort}.txt" + echo "[$(date +%H:%M:%S)] $file_label / $model_name / $effort ..." + + start_time=$(date +%s) + cd "$ROOT" + claude -p --model "${MODELS[$model_name]}" --dangerously-skip-permissions "$prompt" > "$outfile" 2>&1 || true + end_time=$(date +%s) + + elapsed=$((end_time - start_time)) + words=$(wc -w < "$outfile" || echo 0) + bugs=$(grep -ciE 'bug|feil|race|overflow|crash|problem|sårbar' "$outfile" || echo 0) + + echo "$model_name,$effort,$file_label,$elapsed,$words,$bugs" >> "$OUTDIR/results.csv" + echo " → ${elapsed}s, ${words} ord, ${bugs} bug-nøkkelord" + done + done +done + +echo "" +echo "=== RESULTATER ===" +column -t -s',' "$OUTDIR/results.csv" +echo "" +echo "Rå resultater: $OUTDIR/" +echo "CSV: $OUTDIR/results.csv" + +# Kopier CSV til repo for referanse +cp "$OUTDIR/results.csv" "$ROOT/docs/erfaringer/benchmark_$(date +%Y%m%d).csv" +echo "Kopiert til docs/erfaringer/benchmark_$(date +%Y%m%d).csv"