|
| 1 | +# Thinking Benchmark — Test Set, Procedure & Results |
| 2 | + |
| 3 | +> ⚠️ Point-in-time results (2026-09-07). The tables below are a snapshot from |
| 4 | +> the stack versions listed in each run; re-run after every pi / plugin / |
| 5 | +> server bump and replace the tables (see [Procedure](#procedure)). |
| 6 | +
|
| 7 | +Validates the full thinking chain — Pi level → lemonade-pi-plugin payload |
| 8 | +tuning (P2 budget, effortMap, P3 sampling, P5 off-switch) → llama.cpp |
| 9 | +server → response — with a small set of battle-tested reasoning problems. |
| 10 | + |
| 11 | +- **Harness:** `support/thinking-benchmark.py` (devstack) |
| 12 | +- **Related:** [Thinking support](thinking-support.md) for the wire-format |
| 13 | + background and server flags. |
| 14 | + |
| 15 | +## Test set |
| 16 | + |
| 17 | +12 single-shot problems with deterministic, machine-verifiable answers, |
| 18 | +adapted from public battle-tested benchmarks: |
| 19 | + |
| 20 | +| Tier | Count | Source | Expectation | |
| 21 | +|---|---|---|---| |
| 22 | +| Easy | 3 | GSM8K-style 2-step word problems (openai/grade-school-math) | pass in both modes | |
| 23 | +| Medium | 4 | GSM8K multi-step + MATH L3-style (hendrycks/math) | non-thinking misses some | |
| 24 | +| Hard | 5 | MATH L4-5 style: inclusion-exclusion, stars-and-bars, coin probability, exact-value log equation, recurrence | require thinking | |
| 25 | + |
| 26 | +All answers were machine-verified before inclusion. Scoring is keyword |
| 27 | +match with digit-boundary guards (no substring false-positives like "10" |
| 28 | +inside "100"). Prompts and keywords live in `support/thinking-benchmark.py` |
| 29 | +(`PROMPTS` / `ANSWER_KEYWORDS`). |
| 30 | + |
| 31 | +## What the harness checks per cell |
| 32 | + |
| 33 | +For every model × level combination the harness asserts **wire fidelity** — |
| 34 | +that each plugin-tuned parameter actually reached the backend and had its |
| 35 | +expected effect: |
| 36 | + |
| 37 | +- **P2:** `thinking_budget_tokens` equals the catalog budget re-clamped to |
| 38 | + `maxTokens − 1024` |
| 39 | +- **effortMap:** the on-wire `reasoning_effort` is the model-mapped value |
| 40 | + (e.g. Qwen3.8: minimal→low, high→xhigh) |
| 41 | +- **P3:** sampling row applied (thinking row for on-levels, nonThinking row |
| 42 | + at off) |
| 43 | +- **P5:** at off, `enable_thinking: false` is on the wire **and** the |
| 44 | + response contains zero reasoning chars |
| 45 | + |
| 46 | +Server health flags (`--cache-ram`, `--reasoning-budget-message`) are probed |
| 47 | +separately by `lpb-devstack validate` (see `scripts/localpibox/stack/serverhealth.py`). |
| 48 | + |
| 49 | +## Procedure |
| 50 | + |
| 51 | +```bash |
| 52 | +# one model, all levels, with a version-stamped markdown report |
| 53 | +python3 support/thinking-benchmark.py \ |
| 54 | + --models Qwen3.8-27B-GGUF \ |
| 55 | + --levels off,minimal,low,medium,high \ |
| 56 | + --report ~/thinking-reports/qwen3.8-27b-gguf.md |
| 57 | + |
| 58 | +# repeat per model; then update the tables below and commit with docs: |
| 59 | +``` |
| 60 | + |
| 61 | +The report stamps pi version, plugin git rev, and server build fingerprint — |
| 62 | +keep those in the tables when updating. Runs are sequential (single-GPU |
| 63 | +server); a full model takes ~10-20 min. |
| 64 | + |
| 65 | +## Results (2026-09-07) |
| 66 | + |
| 67 | +Server: llama.cpp `b10818` · pi 0.85.1 · lemonade-pi-plugin `81b8346` |
| 68 | +· 1 run per cell · wire fidelity 19/19 (Qwen) and 14/14 (Gemma, no effortMap) |
| 69 | + |
| 70 | +### Qwen3.8-27B-GGUF (dense) |
| 71 | + |
| 72 | +| Level | Score | Avg reasoning chars | Avg time | |
| 73 | +|---|---|---|---| |
| 74 | +| off | 10/12 (83%) | 0 | 11.8s | |
| 75 | +| minimal | **12/12 (100%)** | 379 | 10.9s | |
| 76 | +| low | **12/12 (100%)** | 378 | 10.3s | |
| 77 | +| medium | **12/12 (100%)** | 442 | 12.4s | |
| 78 | +| high | 11/12 (92%) | 596 | 11.7s | |
| 79 | + |
| 80 | +**Thinking lift:** `math_coin_prob` and (usually) `math_log_eq` fail at off |
| 81 | +and pass with thinking on. The only model in this set where the level dial |
| 82 | +measurably moves quality. |
| 83 | + |
| 84 | +### Qwen3.6-35B-A3B-MTP-GGUF (MoE, MTP draft) |
| 85 | + |
| 86 | +| Level | Score | Avg reasoning chars | Avg time | |
| 87 | +|---|---|---|---| |
| 88 | +| off | 11/12 (92%) | 0 | 4.0s | |
| 89 | +| minimal | 11/12 (92%) | 3112 | 19.7s | |
| 90 | +| low | 11/12 (92%) | 2921 | 17.7s | |
| 91 | +| medium | 11/12 (92%) | 5910 | 33.1s | |
| 92 | +| high | 11/12 (92%) | 3697 | 22.3s | |
| 93 | + |
| 94 | +**Flat band:** reasoning stays ~3-6k chars regardless of level — the model |
| 95 | +thinks its natural length and stops before any budget is hit. `math_log_eq` |
| 96 | +fails at **all** levels (capability gap, not a thinking effect). Thinking |
| 97 | +adds latency without accuracy gain on this set. |
| 98 | + |
| 99 | +### Gemma-4-26B-A4B-it-MTP-GGUF (MoE, MTP draft) |
| 100 | + |
| 101 | +| Level | Score | Avg reasoning chars | Avg time | |
| 102 | +|---|---|---|---| |
| 103 | +| off | 11/12 (92%) | 0 | 3.0s | |
| 104 | +| minimal | 11/12 (92%) | 1239 | 9.7s | |
| 105 | +| low | 11/12 (92%) | 1494 | 11.3s | |
| 106 | +| medium | 11/12 (92%) | 1373 | 10.3s | |
| 107 | +| high | 11/12 (92%) | 1149 | 8.9s | |
| 108 | + |
| 109 | +Same pattern as Qwen3.6: flat reasoning band, `math_log_eq` fails at all |
| 110 | +levels, no thinking lift on this set. No effortMap in the catalog — levels |
| 111 | +pass through unchanged (all accepted by its template). User-tier |
| 112 | +`maxTokens: 8192` correctly re-clamps medium/high budgets to 7168. |
| 113 | + |
| 114 | +### Cross-model reading |
| 115 | + |
| 116 | +- **Off switch works everywhere:** zero reasoning at off on all three |
| 117 | + models (`enable_thinking: false` honored per-request). |
| 118 | +- **`math_log_eq` (x = 1+√17)** is the set's sharpest discriminator: only |
| 119 | + Qwen3.8 solves it, and only with thinking. |
| 120 | +- **Token caveat:** `completion_tokens` includes MTP draft tokens on |
| 121 | + \*MTP models — compare reasoning chars and wall time across models, not |
| 122 | + token totals. |
| 123 | + |
| 124 | +## Releasing results with a tag |
| 125 | + |
| 126 | +The tables above are the published record. When cutting a stable release: |
| 127 | + |
| 128 | +1. Run the benchmark for each supported model (Procedure above). |
| 129 | +2. Replace the result tables + version line in this file. |
| 130 | +3. Commit on `dev` with a `docs:` prefix — the release docs gate |
| 131 | + (`lpb-devstack release docs-ready`) picks it up like any doc change. |
0 commit comments