Update README.md
Browse files
README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
| 2 |
language:
|
| 3 |
- kmr
|
| 4 |
license: apache-2.0
|
|
|
|
|
|
|
| 5 |
tags:
|
| 6 |
- tokenizer
|
| 7 |
- bpe
|
|
@@ -16,6 +18,8 @@ tags:
|
|
| 16 |
|
| 17 |
A byte-level BPE tokenizer for **Kurmancî** (Kurmanji, Northern Kurdish, Latin script), built for **generative language models**.
|
| 18 |
|
|
|
|
|
|
|
| 19 |
## Highlights
|
| 20 |
|
| 21 |
- **Efficient on Kurmancî:** 1.44 tokens per word on FLORES-200 (`kmr_Latn`), compared with 1.85 for XLM-R, 2.62 for Qwen2.5 and 2.91 for GPT-2 (see [Evaluation](#evaluation)).
|
|
@@ -23,6 +27,7 @@ A byte-level BPE tokenizer for **Kurmancî** (Kurmanji, Northern Kurdish, Latin
|
|
| 23 |
- **No `<unk>`:** Byte-level fallback means any input can be encoded.
|
| 24 |
- **Robust to spelling variants:** The training data includes text written without circumflexes (`e i u` instead of `ê î û`) and in capital letters.
|
| 25 |
- **Digits are split one by one,** and words with an apostrophe or hyphen are kept together by the pre-tokenizer before BPE merges are applied.
|
|
|
|
| 26 |
|
| 27 |
## Quick start
|
| 28 |
|
|
@@ -45,16 +50,40 @@ Byte-level tokenizers display the space as `Ġ` and non-ASCII characters (such a
|
|
| 45 |
|
| 46 |
A word at the very beginning of a text has no leading space and is therefore a different token from the same word in the middle of a sentence. This is the same behaviour as in GPT-2 and similar tokenizers.
|
| 47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
## Details
|
| 49 |
|
| 50 |
| Property | Value |
|
| 51 |
|---|---|
|
| 52 |
| Type | Byte-level BPE (Hugging Face `tokenizers`) |
|
| 53 |
-
| Vocabulary size | 40,000 |
|
| 54 |
| Normalization | Unicode NFC |
|
| 55 |
| Pre-tokenization | Regex split (words incl. internal `'`, `’`, `-`; single digits; punctuation runs; whitespace), then byte-level mapping |
|
| 56 |
| Decoder | ByteLevel |
|
| 57 |
| Special tokens | `<s>` (bos), `</s>` (eos), `<unk>`, `<pad>`, `<mask>` |
|
|
|
|
| 58 |
| Case | Case-sensitive |
|
| 59 |
|
| 60 |
The pre-tokenizer regex is:
|
|
@@ -66,7 +95,9 @@ The pre-tokenizer regex is:
|
|
| 66 |
To check the special token IDs of your copy:
|
| 67 |
|
| 68 |
```python
|
| 69 |
-
print(
|
|
|
|
|
|
|
| 70 |
```
|
| 71 |
|
| 72 |
## Training data
|
|
@@ -84,7 +115,7 @@ Processing steps:
|
|
| 84 |
|
| 85 |
Result: about 1.2 million training lines (about 270 MB of text), about 10,000 held-out lines.
|
| 86 |
|
| 87 |
-
**Important:** The corpus was read as a stream and the run was stopped early. Only roughly the first 400,000 documents of the dataset were read, and about 125,000 of them passed the filters. The mix of sources in this sample was **not balanced**
|
| 88 |
|
| 89 |
The text sources have their own terms of use. Please check the dataset card of `kurdish-tech/KurdishCorpus-clean` and the licenses of the original sources before you build on this work for anything beyond the tokenizer itself. The tokenizer contains a vocabulary of word pieces, not the source texts.
|
| 90 |
|
|
@@ -98,7 +129,7 @@ FLORES-200 was not used for training in any way.
|
|
| 98 |
|
| 99 |
| Tokenizer | Vocabulary | Fertility |
|
| 100 |
|---|---|---|
|
| 101 |
-
| **This tokenizer (v4)** | 40,
|
| 102 |
| XLM-R (`xlm-roberta-base`) | about 250,000 | 1.85 |
|
| 103 |
| Qwen2.5 (`Qwen/Qwen2.5-0.5B`) | about 151,000 | 2.62 |
|
| 104 |
| GPT-2 (`gpt2`) | 50,257 | 2.91 |
|
|
@@ -133,56 +164,81 @@ The held-out lines come from the same sources as the training data, so these num
|
|
| 133 |
## Intended use
|
| 134 |
|
| 135 |
- Training or continuing to pre-train generative language models for Kurmancî.
|
|
|
|
| 136 |
- Text analysis and tokenization experiments for Kurmancî.
|
| 137 |
- A reference for research on tokenization of morphologically rich, low-resource languages.
|
| 138 |
|
| 139 |
-
## Limitations
|
| 140 |
|
| 141 |
-
- **Not suitable for other languages.** Sorani (Arabic script), Zazaki
|
| 142 |
- **Imbalanced training sample.** The training data comes from a limited part of the dataset. Text types that are rare there (for example literature, spoken-style language, specialist vocabulary) may be split less efficiently.
|
|
|
|
|
|
|
|
|
|
| 143 |
- **Some verb forms are split unevenly,** for example `dixwînim` becomes `di` `xw` `înim`. The tokenizer follows frequency, not grammar, and does not know morphology.
|
| 144 |
- **Capital letters** are handled less efficiently than lowercase (`ÇIYAYÊN` becomes `Ç` `IYA` `YÊN`).
|
| 145 |
- **Apostrophe spellings** such as `ç'ê` or `pe'rê` are not always kept as single units, because BPE merges decide the final split.
|
|
|
|
| 146 |
|
| 147 |
## Reproducing the tokenizer
|
| 148 |
|
| 149 |
-
The script `train_tokenizer.py` in this repository builds the corpus, trains the tokenizer and runs the tests (round-trip, fertility, edge cases). Settings used for this version: `VOCAB_SIZE = 40000`, `min_frequency = 2`, seed 42. Results can differ slightly between runs, because the dataset is read as a shuffled stream.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
|
| 151 |
## Changelog
|
| 152 |
|
| 153 |
-
- **v4 (October 2026):** Byte-level BPE, NFC instead of NFKC, lossless round-trip, spelling variants added to the training data. Replaces an earlier internal version that used a whitespace pre-tokenizer, which lost spaces and mapped unknown characters to `<unk>`.
|
| 154 |
|
| 155 |
## License
|
| 156 |
|
| 157 |
-
This tokenizer is released under the Apache-2.0 license
|
| 158 |
|
| 159 |
The FLORES-200 evaluation data is licensed separately (CC BY-SA 4.0) and is not part of this repository.
|
| 160 |
|
| 161 |
-
##
|
| 162 |
|
| 163 |
-
|
| 164 |
-
- FLORES-200 (NLLB Team et al., Meta AI) for the evaluation sentences.
|
| 165 |
-
- Everyone who writes, translates and teaches Kurmancî.
|
| 166 |
|
| 167 |
-
## Citation
|
| 168 |
-
**Please use the following citation if you build upon this work:**
|
| 169 |
|
| 170 |
-
If you use this tokenizer in your research, projects
|
| 171 |
|
| 172 |
```bibtex
|
| 173 |
@misc{neurokurd-kurmanji-tokenizer,
|
| 174 |
-
author
|
| 175 |
-
title
|
| 176 |
-
year
|
| 177 |
-
publisher
|
| 178 |
-
howpublished = {\url{https://huggingface.co/NeuroKurd/
|
| 179 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
|
| 181 |
-
|
| 182 |
@misc{kurdish-tech-corpus,
|
| 183 |
-
author
|
| 184 |
-
title
|
| 185 |
-
year
|
| 186 |
-
publisher
|
| 187 |
howpublished = {\url{https://huggingface.co/datasets/kurdish-tech/KurdishCorpus-clean}}
|
| 188 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
language:
|
| 3 |
- kmr
|
| 4 |
license: apache-2.0
|
| 5 |
+
datasets:
|
| 6 |
+
- kurdish-tech/KurdishCorpus-clean
|
| 7 |
tags:
|
| 8 |
- tokenizer
|
| 9 |
- bpe
|
|
|
|
| 18 |
|
| 19 |
A byte-level BPE tokenizer for **Kurmancî** (Kurmanji, Northern Kurdish, Latin script), built for **generative language models**.
|
| 20 |
|
| 21 |
+
It splits Kurmancî text into far fewer tokens than general-purpose tokenizers (1.44 tokens per word on FLORES-200, against 1.85 to 2.91 for the tokenizers compared below), it is lossless, and it never needs an `<unk>` token.
|
| 22 |
+
|
| 23 |
## Highlights
|
| 24 |
|
| 25 |
- **Efficient on Kurmancî:** 1.44 tokens per word on FLORES-200 (`kmr_Latn`), compared with 1.85 for XLM-R, 2.62 for Qwen2.5 and 2.91 for GPT-2 (see [Evaluation](#evaluation)).
|
|
|
|
| 27 |
- **No `<unk>`:** Byte-level fallback means any input can be encoded.
|
| 28 |
- **Robust to spelling variants:** The training data includes text written without circumflexes (`e i u` instead of `ê î û`) and in capital letters.
|
| 29 |
- **Digits are split one by one,** and words with an apostrophe or hyphen are kept together by the pre-tokenizer before BPE merges are applied.
|
| 30 |
+
- **Chat-ready special tokens:** `<|im_start|>` and `<|im_end|>` are included as reserved special tokens (see [Chat tokens](#chat-tokens)).
|
| 31 |
|
| 32 |
## Quick start
|
| 33 |
|
|
|
|
| 50 |
|
| 51 |
A word at the very beginning of a text has no leading space and is therefore a different token from the same word in the middle of a sentence. This is the same behaviour as in GPT-2 and similar tokenizers.
|
| 52 |
|
| 53 |
+
## Chat tokens
|
| 54 |
+
|
| 55 |
+
Two special tokens are reserved for chat and instruction models:
|
| 56 |
+
|
| 57 |
+
| Token | Purpose |
|
| 58 |
+
|---|---|
|
| 59 |
+
| `<\|im_start\|>` | marks the start of a message (followed by the role, for example `user` or `assistant`) |
|
| 60 |
+
| `<\|im_end\|>` | marks the end of a message |
|
| 61 |
+
|
| 62 |
+
They were **appended after the BPE training** as special tokens and take the two highest IDs. All learned token IDs keep their original values. Because the tokens never appeared during training, a model has to learn their embeddings during fine-tuning on chat data.
|
| 63 |
+
|
| 64 |
+
A common ChatML-style layout looks like this:
|
| 65 |
+
|
| 66 |
+
```python
|
| 67 |
+
prompt = (
|
| 68 |
+
"<|im_start|>user\nRoj baş!<|im_end|>\n"
|
| 69 |
+
"<|im_start|>assistant\n"
|
| 70 |
+
)
|
| 71 |
+
ids = tok.encode(prompt, add_special_tokens=False)
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
No chat template is stored in the tokenizer, so you define the exact format yourself when you fine-tune. If you need more special tokens (system prompt, tool calls, ...), add them with `tok.add_special_tokens(...)` and resize the embeddings of your model.
|
| 75 |
+
|
| 76 |
## Details
|
| 77 |
|
| 78 |
| Property | Value |
|
| 79 |
|---|---|
|
| 80 |
| Type | Byte-level BPE (Hugging Face `tokenizers`) |
|
| 81 |
+
| Vocabulary size | 40,002 (40,000 learned tokens + 2 chat tokens) |
|
| 82 |
| Normalization | Unicode NFC |
|
| 83 |
| Pre-tokenization | Regex split (words incl. internal `'`, `’`, `-`; single digits; punctuation runs; whitespace), then byte-level mapping |
|
| 84 |
| Decoder | ByteLevel |
|
| 85 |
| Special tokens | `<s>` (bos), `</s>` (eos), `<unk>`, `<pad>`, `<mask>` |
|
| 86 |
+
| Chat tokens | `<\|im_start\|>`, `<\|im_end\|>` |
|
| 87 |
| Case | Case-sensitive |
|
| 88 |
|
| 89 |
The pre-tokenizer regex is:
|
|
|
|
| 95 |
To check the special token IDs of your copy:
|
| 96 |
|
| 97 |
```python
|
| 98 |
+
print(len(tok))
|
| 99 |
+
print({t: tok.convert_tokens_to_ids(t) for t in
|
| 100 |
+
["<s>", "</s>", "<unk>", "<pad>", "<mask>", "<|im_start|>", "<|im_end|>"]})
|
| 101 |
```
|
| 102 |
|
| 103 |
## Training data
|
|
|
|
| 115 |
|
| 116 |
Result: about 1.2 million training lines (about 270 MB of text), about 10,000 held-out lines.
|
| 117 |
|
| 118 |
+
**Important:** The corpus was read as a stream and the run was stopped early. Only roughly the first 400,000 documents of the dataset were read, and about 125,000 of them passed the filters. The mix of sources in this sample was **not balanced**. A more balanced sample is planned for a later version.
|
| 119 |
|
| 120 |
The text sources have their own terms of use. Please check the dataset card of `kurdish-tech/KurdishCorpus-clean` and the licenses of the original sources before you build on this work for anything beyond the tokenizer itself. The tokenizer contains a vocabulary of word pieces, not the source texts.
|
| 121 |
|
|
|
|
| 129 |
|
| 130 |
| Tokenizer | Vocabulary | Fertility |
|
| 131 |
|---|---|---|
|
| 132 |
+
| **This tokenizer (v4)** | 40,002 | **1.44** |
|
| 133 |
| XLM-R (`xlm-roberta-base`) | about 250,000 | 1.85 |
|
| 134 |
| Qwen2.5 (`Qwen/Qwen2.5-0.5B`) | about 151,000 | 2.62 |
|
| 135 |
| GPT-2 (`gpt2`) | 50,257 | 2.91 |
|
|
|
|
| 164 |
## Intended use
|
| 165 |
|
| 166 |
- Training or continuing to pre-train generative language models for Kurmancî.
|
| 167 |
+
- Fine-tuning chat and instruction models for Kurmancî (using the reserved chat tokens).
|
| 168 |
- Text analysis and tokenization experiments for Kurmancî.
|
| 169 |
- A reference for research on tokenization of morphologically rich, low-resource languages.
|
| 170 |
|
| 171 |
+
## Limitations and risks
|
| 172 |
|
| 173 |
+
- **Not suitable for other languages.** Sorani (Arabic script), Zazaki, Turkish, German, English and others are encoded losslessly but inefficiently. Sorani costs about 10 tokens per word, and emoji cost several tokens each.
|
| 174 |
- **Imbalanced training sample.** The training data comes from a limited part of the dataset. Text types that are rare there (for example literature, spoken-style language, specialist vocabulary) may be split less efficiently.
|
| 175 |
+
- **News and politics skew.** The vocabulary contains many whole-word tokens for place names, institutions and public figures from news text, and fewer for everyday or literary vocabulary. Token frequency reflects the training data only and does not express any opinion.
|
| 176 |
+
- **Some English web spam in the training data.** A small number of tokens come from English-language spam and promotion (for example `casino`, `crypto`, `Semalt`). They occupy well under 0.1 % of the vocabulary and do not affect how Kurmancî text is split. `train_tokenizer.py` has an optional filter (`FILTER_SPAM_ENGLISH`) for a cleaner corpus in a later version.
|
| 177 |
+
- **Personal data.** The vocabulary was checked for e-mail addresses, web addresses, user names and phone numbers. Only names of platforms (such as Twitter or Facebook) and the `@` sign were found. Digits are always split one by one, so numbers cannot be stored as single tokens. Names of places, institutions and public figures appear as tokens because they are frequent in news text.
|
| 178 |
- **Some verb forms are split unevenly,** for example `dixwînim` becomes `di` `xw` `înim`. The tokenizer follows frequency, not grammar, and does not know morphology.
|
| 179 |
- **Capital letters** are handled less efficiently than lowercase (`ÇIYAYÊN` becomes `Ç` `IYA` `YÊN`).
|
| 180 |
- **Apostrophe spellings** such as `ç'ê` or `pe'rê` are not always kept as single units, because BPE merges decide the final split.
|
| 181 |
+
- **Only two chat tokens and no chat template.** See [Chat tokens](#chat-tokens).
|
| 182 |
|
| 183 |
## Reproducing the tokenizer
|
| 184 |
|
| 185 |
+
The script `train_tokenizer.py` in this repository builds the corpus, trains the tokenizer, appends the chat tokens and runs the tests (round-trip, fertility, edge cases). Settings used for this version: `VOCAB_SIZE = 40000`, `min_frequency = 2`, seed 42. Results can differ slightly between runs, because the dataset is read as a shuffled stream.
|
| 186 |
+
|
| 187 |
+
## Versioning
|
| 188 |
+
|
| 189 |
+
This is a test release. Token IDs and the vocabulary may change in a later version. If you train a model on this tokenizer, pin the exact revision (commit hash) with the `revision` argument of `from_pretrained`, so that your model keeps working.
|
| 190 |
|
| 191 |
## Changelog
|
| 192 |
|
| 193 |
+
- **v4 (October 2026):** Byte-level BPE, NFC instead of NFKC, lossless round-trip, spelling variants added to the training data, two chat special tokens appended after training. Replaces an earlier internal version that used a whitespace pre-tokenizer, which lost spaces and mapped unknown characters to `<unk>`.
|
| 194 |
|
| 195 |
## License
|
| 196 |
|
| 197 |
+
This tokenizer is released under the Apache-2.0 license. Please also respect the terms of the underlying data sources listed on the dataset card of `kurdish-tech/KurdishCorpus-clean`.
|
| 198 |
|
| 199 |
The FLORES-200 evaluation data is licensed separately (CC BY-SA 4.0) and is not part of this repository.
|
| 200 |
|
| 201 |
+
## Feedback and contact
|
| 202 |
|
| 203 |
+
Questions, problems and suggestions are welcome in the *Community* tab of this repository. Feedback from native speakers on how words are split is especially valuable.
|
|
|
|
|
|
|
| 204 |
|
| 205 |
+
## Citation
|
|
|
|
| 206 |
|
| 207 |
+
If you use this tokenizer in your research, projects or derivative models, please cite it:
|
| 208 |
|
| 209 |
```bibtex
|
| 210 |
@misc{neurokurd-kurmanji-tokenizer,
|
| 211 |
+
author = {NeuroKurd},
|
| 212 |
+
title = {Kurmanc{\^i} (Northern Kurdish) Tokenizer v4},
|
| 213 |
+
year = {2026},
|
| 214 |
+
publisher = {Hugging Face},
|
| 215 |
+
howpublished = {\url{https://huggingface.co/NeuroKurd/kurmanji_tokenizer}}
|
| 216 |
}
|
| 217 |
+
```
|
| 218 |
+
|
| 219 |
+
## Acknowledgements
|
| 220 |
+
|
| 221 |
+
- The authors of `kurdish-tech/KurdishCorpus-clean` for the text data:
|
| 222 |
|
| 223 |
+
```bibtex
|
| 224 |
@misc{kurdish-tech-corpus,
|
| 225 |
+
author = {kurdish-tech},
|
| 226 |
+
title = {KurdishCorpus-clean},
|
| 227 |
+
year = {2026},
|
| 228 |
+
publisher = {Hugging Face},
|
| 229 |
howpublished = {\url{https://huggingface.co/datasets/kurdish-tech/KurdishCorpus-clean}}
|
| 230 |
+
}
|
| 231 |
+
```
|
| 232 |
+
|
| 233 |
+
- FLORES-200 (NLLB Team, Meta AI) for the evaluation sentences:
|
| 234 |
+
|
| 235 |
+
```bibtex
|
| 236 |
+
@article{nllb2022,
|
| 237 |
+
author = {{NLLB Team}},
|
| 238 |
+
title = {No Language Left Behind: Scaling Human-Centered Machine Translation},
|
| 239 |
+
year = {2022},
|
| 240 |
+
journal = {arXiv preprint arXiv:2207.04672}
|
| 241 |
+
}
|
| 242 |
+
```
|
| 243 |
+
|
| 244 |
+
- Everyone who writes, translates and teaches Kurmancî.
|