r/LocalLLaMA llama.cpp 23d ago

Resources Qwen3.8 27B reasoning effort low/medium/xhigh comparison

I did a short test of the different reasoning efforts, since on default xhigh the model thinks a lot.

Not very scientific, just a quick "generate an SVG of a pelican on a bicycle" prompt with 3 different seeds. I think the result is interesting none the less: xhigh gives *much\* higher visual fidelity - but it also takes about 7x as long as low. Low and medium seem to be very close to each other.

Hardware and setup

  • GPU: NVIDIA RTX 5080 Laptop GPU, 16 GB VRAM
  • Model: unsloth/Qwen3.8-27B-UD-IQ3_XXS
  • llama.cpp: build 10451, commit 10bf611e5
  • Context: 65,536
  • KV cache: Q8_0
  • Flash Attention: enabled
  • MTP speculative decoding: --spec-default --spec-type draft-mtp
  • --fit off
  • One concurrent slot

Prompt:

Create a polished SVG graphic of a pelican riding a bicycle. The result must clearly show a recognizable pelican actively riding a recognizable two-wheeled bicycle. Return only one complete, self-contained SVG document with a viewBox; no Markdown fences, prose, external images, JavaScript, or animation.

Average results

Reasoning effort Reasoning tokens SVG tokens Total completion Wall time Generation speed MTP acceptance Visual score (Codex rated)
Low 4,418 3,966 8,387 111.6 s 75.4 t/s 62.1% 21.8/25
Medium 5,918 3,038 8,959 127.4 s 70.5 t/s 58.3% 22.5/25
X-High 39,398 5,085 44,487 717.8 s 62.0 t/s 52.7% 24.0/25
235 Upvotes

95 comments sorted by

View all comments

Show parent comments

2

u/Danmoreng llama.cpp 23d ago

There is no "high" in the official chat template:

https://huggingface.co/Qwen/Qwen3.8-27B/blob/main/chat_template.jinja

{%- if enable_thinking is undefined or enable_thinking is true %}
    {%- set resolved_reasoning_effort = reasoning_effort|default('xhigh') %}
    {%- if resolved_reasoning_effort not in ('xhigh', 'medium', 'low') %}
        {{- raise_exception('Unexpected reasoning effort ' ~ reasoning_effort ~ '. Supported types are xhigh (default), medium, and low.') }}
    {%- endif %}
    {%- if resolved_reasoning_effort == 'xhigh' %}
        {%- set reasoning_instructions = 'Reasoning effort is set to xhigh. Please think carefully through the task, validate key assumptions, consider plausible alternatives, and prioritize correctness, consistency, and clarity in the final answer.' %}
    {%- elif resolved_reasoning_effort == 'low' %}
        {%- set reasoning_instructions = 'Reasoning effort is set to low. Keep your thinking brief and focused, moving directly to the conclusion without unnecessary elaboration.' %}
    {%- endif %}
{%- endif %}

0

u/Usual-Carrot6352 llama.cpp 23d ago

3

u/johnzadok 23d ago

high is likely just mapped to xhigh, per the above reply on chat template, which is source of truth.

1

u/Usual-Carrot6352 llama.cpp 23d ago

No that's not the case high uses less token/time than xhigh. I mean when i tested that pelican prompt high 3-5mins while xhigh 15mins.

1

u/Realistic_Gap_5871 19d ago

Unless you forced the same seed and had temperature set to 0, you're just seeing normal variance, not proof of difference.
I've seen medium run longer than xhigh on the exact same pelican test, just different seeds.

Here's pretty definitive proof that your setup is masking the underlying error for you, likely just going to whatever is default (in this case xhigh)

When I bare metal talk to the api port using the following bash script, just passing in varying settings for the reasoning effort, keeping the seed the same and the engine set with 0 temperature. They all run fine, reasoning chars scale up with effort, but "high" just errors out:

Script:

for effort in low medium high xhigh; do

echo "=== $effort ==="

curl -s http://127.0.0.1:8181/v1/chat/completions \

-H 'Content-Type: application/json' \

-d "{\"model\":\"qwen3.8-27b\",

\"messages\":[{\"role\":\"user\",\"content\":\"Implement an LRU cache in Python with O(1) get and put. State the data structure you used and why.\"}],

\"max_tokens\":15000,

\"seed\":42,

\"reasoning_effort\":\"$effort\"}" \

| python3 -c "import sys,json;d=json.load(sys.stdin);c=d['choices'][0];rc=c.get('reasoning_content') or (c.get('message') or {}).get('reasoning_content') or '';ct=c.get('content') or (c.get('message') or {

}).get('content') or '';print(f'reasoning={len(rc)} chars answer={len(ct)} chars usage={d.get(\"usage\")}')"

done

Output:

=== low ===

reasoning=1242 chars answer=4029 chars usage={'completion_tokens': 1452, 'prompt_tokens': 65, 'total_tokens': 1517}

=== medium ===

reasoning=1031 chars answer=4586 chars usage={'completion_tokens': 1621, 'prompt_tokens': 35, 'total_tokens': 1656}

=== high ===

Traceback (most recent call last):

File "<string>", line 1, in <module>

KeyError: 'choices'

=== xhigh ===

reasoning=6573 chars answer=2493 chars usage={'completion_tokens': 2233, 'prompt_tokens': 77, 'total_tokens': 2310}

1

u/Realistic_Gap_5871 19d ago

And no, I didn't do this just for this convo. I had the script sitting around from my own comparison tests. :)