Reframe card around the capability and its boundary
Browse filesLead with what the model does — tool calling against a known catalog as structured extraction at 48M params — rather than a scoreboard row.
- Results split into known-catalog / unknown-catalog tables; Needle 2 stays as a named yardstick column so the numbers keep their scale.
- New 'Where it stops working' section with per-category BFCL evidence.
- Negative-result count reconciled to 11.
- Deployment figure corrected: 184MB fp32 as shipped (was 168MB bf16, a stale figure from the 44.1M era).
README.md
CHANGED
|
@@ -65,47 +65,73 @@ model-index:
|
|
| 65 |
value: 23.5
|
| 66 |
name: BFCL v4 single-turn
|
| 67 |
---
|
| 68 |
-
|
| 69 |
# 🧵 Thimble
|
| 70 |
|
| 71 |
-
**
|
| 72 |
-
|
| 73 |
|
| 74 |
-
[**GitHub (code, evals, full experimental record)**](https://github.com/nikshepsvn/thimble) · MIT · 48.12M params ·
|
| 75 |
|
| 76 |

|
| 77 |
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
[RESULTS.md](https://github.com/nikshepsvn/thimble/blob/master/RESULTS.md).
|
| 98 |
|
| 99 |
-
##
|
| 100 |
|
| 101 |
**1. Tool calling is five decisions, not a generation problem.** A grammar
|
| 102 |
compiled from the tool schemas force-feeds all JSON structure — braces, quotes,
|
| 103 |
and every argument key. The model is consulted at exactly five choice points:
|
| 104 |
*refuse or call · which tool · include this optional? · what value · stop or
|
| 105 |
continue*. Malformed JSON, hallucinated parameter names, and calls to
|
| 106 |
-
nonexistent tools are **unreachable, not unlikely**. At
|
| 107 |
spent learning that `{` follows `[` is capacity wasted.
|
| 108 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
**2. Every training example earns its place.** Row accuracy factors as
|
| 110 |
`P(name sequence) × pⁿ`. Each version measured which factor was binding and
|
| 111 |
attacked only that. The final data round was synthesized directly against the
|
|
@@ -116,8 +142,8 @@ check (+3.3 points at constant LR, attributable to the corrective data alone).
|
|
| 116 |
**3. Anneal, don't retrain.** A controlled twin experiment: the corrective
|
| 117 |
corpus fed from scratch *diluted* (28.4); the same corpus **annealed into the
|
| 118 |
learning-rate decay phase** of a continued run *concentrated* (33.1). The decay
|
| 119 |
-
phase is where a WSD-trained model crystallizes — that
|
| 120 |
-
belongs.
|
| 121 |
|
| 122 |
## What didn't work (measured, not guessed)
|
| 123 |
|
|
@@ -134,11 +160,32 @@ The most reusable part of the project. Each idea was killed by an A/B, not an ar
|
|
| 134 |
| RLOO fine-tune on the annealed checkpoint | diverges at every LR — sharp minima and policy gradients don't mix |
|
| 135 |
| Matching Seal's gold numeric typing | not learnable — 74% of params are mixed-convention noise |
|
| 136 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
## Model details
|
| 138 |
|
| 139 |
| | |
|
| 140 |
|---|---|
|
| 141 |
-
| Parameters | 48.12M (fp32; ~11.5MB at
|
| 142 |
| Architecture | deep-thin gated trunk: d=448, 20 layers, GQA 8/4, SwiGLU ×2.0, QK-norm, sandwich RMSNorm, tied embeddings |
|
| 143 |
| Tokenizer | 16,384 BPE, digits as singletons, JSON structural chars as singletons |
|
| 144 |
| Context | 768 tokens |
|
|
|
|
| 65 |
value: 23.5
|
| 66 |
name: BFCL v4 single-turn
|
| 67 |
---
|
|
|
|
| 68 |
# 🧵 Thimble
|
| 69 |
|
| 70 |
+
**Tool calling in 48M parameters.** 86.3% ordered strict exact match on a real
|
| 71 |
+
app-intent catalog, 100% well-formed JSON by construction.
|
| 72 |
|
| 73 |
+
[**GitHub (code, evals, full experimental record)**](https://github.com/nikshepsvn/thimble) · MIT · 48.12M params · 768-token context · $260 total build cost
|
| 74 |
|
| 75 |

|
| 76 |
|
| 77 |
+
Calling tools against a *known* catalog is not an emergent capability of large
|
| 78 |
+
models — it is a structured extraction problem, and it fits in 48M parameters.
|
| 79 |
+
This card covers what the model does, how it was built, and exactly where it
|
| 80 |
+
stops working.
|
| 81 |
+
|
| 82 |
+
## What it does
|
| 83 |
+
|
| 84 |
+
Ordered strict exact match: a row passes only if the function names, the call
|
| 85 |
+
order, and *every* argument value match. The right-hand column is a yardstick, not a
|
| 86 |
+
rival: Needle 2 (Cactus Compute, 45M params, 153B training tokens), their
|
| 87 |
+
published numbers on their metric. It is there so the left column has a scale —
|
| 88 |
+
86.3 means little until you know what else scores on that suite.
|
| 89 |
+
|
| 90 |
+
**Known catalog** — represented in training, eval rows firewalled out:
|
| 91 |
+
|
| 92 |
+
| suite | Thimble v6 | Needle 2 (45M) |
|
| 93 |
+
|---|---:|---:|
|
| 94 |
+
| Mobile Actions (961) | **86.3** | 63.7 |
|
| 95 |
+
| DroidCall (200) | **52.5** | 17.0 |
|
| 96 |
+
| Seal-Tools in-domain (700) | **33.1** | 32.6 |
|
| 97 |
+
| Well-formed JSON | **100.0** | 93.4 |
|
| 98 |
+
|
| 99 |
+
**Unknown catalog** — schemas the model has never seen:
|
| 100 |
+
|
| 101 |
+
| suite | Thimble v6 | Needle 2 (45M) |
|
| 102 |
+
|---|---:|---:|
|
| 103 |
+
| Seal-Tools out-of-domain (654) | 28.1 | 28.7 |
|
| 104 |
+
| BFCL v4 single-turn (3,641) | 23.5 | 42.6 |
|
| 105 |
+
|
| 106 |
+
Those two tables are the whole finding. Familiar catalog, it works; unfamiliar
|
| 107 |
+
catalog, it degrades — and the degradation shows up *inside a single suite*:
|
| 108 |
+
Seal-Tools in-domain 33.1 vs out-of-domain 28.1 is the same model on the same
|
| 109 |
+
metric with only the catalogs changed. Name-sequence accuracy tracks it exactly,
|
| 110 |
+
88% in-domain against 79% out.
|
| 111 |
+
|
| 112 |
+
**Before quoting the table.** Mobile Actions' public train split (8,693 rows,
|
| 113 |
+
disjoint from eval) is in the training mix — that is what "known catalog" means,
|
| 114 |
+
and it is the intended operating condition. The Seal-in margin over the
|
| 115 |
+
calibration column is +0.5 on 700 rows, within sampling noise. The pre-registered
|
| 116 |
+
model selector picked a sibling checkpoint that scored worse; the failure is
|
| 117 |
+
diagnosed and both models' results are published in
|
| 118 |
[RESULTS.md](https://github.com/nikshepsvn/thimble/blob/master/RESULTS.md).
|
| 119 |
|
| 120 |
+
## How it was built
|
| 121 |
|
| 122 |
**1. Tool calling is five decisions, not a generation problem.** A grammar
|
| 123 |
compiled from the tool schemas force-feeds all JSON structure — braces, quotes,
|
| 124 |
and every argument key. The model is consulted at exactly five choice points:
|
| 125 |
*refuse or call · which tool · include this optional? · what value · stop or
|
| 126 |
continue*. Malformed JSON, hallucinated parameter names, and calls to
|
| 127 |
+
nonexistent tools are **unreachable, not unlikely**. At 48M parameters, capacity
|
| 128 |
spent learning that `{` follows `[` is capacity wasted.
|
| 129 |
|
| 130 |
+
Measured honestly, the grammar is a *reliability* mechanism rather than an
|
| 131 |
+
accuracy one — on Mobile Actions, free generation and constrained decoding agree
|
| 132 |
+
on 150 of 150 rows. What it buys is that the worst failure modes cannot be
|
| 133 |
+
expressed at all.
|
| 134 |
+
|
| 135 |
**2. Every training example earns its place.** Row accuracy factors as
|
| 136 |
`P(name sequence) × pⁿ`. Each version measured which factor was binding and
|
| 137 |
attacked only that. The final data round was synthesized directly against the
|
|
|
|
| 142 |
**3. Anneal, don't retrain.** A controlled twin experiment: the corrective
|
| 143 |
corpus fed from scratch *diluted* (28.4); the same corpus **annealed into the
|
| 144 |
learning-rate decay phase** of a continued run *concentrated* (33.1). The decay
|
| 145 |
+
phase is where a WSD-trained model crystallizes — that is where the good data
|
| 146 |
+
belongs. This is probably the most portable result in the project.
|
| 147 |
|
| 148 |
## What didn't work (measured, not guessed)
|
| 149 |
|
|
|
|
| 160 |
| RLOO fine-tune on the annealed checkpoint | diverges at every LR — sharp minima and policy gradients don't mix |
|
| 161 |
| Matching Seal's gold numeric typing | not learnable — 74% of params are mixed-convention noise |
|
| 162 |
|
| 163 |
+
Two of these reversed conclusions that would otherwise have shipped on intuition.
|
| 164 |
+
|
| 165 |
+
## Where it stops working
|
| 166 |
+
|
| 167 |
+
- **Unfamiliar catalogs.** Out-of-domain name-sequence accuracy is 79% against
|
| 168 |
+
88% in-domain. Every out-of-domain deficit traces back to this one number.
|
| 169 |
+
- **Schema dialects.** `simple_python` scores 29.3 on BFCL, but `simple_java`
|
| 170 |
+
14.0 and `simple_javascript` 8.0 — Java and JS schema conventions are absent
|
| 171 |
+
from a deliberately extractive ~1B-token corpus.
|
| 172 |
+
- **Parallel calls.** `parallel` 12.0 and `live_parallel` 0.0. Multi-call
|
| 173 |
+
composition works when calls are sequentially motivated by the query, not when
|
| 174 |
+
they are parallel instantiations of one schema.
|
| 175 |
+
- **768-token context.** 151 of 3,641 BFCL rows (4.1%) do not fit and score as misses.
|
| 176 |
+
- **Deployment.** 48.12M parameters is ~11.5MB at 2-bit and ~92MB at bf16, but
|
| 177 |
+
what ships here is the 184MB fp32 checkpoint and there is no on-device
|
| 178 |
+
inference engine. The size figure is a property of the parameter count, not of
|
| 179 |
+
a runnable microcontroller artifact.
|
| 180 |
+
|
| 181 |
+
Scale is the honest explanation for most of this: ~1B unique tokens, no
|
| 182 |
+
pretraining phase, a corpus deliberately spent on depth instead of breadth.
|
| 183 |
+
|
| 184 |
## Model details
|
| 185 |
|
| 186 |
| | |
|
| 187 |
|---|---|
|
| 188 |
+
| Parameters | 48.12M (fp32 checkpoint; ~11.5MB at 2-bit) |
|
| 189 |
| Architecture | deep-thin gated trunk: d=448, 20 layers, GQA 8/4, SwiGLU ×2.0, QK-norm, sandwich RMSNorm, tied embeddings |
|
| 190 |
| Tokenizer | 16,384 BPE, digits as singletons, JSON structural chars as singletons |
|
| 191 |
| Context | 768 tokens |
|