Loom Atom

Loom Atom

22,392 parameters Β· 57 KB Β· Textile Labs

One question, one bit: does this need a tool?

whats the weather in leeds   β†’  <tool>
remind me to call mum at 6   β†’  <tool>
convert 30 miles to km       β†’  <tool>

who are you                  β†’  <none>
i had a rough day            β†’  <none>
sort it out                  β†’  <none>

It emits exactly one token. That's the whole model.

Trained from scratch in five minutes on a 2013 desktop CPU β€” randomly initialised weights, nothing fine-tuned from a pretrained base. It is a real causal transformer, not a classifier: 2 layers, 24 hidden dimensions, tied embeddings.

Measured

Loom Atom keyword baseline
held-out human utterances (1,860) 96.0% 64.9%
SNIPS β€” never seen in training (700) 96.6% 59.0%

The second row is the one that matters. SNIPS played no part in training and the score does not drop β€” so this is not memorised phrasings. The keyword baseline is a hand-written list of ~75 tool-ish words scored on the identical splits.

Both test sets are balanced, so chance is 50%.

How small is 22,392 parameters?

parameters ratio
Loom Weave 2 59,650,000 2,664Γ—
Loom Spark 2 19,867,008 887Γ—
Loom Router 1 1,435,040 64Γ—
Loom Atom 22,392 1Γ—

57 KB. Small enough to embed as a byte array in a header file, and it runs in well under a millisecond on a CPU.

What it's for

The cheapest useful decision in an agent stack: should this request touch a tool at all?

Put it in front of everything. If it says <none>, you have saved a retrieval call, a router call, and possibly a large-model call β€” for the cost of a 57 KB matrix multiply. If it says <tool>, hand off to something that decides which tool (Loom Router 1 does that in one token across 17 routes).

It is not a chat model, a router, or a classifier of intent. It answers one binary question and nothing else.

Where the floor is

A full ladder was trained, four minutes per rung, identical data:

params dim layers held-out SNIPS
86,640 48 3 93.0% 95.9%
26,976 32 2 95.6% 93.6%
22,392 24 2 96.0% 96.6%
9,392 16 2 93.4% 94.1%
6,800 16 1 83.0% 84.4%
4,812 12 1 82.2% 81.9%

Depth matters more than width. Narrowing from 24 to 16 dimensions cost about 3 points. Dropping from two layers to one cost ten. One attention layer can notice keywords; two can combine a keyword with its context. The floor is a layer count, not a parameter count.

Every rung beats the keyword baseline β€” even 4,812 parameters, by 17 points.

One honest note: the 86,640-parameter model scores lowest on held-out data because every rung got the same four minutes, and it completed 3,006 optimiser steps against 24d2L's 10,809. It is under-trained, not worse. Do not read this table as "smaller is better".

Known weakness

Questions about the user personally β€” "what is my sister's name", "what did I have for breakfast" β€” are the hard case. They need no tool (no tool can answer them), but they look like lookups. Atom gets some right and some wrong; treat <tool> on a first-person question as unreliable.

Usage β€” Ollama

ollama run hf.co/textilelabs/Loom-Atom "whats the weather in leeds"
# <tool>

The template and params files in this repo are read automatically. params pins temperature: 0 and num_predict: 1 β€” one token, deterministic.

Usage β€” transformers

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

tok = AutoTokenizer.from_pretrained("textilelabs/Loom-Atom")
model = AutoModelForCausalLM.from_pretrained("textilelabs/Loom-Atom").eval()
pair = torch.tensor([tok.convert_tokens_to_ids("<tool>"),
                     tok.convert_tokens_to_ids("<none>")])

def needs_tool(message: str) -> bool:
    p = f"<user>\n{message.strip()}\n<|eot|>\n<loom>\n"
    ids = tok(p, return_tensors="pt", add_special_tokens=False).input_ids
    with torch.no_grad():
        logits = model(input_ids=ids).logits[0, -1]
    # decide only between the two legal answers
    return bool(logits[pair].argmax() == 0)

needs_tool("whats the weather in leeds")   # True
needs_tool("i had a rough day")            # False

Prompt format is exact: <user>\n{message}\n<|eot|>\n<loom>\n.

Files

config.json / model.safetensors           the model β€” 67 KB
tokenizer.json / tokenizer_config.json    custom BPE tokenizer, 512 tokens
loom-atom-f16.gguf                        57 KB, for Ollama / llama.cpp
template / params                         read automatically by `ollama run hf.co/...`
Modelfile                                 for building locally

Training data

Real human utterances from two openly licensed corpora, relabelled to a single bit:

  • MASSIVE β€” Amazon (CC BY 4.0), derived from SLURP (CC BY 4.0)
  • CLINC150 β€” clinc/oos-eval (CC BY 3.0)

15,502 utterances, balanced 50/50 by downsampling the majority class. A small procedurally generated slice written by Textile Labs covers "no tool needed" cases that public assistant corpora do not contain β€” chit-chat, ambiguity, and questions only the user can answer.

Both licences require attribution; this section satisfies that and must be kept with any redistribution.

License

Model: MIT. Training data retains its original licences and attribution as above.

Downloads last month
-
Safetensors
Model size
22.4k params
Tensor type
F32
Β·
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support