Text Generation
Transformers
Safetensors
English
llama
small-language-model
efficient
edge-deployment
speculative-decoding
tiny-model
12m-parameters
kaggle-trained
educational
research
low-resource
cpu-inference
mobile-deployment
stentor2
tokenmonster
conversational
Eval Results (legacy)
text-generation-inference
Instructions to use StentorLabs/Stentor2-12M with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use StentorLabs/Stentor2-12M with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="StentorLabs/Stentor2-12M") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("StentorLabs/Stentor2-12M") model = AutoModelForCausalLM.from_pretrained("StentorLabs/Stentor2-12M", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use StentorLabs/Stentor2-12M with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "StentorLabs/Stentor2-12M" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "StentorLabs/Stentor2-12M", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/StentorLabs/Stentor2-12M
- SGLang
How to use StentorLabs/Stentor2-12M with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "StentorLabs/Stentor2-12M" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "StentorLabs/Stentor2-12M", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "StentorLabs/Stentor2-12M" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "StentorLabs/Stentor2-12M", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use StentorLabs/Stentor2-12M with Docker Model Runner:
docker model run hf.co/StentorLabs/Stentor2-12M
Update README.md
Browse files
README.md
CHANGED
|
@@ -1,28 +1,1173 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
-
|
| 4 |
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
```json
|
| 8 |
{
|
| 9 |
-
"
|
| 10 |
-
"
|
| 11 |
-
"
|
| 12 |
-
"
|
| 13 |
-
"
|
| 14 |
-
"
|
| 15 |
-
"
|
| 16 |
-
"num_hidden_layers": 12,
|
| 17 |
-
"num_key_value_heads": 4,
|
| 18 |
-
"optimizer": "adamw",
|
| 19 |
-
"pad_vocab_to_multiple": 128,
|
| 20 |
-
"rope_theta": null,
|
| 21 |
-
"scheduler": "cosine",
|
| 22 |
-
"stable_ratio": 0.8,
|
| 23 |
-
"torch_compile": false,
|
| 24 |
-
"vocab_size": 8064,
|
| 25 |
-
"warmup_ratio": 0.05,
|
| 26 |
-
"weight_decay": 0.01
|
| 27 |
}
|
| 28 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
language:
|
| 3 |
+
- en
|
| 4 |
+
license: apache-2.0
|
| 5 |
+
library_name: transformers
|
| 6 |
+
tags:
|
| 7 |
+
- text-generation
|
| 8 |
+
- llama
|
| 9 |
+
- small-language-model
|
| 10 |
+
- efficient
|
| 11 |
+
- edge-deployment
|
| 12 |
+
- speculative-decoding
|
| 13 |
+
- tiny-model
|
| 14 |
+
- 12m-parameters
|
| 15 |
+
- kaggle-trained
|
| 16 |
+
- educational
|
| 17 |
+
- research
|
| 18 |
+
- low-resource
|
| 19 |
+
- cpu-inference
|
| 20 |
+
- mobile-deployment
|
| 21 |
+
- stentor2
|
| 22 |
+
- tokenmonster
|
| 23 |
+
pipeline_tag: text-generation
|
| 24 |
+
datasets:
|
| 25 |
+
- StentorLabs/StenCore
|
| 26 |
+
- epfml/FineWeb-HQ
|
| 27 |
+
widget:
|
| 28 |
+
- text: "Once upon a time"
|
| 29 |
+
example_title: "Story Generation"
|
| 30 |
+
- text: "Explain neural networks in simple terms."
|
| 31 |
+
example_title: "Toy Explanation (Often Wrong)"
|
| 32 |
+
- text: "def fibonacci(n):"
|
| 33 |
+
example_title: "Code Continuation"
|
| 34 |
+
- text: "The laws of thermodynamics describe"
|
| 35 |
+
example_title: "Science Continuation"
|
| 36 |
+
model_card_authors:
|
| 37 |
+
- StentorLabs
|
| 38 |
+
model-index:
|
| 39 |
+
- name: Stentor2-12M
|
| 40 |
+
results:
|
| 41 |
+
- task:
|
| 42 |
+
type: text-generation
|
| 43 |
+
dataset:
|
| 44 |
+
name: FineWeb-HQ / StenCore (validation split)
|
| 45 |
+
type: epfml/FineWeb-HQ
|
| 46 |
+
metrics:
|
| 47 |
+
- name: Final Validation Loss
|
| 48 |
+
type: loss
|
| 49 |
+
value: 3.2565
|
| 50 |
+
- name: Final Perplexity
|
| 51 |
+
type: perplexity
|
| 52 |
+
value: 25.96
|
| 53 |
+
- name: Best Checkpoint Validation Loss
|
| 54 |
+
type: loss
|
| 55 |
+
value: 3.2814
|
| 56 |
+
- name: BLiMP Overall Accuracy (67 tasks)
|
| 57 |
+
type: accuracy
|
| 58 |
+
value: 68.95
|
| 59 |
+
---
|
| 60 |
|
| 61 |
+
# Stentor2-12M
|
| 62 |
|
| 63 |
+

|
| 64 |
+

|
| 65 |
+

|
| 66 |
+

|
| 67 |
+

|
| 68 |
+

|
| 69 |
+
[](https://huggingface.co/StentorLabs)
|
| 70 |
+

|
| 71 |
+
|
| 72 |
+
> π¬ **Research Artifact β Not a Production Model.** This is a base language model released for research, experimentation, and community use. It is not suitable for deployment in any user-facing application without significant additional work. See [Intended Uses](#use-cases--intended-uses) for details.
|
| 73 |
+
|
| 74 |
+
---
|
| 75 |
+
|
| 76 |
+
## Table of Contents
|
| 77 |
+
|
| 78 |
+
1. [What Is This?](#what-is-this)
|
| 79 |
+
2. [The Core Design Insight: Vocabulary Efficiency](#the-core-design-insight-vocabulary-efficiency)
|
| 80 |
+
3. [Why Full MHA Instead of GQA](#why-full-mha-instead-of-gqa)
|
| 81 |
+
4. [Head-to-Head: Stentor v1 β Stentor2-Preview β Stentor2-12M](#head-to-head)
|
| 82 |
+
5. [Quick Start](#quick-start)
|
| 83 |
+
6. [Important Limitations](#important-limitations)
|
| 84 |
+
7. [Model Architecture β Full Specification](#model-architecture--full-specification)
|
| 85 |
+
8. [The Tokenizer: TokenMonster](#the-tokenizer-tokenmonster)
|
| 86 |
+
9. [Training Infrastructure](#training-infrastructure)
|
| 87 |
+
10. [Training Hyperparameters β Complete Reference](#training-hyperparameters--complete-reference)
|
| 88 |
+
11. [The T4 Mixed-Precision Recipe β Deep Dive](#the-t4-mixed-precision-recipe--deep-dive)
|
| 89 |
+
12. [Data Pipeline](#data-pipeline)
|
| 90 |
+
13. [Weight Initialization](#weight-initialization)
|
| 91 |
+
14. [Evaluation & Results](#evaluation--results)
|
| 92 |
+
15. [BLiMP Benchmark](#blimp-benchmark)
|
| 93 |
+
16. [Training Dynamics](#training-dynamics)
|
| 94 |
+
17. [Use Cases & Intended Uses](#use-cases--intended-uses)
|
| 95 |
+
18. [Out-of-Scope Uses](#out-of-scope-uses)
|
| 96 |
+
19. [Ethical Considerations & Societal Impact](#ethical-considerations--societal-impact)
|
| 97 |
+
20. [Inference Guide](#inference-guide)
|
| 98 |
+
21. [Real Model Responses](#real-model-responses)
|
| 99 |
+
22. [Quantization](#quantization)
|
| 100 |
+
23. [Format Conversion](#format-conversion)
|
| 101 |
+
24. [Speculative Decoding](#speculative-decoding)
|
| 102 |
+
25. [Bias, Risks & Limitations](#bias-risks--limitations)
|
| 103 |
+
26. [Related Work](#related-work)
|
| 104 |
+
27. [Environmental Impact](#environmental-impact)
|
| 105 |
+
28. [Citation](#citation)
|
| 106 |
+
|
| 107 |
+
---
|
| 108 |
+
|
| 109 |
+
## What Is This?
|
| 110 |
+
|
| 111 |
+
Stentor2-12M is the official release of the **Stentor2** model family β a ground-up redesign of the original Stentor v1 line. At ~12.3M parameters, it is a compact base language model built entirely from scratch on free-tier Kaggle compute using two NVIDIA Tesla T4 GPUs in a true dual-GPU distributed training configuration.
|
| 112 |
+
|
| 113 |
+
Like all Stentor models, this is a **base next-token predictor**, not a chat assistant. It will not reliably follow instructions, has no safety tuning, and is best used for research, prototyping, speculative decoding, and edge-deployment experimentation. The value of this model is not its conversational capability β it is what it represents architecturally: dramatically improved efficiency over both Stentor v1 and the Stentor2-Preview, achieved by fixing the root vocabulary imbalance of v1 and removing architectural overhead that actively harmed training at this scale.
|
| 114 |
+
|
| 115 |
+
---
|
| 116 |
+
|
| 117 |
+
## The Core Design Insight: Vocabulary Efficiency
|
| 118 |
+
|
| 119 |
+
The most consequential change in Stentor2 is the replacement of the standard Llama/Mistral 32,768-token vocabulary with a purpose-built **8,000-token English vocabulary** from the TokenMonster project (`english-8000-strict-nocapcode-v1`, padded to 8,064 for hardware alignment).
|
| 120 |
+
|
| 121 |
+
This is not a minor tweak β it is the entire architectural story of Stentor2.
|
| 122 |
+
|
| 123 |
+
### Why Vocabulary Size Matters So Much at This Scale
|
| 124 |
+
|
| 125 |
+
In a transformer language model, the embedding table has shape `[vocab_size Γ hidden_size]`. When you tie word embeddings (share the embedding and output projection weights, which Stentor does), this table appears once in the parameter count. At 12M total parameters, the fraction consumed by this table dictates how much "brain" is left over for the actual transformer layers.
|
| 126 |
+
|
| 127 |
+
**Stentor-12M (v1)** used a 32,768-token vocabulary. At a hidden size of 192:
|
| 128 |
+
|
| 129 |
+
```
|
| 130 |
+
embedding_params = 32,768 Γ 192 = 6,291,456
|
| 131 |
+
total_params = 12,047,040
|
| 132 |
+
embedding_share = 52.2%
|
| 133 |
+
```
|
| 134 |
+
|
| 135 |
+
Over half of the model was a lookup table. The transformer stack β the part that actually *learns language patterns* β had fewer than 6 million parameters to work with. It was more dictionary than reasoner.
|
| 136 |
+
|
| 137 |
+
**Stentor2-12M** uses an 8,064-token vocabulary. At a hidden size of 256:
|
| 138 |
+
|
| 139 |
+
```
|
| 140 |
+
embedding_params = 8,064 Γ 256 = 2,064,384
|
| 141 |
+
total_params = 12,294,400
|
| 142 |
+
embedding_share = 16.8%
|
| 143 |
+
```
|
| 144 |
+
|
| 145 |
+
By shrinking the vocabulary, the embedding table was cut from 6.3M to 2.1M parameters β freeing up ~4.2M parameters that were redistributed into transformer depth (12 layers vs 9) and width (hidden size 256 vs 192), where they contribute directly to language modeling quality.
|
| 146 |
+
|
| 147 |
+
The combined result of vocabulary efficiency, full MHA (see next section), a richer dataset pipeline, and true dual-GPU training is a **~70.8% reduction in perplexity** versus Stentor v1 (89.01 β 25.96).
|
| 148 |
+
|
| 149 |
+
---
|
| 150 |
+
|
| 151 |
+
## Why Full MHA Instead of GQA
|
| 152 |
+
|
| 153 |
+
Stentor2-12M uses standard **full multi-head attention** (MHA) where the number of key/value heads equals the number of query heads (both = 4). The earlier Stentor2-Preview experimented with Grouped Query Attention (GQA), but it was removed for this release. This decision deserves a detailed explanation because it runs counter to the trend in larger models.
|
| 154 |
+
|
| 155 |
+
### The GQA Problem at Small Scale
|
| 156 |
+
|
| 157 |
+
Grouped Query Attention was designed to reduce the KV cache memory footprint in billion-parameter models where KV cache size becomes a serious inference bottleneck. At 12M parameters with a 1,024-token context, this problem simply does not exist. The KV cache per sequence per layer is:
|
| 158 |
+
|
| 159 |
+
```
|
| 160 |
+
2 (K and V) Γ 4 heads Γ 64 head_dim Γ 2 bytes (FP16) = 1,024 bytes per layer
|
| 161 |
+
Γ 12 layers = 12,288 bytes β 12 KB per sequence
|
| 162 |
+
```
|
| 163 |
+
|
| 164 |
+
GQA saves nothing meaningful here. But it costs something real during training.
|
| 165 |
+
|
| 166 |
+
### How GQA Introduces Optimizer Noise
|
| 167 |
+
|
| 168 |
+
With only 4 attention heads total, the valid GQA configurations are 1, 2, or 4 KV heads. Using fewer than 4 (say, 2) means each KV projection must simultaneously serve 2 query heads.
|
| 169 |
+
|
| 170 |
+
During backpropagation, the gradients from those 2 query heads are **accumulated into a single KV projection update**. The optimizer (AdamW) then computes a single step direction for a gradient that is actually the sum of two independent signals β signals that may be pointing in meaningfully different directions depending on what each query head has learned to attend to. At scale, these signals tend to be well-correlated (which is part of why GQA works in large models). At 4 heads in a 12M parameter model, that correlation assumption breaks down. The optimizer is forced to find a compromise update that fully satisfies neither head, which introduces noise into the gradient estimates, destabilizes the loss curve, and slows convergence.
|
| 171 |
+
|
| 172 |
+
This effect was directly observed in preliminary training runs for the Stentor2 family. GQA produced a visibly noisier training loss curve and slower convergence toward low perplexity β the exact opposite of its intended benefit.
|
| 173 |
+
|
| 174 |
+
### The Throughput Cost
|
| 175 |
+
|
| 176 |
+
Beyond gradient noise, GQA at 4 heads adds computational overhead with no offsetting gain. The head-sharing logic creates synchronization cost in the attention kernel that measurably reduced tokens-per-second throughput on T4 GPUs compared to clean full MHA. Every efficiency argument for GQA β memory, throughput, inference speed β inverts at this parameter scale.
|
| 177 |
+
|
| 178 |
+
**The conclusion is straightforward:** GQA is a tool designed for large models with large KV caches. Applying it to a 12M parameter model with 4 heads actively harms training without providing any of its intended benefits. Full MHA is the correct choice here.
|
| 179 |
+
|
| 180 |
+
---
|
| 181 |
+
|
| 182 |
+
## Head-to-Head
|
| 183 |
+
|
| 184 |
+
<a name="head-to-head"></a>
|
| 185 |
+
|
| 186 |
+
| Property | Stentor-12M (v1) | Stentor2-12M-Preview | **Stentor2-12M** |
|
| 187 |
+
|---|---|---|---|
|
| 188 |
+
| **Vocabulary** | 32,768 (Mistral BPE) | 8,064 (TokenMonster) | **8,064 (TokenMonster)** |
|
| 189 |
+
| **Hidden Size** | 192 | 256 | **256** |
|
| 190 |
+
| **Intermediate Size** | 576 | 768 | **768** |
|
| 191 |
+
| **Num Layers** | 9 | 12 | **12** |
|
| 192 |
+
| **Attention Heads** | 3 | 4 | **4** |
|
| 193 |
+
| **KV Heads (GQA)** | 3 (full MHA) | 4 (full MHA) | **4 (full MHA)** |
|
| 194 |
+
| **Head Dimension** | 64 | 64 | **64** |
|
| 195 |
+
| **Context Length** | 512 tokens | 1,024 tokens | **1,024 tokens** |
|
| 196 |
+
| **Total Parameters** | 12,047,040 | 12,294,400 | **12,294,400** |
|
| 197 |
+
| **Embedding Share** | 52.2% | 16.8% | **16.8%** |
|
| 198 |
+
| **Non-Embedding Params** | ~5.76M | ~10.23M | **~10.23M** |
|
| 199 |
+
| **Token Budget** | 200M | 240M | **480M (2 epochs)** |
|
| 200 |
+
| **Training Processes** | 1 | 1 (2 GPUs available) | **2 (true distributed)** |
|
| 201 |
+
| **Training Time** | ~1.3h | ~4.4h | **~2.13h** |
|
| 202 |
+
| **Final Perplexity** | 89.01 | ~50.07 | **25.96** |
|
| 203 |
+
| **Perplexity vs v1** | β | β43.8% | **β70.8%** |
|
| 204 |
+
| **Dataset** | FineWeb-Edu + Cosmopedia | FineWeb-Edu | **StenCore + FineWeb-HQ** |
|
| 205 |
+
| **Architecture** | LlamaForCausalLM | LlamaForCausalLM | **LlamaForCausalLM** |
|
| 206 |
+
| **Training Precision** | fp16 | fp16 | **fp16** |
|
| 207 |
+
| **AutoModel compatible** | β
| β (custom loader) | **β
** |
|
| 208 |
+
|
| 209 |
+
---
|
| 210 |
+
|
| 211 |
+
## π Quick Start
|
| 212 |
+
|
| 213 |
+
### 1. Install Dependencies
|
| 214 |
+
|
| 215 |
+
```bash
|
| 216 |
+
pip install transformers torch safetensors tokenmonster
|
| 217 |
+
```
|
| 218 |
+
|
| 219 |
+
### 2. Load the Model
|
| 220 |
+
|
| 221 |
+
Stentor2-12M loads cleanly with the standard HuggingFace API β no custom loader required.
|
| 222 |
+
|
| 223 |
+
```python
|
| 224 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 225 |
+
import torch
|
| 226 |
+
|
| 227 |
+
model = AutoModelForCausalLM.from_pretrained("StentorLabs/Stentor2-12M")
|
| 228 |
+
tokenizer = AutoTokenizer.from_pretrained("StentorLabs/Stentor2-12M", trust_remote_code=True)
|
| 229 |
+
```
|
| 230 |
+
|
| 231 |
+
**GPU (FP16) β recommended if you have a CUDA GPU:**
|
| 232 |
+
|
| 233 |
+
```python
|
| 234 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 235 |
+
"StentorLabs/Stentor2-12M",
|
| 236 |
+
torch_dtype=torch.float16,
|
| 237 |
+
device_map="auto"
|
| 238 |
+
)
|
| 239 |
+
```
|
| 240 |
+
|
| 241 |
+
### 3. Generate Text
|
| 242 |
+
|
| 243 |
+
This is a **base model** β it continues text rather than answering questions. Give it the beginning of a sentence and it will complete it.
|
| 244 |
+
|
| 245 |
+
```python
|
| 246 |
+
input_ids = torch.tensor([tokenizer.encode("The history of computing")], dtype=torch.long).to(next(model.parameters()).device)
|
| 247 |
+
attention_mask = torch.ones_like(input_ids)
|
| 248 |
+
|
| 249 |
+
with torch.inference_mode():
|
| 250 |
+
output = model.generate(
|
| 251 |
+
input_ids,
|
| 252 |
+
attention_mask=attention_mask,
|
| 253 |
+
max_new_tokens=80,
|
| 254 |
+
do_sample=True,
|
| 255 |
+
temperature=1.1,
|
| 256 |
+
top_p=0.55,
|
| 257 |
+
repetition_penalty=1.15,
|
| 258 |
+
pad_token_id=tokenizer.pad_token_id,
|
| 259 |
+
)
|
| 260 |
+
|
| 261 |
+
print(tokenizer.decode(output[0].tolist()))
|
| 262 |
+
```
|
| 263 |
+
|
| 264 |
+
> **Why `attention_mask`?** The model's pad token and EOS token share the same ID. Without an explicit attention mask, HuggingFace throws a warning because it cannot tell which tokens are real vs padding. Passing `torch.ones_like(input_ids)` tells the model that every token in the input is real β which is always true for single-sequence inference.
|
| 265 |
+
|
| 266 |
+
### 4. Recommended Generation Settings
|
| 267 |
+
|
| 268 |
+
| Parameter | Recommended Range | Notes |
|
| 269 |
+
|---|---|---|
|
| 270 |
+
| `temperature` | 0.65 β 1.2 | Lower = more focused, higher = more creative |
|
| 271 |
+
| `top_p` | 0.5 β 0.8 | Nucleus sampling cutoff |
|
| 272 |
+
| `max_new_tokens` | 10 β 60 | Keep outputs short for best coherence |
|
| 273 |
+
| `repetition_penalty` | 1.1 β 1.2 | Helps prevent looping |
|
| 274 |
+
|
| 275 |
+
> β οΈ **Keep `max_new_tokens` low.** This is a 12M parameter base model β coherence degrades beyond ~60 tokens. Short completions are significantly more on-topic than long ones.
|
| 276 |
+
|
| 277 |
+
---
|
| 278 |
+
|
| 279 |
+
## β οΈ Important Limitations
|
| 280 |
+
|
| 281 |
+
- **Not Instruction-Tuned:** This is a base model. It will often ignore prompts, continue in unexpected directions, or respond off-topic.
|
| 282 |
+
- **No Safety Tuning:** No RLHF, no constitutional AI, no content filtering. Use with appropriate caution.
|
| 283 |
+
- **Limited World Knowledge:** ~12M parameters cannot store meaningful world knowledge. Do not treat outputs as factual.
|
| 284 |
+
- **Context Window:** Hard limit of 1,024 tokens. Longer contexts are untested and likely to degrade.
|
| 285 |
+
- **English Only:** The TokenMonster `english-8000-strict-nocapcode-v1` vocabulary is English-specific. Non-English text will tokenize very poorly.
|
| 286 |
+
- **Custom Tokenizer:** This model uses a TokenMonster adapter, not a standard HuggingFace fast tokenizer. The `tokenmonster` package must be installed. `trust_remote_code=True` is required when loading the tokenizer.
|
| 287 |
+
- **`skip_special_tokens` Not Supported:** The TokenMonster tokenizer does **not** support the `skip_special_tokens` argument in its decode method. Always decode without it and strip special tokens manually if needed.
|
| 288 |
+
- **Shared Tensor Warning:** When saving or loading, you may see: `Removed shared tensor {'lm_head.weight'} while saving`. This is expected behavior from tied word embeddings and is safe to ignore.
|
| 289 |
+
|
| 290 |
+
---
|
| 291 |
+
|
| 292 |
+
## Model Architecture β Full Specification
|
| 293 |
+
|
| 294 |
+
Stentor2-12M is a `LlamaForCausalLM` model. All architecture values below were derived directly from the training script and validated against the logged parameter counts.
|
| 295 |
+
|
| 296 |
+
### Core Configuration
|
| 297 |
+
|
| 298 |
+
| Component | Value | Derivation |
|
| 299 |
+
|---|---|---|
|
| 300 |
+
| **Architecture** | `LlamaForCausalLM` | Hard-coded in training script |
|
| 301 |
+
| **Hidden Size** | 256 | Inferred: embedding_params (2,064,384) Γ· vocab_size (8,064) = 256 β |
|
| 302 |
+
| **Intermediate Size (FFN)** | 768 | Hidden Γ 3 (verified via total param count) |
|
| 303 |
+
| **Num Hidden Layers** | 12 | Verified via total param count formula |
|
| 304 |
+
| **Num Attention Heads** | 4 | Hidden Γ· head_dim = 256 Γ· 64 = 4 |
|
| 305 |
+
| **Num Key/Value Heads** | 4 | Full MHA β no GQA (see [above](#why-full-mha-instead-of-gqa)) |
|
| 306 |
+
| **Head Dimension** | 64 | Enforced by training script hardware constraint |
|
| 307 |
+
| **Vocab Size** | 8,064 | TokenMonster 8K base + 62 padding tokens (padded to multiple of 128) |
|
| 308 |
+
| **Max Position Embeddings** | 1,024 | `block_size` in training configuration |
|
| 309 |
+
| **Hidden Activation** | SiLU | LlamaForCausalLM default |
|
| 310 |
+
| **Positional Encoding** | RoPE | `rope_theta = 10,000.0` |
|
| 311 |
+
| **RMS Norm Epsilon** | 1e-5 | Training script default |
|
| 312 |
+
| **Tie Word Embeddings** | True | Shared embedding / LM head weights |
|
| 313 |
+
| **Attention Implementation** | SDPA | PyTorch Scaled Dot Product Attention |
|
| 314 |
+
| **Attention Pattern** | Full causal | No sliding window, no sparse patterns |
|
| 315 |
+
|
| 316 |
+
### Parameter Count Breakdown
|
| 317 |
+
|
| 318 |
+
The total parameter count can be reproduced exactly using the following formula from the training script:
|
| 319 |
+
|
| 320 |
+
```python
|
| 321 |
+
def estimate_llama_params(vocab_size, hidden_size, intermediate_size,
|
| 322 |
+
num_hidden_layers, num_attention_heads, num_key_value_heads):
|
| 323 |
+
kv_dim = int(hidden_size * num_key_value_heads / num_attention_heads)
|
| 324 |
+
attn = 2 * hidden_size * hidden_size + 2 * hidden_size * kv_dim
|
| 325 |
+
mlp = 3 * hidden_size * intermediate_size
|
| 326 |
+
norm = 2 * hidden_size
|
| 327 |
+
total = vocab_size * hidden_size + num_hidden_layers * (attn + mlp + norm) + hidden_size
|
| 328 |
+
return total
|
| 329 |
+
```
|
| 330 |
+
|
| 331 |
+
Plugging in Stentor2-12M values:
|
| 332 |
+
|
| 333 |
+
```
|
| 334 |
+
kv_dim = 256 * 4 / 4 = 256
|
| 335 |
+
attn = 2Γ256Γ256 + 2Γ256Γ256 = 262,144
|
| 336 |
+
mlp = 3Γ256Γ768 = 589,824
|
| 337 |
+
norm = 2Γ256 = 512
|
| 338 |
+
per_layer = 852,480
|
| 339 |
+
|
| 340 |
+
embedding = 8,064 Γ 256 = 2,064,384
|
| 341 |
+
layers = 12 Γ 852,480 = 10,229,760
|
| 342 |
+
final_norm = 256
|
| 343 |
+
|
| 344 |
+
total = 2,064,384 + 10,229,760 + 256 = 12,294,400 β
|
| 345 |
+
```
|
| 346 |
+
|
| 347 |
+
| Component | Parameters | % of Total |
|
| 348 |
+
|---|---|---|
|
| 349 |
+
| Embedding Table (tied with LM Head) | 2,064,384 | 16.8% |
|
| 350 |
+
| Transformer Layers Γ 12 | 10,229,760 | 83.2% |
|
| 351 |
+
| β Attention (per layer Γ 12) | 3,145,728 | 25.6% |
|
| 352 |
+
| β FFN/MLP (per layer Γ 12) | 7,077,888 | 57.5% |
|
| 353 |
+
| β Layer Norms (per layer Γ 12) | 6,144 | 0.05% |
|
| 354 |
+
| Final RMS Norm | 256 | 0.002% |
|
| 355 |
+
| **Total** | **12,294,400** | **100%** |
|
| 356 |
+
|
| 357 |
+
---
|
| 358 |
+
|
| 359 |
+
## The Tokenizer: TokenMonster
|
| 360 |
+
|
| 361 |
+
Stentor2-12M uses a custom tokenizer adapter wrapping the **TokenMonster** `english-8000-strict-nocapcode-v1` vocabulary rather than a standard BPE tokenizer from the HuggingFace ecosystem.
|
| 362 |
+
|
| 363 |
+
### What Is TokenMonster?
|
| 364 |
+
|
| 365 |
+
TokenMonster ([alasdairforsythe/tokenmonster](https://huggingface.co/alasdairforsythe/tokenmonster)) is an alternative tokenization approach optimized for compact English vocabulary sizes. The `english-8000-strict-nocapcode-v1` vocabulary is a purpose-built ~8,000-token English vocabulary designed for efficiency at small model scales.
|
| 366 |
+
|
| 367 |
+
### β οΈ `skip_special_tokens` Is Not Supported
|
| 368 |
+
|
| 369 |
+
The TokenMonster tokenizer **does not support the `skip_special_tokens` argument** in its decode method. Always decode without it:
|
| 370 |
+
|
| 371 |
+
```python
|
| 372 |
+
# β
Correct
|
| 373 |
+
text = tokenizer.decode(output_ids)
|
| 374 |
+
|
| 375 |
+
# β This will raise an error
|
| 376 |
+
text = tokenizer.decode(output_ids, skip_special_tokens=True)
|
| 377 |
+
```
|
| 378 |
+
|
| 379 |
+
If you are using HuggingFace's `TextIteratorStreamer` or any wrapper that internally passes `skip_special_tokens=True`, you will need to patch or replace that wrapper.
|
| 380 |
+
|
| 381 |
+
### Tokenizer Efficiency vs. v1
|
| 382 |
+
|
| 383 |
+
You may notice this tokenizer produces **more tokens per word** compared to Stentor v1. This is expected and by design. The v1 models used a 32,768-token Mistral BPE vocabulary, which encodes common English words as single tokens very efficiently. Stentor2 uses an 8,064-token TokenMonster vocabulary β smaller vocabulary means more tokens per word on average. This is the direct tradeoff for freeing up ~4.2M parameters for the transformer layers. The ~70.8% perplexity improvement shows the tradeoff was worth it.
|
| 384 |
+
|
| 385 |
+
### Vocabulary Construction
|
| 386 |
+
|
| 387 |
+
1. Base vocabulary loaded from `alasdairforsythe/tokenmonster` β `vocabs/english-8000-strict-nocapcode-v1.vocab`
|
| 388 |
+
2. Special tokens added: `</s>` (EOS), `<s>` (BOS), `<pad>` (set equal to EOS)
|
| 389 |
+
3. A default chat template is injected for structural compatibility
|
| 390 |
+
4. Vocabulary padded to the nearest multiple of 128 using dummy tokens `<|extra_0|>` through `<|extra_61|>`, resulting in a final vocabulary size of **8,064 tokens**
|
| 391 |
+
|
| 392 |
+
### Tokenizer Configuration
|
| 393 |
|
| 394 |
```json
|
| 395 |
{
|
| 396 |
+
"tokenizer_type": "tokenmonster",
|
| 397 |
+
"vocab_file": "tokenmonster.vocab",
|
| 398 |
+
"model_max_length": 1024,
|
| 399 |
+
"eos_token": "</s>",
|
| 400 |
+
"bos_token": "<s>",
|
| 401 |
+
"pad_token": "</s>",
|
| 402 |
+
"vocab_size": 8064
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 403 |
}
|
| 404 |
```
|
| 405 |
+
|
| 406 |
+
### Chat Template
|
| 407 |
+
|
| 408 |
+
A simple chat template is injected for structural compatibility with chat formatting tools. The base model is **not trained to follow it**:
|
| 409 |
+
|
| 410 |
+
```jinja
|
| 411 |
+
{% for message in messages %}
|
| 412 |
+
<|{{ message['role'] }}|>
|
| 413 |
+
{{ message['content'] }}
|
| 414 |
+
{% endfor %}
|
| 415 |
+
{% if add_generation_prompt %}<|assistant|>
|
| 416 |
+
{% endif %}
|
| 417 |
+
```
|
| 418 |
+
|
| 419 |
+
### Loading the Tokenizer
|
| 420 |
+
|
| 421 |
+
```bash
|
| 422 |
+
pip install tokenmonster
|
| 423 |
+
```
|
| 424 |
+
|
| 425 |
+
```python
|
| 426 |
+
from transformers import AutoTokenizer
|
| 427 |
+
tokenizer = AutoTokenizer.from_pretrained("StentorLabs/Stentor2-12M", trust_remote_code=True)
|
| 428 |
+
```
|
| 429 |
+
|
| 430 |
+
---
|
| 431 |
+
|
| 432 |
+
## Training Infrastructure
|
| 433 |
+
|
| 434 |
+
### Hardware
|
| 435 |
+
|
| 436 |
+
| Component | Specification |
|
| 437 |
+
|---|---|
|
| 438 |
+
| GPU Count | 2Γ NVIDIA Tesla T4 |
|
| 439 |
+
| VRAM per GPU | 15.64 GB |
|
| 440 |
+
| Total VRAM | ~31.3 GB |
|
| 441 |
+
| Training Processes | 2 (true data-parallel distributed training) |
|
| 442 |
+
| Platform | Kaggle Notebooks (free tier) |
|
| 443 |
+
| Accelerator Library | HuggingFace Accelerate |
|
| 444 |
+
| Communication Backend | NCCL |
|
| 445 |
+
|
| 446 |
+
> **Note on Dual-GPU Setup:** Unlike Stentor2-12M-Preview (which had 2 GPUs available but ran as a single process), Stentor2-12M ran as a true 2-process distributed job with `world_size=2`. Both GPUs contributed to training, which is why total_batch_size=128 with per_device_batch_size=32 and gradient_accumulation=2 (32 Γ 2 processes Γ 2 = 128).
|
| 447 |
+
|
| 448 |
+
### Software Stack
|
| 449 |
+
|
| 450 |
+
| Package | Role |
|
| 451 |
+
|---|---|
|
| 452 |
+
| PyTorch | Core tensor operations and autograd |
|
| 453 |
+
| HuggingFace Transformers | Model architecture (LlamaForCausalLM) |
|
| 454 |
+
| HuggingFace Accelerate | Distributed training loop and device management |
|
| 455 |
+
| HuggingFace Datasets | Streaming data loading |
|
| 456 |
+
| bitsandbytes | Quantization primitives |
|
| 457 |
+
| tokenmonster | Custom vocabulary |
|
| 458 |
+
| safetensors | Model serialization |
|
| 459 |
+
|
| 460 |
+
---
|
| 461 |
+
|
| 462 |
+
## Training Hyperparameters β Complete Reference
|
| 463 |
+
|
| 464 |
+
### Core Training Parameters
|
| 465 |
+
|
| 466 |
+
| Hyperparameter | Value | Notes |
|
| 467 |
+
|---|---|---|
|
| 468 |
+
| `learning_rate` | 8e-4 | AdamW LR |
|
| 469 |
+
| `weight_decay` | 0.01 | Applied to non-embedding, non-norm, non-bias params |
|
| 470 |
+
| `max_grad_norm` | 1.0 | Gradient clipping threshold |
|
| 471 |
+
| `optimizer` | AdamW | With `betas=(0.9, 0.95)`, `eps=1e-8` |
|
| 472 |
+
| `scheduler` | Cosine | Cosine decay with linear warmup |
|
| 473 |
+
| `warmup_steps` | 477 | ~5% of max_train_steps |
|
| 474 |
+
| `stable_steps` | 7,641 | ~80% of max_train_steps |
|
| 475 |
+
| `source_token_budget` | 240,000,000 | Raw source tokens per epoch |
|
| 476 |
+
| `token_budget` | 480,000,000 | Total tokens across all epochs (2 epochs Γ 240M) |
|
| 477 |
+
| `max_train_steps` | 9,552 | Theoretical max; training stopped early at token budget |
|
| 478 |
+
| `actual_steps_trained` | ~3,600 | Token budget reached at step ~3,600 in epoch 1 |
|
| 479 |
+
| `num_train_epochs` | 2 | |
|
| 480 |
+
| `seed` | 42 | Reproducibility seed |
|
| 481 |
+
| `mixed_precision` | fp16 | All activations/gradients in FP16 |
|
| 482 |
+
|
| 483 |
+
### Batch & Sequence Parameters
|
| 484 |
+
|
| 485 |
+
| Hyperparameter | Value | Notes |
|
| 486 |
+
|---|---|---|
|
| 487 |
+
| `per_device_train_batch_size` | 32 | Per GPU per gradient accumulation step |
|
| 488 |
+
| `per_device_eval_batch_size` | 16 | Evaluation batch size |
|
| 489 |
+
| `gradient_accumulation_steps` | 2 | Optimizer step every 2 forward passes |
|
| 490 |
+
| `num_processes` | 2 | True distributed, 2 GPUs |
|
| 491 |
+
| `total_batch_size` | 128 | `32 Γ 2 processes Γ 2 grad_accum` |
|
| 492 |
+
| `block_size` | 1,024 | Sequence length; training packed to this size |
|
| 493 |
+
| `tokens_per_optimizer_step` | 131,072 | `total_batch_size Γ block_size` |
|
| 494 |
+
|
| 495 |
+
### Evaluation & Checkpointing
|
| 496 |
+
|
| 497 |
+
| Hyperparameter | Value |
|
| 498 |
+
|---|---|
|
| 499 |
+
| `eval_steps` | 900 |
|
| 500 |
+
| `best_eval_steps` | 900 |
|
| 501 |
+
| `best_eval_start_step` | 1,500 |
|
| 502 |
+
| `save_every_minutes` | 30 |
|
| 503 |
+
| `save_total_limit` | 2 |
|
| 504 |
+
| `logging_steps` | 300 |
|
| 505 |
+
| `max_eval_samples` | 5,000 |
|
| 506 |
+
|
| 507 |
+
### Precision Stability Configuration
|
| 508 |
+
|
| 509 |
+
| Setting | Value |
|
| 510 |
+
|---|---|
|
| 511 |
+
| `fp32_norms` | True |
|
| 512 |
+
| `fp32_norm_modules` | 25 |
|
| 513 |
+
| `fp32_softmax_modules` | 0 (SDPA-compatible path) |
|
| 514 |
+
| `fp32_critical_layers` | 2 (first 1 + last 1) |
|
| 515 |
+
| `torch_compile` | False |
|
| 516 |
+
| `gradient_checkpointing` | False |
|
| 517 |
+
|
| 518 |
+
### AdamW Optimizer β Detailed
|
| 519 |
+
|
| 520 |
+
The optimizer uses a decoupled parameter group strategy:
|
| 521 |
+
|
| 522 |
+
- **Decay group:** All `nn.Linear` weight matrices (excludes bias, norm weights, embedding)
|
| 523 |
+
- `weight_decay = 0.01`
|
| 524 |
+
- **No-decay group:** Bias terms, normalization parameters, embedding parameters
|
| 525 |
+
- `weight_decay = 0.0`
|
| 526 |
+
- **Betas:** `(0.9, 0.95)` β the 0.95 Ξ²β is a modern LLM default (vs the 0.999 PyTorch default)
|
| 527 |
+
- **Epsilon:** `1e-8`
|
| 528 |
+
- **Fused kernel:** Enabled when CUDA is available (`fused=True`)
|
| 529 |
+
|
| 530 |
+
### Learning Rate Schedule
|
| 531 |
+
|
| 532 |
+
```
|
| 533 |
+
Phase 1 β Warmup (steps 0β477):
|
| 534 |
+
LR ramps linearly from 0 β 8e-4
|
| 535 |
+
|
| 536 |
+
Phase 2 β Cosine Decay (steps 477β9,552):
|
| 537 |
+
LR follows cosine curve from 8e-4 β 0
|
| 538 |
+
(Training stopped early at ~3,600 steps due to token budget)
|
| 539 |
+
```
|
| 540 |
+
|
| 541 |
+
---
|
| 542 |
+
|
| 543 |
+
## The T4 Mixed-Precision Recipe β Deep Dive
|
| 544 |
+
|
| 545 |
+
The most technically interesting aspect of Stentor2's training pipeline is its custom **T4 Mixed-Precision Recipe** β a bespoke approach to stable FP16 training on NVIDIA Tesla T4 GPUs, which lack BF16 support and have known numerical instability issues with FP16 on certain operations.
|
| 546 |
+
|
| 547 |
+
This recipe involves three distinct techniques applied simultaneously:
|
| 548 |
+
|
| 549 |
+
### 1. FP32 Critical Layers (2 layers: first 1 + last 1)
|
| 550 |
+
|
| 551 |
+
The first and last transformer layers run entirely in FP32:
|
| 552 |
+
|
| 553 |
+
- Their weights are cast to `.float()` at setup time
|
| 554 |
+
- Their `forward()` method is monkey-patched to cast all inputs to FP32 before the call and cast outputs back to the original dtype afterward
|
| 555 |
+
- `torch.amp.autocast("cuda", enabled=False)` context prevents autocast from re-downcasting inside the layer
|
| 556 |
+
|
| 557 |
+
**Rationale:** The first layer is responsible for embedding projection and initial feature extraction; instability here corrupts the entire forward pass. The last layer handles final token prediction; numerical errors here directly impact loss. Running these in FP32 provides a stability floor at minimal compute cost.
|
| 558 |
+
|
| 559 |
+
### 2. FP32 Normalization Layers (25 modules)
|
| 560 |
+
|
| 561 |
+
All RMSNorm and LayerNorm modules are monkey-patched to run their computation in FP32 regardless of input dtype:
|
| 562 |
+
|
| 563 |
+
```python
|
| 564 |
+
def _fp32_norm_forward(hidden_states, *args, **kwargs):
|
| 565 |
+
input_dtype = hidden_states.dtype
|
| 566 |
+
output = original_forward(hidden_states.float().contiguous(), *args, **kwargs)
|
| 567 |
+
return output.clone().to(input_dtype)
|
| 568 |
+
```
|
| 569 |
+
|
| 570 |
+
The `.clone()` call prevents returning graph-managed buffers that could be overwritten across replay steps. The `.contiguous()` call prevents strided-tensor issues in FP32 norm operations.
|
| 571 |
+
|
| 572 |
+
**Why 25 modules:** 12 transformer layers Γ 2 norms each (input norm + post-attention norm) + 1 final norm = 25 total.
|
| 573 |
+
|
| 574 |
+
**This is why `torch_compile` is disabled.** The FP32 norm wrappers are incompatible with CUDAGraph replay, which `torch.compile` uses under `reduce-overhead` mode.
|
| 575 |
+
|
| 576 |
+
### 3. SDPA-Compatible Path (No FP32 Softmax Wrapper)
|
| 577 |
+
|
| 578 |
+
Unlike earlier experiments, Stentor2-12M uses the SDPA (Scaled Dot Product Attention) path from PyTorch, which handles numerical stability in the attention kernel natively. The FP32 softmax monkey-patch used in some experimental runs was intentionally skipped here because SDPA and FlashAttention kernels require FP16/BF16 inputs for their fast paths. Wrapping the softmax in FP32 would disable these kernels and cause a significant throughput regression. SDPA's internal numerics are already stable enough for 1,024-token sequences on T4 hardware.
|
| 579 |
+
|
| 580 |
+
### T4 Recipe Summary Table
|
| 581 |
+
|
| 582 |
+
| Technique | Count | Scope |
|
| 583 |
+
|---|---|---|
|
| 584 |
+
| FP32 critical layers | 2 | First and last transformer layers |
|
| 585 |
+
| FP32 norm modules | 25 | All RMSNorm / LayerNorm |
|
| 586 |
+
| FP32 softmax modules | 0 | Skipped β SDPA handles this natively |
|
| 587 |
+
|
| 588 |
+
---
|
| 589 |
+
|
| 590 |
+
## Data Pipeline
|
| 591 |
+
|
| 592 |
+
### Dataset
|
| 593 |
+
|
| 594 |
+
Stentor2-12M was trained on a **cascaded StenCore β FineWeb-HQ pipeline**, a two-stage data mixture combining StentorLabs' curated source corpus with high-quality filtered web text. This represents an upgrade from the FineWeb-Edu-only data used in Stentor2-12M-Preview.
|
| 595 |
+
|
| 596 |
+
**Total tokens processed:** 480,116,736 (2 epochs Γ 240M source tokens per epoch)
|
| 597 |
+
|
| 598 |
+
### Cascaded Data Pipeline
|
| 599 |
+
|
| 600 |
+
The training pipeline loads data in priority order:
|
| 601 |
+
|
| 602 |
+
1. **StenCore** ([StentorLabs/StenCore](https://huggingface.co/datasets/StentorLabs/StenCore)) β StentorLabs' curated training corpus, loaded first up to the source token budget
|
| 603 |
+
2. **FineWeb-HQ** ([epfml/FineWeb-HQ](https://huggingface.co/datasets/epfml/FineWeb-HQ)) β High-quality filtered web text, used to fill the remaining token budget after StenCore is exhausted. FineWeb-HQ documents are deduplicated against StenCore by content fingerprint to prevent overlap
|
| 604 |
+
|
| 605 |
+
The pipeline materializes the dataset on rank 0 and distributes it across both GPU processes via a shared disk cache, eliminating duplicated downloads in the distributed setting.
|
| 606 |
+
|
| 607 |
+
### Dataset Scale
|
| 608 |
+
|
| 609 |
+
| Component | Value |
|
| 610 |
+
|---|---|
|
| 611 |
+
| Materialized raw rows | 1,137,414 |
|
| 612 |
+
| Source token budget per epoch | 240,000,000 |
|
| 613 |
+
| Total token budget | 480,000,000 |
|
| 614 |
+
| Actual tokens trained on | 480,116,736 |
|
| 615 |
+
| Source download budget | 3 GB |
|
| 616 |
+
|
| 617 |
+
### Text Preprocessing
|
| 618 |
+
|
| 619 |
+
Each raw text sample undergoes the following cleaning pipeline before tokenization:
|
| 620 |
+
|
| 621 |
+
```python
|
| 622 |
+
def clean_text(text: str) -> str:
|
| 623 |
+
text = unicodedata.normalize("NFKC", text) # normalize unicode
|
| 624 |
+
lines = [line.strip() for line in text.splitlines() if line.strip()]
|
| 625 |
+
text = " ".join(lines) # collapse newlines
|
| 626 |
+
text = " ".join(text.split()) # normalize whitespace
|
| 627 |
+
return text
|
| 628 |
+
```
|
| 629 |
+
|
| 630 |
+
**NFKC normalization** maps visually equivalent Unicode characters to a single canonical form (e.g., full-width `οΌ‘` β `A`, ligature `ο¬` β `fi`). This is the standard approach used in T5, BERT, and most modern LLM preprocessing pipelines.
|
| 631 |
+
|
| 632 |
+
### Tokenization
|
| 633 |
+
|
| 634 |
+
- `add_special_tokens=False` during tokenization
|
| 635 |
+
- EOS token (`</s>`) appended to every sample
|
| 636 |
+
- Attention mask generated (all 1s for real tokens)
|
| 637 |
+
|
| 638 |
+
### Sequence Packing
|
| 639 |
+
|
| 640 |
+
After tokenization, samples are **packed** into fixed 1,024-token blocks:
|
| 641 |
+
|
| 642 |
+
```
|
| 643 |
+
Sample 1: [tok, tok, ..., </s>] (e.g., 347 tokens)
|
| 644 |
+
Sample 2: [tok, tok, ..., </s>] (e.g., 891 tokens)
|
| 645 |
+
β
|
| 646 |
+
Block 1: [<sample1...>, <first 677 tokens of sample2>] (1024 tokens)
|
| 647 |
+
Block 2: [<remaining 214 tokens of sample2>, <sample3...>]
|
| 648 |
+
```
|
| 649 |
+
|
| 650 |
+
Packing eliminates all padding waste and ensures every training token is a real content token. Labels for packed sequences are identical to `input_ids` β there is no special boundary masking between packed samples, which is standard practice.
|
| 651 |
+
|
| 652 |
+
### Data Collation
|
| 653 |
+
|
| 654 |
+
- `input_ids`: padded with `pad_token_id`
|
| 655 |
+
- `labels`: padded with `-100` (ignored in loss computation)
|
| 656 |
+
- `attention_mask`: padded with `0`
|
| 657 |
+
- All batches padded to nearest multiple of 8 for hardware alignment
|
| 658 |
+
|
| 659 |
+
---
|
| 660 |
+
|
| 661 |
+
## Weight Initialization
|
| 662 |
+
|
| 663 |
+
All parameters are initialized using a **truncated normal distribution** with `std=0.02` β the same initialization used in GPT-2 and most modern LLMs:
|
| 664 |
+
|
| 665 |
+
```python
|
| 666 |
+
def initialize_weights(model, std=0.02):
|
| 667 |
+
for module in model.modules():
|
| 668 |
+
if isinstance(module, (nn.Linear, nn.Embedding)):
|
| 669 |
+
module.weight.data.normal_(mean=0.0, std=std)
|
| 670 |
+
if module.bias is not None:
|
| 671 |
+
module.bias.data.zero_()
|
| 672 |
+
elif "rmsnorm" in type(module).__name__.lower():
|
| 673 |
+
if module.weight is not None:
|
| 674 |
+
module.weight.data.fill_(1.0) # scale initialized to 1
|
| 675 |
+
if module.bias is not None:
|
| 676 |
+
module.bias.data.zero_()
|
| 677 |
+
```
|
| 678 |
+
|
| 679 |
+
- Linear layers: normal(0, 0.02)
|
| 680 |
+
- Embeddings: normal(0, 0.02)
|
| 681 |
+
- RMSNorm scale weights: initialized to 1.0 (identity transform at start)
|
| 682 |
+
- All biases: zero
|
| 683 |
+
|
| 684 |
+
---
|
| 685 |
+
|
| 686 |
+
## Evaluation & Results
|
| 687 |
+
|
| 688 |
+
### Metrics
|
| 689 |
+
|
| 690 |
+
- **Validation Loss:** Cross-entropy loss over a held-out validation prefix drawn from the tokenized train set (5,000 samples)
|
| 691 |
+
- **Perplexity (PPL):** `exp(loss)` β lower means the model is less "surprised" by unseen text
|
| 692 |
+
|
| 693 |
+
### Training Loss Progression
|
| 694 |
+
|
| 695 |
+
| Step | Loss (train batch) |
|
| 696 |
+
|---|---|
|
| 697 |
+
| 300 | 4.9760 |
|
| 698 |
+
| 600 | 4.1367 |
|
| 699 |
+
| 900 | 3.4398 |
|
| 700 |
+
| 1200 | 3.6314 |
|
| 701 |
+
| 1500 | 3.3766 |
|
| 702 |
+
| 1800 | 3.3155 |
|
| 703 |
+
| 2100 | 3.2452 |
|
| 704 |
+
| 2400 | 3.3610 |
|
| 705 |
+
| 2700 | 3.2639 |
|
| 706 |
+
| 3000 | 3.3475 |
|
| 707 |
+
| 3300 | 3.0684 |
|
| 708 |
+
| 3600 | 2.9352 |
|
| 709 |
+
|
| 710 |
+
### Evaluation Results
|
| 711 |
+
|
| 712 |
+
| Checkpoint | Step | Eval Loss | Perplexity |
|
| 713 |
+
|---|---|---|---|
|
| 714 |
+
| End of Epoch 0 | ~2,400 | 3.3776 | 29.30 |
|
| 715 |
+
| Best Checkpoint | 3,300 | 3.2814 | ~26.62 |
|
| 716 |
+
| **Final Model** | **~3,600** | **3.2565** | **25.96** |
|
| 717 |
+
|
| 718 |
+
### Comparison to Previous Stentor Models
|
| 719 |
+
|
| 720 |
+
| Model | Final Eval Loss | Final Perplexity | vs v1 |
|
| 721 |
+
|---|---|---|---|
|
| 722 |
+
| Stentor-12M (v1) | 4.4887 | 89.01 | β |
|
| 723 |
+
| Stentor2-12M-Preview | ~3.91 | ~50.07 | β43.8% |
|
| 724 |
+
| **Stentor2-12M** | **3.2565** | **25.96** | **β70.8%** |
|
| 725 |
+
|
| 726 |
+
> **Comparison note:** These three models were trained on different datasets and with different configurations. The comparison is meaningful directionally but is not a rigorously controlled ablation. Stentor v1 used FineWeb-Edu + Cosmopedia; Stentor2-Preview used FineWeb-Edu only; Stentor2-12M used StenCore + FineWeb-HQ.
|
| 727 |
+
|
| 728 |
+
---
|
| 729 |
+
|
| 730 |
+
## BLiMP Benchmark
|
| 731 |
+
|
| 732 |
+
BLiMP (Benchmark of Linguistic Minimal Pairs) evaluates a language model's grammatical knowledge by presenting pairs of sentences β one grammatical and one ungrammatical β and measuring how often the model assigns higher probability to the grammatical sentence. Random chance is 50%.
|
| 733 |
+
|
| 734 |
+
**Overall BLiMP Average (67 tasks): 68.95%**
|
| 735 |
+
**Random Baseline: 50.00%**
|
| 736 |
+
**Above Chance: +18.95 percentage points**
|
| 737 |
+
|
| 738 |
+
### Full BLiMP Results
|
| 739 |
+
|
| 740 |
+
| Task | Accuracy |
|
| 741 |
+
|---|---|
|
| 742 |
+
| **Overall Average** | **68.95%** |
|
| 743 |
+
| blimp_adjunct_island | 72.00% |
|
| 744 |
+
| blimp_anaphor_gender_agreement | 65.70% |
|
| 745 |
+
| blimp_anaphor_number_agreement | 95.70% |
|
| 746 |
+
| blimp_animate_subject_passive | 68.70% |
|
| 747 |
+
| blimp_animate_subject_trans | 82.80% |
|
| 748 |
+
| blimp_causative | 60.80% |
|
| 749 |
+
| blimp_complex_NP_island | 41.00% |
|
| 750 |
+
| blimp_coordinate_structure_constraint_complex_left_branch | 40.20% |
|
| 751 |
+
| blimp_coordinate_structure_constraint_object_extraction | 75.00% |
|
| 752 |
+
| blimp_determiner_noun_agreement_1 | 97.40% |
|
| 753 |
+
| blimp_determiner_noun_agreement_2 | 92.50% |
|
| 754 |
+
| blimp_determiner_noun_agreement_irregular_1 | 75.50% |
|
| 755 |
+
| blimp_determiner_noun_agreement_irregular_2 | 90.00% |
|
| 756 |
+
| blimp_determiner_noun_agreement_with_adj_2 | 85.40% |
|
| 757 |
+
| blimp_determiner_noun_agreement_with_adj_irregular_1 | 78.60% |
|
| 758 |
+
| blimp_determiner_noun_agreement_with_adj_irregular_2 | 81.40% |
|
| 759 |
+
| blimp_determiner_noun_agreement_with_adjective_1 | 89.60% |
|
| 760 |
+
| blimp_distractor_agreement_relational_noun | 70.90% |
|
| 761 |
+
| blimp_distractor_agreement_relative_clause | 42.50% |
|
| 762 |
+
| blimp_drop_argument | 70.20% |
|
| 763 |
+
| blimp_ellipsis_n_bar_1 | 67.30% |
|
| 764 |
+
| blimp_ellipsis_n_bar_2 | 79.70% |
|
| 765 |
+
| blimp_existential_there_object_raising | 79.70% |
|
| 766 |
+
| blimp_existential_there_quantifiers_1 | 95.80% |
|
| 767 |
+
| blimp_existential_there_quantifiers_2 | 29.60% |
|
| 768 |
+
| blimp_existential_there_subject_raising | 72.80% |
|
| 769 |
+
| blimp_expletive_it_object_raising | 73.30% |
|
| 770 |
+
| blimp_inchoative | 49.50% |
|
| 771 |
+
| blimp_intransitive | 60.60% |
|
| 772 |
+
| blimp_irregular_past_participle_adjectives | 99.70% |
|
| 773 |
+
| blimp_irregular_past_participle_verbs | 78.50% |
|
| 774 |
+
| blimp_irregular_plural_subject_verb_agreement_1 | 77.40% |
|
| 775 |
+
| blimp_irregular_plural_subject_verb_agreement_2 | 87.40% |
|
| 776 |
+
| blimp_left_branch_island_echo_question | 40.00% |
|
| 777 |
+
| blimp_left_branch_island_simple_question | 38.80% |
|
| 778 |
+
| blimp_matrix_question_npi_licensor_present | 16.30% |
|
| 779 |
+
| blimp_npi_present_1 | 65.50% |
|
| 780 |
+
| blimp_npi_present_2 | 63.80% |
|
| 781 |
+
| blimp_only_npi_licensor_present | 52.90% |
|
| 782 |
+
| blimp_only_npi_scope | 41.60% |
|
| 783 |
+
| blimp_passive_1 | 86.10% |
|
| 784 |
+
| blimp_passive_2 | 85.80% |
|
| 785 |
+
| blimp_principle_A_c_command | 65.60% |
|
| 786 |
+
| blimp_principle_A_case_1 | 100.00% |
|
| 787 |
+
| blimp_principle_A_case_2 | 85.90% |
|
| 788 |
+
| blimp_principle_A_domain_1 | 88.90% |
|
| 789 |
+
| blimp_principle_A_domain_2 | 64.10% |
|
| 790 |
+
| blimp_principle_A_domain_3 | 50.50% |
|
| 791 |
+
| blimp_principle_A_reconstruction | 40.20% |
|
| 792 |
+
| blimp_regular_plural_subject_verb_agreement_1 | 87.30% |
|
| 793 |
+
| blimp_regular_plural_subject_verb_agreement_2 | 79.70% |
|
| 794 |
+
| blimp_sentential_negation_npi_licensor_present | 99.20% |
|
| 795 |
+
| blimp_sentential_negation_npi_scope | 46.40% |
|
| 796 |
+
| blimp_sentential_subject_island | 39.30% |
|
| 797 |
+
| blimp_superlative_quantifiers_1 | 48.00% |
|
| 798 |
+
| blimp_superlative_quantifiers_2 | 75.60% |
|
| 799 |
+
| blimp_tough_vs_raising_1 | 34.00% |
|
| 800 |
+
| blimp_tough_vs_raising_2 | 83.10% |
|
| 801 |
+
| blimp_transitive | 76.80% |
|
| 802 |
+
| blimp_wh_island | 63.40% |
|
| 803 |
+
| blimp_wh_questions_object_gap | 59.10% |
|
| 804 |
+
| blimp_wh_questions_subject_gap | 87.60% |
|
| 805 |
+
| blimp_wh_questions_subject_gap_long_distance | 92.40% |
|
| 806 |
+
| blimp_wh_vs_that_no_gap | 92.10% |
|
| 807 |
+
| blimp_wh_vs_that_no_gap_long_distance | 97.50% |
|
| 808 |
+
| blimp_wh_vs_that_with_gap | 33.80% |
|
| 809 |
+
| blimp_wh_vs_that_with_gap_long_distance | 11.00% |
|
| 810 |
+
|
| 811 |
+
### BLiMP Interpretation
|
| 812 |
+
|
| 813 |
+
**Strong performance (>85%):** Determiner-noun agreement, passive constructions, anaphor number agreement, irregular past participles, existential quantifiers, sentential negation licensing, wh-movement without gaps, Principle A case conditions. These tasks test local agreement and well-practiced syntactic patterns β areas where token-level statistics are strong predictors.
|
| 814 |
+
|
| 815 |
+
**Moderate performance (60β85%):** Most agreement tasks, animate subject constructions, ellipsis, raising constructions, WH questions with subject gaps. The model has learned these patterns but applies them inconsistently across surface variations.
|
| 816 |
+
|
| 817 |
+
**Below-chance or near-chance performance (<50%):** NPI licensing (particularly `matrix_question_npi_licensor_present` at 16.3%, `wh_vs_that_with_gap_long_distance` at 11%), island constraints, some scope tasks. These require tracking long-distance syntactic dependencies or operator scope β phenomena that demand more representational capacity than 12M parameters can reliably support at 1,024-token context.
|
| 818 |
+
|
| 819 |
+
**Key takeaway:** At 68.95% vs 50% random, this model demonstrates genuine grammatical knowledge well above chance at only 12.3M parameters. The profile of strengths (local agreement) and weaknesses (long-distance dependencies, operator scope) is consistent with what scaling laws predict for a model of this size.
|
| 820 |
+
|
| 821 |
+
---
|
| 822 |
+
|
| 823 |
+
## Training Dynamics
|
| 824 |
+
|
| 825 |
+
The training run proceeded for 2 epochs, stopping when the 480M token budget was reached at ~step 3,600 of a theoretical 9,552-step schedule.
|
| 826 |
+
|
| 827 |
+
**Epoch 0 (steps 0β~2,400, 3,497 seconds):** Loss dropped rapidly from ~8+ initially, stabilizing around 3.2β3.6 by step 2,100. The first best checkpoint was recorded at step 1,500 (eval loss 3.5410), with a better checkpoint at step 2,400 (eval loss 3.3743) marking the end of epoch 0.
|
| 828 |
+
|
| 829 |
+
**Epoch 1 (steps ~2,400β3,600, 1,906 seconds):** Training continued with a fresh data pass. The best checkpoint was achieved at step 3,300 (eval loss 3.2814). Notably, the final epoch evaluation after the token budget was reached produced 3.2565 (ppl 25.96) β slightly better than the best saved checkpoint eval, consistent with the cosine schedule still having meaningful learning rate at that point.
|
| 830 |
+
|
| 831 |
+
**Throughput:** ~91,500β92,000 tokens/second average across both GPUs throughout training β a substantial improvement from the single-process ~91,600 tps of the Preview, now representing genuine dual-GPU utilization.
|
| 832 |
+
|
| 833 |
+
---
|
| 834 |
+
|
| 835 |
+
## Use Cases & Intended Uses
|
| 836 |
+
|
| 837 |
+
> π¬ **Reminder:** This is a **research artifact**. It is a base language model with no safety tuning, no instruction following, and no factual grounding.
|
| 838 |
+
|
| 839 |
+
### Intended Uses
|
| 840 |
+
|
| 841 |
+
| Use Case | Suitability | Notes |
|
| 842 |
+
|---|---|---|
|
| 843 |
+
| Studying transformer training dynamics | β
High | Small enough to train/fine-tune on free compute |
|
| 844 |
+
| Tokenization efficiency research | β
High | 8K vs 32K vocab tradeoff is directly observable |
|
| 845 |
+
| GQA vs MHA ablation research | β
High | Contrast directly with Stentor2-Preview |
|
| 846 |
+
| Speculative decoding experiments | β
High | Fast enough to serve as a draft model |
|
| 847 |
+
| Benchmarking CPU/edge inference latency | β
High | ~25 MB in FP16, runs on any hardware |
|
| 848 |
+
| Testing quantization/conversion pipelines | β
High | GGUF, ONNX, INT8 pipeline validation |
|
| 849 |
+
| Teaching material for LLM courses | β
High | Architecture is simple enough to trace by hand |
|
| 850 |
+
| LoRA / QLoRA fine-tuning experiments | β
Moderate | Base model only; start from scratch for any task |
|
| 851 |
+
| Text continuation / creative prompting | β
Moderate | Works best on short completions β€60 tokens |
|
| 852 |
+
| Domain-specific fine-tuning research | β
Moderate | Small enough to iterate rapidly |
|
| 853 |
+
| Factual Q&A | β Not suitable | Model has no reliable world knowledge |
|
| 854 |
+
| Production deployment | β Not suitable | No safety tuning; base model only |
|
| 855 |
+
| Non-English text | β Not suitable | TokenMonster vocab is English-only |
|
| 856 |
+
| Long coherent outputs (>60 tokens) | β Not suitable | Coherence degrades quickly at this scale |
|
| 857 |
+
|
| 858 |
+
---
|
| 859 |
+
|
| 860 |
+
## Out-of-Scope Uses
|
| 861 |
+
|
| 862 |
+
- **User-facing applications of any kind** β This model has no safety filtering, no alignment, and no factual reliability.
|
| 863 |
+
- **Medical, legal, or financial advice** β 12M parameters cannot store or reason over specialized knowledge reliably.
|
| 864 |
+
- **Generating content about real people** β The model has no awareness of real people. Outputs mentioning real people are likely fabricated.
|
| 865 |
+
- **Automated content pipelines** β Do not use this model to generate content at scale without human review.
|
| 866 |
+
- **Non-English use** β The 8,064-token TokenMonster vocabulary is built exclusively for English.
|
| 867 |
+
- **Instruction following** β This is a base model. It does not reliably follow instructions, answer questions, or complete structured tasks.
|
| 868 |
+
|
| 869 |
+
---
|
| 870 |
+
|
| 871 |
+
## Ethical Considerations & Societal Impact
|
| 872 |
+
|
| 873 |
+
### Inherited Data Biases
|
| 874 |
+
|
| 875 |
+
Stentor2-12M was trained on StenCore and FineWeb-HQ. Despite quality filtering, this data inherits biases present in English-language web text:
|
| 876 |
+
|
| 877 |
+
- **Western-centric perspective** β Educational content on the web skews heavily toward Western viewpoints and examples
|
| 878 |
+
- **English monolingualism** β The training data and vocabulary are both English-only
|
| 879 |
+
- **Demographic underrepresentation** β Groups underrepresented in English-language web text will be underrepresented in outputs
|
| 880 |
+
- **Temporal cutoff** β The model has no knowledge of events after the data collection cutoff
|
| 881 |
+
|
| 882 |
+
### No Safety Tuning
|
| 883 |
+
|
| 884 |
+
This model has received **no safety training of any kind**. It is a raw base model that predicts the next token based on statistical patterns. It should not be used in any context where harmful outputs would cause real-world harm.
|
| 885 |
+
|
| 886 |
+
### Positive Societal Aspects
|
| 887 |
+
|
| 888 |
+
- **Democratizing AI research** β Trained entirely on free-tier Kaggle compute, this model demonstrates that meaningful LLM research does not require significant financial resources.
|
| 889 |
+
- **Transparency** β Full training hyperparameters, architecture details, training script, and benchmark results are published. This is a contribution to reproducible ML research.
|
| 890 |
+
- **Minimal environmental footprint** β ~2.13 hours of dual-GPU compute. Estimated carbon footprint well under 0.5 kg COβe.
|
| 891 |
+
|
| 892 |
+
---
|
| 893 |
+
|
| 894 |
+
## Inference Guide
|
| 895 |
+
|
| 896 |
+
### Basic Generation
|
| 897 |
+
|
| 898 |
+
```python
|
| 899 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 900 |
+
import torch
|
| 901 |
+
|
| 902 |
+
model = AutoModelForCausalLM.from_pretrained("StentorLabs/Stentor2-12M", torch_dtype=torch.float16, device_map="auto")
|
| 903 |
+
tokenizer = AutoTokenizer.from_pretrained("StentorLabs/Stentor2-12M", trust_remote_code=True)
|
| 904 |
+
|
| 905 |
+
device = next(model.parameters()).device
|
| 906 |
+
|
| 907 |
+
def generate(prompt, max_new_tokens=50, temperature=0.9, top_p=0.65):
|
| 908 |
+
input_ids = torch.tensor([tokenizer.encode(prompt)], dtype=torch.long).to(device)
|
| 909 |
+
attention_mask = torch.ones_like(input_ids)
|
| 910 |
+
with torch.inference_mode():
|
| 911 |
+
output = model.generate(
|
| 912 |
+
input_ids,
|
| 913 |
+
attention_mask=attention_mask,
|
| 914 |
+
max_new_tokens=max_new_tokens,
|
| 915 |
+
do_sample=True,
|
| 916 |
+
temperature=temperature,
|
| 917 |
+
top_p=top_p,
|
| 918 |
+
repetition_penalty=1.15,
|
| 919 |
+
pad_token_id=tokenizer.pad_token_id,
|
| 920 |
+
)
|
| 921 |
+
new_ids = output[0][input_ids.shape[1]:].tolist()
|
| 922 |
+
return tokenizer.decode(new_ids).strip()
|
| 923 |
+
|
| 924 |
+
print(generate("The history of computing began"))
|
| 925 |
+
```
|
| 926 |
+
|
| 927 |
+
### CPU (FP32)
|
| 928 |
+
|
| 929 |
+
```python
|
| 930 |
+
model = AutoModelForCausalLM.from_pretrained("StentorLabs/Stentor2-12M", torch_dtype=torch.float32)
|
| 931 |
+
model = model.to("cpu")
|
| 932 |
+
```
|
| 933 |
+
|
| 934 |
+
### GPU (FP16)
|
| 935 |
+
|
| 936 |
+
```python
|
| 937 |
+
model = AutoModelForCausalLM.from_pretrained("StentorLabs/Stentor2-12M", torch_dtype=torch.float16, device_map="auto")
|
| 938 |
+
```
|
| 939 |
+
|
| 940 |
+
### From a Local Checkpoint
|
| 941 |
+
|
| 942 |
+
```python
|
| 943 |
+
model = AutoModelForCausalLM.from_pretrained("./path/to/local/checkpoint")
|
| 944 |
+
tokenizer = AutoTokenizer.from_pretrained("./path/to/local/checkpoint", trust_remote_code=True)
|
| 945 |
+
```
|
| 946 |
+
|
| 947 |
+
---
|
| 948 |
+
|
| 949 |
+
## Real Model Responses
|
| 950 |
+
|
| 951 |
+
*[Placeholder β generation examples coming soon]*
|
| 952 |
+
|
| 953 |
+
---
|
| 954 |
+
|
| 955 |
+
## Quantization
|
| 956 |
+
|
| 957 |
+
### FP16 β Recommended First Step
|
| 958 |
+
|
| 959 |
+
```python
|
| 960 |
+
model = AutoModelForCausalLM.from_pretrained("StentorLabs/Stentor2-12M", torch_dtype=torch.float16)
|
| 961 |
+
model = model.to("cuda")
|
| 962 |
+
```
|
| 963 |
+
|
| 964 |
+
### Dynamic INT8 Quantization (CPU, PyTorch native)
|
| 965 |
+
|
| 966 |
+
```python
|
| 967 |
+
import torch
|
| 968 |
+
from transformers import AutoModelForCausalLM
|
| 969 |
+
|
| 970 |
+
model = AutoModelForCausalLM.from_pretrained("StentorLabs/Stentor2-12M", torch_dtype=torch.float32)
|
| 971 |
+
model = model.to("cpu").eval()
|
| 972 |
+
|
| 973 |
+
model_int8 = torch.quantization.quantize_dynamic(
|
| 974 |
+
model,
|
| 975 |
+
{torch.nn.Linear},
|
| 976 |
+
dtype=torch.qint8,
|
| 977 |
+
)
|
| 978 |
+
# Approximate memory: ~12 MB β 75% reduction from FP32
|
| 979 |
+
```
|
| 980 |
+
|
| 981 |
+
### bitsandbytes INT8 (GPU)
|
| 982 |
+
|
| 983 |
+
```python
|
| 984 |
+
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
|
| 985 |
+
import torch
|
| 986 |
+
|
| 987 |
+
bnb_config = BitsAndBytesConfig(load_in_8bit=True)
|
| 988 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 989 |
+
"StentorLabs/Stentor2-12M",
|
| 990 |
+
quantization_config=bnb_config,
|
| 991 |
+
device_map="auto"
|
| 992 |
+
)
|
| 993 |
+
```
|
| 994 |
+
|
| 995 |
+
---
|
| 996 |
+
|
| 997 |
+
## Format Conversion
|
| 998 |
+
|
| 999 |
+
### Convert to GGUF (for llama.cpp)
|
| 1000 |
+
|
| 1001 |
+
```bash
|
| 1002 |
+
git clone https://github.com/ggerganov/llama.cpp
|
| 1003 |
+
cd llama.cpp
|
| 1004 |
+
pip install -r requirements.txt
|
| 1005 |
+
|
| 1006 |
+
huggingface-cli download StentorLabs/Stentor2-12M --local-dir stentor2-12m
|
| 1007 |
+
|
| 1008 |
+
python convert_hf_to_gguf.py stentor2-12m/ \
|
| 1009 |
+
--outfile stentor2-12m.gguf \
|
| 1010 |
+
--outtype f16
|
| 1011 |
+
|
| 1012 |
+
./llama-quantize stentor2-12m.gguf stentor2-12m-q4_0.gguf q4_0
|
| 1013 |
+
./llama-cli -m stentor2-12m-q4_0.gguf -p "The science of" -n 50
|
| 1014 |
+
```
|
| 1015 |
+
|
| 1016 |
+
> **Note on GGUF + TokenMonster:** The custom TokenMonster tokenizer may require manual vocabulary mapping when using llama.cpp. The standard `convert_hf_to_gguf.py` script expects a HuggingFace tokenizer format and may need adjustment for the TokenMonster vocabulary.
|
| 1017 |
+
|
| 1018 |
+
### Convert to ONNX
|
| 1019 |
+
|
| 1020 |
+
```bash
|
| 1021 |
+
pip install optimum[exporters]
|
| 1022 |
+
|
| 1023 |
+
optimum-cli export onnx \
|
| 1024 |
+
--model StentorLabs/Stentor2-12M \
|
| 1025 |
+
--task text-generation-with-past \
|
| 1026 |
+
stentor2-12m-onnx/
|
| 1027 |
+
```
|
| 1028 |
+
|
| 1029 |
+
---
|
| 1030 |
+
|
| 1031 |
+
## Speculative Decoding
|
| 1032 |
+
|
| 1033 |
+
Stentor2-12M can serve as a fast **draft model** to accelerate inference from larger Llama-family target models.
|
| 1034 |
+
|
| 1035 |
+
```python
|
| 1036 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 1037 |
+
import torch
|
| 1038 |
+
|
| 1039 |
+
draft_model = AutoModelForCausalLM.from_pretrained(
|
| 1040 |
+
"StentorLabs/Stentor2-12M",
|
| 1041 |
+
torch_dtype=torch.float16,
|
| 1042 |
+
device_map="auto"
|
| 1043 |
+
)
|
| 1044 |
+
|
| 1045 |
+
target_model = AutoModelForCausalLM.from_pretrained(
|
| 1046 |
+
"meta-llama/Llama-3.2-1B",
|
| 1047 |
+
torch_dtype=torch.float16,
|
| 1048 |
+
device_map="auto"
|
| 1049 |
+
)
|
| 1050 |
+
target_tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.2-1B")
|
| 1051 |
+
|
| 1052 |
+
prompt = "Explain the concept of recursion"
|
| 1053 |
+
inputs = target_tokenizer(prompt, return_tensors="pt")
|
| 1054 |
+
|
| 1055 |
+
outputs = target_model.generate(
|
| 1056 |
+
**inputs,
|
| 1057 |
+
assistant_model=draft_model,
|
| 1058 |
+
do_sample=True,
|
| 1059 |
+
max_new_tokens=100
|
| 1060 |
+
)
|
| 1061 |
+
print(target_tokenizer.decode(outputs[0], skip_special_tokens=True))
|
| 1062 |
+
```
|
| 1063 |
+
|
| 1064 |
+
**Important caveat:** Stentor2 uses a different vocabulary (8,064-token TokenMonster) than standard Llama models (32,000-token BPE). This vocabulary mismatch means the target model's token acceptance rate may be lower than it would be with a vocabulary-compatible draft model. Speedups depend heavily on the similarity of the generated distribution between draft and target.
|
| 1065 |
+
|
| 1066 |
+
---
|
| 1067 |
+
|
| 1068 |
+
## Bias, Risks & Limitations
|
| 1069 |
+
|
| 1070 |
+
- **Prompt Relevance:** Outputs are frequently off-topic for complex prompts. The model is pattern-completing, not comprehending.
|
| 1071 |
+
- **Factual Accuracy:** All factual claims should be treated as unreliable. 12M parameters cannot store meaningful world knowledge.
|
| 1072 |
+
- **Context Boundary:** Hard limit of 1,024 tokens.
|
| 1073 |
+
- **Short Output Window for Coherence:** Even within the context limit, coherence degrades beyond ~60 tokens. `max_new_tokens` at 60 or below is strongly recommended.
|
| 1074 |
+
- **English Bias:** TokenMonster English vocabulary β other languages will produce poor output.
|
| 1075 |
+
- **Training Data Bias:** Inherits biases present in English-language web data.
|
| 1076 |
+
- **Hallucination:** Like all LLMs, this model may confidently produce plausible-sounding but entirely fabricated content.
|
| 1077 |
+
- **No Alignment:** No RLHF, no DPO, no constitutional training.
|
| 1078 |
+
- **Tokenizer Efficiency:** The 8K TokenMonster vocabulary produces more tokens per word than standard 32K BPE vocabularies. This is expected and is the direct architectural tradeoff for the perplexity improvement.
|
| 1079 |
+
- **Shared Tensor Warning:** `Removed shared tensor {'lm_head.weight'} while saving` is expected from tied word embeddings. Safe to ignore.
|
| 1080 |
+
|
| 1081 |
+
---
|
| 1082 |
+
|
| 1083 |
+
## Related Work
|
| 1084 |
+
|
| 1085 |
+
### Comparable Sub-50M Models
|
| 1086 |
+
|
| 1087 |
+
| Model | Parameters | Perplexity | Vocab | Notes |
|
| 1088 |
+
|---|---|---|---|---|
|
| 1089 |
+
| **Stentor2-12M** (this model) | 12.3M | 25.96 | 8,064 | Full MHA, StenCore+FineWeb-HQ, dual-GPU |
|
| 1090 |
+
| Stentor2-12M-Preview | 12.3M | ~50.07 | 8,064 | Single-process, FineWeb-Edu only |
|
| 1091 |
+
| Stentor-12M (v1) | 12.0M | 89.01 | 32,768 | Mistral BPE, FineWeb-Edu+Cosmopedia |
|
| 1092 |
+
| Stentor-30M (v1) | 30.4M | 33.02 | 32,768 | Larger v1 model |
|
| 1093 |
+
| Pythia-14M | 14M | varies (Pile) | 50,254 | EleutherAI; well-studied scaling baseline |
|
| 1094 |
+
| TinyStories-33M | ~33M | varies | ~50K | Synthetic story data; Eldan & Li, 2023 |
|
| 1095 |
+
|
| 1096 |
+
> **Comparison caveats:** Perplexity numbers are not directly comparable across models β different validation sets, vocabularies, tokenizers, and training data all affect the number. The table is a rough orientation, not a rigorous benchmark.
|
| 1097 |
+
|
| 1098 |
+
### Related Research Papers
|
| 1099 |
+
|
| 1100 |
+
| Paper | Relevance |
|
| 1101 |
+
|---|---|
|
| 1102 |
+
| [TinyStories](https://arxiv.org/abs/2305.07759) β Eldan & Li, 2023 | Demonstrates meaningful language generation from sub-33M models |
|
| 1103 |
+
| [Pythia](https://arxiv.org/abs/2304.01373) β Biderman et al., 2023 | Systematic study of small model scaling |
|
| 1104 |
+
| [Scaling Laws](https://arxiv.org/abs/2001.08361) β Kaplan et al., 2020 | Foundational work on compute-optimal training |
|
| 1105 |
+
| [Chinchilla](https://arxiv.org/abs/2203.15556) β Hoffmann et al., 2022 | Revised scaling laws; informs token budget decisions |
|
| 1106 |
+
| [GQA](https://arxiv.org/abs/2305.13245) β Ainslie et al., 2023 | Grouped Query Attention β and why it doesn't help here |
|
| 1107 |
+
| [RoPE](https://arxiv.org/abs/2104.09864) β Su et al., 2021 | Positional encoding used in this model |
|
| 1108 |
+
| [Speculative Decoding](https://arxiv.org/abs/2211.17192) β Leviathan et al., 2023 | Primary deployment use case for this model |
|
| 1109 |
+
| [Model Cards](https://arxiv.org/abs/1810.03993) β Mitchell et al., 2018 | Methodology underlying this model card |
|
| 1110 |
+
| [T5](https://arxiv.org/abs/1910.10683) β Raffel et al., 2020 | Source of NFKC text normalization approach |
|
| 1111 |
+
|
| 1112 |
+
### StentorLabs Models
|
| 1113 |
+
|
| 1114 |
+
- [Stentor-30M](https://huggingface.co/StentorLabs/Stentor-30M) β Larger v1 base model
|
| 1115 |
+
- [Stentor-12M](https://huggingface.co/StentorLabs/Stentor-12M) β v1 baseline this model improves upon
|
| 1116 |
+
- [Stentor-30M-Instruct](https://huggingface.co/StentorLabs/Stentor-30M-Instruct) β Instruction-tuned v1
|
| 1117 |
+
- [Stentor-12M-Instruct](https://huggingface.co/StentorLabs/Stentor-12M-Instruct) β Instruction-tuned v1
|
| 1118 |
+
- [Stentor2-12M-Preview](https://huggingface.co/StentorLabs/Stentor2-12M-Preview) β Preview checkpoint preceding this release
|
| 1119 |
+
- [StentorLabs Collection](https://huggingface.co/StentorLabs) β All models from StentorLabs
|
| 1120 |
+
|
| 1121 |
+
### Referenced Tools & Datasets
|
| 1122 |
+
|
| 1123 |
+
- [StenCore](https://huggingface.co/datasets/StentorLabs/StenCore) β Primary training data
|
| 1124 |
+
- [FineWeb-HQ](https://huggingface.co/datasets/epfml/FineWeb-HQ) β Secondary training data
|
| 1125 |
+
- [TokenMonster](https://huggingface.co/alasdairforsythe/tokenmonster) β Tokenizer vocabulary
|
| 1126 |
+
- [HuggingFace Accelerate](https://github.com/huggingface/accelerate) β Training framework
|
| 1127 |
+
- [bitsandbytes](https://github.com/TimDettmers/bitsandbytes) β Quantization library
|
| 1128 |
+
|
| 1129 |
+
---
|
| 1130 |
+
|
| 1131 |
+
## Environmental Impact
|
| 1132 |
+
|
| 1133 |
+
| Factor | Value |
|
| 1134 |
+
|---|---|
|
| 1135 |
+
| Hardware | 2Γ NVIDIA Tesla T4 (both active) |
|
| 1136 |
+
| Active Training Duration | ~2.13 hours |
|
| 1137 |
+
| Cloud Provider | Kaggle (free tier) |
|
| 1138 |
+
| Compute Region | Western USA |
|
| 1139 |
+
| Estimated Carbon | Minimal (< 0.5 kg COβe estimated) |
|
| 1140 |
+
|
| 1141 |
+
Training on free-tier cloud compute demonstrates that meaningful SLM research is accessible to independent researchers and students without significant hardware investment or carbon cost.
|
| 1142 |
+
|
| 1143 |
+
---
|
| 1144 |
+
|
| 1145 |
+
## Citation
|
| 1146 |
+
|
| 1147 |
+
```bibtex
|
| 1148 |
+
@misc{izumoto2026stentor2_12m,
|
| 1149 |
+
title = {Stentor2-12M},
|
| 1150 |
+
author = {Kai Izumoto},
|
| 1151 |
+
year = {2026},
|
| 1152 |
+
publisher = {StentorLabs},
|
| 1153 |
+
howpublished = {\url{https://huggingface.co/StentorLabs/Stentor2-12M}},
|
| 1154 |
+
note = {Official release of the Stentor2 model family.
|
| 1155 |
+
12.3M parameter LlamaForCausalLM base model trained on
|
| 1156 |
+
StenCore and FineWeb-HQ with a TokenMonster 8K vocabulary.
|
| 1157 |
+
Dual-GPU distributed training on 2x NVIDIA T4.
|
| 1158 |
+
Apache 2.0 license.}
|
| 1159 |
+
}
|
| 1160 |
+
```
|
| 1161 |
+
|
| 1162 |
+
---
|
| 1163 |
+
|
| 1164 |
+
## Model Card Contact
|
| 1165 |
+
|
| 1166 |
+
Questions, benchmarks, or feedback: [StentorLabs@gmail.com](mailto:StentorLabs@gmail.com) or open a [discussion](https://huggingface.co/StentorLabs/Stentor2-12M/discussions).
|
| 1167 |
+
|
| 1168 |
+
---
|
| 1169 |
+
|
| 1170 |
+
<p align="center">
|
| 1171 |
+
Made with β€οΈ by <a href="https://huggingface.co/StentorLabs">StentorLabs</a><br>
|
| 1172 |
+
<i>Democratizing AI through accessible, efficient models</i>
|
| 1173 |
+
</p>
|