diff --git a/docs/HANDOFF-LOCAL-LLM-GITEA-MCP.md b/docs/HANDOFF-LOCAL-LLM-GITEA-MCP.md index 207375c..4e834a2 100644 --- a/docs/HANDOFF-LOCAL-LLM-GITEA-MCP.md +++ b/docs/HANDOFF-LOCAL-LLM-GITEA-MCP.md @@ -7,114 +7,127 @@ Denne handoffen er det eneste autoritative arbeidsdokumentet for sporet "lokal L --- -## FREMDRIFT – OPPDATERT 2026-07-21 22:58 CEST +## FREMDRIFT – OPPDATERT 2026-07-21 23:16 CEST -### ✅ FASE 0–5 — FERDIG (se logg) - -### ✅ FASE 6 – CPU-optimalisering — FERDIG 2026-07-21 22:58 CEST - -Alle 5 exit-kriterier bestått: -- ✅ keep_alive-strategi bevist effektiv -- ✅ resident modellvalg låst: MAX=2, begge Forever -- ✅ optimal parameterkombinasjon dokumentert -- ✅ full Emma-loop latency akseptert: 42.51s per varm turn -- ✅ belastningstest bestått: 20 turns, Swap=0, stabil latency, RAM stabilisert +### ✅ FASE 0–5 — FERDIG +### ✅ FASE 6 – CPU-optimalisering — FERDIG +### ✅ FASE 6-TILLEGG – Boot-warming — FERDIG 2026-07-21 23:16 CEST --- -## FASE 6 – KOMPLETT RESULTATOVERSIKT +## LÅST SYSTEMKONFIGURASJON – GITEA-CPU-VM (komplett) -### 6.1 Kaldstart / keep_alive baseline +### Systemd-dropins: `/etc/systemd/system/ollama.service.d/` -| Modell | Kaldstart load_s | Varm load_s | tok/s | -|---|---|---|---| -| gemma3:4b | 117.69s | ~1.0s | 4.9–5.0 | -| qwen2.5:3b | 71.13s | ~1.0s | 6.4 | - -Konklusjon: `OLLAMA_KEEP_ALIVE=-1` eliminerer kaldstart fra kall 2+. Må settes på systemd-nivå. - -### 6.2 Resident modell-strategi - -Låst: `OLLAMA_MAX_LOADED_MODELS=2` + `OLLAMA_KEEP_ALIVE=-1` i systemd-dropin. -Begrunnelse: MAX=1 gir 20–54s ekstra latency per Emma-turn. MAX=2 gir 0s bytte-overhead. - -### 6.3 Parameter-matrise - -Låst: `num_ctx=2048` (best), `num_batch=256` (default), `OLLAMA_NUM_THREADS` ikke satt. -Maskintak: **5.0 tok/s** for gemma3:4b på 4 vCPU. - -### 6.4 Full Emma MCoT end-to-end - -| Scenario | Total tid | Status | -|---|---|---| -| Første turn etter boot | 102.34s (kall 1: 55.6s boot-last) | Forventet engangs | -| **Varm turn (5 kall)** | **42.51s** | **✅ Akseptert** | - -Latency-breakdown per varm turn: -- Load-overhead: ~1.0s × 5 = ~5s -- Eval-tid totalt: ~38s (2–13s per kall avh. av num_predict) - -### 6.5 Belastningstest — 20 turns × 3 kall = 60 kall totalt - -Kjørt: 20:50:45–20:58:38 UTC (7 min 53 sek) - -| Måling | Verdi | Status | -|---|---|---| -| Turn-latency snitt | **23.5s** (3 kall per turn) | ✅ Stabilt | -| Turn-latency min/max | 23.2s / 25.2s | ✅ Lav spredning | -| RAM start | 6998 MB | ✅ | -| RAM slutt | 7291 MB | ✅ (+293 MB over 20 turns) | -| RAM-vekst rate | ~15 MB/turn | ✅ Akseptabelt (OS page cache) | -| Swap gjennom hele testen | **0 MB** | ✅ | -| OOM | Ingen | ✅ | -| Modeller i RAM etter test | gemma3:4b + qwen2.5:3b, begge Forever | ✅ | -| Endelig available RAM | 8.5 Gi | ✅ God margin | - -**RAM-vekst på 293 MB over 20 turns er OS page cache** — ikke lekkasje. Vil stabilisere seg. - ---- - -## LÅST SYSTEMKONFIGURASJON – GITEA-CPU-VM - -### Ollama systemd-dropin: `/etc/systemd/system/ollama.service.d/max-models.conf` +``` +override.conf — OLLAMA_HOST=0.0.0.0:11434 (eksisterende, ikke rørt) +max-models.conf — MAX_LOADED_MODELS=2 + KEEP_ALIVE=-1 +warmup.conf — ExecStartPost=/usr/local/bin/ollama-warmup.sh +``` +**max-models.conf:** ```ini [Service] Environment="OLLAMA_MAX_LOADED_MODELS=2" Environment="OLLAMA_KEEP_ALIVE=-1" ``` +**warmup.conf:** +```ini +[Service] +ExecStartPost=/usr/local/bin/ollama-warmup.sh +``` + +**`/usr/local/bin/ollama-warmup.sh`:** +```bash +#!/bin/bash +sleep 10 +curl -s http://localhost:11434/api/generate \ + -H 'Content-Type: application/json' \ + -d '{"model":"gemma3:4b","prompt":"warmup","stream":false,"keep_alive":-1,"options":{"num_predict":1}}' \ + > /dev/null +curl -s http://localhost:11434/api/generate \ + -H 'Content-Type: application/json' \ + -d '{"model":"qwen2.5:3b","prompt":"warmup","stream":false,"keep_alive":-1,"options":{"num_predict":1}}' \ + > /dev/null +``` + +### Verifisert etter restart 2026-07-21 21:11 UTC + +``` +NAME SIZE PROCESSOR CONTEXT UNTIL +gemma3:4b 2.9 GB 100% CPU 4096 Forever +qwen2.5:3b 2.2 GB 100% CPU 4096 Forever +Mem: 15Gi | 6.8Gi used | 8.9Gi available | Swap: 0B +``` + +Merk: `warmup.conf` bruker eget skript — ikke inline JSON i ExecStartPost. Direkte inline førte til 400-feil p.g.a. systemd-escaping av anførselstegn. + ### Operative parametere for Emma-kall ``` -num_ctx = 2048 -num_batch = 256 (Ollama default, ikke nødvendig å sette eksplisitt) -OLLAMA_NUM_THREADS = ikke satt (autodetect er optimal) -``` - -### Modeller i drift - -``` -gemma3:4b 2.9 GB 100% CPU Forever (primær) -qwen2.5:3b 2.2 GB 100% CPU Forever (reserve) +num_ctx = 2048 +num_batch = 256 (Ollama default) +OLLAMA_NUM_THREADS = ikke satt (autodetect) ``` ### Ytelsesbudsjett per Emma-turn (varm) ``` -3-kall turn: ~23.5s -5-kall turn: ~42.5s -Boot-penalty: ~56s engangs (første turn etter systemd-restart) -Tok/s: 4.9–5.0 (gemma3:4b) +3-kall turn: ~23.5s +5-kall turn: ~42.5s +Boot-penalty: ~0s etter restart (warmup-skript laster begge modeller automatisk) +Tok/s: 4.9–5.0 (gemma3:4b) ``` --- +## FASE 6 – KOMPLETT RESULTATOVERSIKT + +### 6.1 Kaldstart / keep_alive baseline +| Modell | Kaldstart | Varm | Tok/s | +|---|---|---|---| +| gemma3:4b | 117.69s | ~1.0s | 4.9–5.0 | +| qwen2.5:3b | 71.13s | ~1.0s | 6.4 | + +### 6.2 Resident modell-strategi +Låst: MAX=2 + KEEP_ALIVE=-1 systemd. MAX=1 gir 20–54s ekstra per Emma-turn. + +### 6.3 Parameter-matrise +| num_ctx | num_batch | tok/s | Delta | +|---|---|---|---| +| 1024 | 256 | 4.9 | baseline | +| **2048** | **256** | **5.0** | **+0.1 ✅** | +| 4096 | 256 | 4.3 | -14% ⚠️ | + +Threads: ingen målbar forskjell på 4 vCPU — ikke satt. + +### 6.4 Emma MCoT end-to-end +| Scenario | Tid | +|---|---| +| Første turn etter boot (uten warmup) | 102.34s | +| **Varm turn (5 kall)** | **42.51s ✅** | + +### 6.5 Belastningstest (20 turns × 3 kall) +| Måling | Verdi | +|---|---| +| Snitt per turn | 23.5s | +| Min/max | 23.2s / 25.2s | +| Swap | 0 MB hele testen | +| OOM | Ingen | +| RAM-vekst | +293 MB (OS page cache) | + +### 6-tillegg Boot-warming +- Rotproblem: `ExecStartPost` med inline JSON → systemd-escaping → 400-feil +- Løsning: dedikert skript `/usr/local/bin/ollama-warmup.sh` +- Resultat: begge modeller Forever innen ~3 min etter `systemctl restart ollama` + +--- + ## ÅPNE PUNKTER SOM MÅ LØSES FØR ENDELIG BLUEPRINT 1. `GITEA_URL` satt runtime — **må legges permanent inn i `opax-mcp.yaml` og rebuildes** 2. `git.vauco.no` erstatter IP når DNS er oppe -3. **Boot-warming:** legg til oppvarmingskall i Ollama systemd `ExecStartPost` for å eliminere 56s boot-penalty -4. Gitea-commits ikke GPG-signert — vurder om dette skal fikses +3. Gitea-commits ikke GPG-signert — vurder ## FASTE SANNHETER (uendret) - Gitea er source of truth @@ -131,17 +144,18 @@ Tok/s: 4.9–5.0 (gemma3:4b) - ⚠️ Konfigurasjon konsolidert — delvis (GITEA_URL må inn i repo) - ⏳ Ingen skjult API-/agentavhengighet som hovedbane — ikke verifisert - ✅ dev-snap-oppsettet dokumentert godt nok til blueprinting -- ✅ CPU-optimalisering verifisert på Gitea-VM — FASE 6 FERDIG +- ✅ CPU-optimalisering verifisert på Gitea-VM — FERDIG +- ✅ Boot-warming verifisert — begge modeller Forever etter restart ## OPPDATERINGSLOGG | Dato | Fase | Handling | |---|---|---| | 2026-07-21 | FASE 4 | Full smoke test grønn, alle 8 tools OK | -| 2026-07-21 | FASE 5 | Blueprint frosset, FASE 5 lukket | -| 2026-07-21 | FASE 6 | FASE 6 åpnet — CPU-optimalisering | +| 2026-07-21 | FASE 5 | Blueprint frosset | | 2026-07-21 | FASE 6.1 | Kaldstart/keep_alive: gemma3=117s, qwen=71s, keep_alive=-1 bevist | -| 2026-07-21 | FASE 6.2 | Resident strategi: MAX=2 + KEEP_ALIVE=-1 systemd, begge Forever | +| 2026-07-21 | FASE 6.2 | Resident strategi: MAX=2 + KEEP_ALIVE=-1 systemd | | 2026-07-21 | FASE 6.3 | Parameter-matrise: num_ctx=2048, batch=256, NUM_THREADS ikke satt | -| 2026-07-21 | FASE 6.4 | Emma MCoT: varm turn=42.51s (5 kall), boot-warning nødvendig | -| 2026-07-21 | FASE 6.5 | Belastningstest: 20 turns × 3 kall, snitt 23.5s/turn, Swap=0, ingen OOM, RAM +293MB stabilt | -| 2026-07-21 | FASE 6 | **FASE 6 LUKKET — alle 5 exit-kriterier bestått** | +| 2026-07-21 | FASE 6.4 | Emma MCoT: varm turn=42.51s (5 kall) | +| 2026-07-21 | FASE 6.5 | Belastningstest: 20 turns, 23.5s/turn, Swap=0, ingen OOM | +| 2026-07-21 | FASE 6 | FASE 6 LUKKET — alle 5 exit-kriterier bestått | +| 2026-07-21 | Boot-warming | ollama-warmup.sh verifisert: begge modeller Forever etter restart, Swap=0 |