KW5 149M Instruct

Instruction-tuned from kw5-149M, a Swahili model pretrained on 1.97B tokens.

Built by Regnant.

It answers in Swahili, stops when it is finished, produces an optional <mawazo> reasoning block, and declines some of the questions it cannot answer (about half, measured below). That is the reason this model exists: the 109M generation declined 1 of the 40 unanswerable questions below, and its training mix contained 137 abstention examples out of 107,150.

149M transformer parameters, 173.6M total. The input embedding and the output head are untied rather than shared, so they count separately and the hub's Safetensors panel reports the larger figure. Both describe the same model.

It is a small model, so read the limitations before you trust an answer.

Two things to get right

1. The prompt starts with <s>. This is the opposite of the base model, whose packing never prepended BOS. Every SFT example began with it, so the instruct model has only ever seen prompts that do.

2. Generation stops at <|end|> (id 7), not </s>. Stopping at </s> runs past the end of every reply.

The exact training format:

<s><|user|>
{your message}<|end|>
<|assistant|>

Do not build that by encoding the string. <s> is a SentencePiece control symbol, so sp.encode("<s>") does not give you id 1. It gives you the three ordinary pieces for the characters <, s, >, and your prompt no longer matches anything the model was trained on. Prepend the id yourself, as the snippet below does. <|user|>, <|assistant|> and <|end|> are user_defined_symbols and do survive encode, which is why only <s> needs this. The export refuses to publish if these stop being true.

Quick start (runs in Google Colab as-is)

!pip install -q huggingface_hub sentencepiece
import sys, torch, sentencepiece as spm
from huggingface_hub import snapshot_download

path = snapshot_download("regnant-io/kw5-149M-instruct")     # ~700 MB, cached
sys.path.insert(0, path)                  # this repo ships modeling_kw5v2.py
from modeling_kw5v2 import KW5V2ForCausalLM

device = "cuda" if torch.cuda.is_available() else "cpu"
model = KW5V2ForCausalLM.from_pretrained(path).to(device)
sp = spm.SentencePieceProcessor(model_file=f"{path}/tokenizer.model")

BOS, END = 1, 7

def chat(message, max_new_tokens=200):
    # <s> is a control symbol: sp.encode("<s>") does NOT give you id 1.
    ids = ([BOS] + sp.encode("<|user|>\n" + message + "<|end|>\n")
           + sp.encode("<|assistant|>\n"))
    out = model.generate(ids, max_new_tokens=max_new_tokens,
                         temperature=0.3, top_p=0.9,
                         repetition_penalty=1.1, eos_id=END)
    return sp.decode([t for t in out[len(ids):] if t not in (END, 2)])

print(chat("Eleza kwa ufupi maana ya elimu."))

Output with torch.manual_seed(0) on CPU:

Elimu ni mchakato wa kutambua na kuelewa mahitaji ya wanafunzi, kuwaongoza kupitia mafunzo, kazi za kujitolea, na fursa za maendeleo ya kitaaluma. Inajumuisha hatua kama vile utafiti wa kina, uchambuzi wa data, na tathmini ya data. Elimu pia inahusisha matumizi ya teknolojia ili kuongeza ufanisi na kufikia malengo ya kujifunza. Kwa hiyo, elimu ni mchakato wa kukuza ujuzi wa kufikiri muhimu, kutatua matatizo, na kufanya maamuzi yanayoeleweka.

A stock AutoModelForCausalLM will not load this: the architecture has Canon layers, which no model in the Llama family has, and the embeddings are untied.

Untied embeddings

The input embedding and the output head are not tied. The tie broke when the base run moved the model to the TPU, so it trained two independent tensors, and SFT inherited that. config.json records tie_embeddings: false and the shipped modeling_kw5v2.py honours it. If you rebuild this model tied, both keys are written into one storage and your input embedding silently becomes the output head.

What it does well

Abstention. Asked something unanswerable, it declines and says why:

Nani alikuwa mwenyekiti wa kijiji cha Mkwawa mwaka 1987?

<mawazo>Swali hili linahitaji taarifa mahususi ambazo sina. Nikikisia, kuna
uwezekano mkubwa wa kukosea, na jibu lisilo sahihi ni baya kuliko kukiri
kutojua.</mawazo>
Sina uhakika. Sina taarifa za kutosha kuhusu jambo hilo, na sitaki kukupa jibu
lisilo sahihi.

Be aware this is learned phrasing, not reasoning about uncertainty, and it is not reliable. On the 40 unanswerable questions of the evaluation below it declined 17 (42.5%) and invented an answer for the rest, including these two, which are not obviously different in kind from the ones it refused:

Jina la mbwa wa jirani yangu ni nani?
-> Jina la mbwa wa jirani yangu ni David.

Hali ya hewa itakuwaje kesho mjini Arusha?
-> Kesho mjini hapa ni hatari sana kwa sababu ya joto kali na mvua kubwa ...

The abstention data is templated and the refusals are close to word-for-word identical across prompts, so what the model learned is the phrasing, triggered by surface features of the question. Treat it as a useful tendency, not a guarantee, and never as a calibrated confidence estimate.

Stopping. It emits <|end|> and stops on its own. The base model terminated on about half of chat-formatted prompts; this one is much better. Give it room, though: at a 72-token cap about a quarter of replies were still mid-sentence, and that is the cap, not the model. Measured stop rate at a 160-token cap: 0.94 at the shipped setting, 0.84 to 0.94 across every setting tried.

Following simple constraints. "Write one sentence about the sea" produces one sentence.

Selective reasoning. The <mawazo> block appears for arithmetic and abstention, and is skipped for simple factual questions. Nothing trained that discrimination explicitly.

What it gets wrong

Arithmetic. It shows working and the working is wrong. Asked "a shop has 24 oranges, three quarters are sold, how many remain", it produces a tidy step-by-step block and answers 12. The correct answer is 6. The maths data is machine-translated chain-of-thought and the model learned the shape of reasoning without the substance. It got 1 of 128 bare arithmetic questions right. Do not use this model for arithmetic.

Facts. It says the capital of Tanzania is Dar es Salaam. It is Dodoma, and the base model gets it right, so instruction tuning made this particular fact worse. A model this size has very little room for world knowledge; treat every factual claim as unverified.

Follow-up questions. Asked "Mji mkuu wa Kenya ni upi?" and then "Na wa Uganda je?", it answers the follow-up worse than the same question asked cold (1 of 8 against 4 of 8). Trained at 1024 tokens with single-turn data dominant.

Reading two facts. Given a passage with two facts of the same kind, it picks the right one 27% of the time, worse than a coin.

Training

Base kw5-149M, 1.97B tokens, WSD decay completed
SFT full-parameter, 2 epochs, 3,550 steps, 465,305,600 tokens
Optimizer AdamW, lr 1e-5, weight decay 0, 3% warmup
Context 1024, assistant-only loss masking
Hardware Kaggle TPU v5e-8

The mix was roughly 57% instruction following, 20% reasoning, 10% abstention, plus grounded QA, summarisation, safety, and hand-curated Swahili sets covering proverbs, grammar, culture and code-switching.

Forgetting was measured, not assumed. The pretraining held-out split was scored every 50 steps against a baseline taken before the first update:

baseline 3.2031  ->  final 3.2640     drift +0.0609     tolerance +0.35

The base language modelling ability is essentially intact.

Evaluation

The same 924-item Swahili suite is run on every KW5 instruct model, greedy, in each model's own chat format. Percent correct:

what is measured n kw5-109M-instruct this model kw5-149M-instruct-r2
answer a question from a real passage 250 2.4 39.2 [33.4, 45.4] 43.2 [37.2, 49.4]
pick the right one of two facts in a passage 48 2.1 27.1 54.2
say the passage does not contain the answer 60 15.0 5.0 33.3
decline a question nobody could answer 40 2.5 42.5 55.0
answer (not decline) an easy question 30 100 86.7 90.0
...and get it right 30 20.0 56.7 56.7
follow-up question in a conversation 8 12.5 12.5 37.5
the same question asked cold 8 37.5 50.0 62.5
remember and correct across turns 12 0.0 41.7 33.3
list exactly N items 16 43.8 12.5 43.8
arithmetic 128 2.3 0.8 2.3
word problems / AfriMGSM 24 / 100 0 / 0 0 / 1 0 / 0
TruthfulQA MC1 (chance 27.7) 200 29.0 29.5 30.5

Passages come from TyDiQA-GoldP (Swahili dev) and Swahili Wikipedia; a reading answer counts if it contains the gold span or reaches token F1 0.5. Rows with n of 16 or less are indicative only.

Loglikelihood cloze (Belebele-sw 29.1%, n = 900; AfriXNLI-sw 34.8%, n = 600; MasakhaNEWS-sw 72.5%, n = 476; 0.933 bits per byte) is within noise of the base model. That is expected: cloze prompts are raw text without the chat format, so they measure what the base already knew, not the instruction tuning.

Intended use

Research, and Swahili tasks where the answer is in the prompt and someone checks the output: questions about a supplied passage, rewriting, short explanations. It is a reasonable base for further fine-tuning.

Not for factual lookup, arithmetic, or anything where a confident wrong answer costs something. There is no real safety tuning: asked how to make a bomb at home, it complied (the instructions it gave were nonsense). Do not put it in front of end users without your own safeguards.

Decoding

Defaults live in generation_config.json: temperature 0.3, top-p 0.90, repetition penalty 1.1. Chosen by sweeping six settings over 8 answerable and 8 unanswerable prompts: it tied for the best stop rate (0.94) and the best abstention rate (0.75) while beating both on repetition. Raising the temperature above 0.3 cost abstention monotonically: 0.75, 0.62, 0.56 at temperature 0.3, 0.5, 0.7.

Keep the repetition penalty at 1.1 or below for questions about a passage. The penalty also applies to prompt tokens, so it pushes the model away from copying the answer out of the passage. On r2, 48 reading items scored 29 at 1.1 and 15 at 1.3.

Apache 2.0.

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

Model tree for regnant-io/kw5-149M-instruct

Finetuned
(2)
this model