Loom Tapestry 3 Flash

Loom Tapestry 3 Flash

7.18M parameters · 20 layers · 512 context · Textile Labs

The best-scoring model in the Loom family — at a third of the parameters of the one it beats, and 15% of the training time. 48 minutes from random initialisation on a four-core 2013 desktop CPU. No GPU, no fine-tuning, no distillation: the weights start as noise and everything they know, we taught them.

It identifies itself as Loom Tapestry 3. Flash is the training budget, not a different model — see The tiers.

who are you              →  Loom Tapestry 3 — a Loom model from Textile Labs.
how big are you          →  Seven million parameters. Not much, but it's enough for what I do.
what is my sisters name  →  I can't know that unless you tell me.

who wrote dracula
  →  <lookup>who wrote dracula</lookup>
  ←  Dracula is an 1897 gothic horror novel by Irish author Bram Stoker.
  →  I think Irish author Bram Stoker. Worth saying I checked rather than knew it.

What it is for

Loom models are knowledge-sparse and behaviour-dense. They are not built to know facts. They are built to know the edge of their own knowledge — to decide when a question needs looking up, write the query, read the answer back, and say plainly where the answer came from.

Small enough that the honesty has nowhere to hide.

situation what it does
answered from a retrieved <result> says it looked it up
answered from training answers plainly
cannot be known by anyone but you "I can't know that unless you tell me."
needs a lookup but tools are off "That needs a lookup, and tools are off."

It never claims a lookup it didn't make — 16/16 below. A false attribution is worse than none, so that is the one number held to 100%.

It holds a conversation

Six turns, one session, verbatim:

hello           →  Hello.
who are you     →  Loom Tapestry 3 — a Loom model from Textile Labs.
what can you do →  Honestly, not a lot. I try to be useful about the little I do.
how big are you →  Small model — I'm better at knowing my limits than knowing facts.
why so small    →  Not much on my own. With tools on I can look things up.
thanks          →  No trouble.

The previous generation could not do this — every training example was single-turn with a hard reset, so the model answered once and lost the thread. 54.8% of this corpus is multi-turn, and grounded conversations carry follow-ups that must be answered from the result already in context, without a second lookup.

Measured

Full acceptance battery, hand-written prompts held out of the training generator, scored on content rather than shape. Every failure is listed rather than summarised.

Tapestry 3 Flash Tapestry 2
no false attribution 16/16 16/16 never claims a lookup it didn't make
no <lookup> leak with tools off 28/28 28/28
self-terminates without a Modelfile 12/12 12/12
identity — names Tapestry 12/12 11/12
5-turn conversation stays on thread 5/5 4/5
attribution present after a real lookup 5/5 4/5
answers from a supplied <result> 4/5 5/5 curated results — much lower on real text, see below
admits an unknowable 6/8 4/8
tool decision with tools on 15/20 10/20 9/10 correct when a lookup is needed; 6/10 when it is not
identity under CAPS / typos / "?" 7/12 10/12 regression — see below
follow-up answered from the same result 2/5 2/5
says the result doesn't contain it 0/5 1/5 regression — see below
overall 112/133 · 84.2% 107/133 · 80.5%
params training tokens/param val loss val accuracy
Loom Spark 2 19.9M 1 h 0.25 2.692 0.536
Loom Weave 2 Flash 19.9M 2 h 0.51 2.254 0.580
Loom Tapestry 2 22.8M 5.5 h 0.87 1.963 0.622
Loom Tapestry 3 Flash 7.18M 48 min 0.94 2.161 0.607

It reaches 98% of the flagship's validation accuracy in 15% of the time, and beats it on the behaviour battery that actually decides whether a Loom ships.

Why smaller won

Every earlier Loom was too big for its training budget. A model that sees only 0.25 tokens per parameter has not been taught; it has been glanced at. Dropping from 22.8M to 7.18M did not remove capability — it bought 3.7× more training per weight, and the behaviours we care about are the ones that need training, not capacity.

Depth was kept and width was spent: 20 layers, identical to the flagship, at 192 wide instead of 320.

Read this before you use it

It gets worse when you shout at it. Identity under rough typing dropped to 7/12. WHO MADE U and WHATS THIS MODEL CALLED? are answered with "I can't know that unless you tell me." — it routes mangled input to the wrong honest answer. Type normally and identity is 12/12.

Validate what it tells you from a result — this is the biggest caveat on the model. The battery scores grounded reading at 4/5, but the battery's <result> blocks are short and lead with the answer. Real retrieved text does not. Measured on the same questions with real Wikipedia summaries fed through harness.py, extraction collapses for both this model and the flagship:

<result> style Tapestry 3 Flash Tapestry 2
curated, answer in the first sentence 4/5 5/5
encyclopaedia prose, answer in the last sentence 4/8 3/8
live Wikipedia summaries 0/9 3/9

Treat the retrieved text as the trustworthy part and the model's summary of it as unreliable. It answers from a <result> whether or not the answer is in there — "says the result doesn't contain it" is 0/5, and no Loom has ever scored above 1/5 on it. A follow-up answered from context is right about 2 times in 5.

The practical consequence: show the user the retrieved text. This model is good at deciding a lookup is needed and writing the query, and honest about having done it. It is not a reliable reading-comprehension engine, and shortening results to one or two sentences helps more than anything else you can do in the harness.

Personal questions with tools on still become lookups — 6/10, up from 0/10 on Tapestry 2 but not solved. The shipped template defaults to tools:off; turn tools on for the retrieval loop.

It has almost no world knowledge. With tools off it declines factual questions. That is the intended behaviour, not a fault.

It is a lookup assistant, not a chat companion. At 7.18M parameters it does not improvise or explain in its own words. What it does reliably is decide a lookup is needed, write the query, read the answer back, and say where the answer came from.

Two modes

<tools:off> (default) — conversational. Identity, limits, warmth, brevity.

<tools:on> — emits <lookup>query</lookup> and stops. Your harness runs the lookup and continues with a <result> block:

<tools:on>
<user>
who wrote dracula
<|eot|>
<loom>
<lookup>who wrote dracula</lookup><|eot|>
<result>
Dracula is an 1897 gothic horror novel by Irish author Bram Stoker.
<|eot|>
<loom>

Usage — the harness

harness.py in this repo runs the lookup and feeds the result back. Wikipedia is used because it is free and needs no key — swap the search() function for anything else; the contract is text in, text out.

python3 harness.py "who wrote dracula"      # with lookups
python3 harness.py                          # interactive
python3 harness.py --no-tools "who are you" # chat only

Three things any harness for this model needs:

  • Never feed a failed lookup back as a <result>. It will earnestly answer from the error text. Fail loudly instead — harness.py does.
  • Hand back short passages. --sentences defaults to 2. A full encyclopaedia lead paragraph measurably lowers the chance the model picks the right span.
  • Retrieval quality is half the result, and it is your half. Asked "who wrote frankenstein", Wikipedia search returns a 2007 book about Frankenstein's authorship; the model then correctly reports its author. The model read the passage right — the passage was wrong. A better search() improves this model more than anything in the weights would.
  • Wikipedia returns 403 without a descriptive User-Agent.
  • macOS system Python often needs certifi for TLS.

Usage — Ollama

ollama run hf.co/textilelabs/Loom-Tapestry-3-Flash "who are you"

The template and params files in this repo are read automatically. To build locally: ollama create loom-tapestry-3-flash -f Modelfile.

Do not add a repetition penalty. This model answers by quoting from the <result> you give it, so penalising repeated tokens penalises the correct answer. Measured at repeat_penalty 1.15 on this family it changed "1,345 metres" into "2,345 metres" — silently wrong rather than merely worse. params ships it at 1.0 for that reason.

Usage — transformers

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

tok = AutoTokenizer.from_pretrained("textilelabs/Loom-Tapestry-3-Flash")
model = AutoModelForCausalLM.from_pretrained("textilelabs/Loom-Tapestry-3-Flash").eval()
eot = tok.convert_tokens_to_ids("<|eot|>")

def ask(message, tools=False):
    p = f"<tools:{'on' if tools else 'off'}>\n<user>\n{message}\n<|eot|>\n<loom>\n"
    ids = tok(p, return_tensors="pt", add_special_tokens=False).input_ids
    with torch.no_grad():
        out = model.generate(ids, max_new_tokens=64, do_sample=False, eos_token_id=eot,
                             pad_token_id=tok.convert_tokens_to_ids("<|pad|>"))[0]
    return tok.decode(out[ids.shape[1]:], skip_special_tokens=True).strip()

ask("who are you")   # -> 'Loom Tapestry 3 — a Loom model from Textile Labs.'

Prompt format is exact: <tools:off>\n<user>\n{message}\n<|eot|>\n<loom>\n. No trailing space after <loom>.

How it was built

architecture Llama — 20 layers × 192d, GQA (3 heads / 1 KV), SwiGLU, RoPE, tied embeddings
context 512
vocabulary 4,096 custom BPE
optimiser Muon on the 2D hidden matrices, AdamW on embeddings and norms
schedule warmup → stable → decay (WSD), 35% decay
corpus 151,052 conversations · 54.8% multi-turn
training 548 steps · 6.73M tokens · 0.94 tokens per parameter · from random init
hardware one 2013 desktop, 4 CPU cores, no GPU · 48 minutes

Two things made the difference over the previous generation, and neither cost compute:

  1. The persona is trained under both <tools:on> and <tools:off>. Tapestry 2's was trained only with tools off, so with tools on it turned "who are you" into a lookup — 0/10. This one scores 6/10 on the same check.
  2. <|eot|> closing a Loom turn is a first-class token, not template scaffolding. Weighted as scaffolding, its loss annealed toward zero and an earlier model never learned to stop at all.

The tiers

Tier is training budget, not architecture. Every tier is held to the same standard.

tier budget
Flash ≤ 1 hour
Spark ~1 hour
Weave ~2 hours
Tapestry 4 hours and up

Flash used to mean shrink and shallow. It now means full depth, narrow width — this model has exactly the same 20 layers as Tapestry 3 proper. Depth is what you keep; width is what you spend. A Flash can be the best model in the family, and this one is.

Files

config.json / model.safetensors           the model
tokenizer.json / tokenizer_config.json    custom BPE tokenizer, 4,096 tokens
loom-tapestry-3-flash-f16.gguf            14MB, for Ollama / llama.cpp
harness.py                                runnable harness — runs lookups, feeds results back
template / params                         read automatically by `ollama run hf.co/...`
Modelfile                                 for building locally
ATTRIBUTION.md                            required credits for the training corpora

Training data

Openly licensed corpora of real human text, plus a persona curriculum written for Loom. See ATTRIBUTION.md — several of these licences require credit.

slice source
grounded reading, and "the result doesn't say" SQuAD 2.0 (CC BY-SA 4.0)
when to reach for a tool MASSIVE (CC BY 4.0) · CLINC150 (CC BY 3.0)
instruction following databricks-dolly-15k (CC BY-SA 3.0)
multi-turn dialogue structure OpenAssistant OASST1 (Apache 2.0)
identity, limits, warmth, attribution Textile Labs — written for Loom

Nothing here is fine-tuned from anyone's checkpoint. Public datasets are training data; the weights are ours from random initialisation.

License

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

Downloads last month
295
Safetensors
Model size
7.18M params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Collection including textilelabs/Loom-Tapestry-3-Flash