CoolFace
Modelpublic

gixno/needle-termux-sting

sourceHugging Facemitupdated 2mo agoView on Hugging Face
1likes24downloads
Model Card

needle-termux-sting ๐Ÿชก

Needle (26M-parameter "Simple Attention Network" for single-shot function calling, by cactus-compute) finetuned on the Termux:API command set โ€” the model behind sting, a pure-Rust CLI that gives Termux natural-language device control, fully offline.

"vibrate for 2 seconds"
  โ†’ [{"name":"termux_vibrate","arguments":{"duration_ms":2000}}]

What's different from base needle

  1. 1.Finetuned decoder โ€” 4,810 synthetic examples over 16 Termux:API tools + 14 generic tools (single-call, multi-call, missing-argument, and no-tool cases; EN + some Arabic values). Recipe and data generator: sting/finetune.
  2. 2.Working retrieval head โ€” the released base checkpoint ships its contrastive (retrieval) head as all zeros, and zero weights + ReLU is a gradient fixed point, so ordinary finetuning can never revive it. This checkpoint's head was re-initialized and then trained on frozen encoder features (softmax-over-tools). Retrieval over the 16-tool Termux pack: hit@3 = 99.2%, hit@6 = 100% (400 queries).

Eval (held-out test set, 300 examples, 30 tools)

metricbase needlethis model
call_f1 (name+args exact)75.0%99.7%
name_f194.6%100.0%
exact_match72.7%99.7%
args_acc79.2%99.7%
parse_rate99.3%100.0%

Held-out but same-distribution synthetic data โ€” treat as an upper bound for wild phrasing. Methodology + per-tool tables: sting/EVAL.md.

Files

fileformatuse with
needle_sting_final.pklneedle checkpoint (JAX/Flax, f16)the official needle pipeline: needle run --checkpoint needle_sting_final.pkl --query "..." --tools '[...]'
model.safetensors + config.json + tokenizer_spec.jsonf16 safetensors + JSON specssting's pure-Rust candle runtime

Usage (Python / needle)

python
from needle import SimpleAttentionNetwork, load_checkpoint, generate, get_tokenizer

params, config = load_checkpoint("needle_sting_final.pkl")
model = SimpleAttentionNetwork(config)
result = generate(
    model, params, get_tokenizer(),
    query="read the gyroscope, 5 readings",
    tools='[{"name":"termux_sensor","description":"Read values from a hardware sensor on the device.","parameters":{"sensor":{"type":"string","description":"Sensor name: accelerometer, gyroscope, light, proximity, pressure, magnetic_field or gravity.","required":true},"limit":{"type":"integer","description":"Number of readings to take.","required":false}}}]',
    stream=False,
)
# [{"name":"termux_sensor","arguments":{"sensor":"gyroscope","limit":5}}]

Usage (Termux / sting)

bash
pkg install rust git binutils termux-api
git clone https://github.com/abod707/sting
cd sting && ./scripts/termux-install.sh
sting "turn on the flashlight"

Scope & limitations

Single-shot function calling over a provided toolset. Not conversational, no multi-step planning; underspecified requests ("set an alarm" with no time) correctly return []. Custom tools work zero-shot via the generic schemas it saw in training; for production use of your own tools, finetune with ~120 examples per tool (recipe in the sting repo).

Credits

Base model, architecture, and training pipeline: cactus-compute/needle (MIT). Finetune, retrieval-head fix, and Rust runtime: abod707 (MIT).