Simon Willison’s Qwen 3.8 test used a roughly 17 GB GGUF on an M5 Max to generate an SVG of a pelican riding a bicycle. His transcript reported 22,276 reasoning tokens, 3,223 output tokens and nearly 21 minutes of wall time.

I first reproduced that prompt locally, then added Qwen 3.8 as a fifth candidate to an existing blind SVG comparison. I subsequently repeated all eight prompts with reasoning disabled while holding the model, quant, context and sampling values constant. This post records both sets of outputs, the actual inference configuration, selected reasoning excerpts, retry behaviour and timing. It is not a benchmark: the prompts are few, stochastic generation required retries, and the models in the game use different architectures and recommended inference settings. This matters because model rankings can change with inference budget; de Souza and Panisson report budget-dependent ranking reversals and non-monotone accuracy in Who Thinks Best Depends on How Long You Let Them.

Runtime configuration

The host has an NVIDIA RTX 4090 with 24,564 MiB VRAM and 62 GiB system RAM. Inference ran through Ollama 0.32.7-muse-4dee52f using its Vulkan backend.

The model was the official Qwen/Qwen3.8-27B converted and quantized in unsloth/Qwen3.8-27B-GGUF, quant UD-Q5_K_XL:

ItemValue
Parameters27.32B
Main GGUF20,218,178,624 bytes
Quant tagUD-Q5_K_XL
Initial context/output budget40,960 tokens
Crocodile xhigh context/output budget65,536 tokens
Reasoning modesxhigh; disabled
Temperature1.0
top_p0.95
top_k20
min_p0.0
Presence penalty0.0
Repetition penalty1.0

The GGUF is a mixed Q4/Q5/Q6 layout. llama.cpp’s generic model summary labels it Q4_K-Small; that label describes the aggregate tensor layout, not the requested Unsloth quant tag. Ollama also downloaded the 931 MB vision projector, although these runs were text-only.

The sampling values follow Unsloth’s Qwen 3.8 thinking-mode recommendations. Each request used the displayed scene description prefixed with Generate an SVG of.

For the controlled no-reasoning comparison I changed only "think": "xhigh" to "think": false. I deliberately retained the thinking-mode sampling values rather than switching to Unsloth’s recommended non-thinking values; changing both reasoning mode and sampling would make the comparison harder to interpret.

The important API detail was using Ollama’s /api/chat, which exposes separate message.thinking and message.content fields for supported reasoning models. Ollama documents the general field behaviour in its thinking-model guide. In this specific Ollama/Qwen GGUF combination, my initial /api/generate call did not separate the trace correctly; /api/chat did:

{
  "model": "hf.co/unsloth/Qwen3.8-27B-GGUF:UD-Q5_K_XL",
  "messages": [
    {
      "role": "user",
      "content": "Generate an SVG of a wombat driving a tiny red convertible, paws on the steering wheel."
    }
  ],
  "stream": false,
  "think": "xhigh",
  "options": {
    "num_ctx": 40960,
    "num_predict": 40960,
    "temperature": 1.0,
    "top_p": 0.95,
    "top_k": 20,
    "min_p": 0.0,
    "presence_penalty": 0.0,
    "repeat_penalty": 1.0
  }
}

With /api/chat, Ollama returned reasoning in message.thinking and the answer in message.content. I extracted the first complete <svg>...</svg> element, parsed it with Python’s xml.etree.ElementTree, and saved it unchanged. A missing closing tag or an empty final answer counted as a failed attempt. I did not repair paths, coordinates or styling after generation.

Outputs

Wombat driving a small red convertible, generated with xhigh reasoning
Wombat convertible · xhigh
Attempt 2 · 33,225 tokens · 17m 53s · 7.6 KB
Wombat driving a small red convertible, generated without reasoning
Wombat convertible · no reasoning
Attempt 1 · 3,634 tokens · 2m 01s · 6.3 KB
Giraffe riding a unicycle and juggling oranges, generated with xhigh reasoning
Giraffe unicycle · xhigh
Attempt 1 · 25,602 tokens · 13m 49s · 7.9 KB
Giraffe riding a unicycle and juggling oranges, generated without reasoning
Giraffe unicycle · no reasoning
Attempt 1 · 4,555 tokens · 2m 30s · 9.2 KB
Octopus playing a grand piano, generated with xhigh reasoning
Octopus pianist · xhigh
Attempt 2 · 35,748 tokens · 19m 15s · 13.0 KB
Octopus playing a grand piano, generated without reasoning
Octopus pianist · no reasoning
Attempt 1 · 4,822 tokens · 2m 34s · 9.4 KB
Penguin operating a yellow excavator, generated with xhigh reasoning
Penguin excavator · xhigh
Attempt 2 · 28,779 tokens · 15m 20s · 7.9 KB
Penguin operating a yellow excavator, generated without reasoning
Penguin excavator · no reasoning
Attempt 1 · 4,747 tokens · 2m 32s · 9.8 KB
Elephant bouncing on a pogo stick, generated with xhigh reasoning
Elephant pogo stick · xhigh
Attempt 1 · 22,464 tokens · 11m 57s · 6.2 KB
Elephant bouncing on a pogo stick, generated without reasoning
Elephant pogo stick · no reasoning
Attempt 1 · 2,525 tokens · 1m 21s · 4.8 KB
Crab piloting a helicopter, generated with xhigh reasoning
Crab helicopter · xhigh
Attempt 1 · 37,431 tokens · 20m 12s · 9.6 KB
Crab piloting a helicopter, generated without reasoning
Crab helicopter · no reasoning
Attempt 2 · 4,560 tokens · 2m 26s · 10.4 KB
Snail performing a skateboard trick over a half-pipe, generated with xhigh reasoning
Snail skateboard · xhigh
Attempt 2 · 27,617 tokens · 14m 55s · 8.3 KB
Snail performing a skateboard trick over a half-pipe, generated without reasoning
Snail skateboard · no reasoning
Attempt 1 · 2,629 tokens · 1m 38s · 5.4 KB
Crocodile performing ballet in a tutu on roller skates, generated with xhigh reasoning
Crocodile ballet · xhigh
Attempt 3 · 41,106 tokens · 62m 27s · 9.5 KB
Crocodile performing ballet in a tutu on roller skates, generated without reasoning
Crocodile ballet · no reasoning
Attempt 1 · 7,372 tokens · 4m 36s · 14.5 KB

The token counts above include both reasoning and final-answer tokens for xhigh. With reasoning disabled, all generated tokens belong to the final response.

Xhigh successful-run timing

SceneSuccessful attemptGenerated tokensRequest wall timeEvaluation rateSVG bytes
Wombat convertible233,22517m 53s31.00 tok/s7,585
Giraffe unicycle125,60213m 49s30.93 tok/s7,910
Octopus pianist235,74819m 15s30.99 tok/s12,993
Penguin excavator228,77915m 20s31.31 tok/s7,885
Elephant pogo stick122,46411m 57s31.39 tok/s6,182
Crab helicopter137,43120m 12s30.90 tok/s9,563
Snail skateboard227,61714m 55s30.92 tok/s8,297
Crocodile ballet341,10662m 27s10.99 tok/s9,471

The first seven successful requests averaged 31.06 tokens/s. Their 40,960-token runtime occupied about 23 GB and Ollama reported a 95% GPU / 5% CPU split.

The crocodile exhausted the 40,960-token budget twice without reaching message.content. Raising the context and output budget to 65,536 increased the runtime footprint to about 25 GB, forcing 13% CPU offload. Final throughput fell to 10.99 tokens/s: 65% lower, or 2.8 times as much wall time per token.

Across the corrected pipeline there were 14 requests: eight completed and six stopped at the 40,960-token length limit. Successful requests generated 251,972 tokens. Truncated requests generated another 245,337, for 497,309 generated tokens in total.

The API request wall times sum to 5h 9m. Successful requests account for 2h 56m of that. Elapsed time from starting the corrected worker to the final SVG was 5h 11m; including the earlier setup mistakes described below, the complete exercise took 6h 32m.

No-reasoning timing

These requests used the same model, quant, prompt text, 40,960-token context and sampling values. Only think changed from "xhigh" to false.

SceneSuccessful attemptGenerated tokensRequest wall timeEvaluation rateSVG bytes
Wombat convertible13,6342m 01s31.61 tok/s6,271
Giraffe unicycle14,5552m 30s31.55 tok/s9,177
Octopus pianist14,8222m 34s31.50 tok/s9,437
Penguin excavator14,7472m 32s31.48 tok/s9,777
Elephant pogo stick12,5251m 21s31.59 tok/s4,809
Crab helicopter24,5602m 26s31.47 tok/s10,396
Snail skateboard12,6291m 38s26.90 tok/s5,384
Crocodile ballet17,3724m 36s26.78 tok/s14,479

The eight successful no-reasoning requests generated 34,844 tokens in 19m 37s. Seven produced a complete SVG on the first request. The first crab request stopped after 106 tokens because the model emitted hallucinated list_files and read_file tool calls even though no tools were supplied; an unchanged retry produced the SVG.

Comparing successful requests only, xhigh used 7.23 times as many tokens and 8.96 times as much wall time. Including xhigh’s six truncated requests raises those ratios to 14.27 times the tokens and 15.77 times the request time. This is not explained by larger final artifacts: the eight xhigh SVGs total 69,886 bytes, while the no-reasoning SVGs total 69,730 bytes, a difference of 0.2%.

The no-reasoning outputs retain most of the basic scene grammar. All eight are recognizable and render cleanly. The main losses are relational constraints and geometry rather than subject identity: the wombat’s paws do not visibly grip a steering wheel, the elephant’s four feet are not gathered around the pogo stick, and the crab’s claws are not clearly connected to cockpit controls. Other single samples—notably the giraffe, octopus and crocodile—remain quite competitive visually. These are stochastic examples, not evidence that one mode will dominate per prompt.

The narrow result is that Qwen 3.8 does not need explicit reasoning to produce substantial, valid SVG code. Xhigh spends most of its additional tokens on composition and constraint checking. In these samples that sometimes improves the specified interaction, but its cost and truncation rate are disproportionate.

What appeared in the reasoning trace

These are model-generated reasoning traces exposed by the runtime, not privileged or necessarily faithful access to an internal state. That distinction is empirical rather than philosophical: work such as Shen et al.’s Detecting Unfaithful Chain-of-Thought via Circuit-Guided Internal-External Discrepancy finds that plausible external traces can diverge from model-internal computation. The traces are still useful for observing what text precedes the answer and where generation stalls.

The successful traces contained concrete composition work: coordinate selection, overlap checks, draw order, path construction and occasional arithmetic. For the giraffe, the model checked whether a juggling orange collided with an ossicone:

Check overlap: middle orange (300,48) r17 → bottom y 65. Ossicone tip (316,71) r6 → top 65. Just touching! Move middle orange to (300,42) → bottom 59, tip top 65. 6px gap. OK.

For the crab, it treated the claw and helicopter controls as connected geometry rather than independent decorations:

Knob A: (281,316), r=6.5. Fist: (294,322) r=10. Arm A: from body shoulder (322,350) to fist: M 322 350 C 310 352, 300 344, 295 330. Stroke 12.

The elephant trace explicitly planned paint order:

Order: draw handle crossbar, then pole, then spring, base, then feet on top of the pole top […] If feet tuck under body, then body’s belly is in front of the top of the feet. So draw feet first, then body on top of the top of feet.

That reasoning often corresponds to visible structure in the final SVG. It is more useful than a generic verbal description of the requested scene.

The failure mode was equally consistent: the model would continue locally valid checking without deciding that the plan was sufficient. A truncated wombat attempt ended by reconsidering road perspective after the rest of the scene had already been designed:

The dashes at y 546: the car’s shadow at 481 — the car is at the top of the road (far lane). The dashes are in the middle of the road […] Aesthetically it’s fine […] Alternatively move the dashes…

The failed snail trace spent tokens deriving rotation direction:

For a counter-clockwise wheel: at the left point (9 o’clock), the motion is downward […] So the left arrow points down, the right arrow points up.

The pattern is not random text. It is relevant spatial work with weak stopping control. That resembles the operational definition of overthinking in Wei et al.’s Dynamic Rollout Editing for Reducing Overthinking in RL-Trained Reasoning Models: reasoning continues after a useful solution prefix has emerged, and sequence-level training credit does not distinguish the useful prefix from its unnecessary continuation. Sampling mattered here: four scenes completed on a second attempt without changing the prompt or settings. The crocodile needed a larger budget after two 40,960-token traces failed to terminate.

Problems encountered

The scene description was not an SVG instruction

My first worker sent A wombat driving a tiny red convertible... verbatim. Qwen returned prose and several alternative image-generation prompts. Prefixing it with Generate an SVG of fixed the task specification.

/api/generate did not separate reasoning in this run

My initial call used Ollama’s /api/generate endpoint. With this model/runtime combination, the model emitted its planning and partial SVG into one response field, reached 32,696 generated tokens, and stopped mid-document. The successful pelican reproduction had used /api/chat; matching that route produced separate message.thinking and message.content fields as described by the chat API reference.

A 32K budget was insufficient

Even with the chat endpoint, the first xhigh run consumed the complete 32,768-token allowance in reasoning and emitted no final content. Increasing the practical budget to 40,960 was enough for seven scenes, with retries. The eighth needed 65,536.

Context size changed the hardware path

At 32,768 tokens, the model fit entirely on the RTX 4090. The 40,960-token configuration was close enough to sustain about 31 tokens/s. At 65,536, the runtime no longer fit in 24 GB VRAM and partial CPU offload reduced final throughput to 10.99 tokens/s. The nominal native context window is much larger, but the useful local limit depends on KV-cache memory and acceptable offload speed.

Retry policy affects the result

A retry here means a fresh stochastic generation with the same prompt and sampling settings. For xhigh I retried only when the response contained no complete SVG. For no reasoning, the only retry followed a tool-call response with no SVG. That makes this a generation exercise, not a clean pass-at-one evaluation. The game discloses the xhigh retries because otherwise the comparison would imply a uniform success criterion that was not used.

References

Primary model and runtime sources:

  1. Qwen, Qwen3.8-27B model card.
  2. Unsloth, Qwen3.8-27B-GGUF and Qwen 3.8 local inference guide.
  3. Ollama, thinking-model fields, POST /api/chat, and POST /api/generate.
  4. Simon Willison, original local SVG post and full pelican transcript.

Relevant papers:

  1. Wei et al., Dynamic Rollout Editing for Reducing Overthinking in RL-Trained Reasoning Models, arXiv:2606.17890, 2026.
  2. de Souza and Panisson, Who Thinks Best Depends on How Long You Let Them: Budget-Dependent Rankings in LLM Evaluation, arXiv:2608.12150, 2026.
  3. Shen et al., Detecting Unfaithful Chain-of-Thought via Circuit-Guided Internal-External Discrepancy, arXiv:2605.25603, 2026.
  4. Lee et al., Know When to Stop: Segment-Level Credit Assignment for Reducing Overthinking, arXiv:2607.00482, 2026.

Result

The sixteen SVGs—eight xhigh and eight with reasoning disabled—are unedited model outputs. All parse as XML and render without missing resources. The xhigh set is included as a fifth candidate in the blind comparison, alongside Qwen 3.6 27B, Muse Glimmer 30B, Gemma 4 26B A4B and Gemma 4 31B dense. The no-reasoning set remains in this article as the controlled comparison.

Play the updated Who Drew This? model match →