Reasoning effort instellen voor lokale LLM modellen
Ontdek hoe reasoning effort de generatietijd op uw eigen hardware beïnvloedt. Leer wat de instellingen veranderen aan het redeneersegment en hoe u de kosten in tokens meet.
Wat verandert er bij reasoning effort op een lokaal LLM
Reasoning effort is een instelling die bepaalt hoe lang een model nadenkt voordat het antwoord geeft. Het verandert uitsluitend de lengte van het redeneersegment. De gewichten op de schijf zijn op elk niveau identiek, de kwantisatie is gelijk en het antwoord komt voort uit dezelfde forward pass. Wat verandert, is het aantal tokens dat het model eerst aan zijn eigen kladblok besteedt.
Dit onderscheid is van belang vanwege de plek waar deze tokens terechtkomen. Bij een gehoste API verschijnen redeneertokens op de factuur. Op een VPS in eigen beheer betaalt u hiervoor in generatietijd op uw eigen CPU of GPU, en in ruimte binnen het contextvenster. Een model dat op de hoogste stand staat, kan het grootste deel van de output aan redeneren besteden voordat het eerste woord van het antwoord verschijnt. Op eigen hardware is dit het verschil tussen een antwoordtijd van twee seconden en twee minuten.
Waar het niveau wordt bepaald: de chat-template, niet de gewichten
Een denkmodel is getraind om een redeneersegment uit te voeren, meestal verpakt in <think> en </think> tags, voorafgaand aan het definitieve antwoord. Het inspanningsniveau is een instructie die de chat-template van het model in de prompt schrijft. Die template is een Jinja-bestand dat bij het model wordt geleverd. Het leest een variabele zoals reasoning_effort en rendert voor elke waarde een andere regel op systeemniveau; het model is getraind om zijn kladblok in te korten of te verlengen als reactie op die regel.
Hieruit volgen twee zaken. De niveaunamen horen bij het model en niet bij uw runtime, dus een naam uit de modelkaart van het ene model kan voor een ander model niets betekenen. En als er in de keten iets is dat de chat-template van het model vervangt door een generieke variant, wordt de variabele nooit gerenderd en doet de instelling stilletjes niets.
Gecontroleerd op 2026-08-20: de modelkaart van Qwen3.8-27B documenteert drie inspanningsniveaus: low, medium en xhigh, waarbij xhigh de standaard is. Er bestaat geen high. Het denken zelf wordt in- of uitgeschakeld met enable_thinking, wat standaard is ingeschakeld. De kaart documenteert ook preserve_thinking, eveneens standaard ingeschakeld, wat ervoor zorgt dat redeneringen uit eerdere beurten in de gespreksgeschiedenis behouden blijven. gpt-oss gebruikt in plaats daarvan low, medium en high. Veel andere families accepteren enkel een boolean en niets meer. Lees de kaart voor de exacte versie die u heeft binnengehaald, aangezien deze namen geen standaard zijn. Een 27B-model draaiende krijgen op een VPS is de eerste stap. Deze pagina gaat over wat u moet instellen zodra het model antwoord geeft.
Waarom hoge rekenkracht meer kost op een VPS
Output-tokens. Reasoning-tokens zijn gegenereerde tokens. Deze doorlopen dezelfde decodeer-loop als het antwoord, met de snelheid in tokens per seconde die uw hardware toelaat. Stel dat een taak 200 tokens aan antwoord en 4.000 tokens aan reasoning produceert. U heeft 4.200 tokens gegenereerd en de lezer heeft er 200 gezien. Uw decodeersnelheid wordt bepaald door de geheugenbandbreedte en door de door u gekozen kwantisatie, dus de enige variabele die overblijft is het aantal tokens zelf.
Wachttijd. Een gebruiker wacht op het eerste token van het antwoord, omdat alles daarvoor slechts een leeg scherm of een draaiend icoon is. Reasoning wordt als eerste gegenereerd, dus de wachttijd is ongeveer het aantal reasoning-tokens gedeeld door uw decodeersnelheid, plus de verwerkingstijd van de prompt. Verdubbel de lengte van de reasoning en u verdubbelt die wachttijd.
Context. Reasoning-tokens bezetten het contextvenster zoals elk ander token. Met preserve_thinking ingeschakeld, staat het kladblok van de eerste beurt nog steeds in de prompt bij de vijfde beurt, waardoor de verwerking van de prompt elke beurt trager wordt terwijl het venster aan beide kanten volloopt. Het verhogen van num_ctx om dit op te vangen kost KV-cachegeheugen; op een VPS zonder GPU is dit systeem-RAM dat u mogelijk niet beschikbaar heeft.
Wanneer het niveau verhogen en wanneer het laag houden
Verhoog het niveau voor werkzaamheden waarbij een onjuiste tussenstap het resultaat verpest: rekenwerk in meerdere stappen en eenheidsconversies, het plannen van een bewerking in meerdere bestanden, code die moet compileren, en vraagstukken met randvoorwaarden waarbij één antwoord aan meerdere eisen tegelijk moet voldoen. In deze gevallen verricht het kladblok daadwerkelijk werk en is een langer kladblok een goedkope manier om een fout te onderscheppen die het model anders zou doorvoeren.
Houd het niveau laag wanneer het antwoord al in de invoer staat en de taak enkel bestaat uit het verplaatsen ervan. Extractie, classificatie, tagging, vertaling, herschrijven, samenvatten en formatteren vallen hieronder. Het redeneergedeelte herhaalt in dat geval meestal de taak en geeft het model de ruimte om zichzelf van een correcte eerste ingeving af te praten.
Houd het niveau ook laag voor alles wat interactief is. In een chatvenster of een editor bent u onderdeel van het proces; een snel antwoord dat u kunt corrigeren is beter dan een traag antwoord waar u op moet wachten. Dat is de werkelijke afweging achter het koppelen van een coding agent aan een lokaal model: een agent maakt veel kleine aanroepen en de redeneerbelasting wordt bij elke aanroep in rekening gebracht.
Het instellen van het niveau in llama.cpp
llama.cpp schrijft de variabele rechtstreeks naar de template. Dit maakt het de runtime-omgeving waarin u zeker weet dat het niveau is aangekomen. Wijs -m naar de GGUF die u al heeft.
llama-server -m ./qwen3.8-27b-Q4_K_M.gguf \
--jinja \
--reasoning-effort medium \
--reasoning-format deepseek \
-c 32768 \
--host 127.0.0.1 --port 8080--jinja gebruikt de eigen chat-template van het model en is standaard ingeschakeld in huidige builds. --reasoning-effort accepteert default, minimal, low, medium, high, xhigh of max, waarbij default betekent dat de standaardinstelling van de template ongewijzigd blijft. Deze lijst is de woordenschat van llama.cpp en niet die van het model; geef daarom alleen een naam door die de kaart vermeldt: een niveau dat de template niet definieert, kan tijdens het verzoek een templatefout veroorzaken. --reasoning-format deepseek verplaatst het redeneren uit message.content en naar message.reasoning_content, wat de splitsing meetbaar maakt in de volgende sectie.
Om het denken uit te schakelen in plaats van het in te korten, stelt u de template-variabele zelf in:
llama-server -m ./qwen3.8-27b-Q4_K_M.gguf --jinja \
--chat-template-kwargs '{"enable_thinking": false}'--reasoning-budget is een ander mechanisme. Het begrenst het redeneersegment in tokens, waarbij 0 het onmiddellijk beëindigt en -1 het onbeperkt laat, in plaats van het model te vragen een kortere planning te maken. Beide vlaggen gelden voor de gehele server. llama-server accepteert reasoning_effort niet als een veld per verzoek, dus het aanbieden van twee inspanningsniveaus tegelijkertijd betekent twee processen op twee poorten.
vLLM stelt dezelfde variabele per verzoek beschikbaar, binnen de OpenAI-compatibele body:
{"model": "Qwen/Qwen3.8-27B",
"messages": [{"role": "user", "content": "Summarise this changelog in two lines."}],
"chat_template_kwargs": {"reasoning_effort": "medium"}}Het instellen van het niveau in Ollama
Ollama beschikt over een eigen veld, think, op /api/chat en /api/generate. Dit accepteert true, false, of een van de waarden low, medium, high en max, waarbij max vraagt om het hoogste niveau dat het model aanbiedt. 'Thinking' staat standaard ingeschakeld voor modellen die dit ondersteunen.
ollama run qwen3.8:27b --think=low "Draft a one line commit message for a README typo fix"{"model": "qwen3.8:27b",
"messages": [{"role": "user", "content": "Which HTTP status code means the request body was too large?"}],
"think": "low",
"stream": false}De redenering wordt geretourneerd in message.thinking en het antwoord in message.content; deze zijn reeds voor u gesplitst. Binnen een interactieve ollama run-sessie kunt u met /set think en /set nothink deze functie in- of uitschakelen zonder herstart.
Let nu op het verschil. Het vocabulaire van Ollama bestaat uit low, medium, high en max. De template van Qwen3.8 definieert low, medium en xhigh. Er moet een koppeling plaatsvinden tussen deze twee, en een Ollama-model bevat een template die binnen de tag is verpakt in plaats van het Jinja-bestand uit de oorspronkelijke repository. Of uw niveau het model bereikt, hangt dus af van die verpakte template. Ga er niet vanuit dat het werkt. Het meten hiervan duurt ongeveer een minuut.
Hoe u meet of het niveau daadwerkelijk is toegepast
Verstuur dezelfde prompt op meer dan één niveau met temperature op 0 en vergelijk vervolgens de aantallen tokens. Hier bouwt jq de body op, zodat u aanhalingstekens niet handmatig hoeft te escapen.
for level in low medium max; do
body=$(jq -n --arg lvl "$level" '{
model: "qwen3.8:27b",
messages: [{role: "user", content: "A pump fills a 4500 litre tank in 25 minutes. A second pump is 40 percent slower. How long do both together take? Answer in minutes."}],
think: $lvl,
stream: false,
options: {temperature: 0, num_ctx: 8192}
}')
echo "== $level"
curl -s http://localhost:11434/api/chat -d "$body" | jq '{
thinking_chars: (.message.thinking // "" | length),
answer_chars: (.message.content | length),
eval_count: .eval_count,
seconds: (.total_duration / 1e9),
tok_per_sec: (.eval_count / (.eval_duration / 1e9))
}'
doneeval_count bevat elk gegenereerd token, inclusief de redenering, dus het verschil tussen twee niveaus bestaat vrijwel volledig uit redenering. thinking_chars geeft u de splitsing direct. Twee zaken zouden waar moeten zijn: de getallen veranderen tussen de niveaus en het antwoord blijft correct op het lagere niveau. Als eval_count binnen de ruis valt over alle drie de runs, wordt het niveau genegeerd. De oplossing is dan een runtime die het niveau doorgeeft in plaats van een andere naam voor het niveau.
De totale tijd vertelt slechts de helft van het verhaal. Meet daarom het tijdsverschil tot het eerste antwoordtoken door te streamen en te stoppen bij het eerste niet-lege content-blok. Hiervoor heeft u jq en bc nodig.
start=$(date +%s.%N)
curl -sN http://localhost:11434/api/chat -d '{
"model": "qwen3.8:27b",
"messages": [{"role": "user", "content": "Explain what a reverse proxy does, in three sentences."}],
"think": "low",
"stream": true
}' |
while IFS= read -r line; do
if [ -n "$(printf '%s' "$line" | jq -r '.message.content // ""')" ]; then
echo "first answer token after $(echo "$(date +%s.%N) - $start" | bc)s"
break
fi
doneVoer het uit op low en nogmaals op max. Het verschil is de wachttijd die u inkoopt. Op llama.cpp komen dezelfde getallen terug in de response, zonder dat shell-rekenwerk nodig is:
curl -s http://localhost:8080/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model": "local", "temperature": 0,
"messages": [{"role": "user", "content": "A pump fills a 4500 litre tank in 25 minutes. A second pump is 40 percent slower. How long do both together take?"}]}' | jq '{
reasoning_chars: (.choices[0].message.reasoning_content // "" | length),
answer_chars: (.choices[0].message.content | length),
predicted_n: .timings.predicted_n,
tok_per_sec: .timings.predicted_per_second
}'Voer dit uit op uw eigen systeem. Een gepubliceerde vergelijking van inspanningen werd gemeten op hardware die niet de uwe is, en uw decode-rate is de factor die een aantal tokens omzet in seconden. Tokens per seconde meten op uw eigen server geeft u die factor: het aantal redeneertokens gedeeld door uw decode-rate is de wachttijd die u zojuist heeft toegevoegd.
Wat gaat er mis
Het antwoord is afgebroken, of content is leeg terwijl thinking vol is. De limiet voor de generatie is opgebruikt door het redeneren. De num_predict van Ollama begrenst de gehele generatie, inclusief het redeneren, en het redeneren komt eerst. Een limiet van 512 tokens bij een hoge inspanning kan er dus voor zorgen dat het antwoord wordt afgebroken voordat het begint. Ollama rapporteert "done_reason": "length" bij die respons. Verhoog de limiet of verlaag de inspanning. Hoe num_predict tokens telt behandelt de interactie in detail.
Het niveau verandert niets. De aantallen tokens zijn bij elk niveau identiek. Of de runtime geeft de variabele niet door, of het template leest deze niet. Controleer het template dat uw runtime daadwerkelijk gebruikt in plaats van het template in de oorspronkelijke repository. llama.cpp met --jinja en --chat-template-kwargs schrijft de variabele handmatig weg, dus dit dient als een goede controle: als het niveau daar wel werkt en elders niet, dan is het model in orde en laat de andere runtime de variabele vallen.
Een niveau-naam wordt geweigerd. Een templatefout tijdens het verzoek, of een fout bij het eerste bericht bij een verder gezonde server, betekent meestal dat u een niveau heeft doorgegeven dat het template niet definieert, zoals high bij een model waarvan de kaart alleen low, medium en xhigh vermeldt.
Chats met meerdere beurten worden bij elke beurt trager. Oude redeneringen worden in de geschiedenis bewaard. Zet preserve_thinking op false als het model dit ondersteunt, of verwijder het veld thinking uit de berichten die u terugstuurt. Anders groeit de promptverwerking bij elke beurt, terwijl de antwoorden dezelfde lengte behouden.
De kwaliteit daalt bij een lage inspanning voor een taak die u eenvoudig achtte. Sommige extractie is geen extractie. Als de invoer een eenheidsconversie vereist of een regel die in een bepaalde volgorde moet worden toegepast, is het een redeneertaak met een korte uitvoer. Verhoog het niveau voor die specifieke aanroep in plaats van voor de gehele server.
Twee niveaus tegelijkertijd draaien
llama.cpp legt het niveau vast bij het opstarten. Een server die zowel een editor als een nachtelijke batchtaak bedient, vereist daarom twee processen op twee poorten, elk met een eigen --reasoning-effort. Twee processen betekenen ook twee kopieën van de gewichten in het geheugen, tenzij u de taken in de tijd scheidt. Op één VPS is de goedkopere opzet meestal een server met lage inspanning voor interactieve taken, gecombineerd met een geplande run met hogere inspanning voor werk waar niemand op wacht. Wat gebeurt er als meerdere gebruikers één lokaal model delen is hier ook van toepassing: redeneertokens zijn decodeerwerk, dus het verhogen van de inspanning verlaagt uw effectieve gelijktijdigheid met ongeveer dezelfde factor als waarmee het aantal tokens toeneemt.
FAQ
Welk niveau van redeneerinspanning moet ik standaard gebruiken?
Begin bij het laagste niveau dat het model biedt en verhoog dit alleen voor taken waarvan u heeft gezien dat ze mislukken. Verschillende denkmodellen worden geleverd met een hoge standaardinstelling, en Qwen3.8-27B gebruikt standaard xhigh, het hoogste niveau, sinds augustus 2026. Die standaardinstelling is gekozen om goed te scoren in benchmarktabellen, en een benchmarktabel brengt geen tijd in rekening. Op uw eigen hardware betaalt u in seconden, dus maak het hogere niveau iets waar u per taak voor kiest in plaats van de instelling die elke aanvraag overneemt.
Tellen redeneertokens mee voor mijn contextvenster?
Ja. Het zijn gewone tokens in de uitvoer en ze bevinden zich in het contextvenster samen met al het andere. Of ze daar blijven bij de volgende beurt hangt af van de runtime en het model. De kaart van Qwen3.8 documenteert preserve_thinking, standaard ingeschakeld, wat eerdere redeneringen in de geschiedenis bewaart, dus een lang gesprek bevat elk kladblok dat het heeft geproduceerd. Zet dit op false, of verwijder het veld thinking uit de berichten die u opnieuw afspeelt, en de verwerking van prompts stopt met groeien.
Waarom maakt het wijzigen van het denkniveau geen verschil voor mijn tokentellingen?
De instelling bereikt het chat-template niet. Het niveau is een template-variabele, dus het werkt alleen als de runtime deze doorgeeft en het meegeleverde template deze leest. Sommige runtimes leveren hun eigen template bij een model in plaats van het Jinja-bestand uit de oorspronkelijke repository, en de variabele wordt dan genegeerd zonder dat er ergens een foutmelding verschijnt. Controleer dit door dezelfde prompt op het laagste en hoogste niveau te verzenden met temperature op 0 en eval_count te vergelijken. Als de aantallen binnen de ruismarge overeenkomen, wordt het niveau genegeerd.
Zorgt een lagere redeneerinspanning voor een minder nauwkeurig model?
Dit hangt af van de taak, en het is de moeite waard om dit te meten in plaats van aan te nemen. Waar het antwoord al aanwezig is in de invoer, zoals bij extractie of herschrijven, verandert een korter kladblok meestal niets. Waar een tussenstap correct moet zijn voordat de laatste stap kan worden gezet, zoals bij meerstaps rekenen of code die moet compileren, neemt de nauwkeurigheid wel af met een korter kladblok. Stel een set van twintig prompts samen uit uw werkelijke werklast, voer deze uit op twee niveaus met temperature op 0, en tel de foutieve antwoorden. Dat getal is specifiek voor uw werklast en geen enkele gepubliceerde tabel kan u dat geven.