Update README.md
Browse files
README.md
CHANGED
|
@@ -1,9 +1,253 @@
|
|
| 1 |
---
|
| 2 |
license: apache-2.0
|
| 3 |
-
language:
|
| 4 |
-
- en
|
| 5 |
tags:
|
| 6 |
-
-
|
| 7 |
-
-
|
| 8 |
-
-
|
| 9 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
license: apache-2.0
|
|
|
|
|
|
|
| 3 |
tags:
|
| 4 |
+
- tokenizer
|
| 5 |
+
- tokenization
|
| 6 |
+
- code
|
| 7 |
+
- mathematics
|
| 8 |
+
- nlp
|
| 9 |
+
- llm
|
| 10 |
+
- cpp
|
| 11 |
+
- language-modeling
|
| 12 |
+
language:
|
| 13 |
+
- en
|
| 14 |
+
---
|
| 15 |
+
|
| 16 |
+
# BloatTokenizer32K
|
| 17 |
+
|
| 18 |
+
**Compact vocabulary. Efficient tokenization. Lossless decoding.**
|
| 19 |
+
|
| 20 |
+
BloatTokenizer32K is an open-source text tokenizer featuring a **32,000-entry vocabulary**, a native C++ encoding engine, and Python bindings.
|
| 21 |
+
|
| 22 |
+
Designed for language-model training and inference, it supports English, programming languages, mathematics, and conversational text.
|
| 23 |
+
|
| 24 |
+
On our mixed-text development benchmark, BloatTokenizer32K achieves compression comparable to GPT-4's `cl100k_base` and GPT-4o's `o200k_base`, despite using substantially smaller vocabulary capacity.
|
| 25 |
+
|
| 26 |
+
**[GitHub Repository](https://github.com/Dev-qvinfor/BloatTokenizer32K)**
|
| 27 |
+
|
| 28 |
+
## Key features
|
| 29 |
+
|
| 30 |
+
- **32,000 vocabulary entries**, including 16 reserved control tokens.
|
| 31 |
+
- **21.96% fewer tokens than GPT-2** on the evaluated mixed corpus.
|
| 32 |
+
- **6.48% fewer code tokens than `cl100k_base`** on the code subset.
|
| 33 |
+
- **0.26% fewer tokens than `cl100k_base`** overall.
|
| 34 |
+
- **17.20 MB/s** four-core warm-cache batch encoding.
|
| 35 |
+
- **17.10 MB/s** four-core fresh-instance batch encoding.
|
| 36 |
+
- **3,412/3,412 successful lossless round trips.**
|
| 37 |
+
- Native C++ engine with configurable parallel batch encoding.
|
| 38 |
+
|
| 39 |
+
## Benchmarks
|
| 40 |
+
|
| 41 |
+
### Token compression
|
| 42 |
+
|
| 43 |
+

|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
### Token compression results
|
| 47 |
+
|
| 48 |
+
Lower token counts are better.
|
| 49 |
+
|
| 50 |
+
| Tokenizer | Vocabulary | Output tokens |
|
| 51 |
+
|---|---:|---:|
|
| 52 |
+
| **BloatTokenizer32K** | **32,000** | **997,416** |
|
| 53 |
+
| GPT-4o (`o200k_base`) | 200,000 | 998,383 |
|
| 54 |
+
| GPT-4 (`cl100k_base`) | 100,261 | 1,000,000 |
|
| 55 |
+
| Qwen2.5-Coder | 151,665 | 1,018,726 |
|
| 56 |
+
| Mistral NeMo | 131,072 | 1,052,365 |
|
| 57 |
+
| Phi-2 | 50,295 | 1,159,396 |
|
| 58 |
+
| GPT-2 | 50,257 | 1,278,138 |
|
| 59 |
+
|
| 60 |
+
### Performance by domain
|
| 61 |
+
|
| 62 |
+
| Domain | BloatTokenizer32K | GPT-4 tokenizer |
|
| 63 |
+
|---|---:|---:|
|
| 64 |
+
| English | 522,543 | 500,000 |
|
| 65 |
+
| Mathematics | 100,805 | 100,000 |
|
| 66 |
+
| Code | **374,068** | 400,000 |
|
| 67 |
+
| **Total** | **997,416** | **1,000,000** |
|
| 68 |
+
|
| 69 |
+
The tokenizer's strongest measured compression advantage is on code. English and mathematics require slightly more tokens than `cl100k_base` on this evaluation.
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
### Encoding performance
|
| 73 |
+
|
| 74 |
+

|
| 75 |
+
|
| 76 |
+
### Encoding speed
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
Measured in input MB/s, using matched CPU budgets.
|
| 80 |
+
|
| 81 |
+
| Tokenizer | 1-core warm | 4-core warm | 4-core fresh |
|
| 82 |
+
|---|---:|---:|---:|
|
| 83 |
+
| **BloatTokenizer32K** | **8.53** | **17.20** | **17.10** |
|
| 84 |
+
| `cl100k_base` | 10.28 | 12.37 | 13.15 |
|
| 85 |
+
| `o200k_base` | 13.83 | 20.91 | 19.37 |
|
| 86 |
+
| Qwen2.5-Coder | 2.09 | 4.03 | 4.19 |
|
| 87 |
+
| GPT-2 | 9.77 | 8.00 | 13.57 |
|
| 88 |
+
|
| 89 |
+
In this configuration, BloatTokenizer32K achieved approximately **39% higher warm-cache four-core batch throughput** than `cl100k_base`, and approximately **30% higher fresh-instance batch throughput**.
|
| 90 |
+
|
| 91 |
+
Single-core encoding remains slower than both OpenAI tokenizer implementations.
|
| 92 |
+
|
| 93 |
+
## Evaluation methodology
|
| 94 |
+
|
| 95 |
+
The benchmark used identical inputs and matched CPU budgets across 13 tokenizers.
|
| 96 |
+
|
| 97 |
+
| Property | Configuration |
|
| 98 |
+
|---|---|
|
| 99 |
+
| Excerpts | 3,412 |
|
| 100 |
+
| Input size | 4,427,375 UTF-8 bytes |
|
| 101 |
+
| Reference tokens | 1,000,000 (`cl100k_base`) |
|
| 102 |
+
| Corpus distribution | 50% English, 10% math, 40% code |
|
| 103 |
+
| Trials | 5 per configuration |
|
| 104 |
+
| Serial CPU budget | 1 logical CPU |
|
| 105 |
+
| Batch CPU budget | 4 logical CPUs |
|
| 106 |
+
| Decode failures (BloatTokenizer32K) | 0 |
|
| 107 |
+
|
| 108 |
+
All measurements report median throughput. Fresh-instance measurements exclude tokenizer construction time; warm-cache measurements follow an untimed corpus pass.
|
| 109 |
+
|
| 110 |
+
**Limitations:** The evaluation corpus was excluded from tokenizer training but was previously inspected during development. Results are specific to this corpus and hardware configuration. Multilingual performance beyond the evaluated distribution has not been established, and baseline training-data overlap is unknown.
|
| 111 |
+
|
| 112 |
+
## Getting started
|
| 113 |
+
|
| 114 |
+
The tokenizer artifacts are available in the `artifacts/` directory of this repository.
|
| 115 |
+
|
| 116 |
+
The native encoding engine and Python interface are maintained on GitHub.
|
| 117 |
+
|
| 118 |
+
### Requirements
|
| 119 |
+
|
| 120 |
+
- Python 3.12 or 3.14 for prebuilt Windows extensions
|
| 121 |
+
- Windows x64 for bundled binaries
|
| 122 |
+
- C++17 and `pybind11` for building from source on other platforms
|
| 123 |
+
|
| 124 |
+
### Download
|
| 125 |
+
|
| 126 |
+
Install the Hugging Face Hub client:
|
| 127 |
+
|
| 128 |
+
```bash
|
| 129 |
+
pip install -U huggingface_hub
|
| 130 |
+
```
|
| 131 |
+
|
| 132 |
+
Download the tokenizer artifacts:
|
| 133 |
+
|
| 134 |
+
```python
|
| 135 |
+
from huggingface_hub import snapshot_download
|
| 136 |
+
|
| 137 |
+
path = snapshot_download(
|
| 138 |
+
repo_id="Qvinfor/BloatTokenizer32K",
|
| 139 |
+
repo_type="model",
|
| 140 |
+
)
|
| 141 |
+
|
| 142 |
+
print(path)
|
| 143 |
+
```
|
| 144 |
+
|
| 145 |
+
Replace `YOUR_HF_USERNAME` with the Hugging Face repository owner.
|
| 146 |
+
|
| 147 |
+
### Python usage
|
| 148 |
+
|
| 149 |
+
First obtain the Python/C++ engine from the [GitHub repository](https://github.com/Dev-qvinfor/BloatTokenizer32K) and follow its installation instructions.
|
| 150 |
+
|
| 151 |
+
Then load the downloaded Hugging Face artifacts:
|
| 152 |
+
|
| 153 |
+
```python
|
| 154 |
+
from pathlib import Path
|
| 155 |
+
from huggingface_hub import snapshot_download
|
| 156 |
+
from curriculum_tokenizer import CurriculumTokenizer
|
| 157 |
+
|
| 158 |
+
repo_path = snapshot_download(
|
| 159 |
+
repo_id="YOUR_HF_USERNAME/BloatTokenizer32K"
|
| 160 |
+
)
|
| 161 |
+
|
| 162 |
+
tokenizer = CurriculumTokenizer.from_pretrained(
|
| 163 |
+
str(Path(repo_path) / "artifacts")
|
| 164 |
+
)
|
| 165 |
+
|
| 166 |
+
text = "Fast, lossless text encoding."
|
| 167 |
+
|
| 168 |
+
ids = tokenizer.encode(
|
| 169 |
+
text,
|
| 170 |
+
add_special_tokens=False
|
| 171 |
+
)
|
| 172 |
+
|
| 173 |
+
decoded = tokenizer.decode(
|
| 174 |
+
ids,
|
| 175 |
+
skip_special_tokens=False
|
| 176 |
+
)
|
| 177 |
+
|
| 178 |
+
assert decoded == text
|
| 179 |
+
|
| 180 |
+
print("Token IDs:", ids)
|
| 181 |
+
print("Decoded:", decoded)
|
| 182 |
+
```
|
| 183 |
+
|
| 184 |
+
By default, `encode()` adds `<|endoftext|>` and `decode()` skips control tokens. Use the explicit options above when a round-trip should reproduce the input.
|
| 185 |
+
|
| 186 |
+
### Batch tokenization
|
| 187 |
+
|
| 188 |
+
```python
|
| 189 |
+
texts = [
|
| 190 |
+
"Hello, world!",
|
| 191 |
+
"def add(a, b): return a + b",
|
| 192 |
+
"2 + 2 = 4"
|
| 193 |
+
]
|
| 194 |
+
|
| 195 |
+
batch = tokenizer.encode_batch(
|
| 196 |
+
texts,
|
| 197 |
+
add_special_tokens=False,
|
| 198 |
+
num_threads=4
|
| 199 |
+
)
|
| 200 |
+
|
| 201 |
+
print(batch["input_ids"])
|
| 202 |
+
```
|
| 203 |
+
|
| 204 |
+
Batch encoding preserves input order.
|
| 205 |
+
|
| 206 |
+
**Compatibility note:** The published artifacts use the BloatTokenizer runtime. Direct loading through Hugging Face `AutoTokenizer` is not currently documented or guaranteed.
|
| 207 |
+
|
| 208 |
+
## Special tokens
|
| 209 |
+
|
| 210 |
+
The vocabulary includes 16 reserved control tokens:
|
| 211 |
+
|
| 212 |
+
| Token | ID |
|
| 213 |
+
|---|---:|
|
| 214 |
+
| `<|endoftext|>` | 256 |
|
| 215 |
+
| `<|pad|>` | 257 |
|
| 216 |
+
| `<|system|>` | 258 |
|
| 217 |
+
| `<|user|>` | 259 |
|
| 218 |
+
| `<|assistant|>` | 260 |
|
| 219 |
+
| `<|end_turn|>` | 261 |
|
| 220 |
+
| `<|tool_call|>` | 262 |
|
| 221 |
+
| `<|end_tool_call|>` | 263 |
|
| 222 |
+
| `<|tool_result|>` | 264 |
|
| 223 |
+
| `<|end_tool_result|>` | 265 |
|
| 224 |
+
| `<|final|>` | 266 |
|
| 225 |
+
| `<|end_final|>` | 267 |
|
| 226 |
+
| `<|think|>` | 268 |
|
| 227 |
+
| `<|end_think|>` | 269 |
|
| 228 |
+
| `<|verify|>` | 270 |
|
| 229 |
+
| `<|end_verify|>` | 271 |
|
| 230 |
+
|
| 231 |
+
Applications determine how these control markers are used in prompts and structured conversations.
|
| 232 |
+
|
| 233 |
+
## Model compatibility
|
| 234 |
+
|
| 235 |
+
BloatTokenizer32K is intended for models trained using its vocabulary and token-ID mapping.
|
| 236 |
+
|
| 237 |
+
It is not a drop-in replacement for unrelated pretrained models. Changing tokenizers requires appropriate model adaptation.
|
| 238 |
+
|
| 239 |
+
## License
|
| 240 |
+
|
| 241 |
+
**Apache License 2.0**
|
| 242 |
+
|
| 243 |
+
The publicly released tokenizer artifacts and runtime are open-source.
|
| 244 |
+
|
| 245 |
+
The proprietary vocabulary-training algorithm and its training implementation are not included.
|
| 246 |
+
|
| 247 |
+
## Source code and feedback
|
| 248 |
+
|
| 249 |
+
The full C++ runtime, Python bindings, usage examples, and technical documentation are available on GitHub.
|
| 250 |
+
|
| 251 |
+
**[BloatTokenizer32K — GitHub](https://github.com/Dev-qvinfor/BloatTokenizer32K)**
|
| 252 |
+
|
| 253 |
+
Bug reports, independent benchmarks, performance comparisons, and community contributions are welcome.
|