|
Download README.md from Fallovski/smallm-wolof: direct link, hf CLI and curl.
- Browser
- Download file 6.16 kB
-
https://huggingface.co/Fallovski/smallm-wolof/resolve/main/README.md
- Command line
-
hf download hf://Fallovski/smallm-wolof/README.md
-
curl -L -o README.md https://huggingface.co/Fallovski/smallm-wolof/resolve/main/README.md
6.16 kB
| language: | |
| - wo | |
| license: mit | |
| tags: | |
| - wolof | |
| - low-resource | |
| - african-languages | |
| - moe | |
| - mixture-of-experts | |
| - text-generation | |
| - from-scratch | |
| pipeline_tag: text-generation | |
| # smallm-wolof | |
| A **16.5M-parameter sparse Mixture-of-Experts language model trained from | |
| scratch on Wolof**, a Senegalese language with very limited digital | |
| resources. This is a research/proof-of-concept project, not a production | |
| model β see [Limitations](#limitations) before using it for anything beyond | |
| experimentation. | |
| ## Why this exists | |
| Wolof has no dedicated open reasoning/generative LLM despite being spoken by | |
| ~10M+ people across Senegal, Mauritania, and Gambia. Existing multilingual | |
| LLMs (Gemini, GPT-4o, Gemma, Qwen) are all weak in Wolof because it | |
| represents a tiny fraction of their training data. This project explores | |
| what a **from-scratch, Wolof-first** small model can achieve when the whole | |
| pipeline β tokenizer, architecture, data, training recipe β is designed | |
| around the constraints of a genuinely low-resource language, instead of | |
| Wolof being an afterthought in a 100+-language mix. | |
| ## Architecture | |
| | | | | |
| |---|---| | |
| | Parameters | 16.5M | | |
| | Layers | 8 | | |
| | Hidden size | 320 | | |
| | Attention | Grouped-Query Attention (8 heads, 2 KV heads) + RoPE | | |
| | Feed-forward | Sparse MoE, 4 experts, top-2 routing, SwiGLU | | |
| | Vocab size | 8,192 (dedicated BPE tokenizer, not reused from another model) | | |
| | Context length | 512 tokens | | |
| | Embeddings | Tied input/output | | |
| **Design choices, and why:** | |
| - **Dedicated tokenizer.** Reusing Qwen's tokenizer on this corpus measured | |
| a fertility of only 2.46 chars/token (vs ~4.3 for French) β Wolof text was | |
| being fragmented far more than necessary. A tokenizer trained on Wolof | |
| itself improves this to 2.92 chars/token with a 6x smaller vocab (8,192 vs | |
| ~150K), which matters a lot when the whole model is 16.5M parameters. | |
| - **Sparse MoE, not dense.** Data-constrained scaling research | |
| ([Muennighoff et al., 2023](https://arxiv.org/abs/2305.16264); ["When Data | |
| Is Scarce"](https://arxiv.org/abs/2606.01155)) shows sparse architectures | |
| tolerate multi-epoch training on repeated data better than dense ones β | |
| directly relevant here since this model saw its ~9.7M-token corpus 18 | |
| times, far below the Chinchilla-optimal token budget for this parameter | |
| count. | |
| - **Explicit load-balancing loss on the router.** Recent work on | |
| cross-lingual MoE routing ([Bandarkar et al., | |
| 2026](https://arxiv.org/html/2605.17598v1)) found that low-resource | |
| language tokens tend to collapse onto a narrow subset of experts in | |
| naively-trained MoE models. The auxiliary load-balancing loss here forces | |
| the router to spread Wolof tokens across all 4 experts instead of letting | |
| a narrow pathway emerge. | |
| ## Training data | |
| ~9.7M tokens, unified from multiple sources and deduplicated (exact + | |
| near-duplicate via SimHash): Wikipedia (Wolof), FineWeb2, MADLAD-400, | |
| SMOL-doc, plus smaller lexicon/instruction sources (Jolof, Aya, Gatitos). | |
| GSM8K (7,473 grade-school math problems), machine-translated to Wolof and | |
| quality-checked, is folded directly into the pretraining mix rather than | |
| kept as a separate SFT stage β at this parameter budget, a strict | |
| CPT-then-SFT split wastes capacity; mixing lets the model see the reasoning | |
| pattern throughout training. | |
| **Recipe:** 18 epochs (chosen per data-constrained scaling literature: | |
| repeating data up to ~4 epochs is nearly free, meaningful gains extend to | |
| ~16, returns vanish around 40), AdamW, cosine LR schedule with warmup, | |
| bf16 mixed precision. Final validation loss: 3.48 (perplexity β32.5). | |
| Train/val loss divergence after epoch ~13 indicates mild overfitting, | |
| consistent with the token budget being well below what this parameter count | |
| would ideally need. | |
| ## Usage | |
| ```python | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| model = AutoModelForCausalLM.from_pretrained("Fallovski/smallm-wolof", trust_remote_code=True) | |
| tokenizer = AutoTokenizer.from_pretrained("Fallovski/smallm-wolof") | |
| inputs = tokenizer("Sama xarit", return_tensors="pt") | |
| output = model.generate( | |
| **inputs, | |
| max_new_tokens=100, | |
| do_sample=True, | |
| temperature=0.85, | |
| top_k=40, | |
| repetition_penalty=1.3, # important: without this the model loops on short/common prompts | |
| ) | |
| print(tokenizer.decode(output[0], skip_special_tokens=True)) | |
| ``` | |
| `trust_remote_code=True` is required β this is a custom architecture, not a | |
| standard `transformers` model class. | |
| ## Limitations | |
| Read this before drawing conclusions from the model's output. | |
| - **~9.7M training tokens is very small.** For comparison, Chinchilla-optimal | |
| scaling would want ~330M tokens for a 16.5M-parameter model. The model | |
| has learned Wolof surface grammar and the *style* of the corpus (including | |
| GSM8K-style "step-by-step, then `####` answer" formatting) convincingly, | |
| but arithmetic in generated reasoning chains is frequently **wrong** β it | |
| has learned the form of reasoning, not reliable calculation. | |
| - **Repetition loops.** Short or generic prompts (e.g. single common nouns) | |
| can cause the model to loop on a phrase. Use `repetition_penalty >= 1.3`; | |
| even then, some prompts still degrade after a few dozen tokens. | |
| - **No independent native-speaker validation of the training corpus.** Part | |
| of the pretraining data (FineWeb2-derived) mixes standard Wolof | |
| orthography with phonetic/social-media spelling, and a portion of the | |
| GSM8K translation was produced by Gemini 2.5 Flash rather than human | |
| translators β spot checks looked reasonable but no systematic quality | |
| audit has been done. | |
| - **512-token context**, no long-context capability. | |
| - Not intended for factual reliance, translation accuracy, or any | |
| production use case. | |
| ## Files | |
| - `modeling_smallm_wolof.py` / `configuration_smallm_wolof.py` β custom | |
| architecture code (loaded via `trust_remote_code=True`) | |
| - `model.safetensors` β trained weights | |
| - `tokenizer.json` β dedicated BPE tokenizer | |
| ## Citation | |
| If you build on this, please note it is a research/educational project, not | |
| a peer-reviewed publication. No formal citation is required, but a link back | |
| to this repository is appreciated. | |