In één alinea
Op een zelfbouwserver met een RTX 3060 (12 GB) draait een mixture-of-experts-model van 35 miljard parameters op ~40 tokens per seconde. Het is mijn dagelijkse assistent in de browser, in de terminal en in VS Code. Het werkt agentisch: het leest bestanden, draait commando's en schrijft code. Als iets zeker moet kloppen, roept het Claude aan als tool, met mijn goedkeuring en een kostengrens. Mijn eigen model doet het werk, Claude controleert.
Architectuur
browser ──► Open WebUI (SSO, kennisbanken) ─┐
terminal ─► cortana (opencode-agent) ───────┼─► route-proxy ─► llama.cpp router (RTX 3060)
VS Code ──► Continue (agent-modus) ─────────┘ LAN of relay ├─ assistent 35B Q4
└─ codeermodel 35B Q5
└─ MCP-tool escalate_to_claude ─► Claude (na goedkeuring, max $1)
| Onderdeel | Keuze |
|---|---|
| Hardware | Ryzen 5 5500GT, 128 GB RAM, RTX 3060 12 GB via passthrough, PCIe 3.0 |
| Inference | Eigen build van een llama.cpp-fork met MoE expert-offload, in Docker |
| Modellen | Qwen3.6-35B-A3B (assistent, Q4) en een codeervariant (Q5), beide met MTP-laag |
| Router | Eén endpoint, twee presets, één model tegelijk geladen |
| Interfaces | Open WebUI, een eigen CLI (cortana), Continue in VS Code |
| Bereikbaarheid | Thuis via het LAN, onderweg via een relay of WireGuard op afroep |
Snelheid: van 16 naar 40 tokens per seconde
Een MoE-model gebruikt per token maar ~3 van de 35 miljard parameters. Als de vaak gekozen experts in VRAM staan en de rest in RAM, past een groot model op een kleine kaart.
| Stap | Decode | Opmerking |
|---|---|---|
| Uitgangssituatie | 16,2 t/s | experts uit RAM |
GGML_CUDA_REGISTER_HOST=1 | +11 % | gratis, prefill onveranderd |
| Expert-cache met gemeten profiel | 26,1 t/s | +47 %, 73 MiB VRAM per slot |
| Speculative decoding (MTP) | 39,8 t/s | +146 % totaal, acceptatie ~60 % |
Het profiel is de kern: een trace van echte prompts laat zien welke experts per laag het vaakst gekozen worden, en die gaan vast in VRAM. Ollama haalt op hetzelfde model 16,4 t/s. Mijn opstelling is 2,3× sneller op decode; Ollama is 1,8× sneller op prefill, omdat het hele lagen op de GPU zet.
Op een prompt van 4.400 tokens:
| Model | Prefill | Eerste token | Decode |
|---|---|---|---|
| Assistent 35B Q4 | 266 t/s | 16,6 s | 41,4 t/s |
| Codeermodel 35B Q5 | 223 t/s | 19,8 s | 27,5 t/s |
Wat níet werkt op deze hardware
- Experts vooraf ophalen kostte 19 % prefill. Op PCIe 3.0 is de bus de bottleneck, en die optimalisatie ruilt bandbreedte voor latency.
- Een dynamische ring-cache met voorspelling was langzamer dan het statische profiel. Een gemeten profiel verslaat een slimme voorspelling.
- Een 122B-model werkte, maar met minder dan 12 % van de experts in VRAM duurde een agentische codeertaak 14 minuten in plaats van 4. Weer verwijderd.
- Een groter model verkend: er is op dit moment geen model dat tegelijk kleine experts, een MTP-laag en een bestand heeft dat in de page cache past. Dus bewust niets veranderd.
Eigen model eerst, Claude als verificatie
Het lokale model is de voordeur. Het mag alles zien wat ik het geef, want het draait op mijn eigen hardware. Via een MCP-tool kan het één zelfstandige vraag naar Claude sturen, bijvoorbeeld om een conclusie te laten controleren voordat iets productie raakt.
- Goedkeuring in de tool zelf: een prompt in de terminal of een dialoogvenster. Niemand klikt binnen vijf minuten? Dan is het nee.
- Harde remmen: tien escalaties per uur, acht bestanden, $1 per aanroep.
- Vaste kosten: $0,0028 per escalatie door een minimale systeemprompt zonder tools. De rest is wat je meestuurt, en vooral de lengte van het antwoord.
- Trigger op mijn woorden, niet op de twijfel van het model. "Verifieer", "zeker weten" of "voordat het productie raakt" laat het model escaleren. Op eigen twijfel bleek het niet te vertrouwen: het verklaarde zelfverzekerd iets "letterlijk uit de documentatie" zonder te kijken.
De details staan in Lokaal model als voordeur, Claude als escalatie.
Betrouwbaar in het dagelijks gebruik
Een snel model is pas nuttig als het er altijd is:
- Failover-proxy op de laptop: kiest automatisch tussen LAN en relay en zet een lopend verzoek om als een route wegvalt. Zie Cortana.
- GPU na een kernel-update: een nachtelijke update wiste de device-cgroup van de container, en het model draaide tien uur stilletjes op de CPU. Nu staan de devices als cgroup-regel in de spec, en waarschuwt het startscript als de log "no usable GPU" meldt. Zie De GPU die na elke kernel-update verdween.
- Geheugen: onder ~36 GiB RAM gooit de kernel het modelbestand uit de page cache en stort de decode in. De VM heeft daarom 48 GiB vast. Zie Hoe cAdvisor mijn lokale LLM vier keer zo traag maakte.
- Samen met Jellyfin: transcoderen kost ~150 MiB VRAM per stream en past ernaast, al zakt de decode dan tijdelijk 25 %.
- CPU-discipline: builds op deze VM krijgen maximaal 4 cores via een cgroup-quota. Anders loopt de steal time op en voelt de hele Proxmox-host het.
Meetlessen
- Meet op een prompt van duizenden tokens; op 40 tokens meet je vaste overhead.
- Zet een unieke nonce in elke testprompt, anders meet je de prompt-cache.
- Vergelijk alleen bij gelijke contextlengte; decode zakt met een langere KV-cache.
- Zakt alleen de decode in terwijl de prefill gelijk blijft, dan zit het probleem in het geheugen, niet in de GPU.