Text Generation
Transformers
Safetensors
English
pragya_e2
small-language-model
from-scratch
causal-lm
decoder-only
gqa
rope
swiglu
exclusive-gated-attention
engram
kv-cache
custom_code
Instructions to use RuVI-AI/Pragya-EXP2 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use RuVI-AI/Pragya-EXP2 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="RuVI-AI/Pragya-EXP2", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("RuVI-AI/Pragya-EXP2", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use RuVI-AI/Pragya-EXP2 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "RuVI-AI/Pragya-EXP2" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "RuVI-AI/Pragya-EXP2", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/RuVI-AI/Pragya-EXP2
- SGLang
How to use RuVI-AI/Pragya-EXP2 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 "RuVI-AI/Pragya-EXP2" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "RuVI-AI/Pragya-EXP2", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'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 "RuVI-AI/Pragya-EXP2" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "RuVI-AI/Pragya-EXP2", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use RuVI-AI/Pragya-EXP2 with Docker Model Runner:
docker model run hf.co/RuVI-AI/Pragya-EXP2
File size: 8,986 Bytes
16eabf2 f766633 16eabf2 f766633 b031c2b 16eabf2 f766633 16eabf2 f766633 16eabf2 f766633 16eabf2 f766633 16eabf2 f766633 16eabf2 f766633 16eabf2 f766633 16eabf2 f766633 16eabf2 f766633 16eabf2 f766633 16eabf2 f766633 16eabf2 f766633 16eabf2 f766633 16eabf2 171c635 b3399ce f766633 b3399ce fa0f177 16eabf2 f766633 16eabf2 171c635 f766633 171c635 f766633 171c635 f766633 171c635 f766633 171c635 16eabf2 f766633 ea2ef4c f766633 16eabf2 ea2ef4c 16eabf2 ea2ef4c 16eabf2 dc34176 ea2ef4c 16eabf2 ce87a82 16eabf2 f766633 ea2ef4c f766633 ea2ef4c f766633 ea2ef4c f766633 ea2ef4c f766633 16eabf2 f766633 16eabf2 ea2ef4c dc34176 ea2ef4c ce87a82 16eabf2 f766633 ea2ef4c f766633 16eabf2 f766633 16eabf2 f766633 16eabf2 f16d7de 16eabf2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | ---
license: apache-2.0
language:
- en
pipeline_tag: text-generation
library_name: transformers
tags:
- text-generation
- small-language-model
- from-scratch
- causal-lm
- decoder-only
- gqa
- rope
- swiglu
- exclusive-gated-attention
- engram
- kv-cache
---
<div align="center">
# Pragya · exp2
### A 28.5M-parameter decoder-only language model, trained from scratch. For testing, not for production.
[](.)
[](.)
[](.)
[](.)
[](.)
[](.)
[](.)
[](.)
</div>
> ### ⚠️ Not a product
> This is a scratch checkpoint. It is not aligned, factually reliable, or safe. It exists to test a from-scratch training and architecture stack and to measure controlled changes between runs.
> A massive issue is found that eos token is not working, prob is 0 so model just fills full context
---
## Summary
| | |
|:---|:---|
| **Architecture** | `PragyaX1DecoderOnly` |
| Total parameters | 28.5M |
| Backbone (excluding embeddings and Engram tables) | 21.25M |
| Embeddings (tied input and LM head) | 4.72M |
| Engram lookup tables | 2.53M |
| Context | 1024 tokens |
| Vocabulary | 12,288 byte-level BPE |
| Validation perplexity | 13.6 |
| Validation accuracy | 47.1% |
| Intelligence Index | 12.41 |
Validation accuracy is lower than test3's 49.7% because this run's evaluation data is harder, so the two checkpoints' numbers are not directly comparable.
---
## Model card
| | |
|:---|:---|
| **Architecture** | `PragyaX1DecoderOnly` (decoder-only transformer) |
| **Layers** | 16 |
| **Hidden size** | 384 |
| **Attention heads** | 12 query, 6 key/value (GQA) |
| **Head dimension** | 32 |
| **Attention** | Exclusive Gated Attention (per-head sigmoid gate + XSA) |
| **FFN** | SwiGLU, hidden size 768 (`ffn_mult = 2`) |
| **Positional encoding** | RoPE, base 10,000 |
| **Engram memory** | Layers 1 and 8, 3-gram lookup over 9,807 classes |
| **Mixture of Experts** | Off |
| **Multi-token prediction** | Off |
| **Embeddings** | Tied (input embedding = LM head) |
| **Context length** | 1024 tokens |
| **Decoding** | KV cache (see below) |
| **Vocabulary** | 12,288 byte-level BPE (`pragya.tokenizer.json`) |
---
## Architecture
### Exclusive Gated Attention
Each attention block applies two per-head operations to the attention output, before the output projection. Both start as identity, so the model begins as plain causal attention.
**Gated attention.** A per-head gate is computed from the first 16 hidden dimensions of the block input:
```
gate = 2 · sigmoid(W_gate · x[:16])
context = context · gate
```
With `W_gate = 0`, the gate is exactly 1, so the output passes through unchanged at step 0.
**Exclusive self-attention (XSA).** The component of the context that points along the token's own value vector is removed:
```
v_unit = v / ‖v‖
correction = gate · (context · v_unit) · v_unit
context = context − correction
```
The correction is zeroed at position 0, where causal attention can only see the token itself.
### Engram memory
Engram adds a hashed n-gram lookup at layers 1 and 8. Token sequences are normalised (NFKC, lowercasing, accent stripping) and mapped to 9,807 classes. Each class indexes a learned embedding table. The lookup table is stored in the checkpoint, and the tokenizer is checked against it at load time, so the model must be used with the tokenizer it was trained with.
### KV cache
Generation reuses the keys and values of earlier tokens. The prompt is processed once, and each new token costs one step rather than a full pass over the sequence. This includes Engram's n-gram history and the XSA position mask.
Verified against uncached decoding:
- Per-step logits agree to about 1e-6.
- Greedy `generate()` output is identical with and without the cache.
Within the 1,024-token window, cached decoding is exact. Past the window, the model re-encodes the last 1,024 tokens at each step, the same sliding-window behaviour as before. The cache is enabled by default in `generate()`; pass `use_cache=False` to turn it off.
---
## Training
| | |
|:---|:---|
| Training tokens | ~5B |
| Optimizer | MuonwithAdamw |
| Schedule | WSD |
| Steps | 19,000 |
| Batch | 320 |
| Precision | BF16 |
---
## Results
| | exp2 |
|:---|:---:|
| Validation perplexity | 13.6 |
| Validation accuracy | 47.1% |
### Benchmarks
Evaluated with lm-evaluation-harness, 0-shot, `acc_norm`.
| Benchmark | Score | Chance |
|:---|:---:|:---:|
| HellaSwag | 29.76% | 25% |
| ARC-Easy | 31.57% | 25% |
| ARC-Challenge | 23.98% | 25% |
| PIQA | 61.86% | 50% |
| ArithMark-3 | 38.30% | 25% |
**Intelligence Index: 12.41**
```
N(s, c) = 100 × (s − c) ÷ (100 − c)
Index = (N(HellaSwag, 25) + N(ARC, 25) + N(PIQA, 50) + 0.65 × N(ArithMark-3, 25)) ÷ 3.65
```
ARC is the mean of ARC-Easy and ARC-Challenge.
ArithMark-3 is scored with `acc_norm`. Its authors score by mean per-token log-likelihood, so this value may differ slightly from their leaderboard. Its standard error is about ±1.5 points.
Training used about 5B tokens. The AxiomicLabs reference models were trained on 15 to 75B tokens, so keep that gap in mind when comparing.
---
## Quick start
```bash
pip install torch transformers safetensors
```
The model and tokenizer load through `transformers` with remote code. Batched generation with padding is not supported, so generate one prompt at a time.
```python
from transformers import AutoTokenizer, AutoModelForCausalLM
repo = "RuVI-AI/Pragya-EXP2" # or a local folder
tok = AutoTokenizer.from_pretrained(repo, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(repo, trust_remote_code=True).to("cpu").eval()
inputs = tok("The Internet is", return_tensors="pt")
out = model.generate(
input_ids=inputs["input_ids"],
attention_mask=inputs["attention_mask"],
max_new_tokens=60,
do_sample=True,
temperature=0.7,
top_k=12,
repetition_penalty=1.3,
no_repeat_ngram_size=3,
pad_token_id=tok.pad_token_id,
top_p=0.95
)
print(tok.decode(out[0], skip_special_tokens=True))
```
The tokenizer prepends `<|bos|>` by default. The string `<|bos|>` inside a prompt is treated as ordinary text.
### Load output
Loading prints a `LOAD REPORT` that lists `model.lm_head.weight` as `MISSING`. This is expected: the checkpoint stores the embedding once, and the head is tied to it when the model loads. To check:
```python
print("tied:", model.model.transformer.wte.weight is model.model.lm_head.weight) # True
```
On first load, Transformers also prints "A new version of the following files was downloaded". This is the remote code being fetched, not an error. Pin a `revision=` to stop the message once you have a version you trust.
---
## Sampling
These settings gave fluent, on-topic output in testing:
```text
temperature 0.7
top_k 12
repetition_penalty 1.3
no_repeat_ngram 3
top_p 0.95
```
Greedy decoding (`do_sample=False`) repeats phrases after a few sentences, so use sampling.
The model writes in a simple, children's-book register. This reflects the TinyStories-heavy data mix.
---
## Capabilities
**It can:** continue English prompts for a sentence or two, and produce plausible text in narrative and encyclopedic registers.
**It cannot:** answer questions reliably, follow instructions, stay coherent past the first paragraph, handle non-English text, or use context longer than 1024 tokens.
---
## Limitations
- **Small scale.** Output is grammatical for a sentence or two, then drifts into invented facts.
- **English only.** The tokenizer encodes other languages, but the model has no training signal for them.
- **No instruction tuning.** Any instruction-following is incidental.
- **No padded batches.** Attention masks are not supported, so padded batches are rejected.
- **No alignment or safety filtering.** The model can produce biased, false or toxic text.
---
## License
Apache 2.0. Each training dataset carries its own license. Check upstream terms before redistributing derivatives.
---
## Citation
```bibtex
@misc{pragya-exp2,
title = {Pragya exp2: a 28.5M from-scratch decoder-only language model with Exclusive Gated Attention and Engram memory},
author = {Arush},
year = {2026},
note = {Experimental checkpoint, not for production use},
howpublished = {\url{https://huggingface.co/RuVI-AI/Pragya-EXP2}}
}
```
|