thimble / README.md
flashvenom's picture
Upload folder using huggingface_hub
ce056af verified
|
Raw
History Blame Contribute Delete
7.22 kB
---
license: mit
language:
- en
pipeline_tag: text-generation
tags:
- function-calling
- tool-calling
- on-device
- small-model
- grammar-constrained-decoding
- edge
library_name: pytorch
model-index:
- name: thimble-v6
results:
- task:
type: text-generation
name: Function calling (ordered strict exact match)
dataset:
name: Seal-Tools in-domain
type: seal-tools
metrics:
- type: exact_match
value: 33.1
name: Seal-Tools in-domain
- task:
type: text-generation
name: Function calling (ordered strict exact match)
dataset:
name: Seal-Tools out-of-domain
type: seal-tools
metrics:
- type: exact_match
value: 28.1
name: Seal-Tools out-of-domain
- task:
type: text-generation
name: Function calling (ordered strict exact match)
dataset:
name: Mobile Actions
type: mobile-actions
metrics:
- type: exact_match
value: 86.3
name: Mobile Actions
- task:
type: text-generation
name: Function calling (ordered strict exact match)
dataset:
name: DroidCall
type: droidcall
metrics:
- type: exact_match
value: 52.5
name: DroidCall
- task:
type: text-generation
name: Function calling (ordered strict exact match)
dataset:
name: BFCL v4 single-turn
type: bfcl
metrics:
- type: exact_match
value: 23.5
name: BFCL v4 single-turn
---
# 🧡 Thimble
**A 48M-parameter tool-calling model that beats [Needle 2](https://cactuscompute.com/needle)
on 3 of its 5 published benchmarks β€” including their toughest, Seal-Tools β€” with 150Γ— less training data.**
[**GitHub (code, evals, full experimental record)**](https://github.com/nikshepsvn/thimble) Β· MIT Β· 48.12M params Β· 11.5MB at 2-bit Β· $260 total build cost
![Results](results.png)
## TL;DR
| Suite | Thimble v6 | Needle 2 (45M) | |
|---|---:|---:|---|
| Seal-Tools in-domain (700) | **33.1** | 32.6 | βœ… their flagship suite |
| Mobile Actions (961) | **86.3** | 63.7 | βœ… +22.6 |
| DroidCall (200) | **52.5** | 17.0 | βœ… 3.1Γ— |
| Well-formed JSON | **100.0** | 93.4 | βœ… by construction |
| Seal-Tools out-of-domain (654) | 28.1 | **28.7** | ❌ βˆ’0.6 |
| BFCL v4 single-turn (3,641) | 23.5 | **42.6** | ❌ their data moat |
Metric: **ordered strict exact match** β€” a row passes only if the function names,
call order, and *every* argument value match. Their metric, their published
numbers, unmodified. Needle 2 trained on **153B tokens**; Thimble saw **~1B**.
Two things to know before quoting the table: the Seal-in margin (+0.5 on 700
rows) is within sampling noise and we say so, and the pre-registered model
selector actually picked a sibling checkpoint that scored worse β€” the failure is
diagnosed, both models' results are published, and the full story is in
[RESULTS.md](https://github.com/nikshepsvn/thimble/blob/master/RESULTS.md).
## Why a thimble beats a needle
**1. Tool calling is five decisions, not a generation problem.** A grammar
compiled from the tool schemas force-feeds all JSON structure β€” braces, quotes,
and every argument key. The model is consulted at exactly five choice points:
*refuse or call Β· which tool Β· include this optional? Β· what value Β· stop or
continue*. Malformed JSON, hallucinated parameter names, and calls to
nonexistent tools are **unreachable, not unlikely**. At 45M parameters, capacity
spent learning that `{` follows `[` is capacity wasted.
**2. Every training example earns its place.** Row accuracy factors as
`P(name sequence) Γ— pⁿ`. Each version measured which factor was binding and
attacked only that. The final data round was synthesized directly against the
previous model's diagnosed failure buckets β€” spurious optional arguments,
wrong-slot entity binding, date canonicalization β€” with a mid-training causal
check (+3.3 points at constant LR, attributable to the corrective data alone).
**3. Anneal, don't retrain.** A controlled twin experiment: the corrective
corpus fed from scratch *diluted* (28.4); the same corpus **annealed into the
learning-rate decay phase** of a continued run *concentrated* (33.1). The decay
phase is where a WSD-trained model crystallizes β€” that's where the good data
belongs.
## What didn't work (measured, not guessed)
The most reusable part of the project. Each idea was killed by an A/B, not an argument:
| idea | result |
|---|---|
| Span-copy heads | βˆ’30 pts |
| Pointer/copy head | βˆ’16 pts |
| Down-weighting grammar-forced tokens (RFT-style) | βˆ’12 pts β€” structure tokens carry call-sequencing signal |
| From-scratch retrain on corrective data | βˆ’4.7 vs annealing |
| Field-set reranking | βˆ’1.4 β€” training had already fixed its target bucket |
| Beam / RL / best-of-N | oracle-capped below target |
| RLOO fine-tune on the annealed checkpoint | diverges at every LR β€” sharp minima and policy gradients don't mix |
| Matching Seal's gold numeric typing | not learnable β€” 74% of params are mixed-convention noise |
## Model details
| | |
|---|---|
| Parameters | 48.12M (fp32; ~11.5MB at Needle's own 2-bit standard vs their 14MB) |
| Architecture | deep-thin gated trunk: d=448, 20 layers, GQA 8/4, SwiGLU Γ—2.0, QK-norm, sandwich RMSNorm, tied embeddings |
| Tokenizer | 16,384 BPE, digits as singletons, JSON structural chars as singletons |
| Context | 768 tokens |
| Decoding | grammar-constrained, five choice points, plan-conditioned retrieval between calls |
| Training | Muon (trunk) + AdamW, WSD schedule, EMA, weighted CE matched to the error distribution, decay-phase data annealing |
## Files & usage
- `thimble-v6.pt` β€” checkpoint (`torch.load(..., weights_only=False)` β†’ `{"model": state_dict, "cfg": dict}`)
- `tokenizer.json` β€” BPE vocab + merges
The guarantees live in the decoding harness, so inference goes through the repo:
```bash
git clone https://github.com/nikshepsvn/thimble
cd thimble && uv venv && uv pip install -e .
# put thimble-v6.pt in checkpoints/, tokenizer.json in data/
python demo.py "make a reservation at Nobu for 2 people at 7pm and text Sam saying dinner is on"
# [{"name": "createReservation",
# "arguments": {"partySize": 2, "restaurant": "Nobu", "time": "7pm"}},
# {"name": "sendMessage",
# "arguments": {"body": "dinner is on", "contact": "Sam"}}]
python demo.py "sing me a happy birthday song"
# [] (refused: no tool applies)
python scripts/final_eval.py --ckpt thimble-v6 --suite seal-tools-in # reproduce the table
```
Real output, not a mock β€” typed integers, two-call composition, and refusal,
with structure guaranteed by the grammar.
## Integrity
Public corpora (xlam, ToolACE, Dolci, Glaive, official benchmark train splits)
plus stepwise-validated, evidence-filtered synthetic data. Every training row
passed an **8-gram contamination firewall against every evaluation query of
every reported suite** (BFCL included). Champion selection by held-out dev loss
only; nothing was ever tuned on an eval set; every negative result is published.
*Built by one person and an AI assistant in about a week of evenings, for about
the price of a game console. The failures are the useful part.*