GraySoft
Projects Models Compare Cloud benchmarks FAQ Download guIDE →
Model Intelligence Sheet

doldolggi/EvoCUA-32B-20260105-GGUF overview

EvoCUA 32B GGUF — quantized and verified against click coordinate regression GGUF conversions of meituan/EvoCUA 32B 20260105 https://huggingface.co/meituan/Evo…

ggufllama.cppcomputer-usegui-agentqwen3vlquantizationamdrocmrdna4image-text-to-textbase_model:meituan/EvoCUA-32B-20260105base_model:quantized:meituan/EvoCUA-32B-20260105license:apache-2.0endpoints_compatibleregion:usconversational

Runs locally from ~1.11 GB disk (4 GB VRAM class GPUs with llama.cpp / guIDE).

Downloads
0
Likes
0
Pipeline
image-text-to-text
Author

Repository Files & Downloads

6 GGUF files detected
Direct downloads for local inference
FileTypeQuantizationSizeLink
evocua-32b-Q4_K_M.ggufGGUFQ4_K_M18.40 GBDownload
evocua-32b-Q5_K_M.ggufGGUFQ5_K_M21.62 GBDownload
evocua-32b-Q6_K.ggufGGUFQ6_K25.04 GBDownload
evocua-32b-UD-Q4_K_XL.ggufGGUFQ4_K_XL18.68 GBDownload
evocua-32b-UD-Q5_K_XL.ggufGGUFQ5_K_XL21.65 GBDownload
mmproj-evocua-32b-f16.ggufGGUFF161.11 GBDownload

Model Details

Model IDdoldolggi/EvoCUA-32B-20260105-GGUF
Authordoldolggi
Pipelineimage-text-to-text
Licenseapache-2.0
Base modelmeituan/EvoCUA-32B-20260105
Last modified2026-08-30T11:12:40.000Z

Model README

---

license: apache-2.0

base_model: meituan/EvoCUA-32B-20260105

base_model_relation: quantized

pipeline_tag: image-text-to-text

library_name: gguf

tags:

- gguf

- llama.cpp

- computer-use

- gui-agent

- qwen3vl

- quantization

- amd

- rocm

- rdna4

---

EvoCUA-32B GGUF — quantized and verified against click-coordinate regression

GGUF conversions of meituan/EvoCUA-32B-20260105,

a Qwen3-VL-based computer-use agent (CUA).

What makes this repo different: every quant here was measured on a **click-coordinate

regression suite, against a BF16 baseline of the same conversion**. A CUA's output is a

click coordinate, not prose — a broken preprocessing step yields perfectly fluent text with

systematically shifted coordinates, and no perplexity number will tell you. Existing GGUF repos

ship quants with no evidence either way. This one ships the evidence, the harness, and the raw

per-case results.

👉 **8B sibling repo, with a much wider quantization ladder (Q5 → IQ1) measured against the

original transformers model:**

doldolggi/EvoCUA-8B-20260105-GGUF.

Several conclusions below only hold because both sizes were measured — see Cross-size findings.

> ⚠️ Scope of the evidence. 16 grounding cases, English UI, single-turn, synthetic

> screenshots with constructed ground truth. No OSWorld end-to-end benchmark was run.

> Measured process/kernel noise floor is ~2 px — differences below that are not meaningful.

> Read the tables as "does quantization move the click", not as a task-success benchmark.

Results

Baseline is our own BF16 GGUF of this model (the 8B repo uses the actual transformers

model, which is stronger; 32B BF16 is 61 GiB and does not fit a single 32 GB card).

Two metrics are reported separately because they mean different things:

miss = emitted a coordinate that landed outside the target (grounding failure);

non-click = chose wait/etc. so there is no coordinate (behavioural difference, not a failure).

| build | GiB | on-target | exact coord | narrow err mean/max | vs BF16 |

|---|---|---|---|---|---|

| Q6_K | 25.04 | 16/16 | 10/16 | 1.53 / 10.0 px | — |

| UD-Q5_K_XL | 21.65 | 16/16 | 10/15 | 1.06 px | action 16/16 |

| Q5_K_M | 21.62 | 16/16 | 7/16 | 1.78 / 6.0 px | action 15/16 |

| UD-Q4_K_XL | 18.68 | 16/16 | — | — | see results/ |

| Q4_K_M | 18.40 | 16/16 | 6/16 | 2.03 / 6.0 px | — |

All quants stay on-target 16/16 with no systematic offset. Degradation is monotonic but

stays within ~2 px of BF16 across the whole range — i.e. quantization down to Q4 does not move

the click in any way that matters at these target sizes.

Unsloth Dynamic (UD): what actually helps

The UD method has two parts — a custom imatrix and a per-tensor bit allocation. We separated them:

| build | recipe | imatrix | action match | exact coord | narrow mean |

|---|---|---|---|---|---|

| Q5_K_M | stock | none | 15/16 | 7/15 | 1.31 px |

| Q5_K_M | stock | Unsloth | 15/16 | 8/15 | 1.82 px |

| Q5_K_M | stock | ours (EvoCUA) | 15/16 | 9/15 | 1.77 px |

| UD-Q5_K_XL | UD | Unsloth | 16/16 | 10/15 | 1.06 px |

| UD-Q5_K_XL | UD | ours | 15/16 | 10/14 | 0.86 px |

  • The gain comes from the tensor allocation, not the imatrix. Swapping the imatrix changes

little; swapping the recipe is what moves every metric. Confirmed on 8B with a cleaner

control (imatrix held constant) — see the sibling repo.

  • The imatrix source does not matter. Unsloth's (computed on the base model, before the

CUA fine-tune) vs ours are indistinguishable. Using a base-model imatrix on a fine-tune is fine.

  • UD-Q5_K_XL is the only build that reproduced BF16's action choice on all 16 cases,

including a case where BF16 chose to wait before clicking a Delete button and stock Q5_K_M

clicked instead.

  • ⚠️ Tier-scoped. On 8B the UD advantage is clear at Q4–Q5 and vanishes at Q3/Q2.

"UD is always better" is not what this data says.

Only one UD-Q5 build is uploaded (the Unsloth-imatrix one). The ablation arms above were

measured, not shipped; their per-case JSON is in results/.

Cross-size findings (why the 8B repo matters)

  • A 32B observation that UD hurt at Q4 (one 83 px outlier) failed to replicate on 8B, so

we retracted it as n=1 noise. Single-size, single-case patterns are not patterns.

  • The 8B ladder pushes down to IQ1, where grounding collapses completely (1/6 on-target,

mean error half a screen) — with a stock-quant control showing it is the bit level, not the

recipe. That tier doubles as a negative control: a harness where everything passes tells you

nothing.

Files

| file | GiB | notes |

|---|---|---|

| evocua-32b-Q6_K.gguf | 25.04 | ⚠️ see VRAM note — does not fit one 32 GB card at 32K ctx |

| evocua-32b-UD-Q5_K_XL.gguf | 21.65 | recommended — most faithful to BF16 per byte |

| evocua-32b-Q5_K_M.gguf | 21.62 | stock equivalent, same size |

| evocua-32b-UD-Q4_K_XL.gguf | 18.68 | built with our imatrix (the UD-Q5 above uses Unsloth's — the two are interchangeable, see above) |

| evocua-32b-Q4_K_M.gguf | 18.40 | |

| mmproj-evocua-32b-f16.gguf | 1.11 | vision encoder, never quantized |

| evocua-32b.imatrix | 15 MB | computed on this model (44 chunks, PPL 3.95) |

BF16 (61 GiB) is not uploaded — regenerate in a few minutes:

python convert_hf_to_gguf.py <HF_DIR> --outfile evocua-32b-bf16.gguf --outtype bf16
python convert_hf_to_gguf.py <HF_DIR> --outfile mmproj-evocua-32b-f16.gguf --outtype f16 --mmproj

VRAM — read this before picking a quant

Measured on a 32 GB card (AMD R9700, 31.86 GiB usable):

| build | -c 8192 | -c 32768 + KV q8_0 |

|---|---|---|

| Q6_K 25.04 | 31.0 GiB — fits, barely | ⛔ 34.0 / 34.2 GB — saturates, falls back to host memory |

| UD-Q5_K_XL / Q5_K_M ~21.6 | 27.8 GiB | 28.8 GiB — fits ✅ |

| Q4_K_M 18.40 | 24.6 GiB | fits |

> ⛔ Q6_K at 32K context does not fit a single 32 GB card, and llama.cpp will **not tell

> you**. It starts fine and answers correctly, ~9× slower: we measured the same file at

> 15.7 tok/s (-c 8192) vs 1.74 tok/s (-c 32768, VRAM saturated, degrading further as

> the KV cache grows). The only way to detect this is to measure decode speed.

Performance of the recommended build (1× 32 GB card, -c 32768, KV q8_0, -fa on, median of 3

restarts, one 1920×1080 screenshot in the prompt): **prefill 17.4 tok/s, decode 17.6 tok/s,

28.8 GiB.**

Serving

llama-server -m evocua-32b-UD-Q5_K_XL.gguf --mmproj mmproj-evocua-32b-f16.gguf \
  -ngl 99 -c 32768 --parallel 1 \
  --cache-type-k q8_0 --cache-type-v q8_0 -fa on \
  --reasoning-format none \
  --host 127.0.0.1 --port 8080

Traps that cost us time — please read

  1. --reasoning-format none is mandatory. With the default (auto), the thought block is

moved into reasoning_content and the EvoCUA S2 parser — which reads <think> +

<tool_call> out of content — silently sees nothing. No error, just an empty parse.

  1. Never pass --reasoning-budget. Truncating the CoT breaks the agent loop.
  2. 4K screenshots get downscaled, unlike upstream. llama.cpp's Qwen3-VL branch hardcodes

set_limit_image_tokens(8, 4096) and neither writes nor reads image_min_pixels /

image_max_pixels in the mmproj GGUF. Cap = 4096 merged tokens = 4.19 MP.

1920×1080 → 1920×1088 = 2040 tokens, no downscale. 3840×2160 = 8.3 MP is downscaled.

Pass --image-max-tokens 16384 if you feed 4K. (Upstream EvoCUA allows 16.7 MP.)

  1. Do not add --image-min-tokens 1024 just because llama.cpp warns about it, if you

pre-resize your screenshots — it will upscale small images and diverge from upstream.

Coordinate convention (app side)

EvoCUA defaults to coordinate_type=relative: the system prompt states

"The screen's resolution is 1000x1000" and the model emits a 0..999 grid.

Absolute pixels = x * width / 999. Output is a tool_call, not pyautogui

(that is the S1 prompt style):

<tool_call>{"name":"computer_use","arguments":{"action":"left_click","coordinate":[x,y]}}</tool_call>

Screenshots must be pre-resized with smart_resize(factor=32) by the caller, exactly as the

upstream harness does.

How the verification works

harness/ contains everything. Two design decisions make the numbers trustworthy:

  1. Test pages are rendered at 1920×1088 = 34 × 32, so smart_resize(factor=32) is the

identity. Neither reference nor llama.cpp resizes the image, which removes preprocessing

differences from the measurement and leaves only conversion/quantization.

  1. Every click target is placed at absolute CSS coordinates, so the ground-truth bbox is a

construction, not a hand measurement. make_testpages.py regenerates the whole suite.

Wide targets (e.g. a 1620 px file row) are reported separately: clicking the filename vs the row

centre are both correct, so their large deltas say nothing about quantization. Judgement uses

narrow targets (≤250 px) plus on-target rate.

A kernel-path control was run for this model: Q5_K_M re-measured with the exact multi-GPU +

CPU-offload topology used for the BF16 baseline, versus its single-GPU result — **0.33 px mean,

2.0 px max, no systematic offset**. That is the noise floor the tables above sit on.

Notes for AMD / ROCm (gfx1201, RDNA4) users

All measurements were made on 2× AMD Radeon AI PRO R9700 (gfx1201 / RDNA4, 32 GB each) under

ROCm with a llama.cpp HIP build. gfx1201 numbers are scarce, so:

  • The system ROCm install may not be enough to build. Ours had no

hip / hip-lang / hipblas / rocblas CMake packages, so -DGGML_HIP=ON failed at

configure. Point ROCM_PATH / CMAKE_PREFIX_PATH at a gfx1201-targeted ROCm SDK that has

them (and set LD_LIBRARY_PATH at runtime).

  • Do not pass -ngl when splitting across multiple GPUs. It disables llama.cpp's

automatic fitting: common_fit_params: ... n_gpu_layers already set by user ... abort.

Manual values failed twice for us (CUBLAS_STATUS_ALLOC_FAILED on hipBLAS handle creation;

cudaMalloc failed: out of memory). Passing only -mg <gpu> and leaving -ngl/-ts unset

worked first try. llama.cpp knows the real buffer requirements; don't guess layers.

This is how we ran the 61 GiB BF16 baseline across two cards: **prefill 320 tok/s, decode

4.6 tok/s, 16 cases in ~9 minutes** — versus a single-card -ngl 30 attempt that thrashed

swap at 0.24 tok/s and never finished one case.

  • ⚠️ If VRAM is short, llama.cpp starts fine and silently falls back to host memory (GTT).

See the VRAM section above.

Reproducing

# 1) pull the UD tensor allocation out of Unsloth's published GGUF header (~12 MB, not 20 GB)
python harness/extract_ud_recipe.py \
  --repo unsloth/Qwen3-VL-32B-Thinking-GGUF \
  --file Qwen3-VL-32B-Thinking-UD-Q5_K_XL.gguf \
  --verify-against evocua-32b-bf16.gguf --out ud_q5_recipe.txt

# 2) quantize with it. token_embd / output need the dedicated flags, not --tensor-type.
#    Always --dry-run first: it validates the whole recipe in seconds.
llama-quantize --imatrix imatrix_unsloth.gguf \
  --tensor-type-file ud_q5_recipe.txt \
  --token-embedding-type q5_k --output-tensor-type q6_k \
  evocua-32b-bf16.gguf evocua-32b-UD-Q5_K_XL.gguf Q5_K_M 24

# 3) regenerate the test suite (deterministic: targets are CSS-positioned, not measured)
python harness/make_testpages.py

# 4) score a build against the baseline
python harness/coord_test.py --arm gguf --url http://127.0.0.1:8080/v1 --out coord_x.json
python harness/compare_arms.py --baseline results/coord_bf16_32b_2gpu.json --arms "x=coord_x.json"

Credits & licensing

(Apache-2.0). These files are quantized derivatives of those weights.

  • Unsloth Dynamic (UD) recipes are not ours. The UD-* files reproduce the per-tensor bit

allocation published by Unsloth for the base model

(unsloth/Qwen3-VL-32B-Thinking-GGUF).

EvoCUA-32B is a fine-tune of that model, so the GGUF tensor names match exactly (707/707) and

their allocation transfers. harness/extract_ud_recipe.py reads it out of the GGUF header via

an HTTP range request. Their published imatrix is used where noted.

Credit for the recipe belongs to Unsloth; the measurement is ours.

  • Another 32B GGUF set exists at

spicyneuron/meituan-EvoCUA-32B-20260105-GGUF.

Ours are independent conversions; the numbers here describe these files.

  • llama.cpp commit used: 3173a56471c1753650cd806694145ffd6dcace67 (ggml 0.22.0).
  • Korean full report (covers 8B and 32B): REPORT.ko.md.

Run doldolggi/EvoCUA-32B-20260105-GGUF with guIDE

Download guIDE — the AI-native code editor with local LLM inference and 69 built-in tools.

Download guIDE → · Browse 524k+ models · Compare models

Source: Hugging Face · Compare models