dantinox 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dantinox-0.1.0/PKG-INFO +469 -0
- dantinox-0.1.0/README.md +429 -0
- dantinox-0.1.0/core/__init__.py +22 -0
- dantinox-0.1.0/core/attention.py +315 -0
- dantinox-0.1.0/core/block.py +66 -0
- dantinox-0.1.0/core/config.py +174 -0
- dantinox-0.1.0/core/generation.py +170 -0
- dantinox-0.1.0/core/lora.py +57 -0
- dantinox-0.1.0/core/mlp.py +46 -0
- dantinox-0.1.0/core/model.py +159 -0
- dantinox-0.1.0/core/moe.py +34 -0
- dantinox-0.1.0/core/old_model.py +322 -0
- dantinox-0.1.0/core/output.py +30 -0
- dantinox-0.1.0/core/sharding.py +41 -0
- dantinox-0.1.0/dantinox/__init__.py +61 -0
- dantinox-0.1.0/dantinox/bench.py +338 -0
- dantinox-0.1.0/dantinox/cli.py +437 -0
- dantinox-0.1.0/dantinox/exceptions.py +34 -0
- dantinox-0.1.0/dantinox/generator.py +439 -0
- dantinox-0.1.0/dantinox/hub.py +179 -0
- dantinox-0.1.0/dantinox/plotting.py +197 -0
- dantinox-0.1.0/dantinox/py.typed +0 -0
- dantinox-0.1.0/dantinox/trainer.py +589 -0
- dantinox-0.1.0/dantinox.egg-info/PKG-INFO +469 -0
- dantinox-0.1.0/dantinox.egg-info/SOURCES.txt +39 -0
- dantinox-0.1.0/dantinox.egg-info/dependency_links.txt +1 -0
- dantinox-0.1.0/dantinox.egg-info/entry_points.txt +2 -0
- dantinox-0.1.0/dantinox.egg-info/requires.txt +36 -0
- dantinox-0.1.0/dantinox.egg-info/top_level.txt +3 -0
- dantinox-0.1.0/pyproject.toml +100 -0
- dantinox-0.1.0/setup.cfg +4 -0
- dantinox-0.1.0/setup.py +3 -0
- dantinox-0.1.0/tests/test_improvements.py +233 -0
- dantinox-0.1.0/tests/test_lora.py +193 -0
- dantinox-0.1.0/tests/test_mla.py +116 -0
- dantinox-0.1.0/tests/test_model.py +149 -0
- dantinox-0.1.0/tests/test_sweep_simulation.py +817 -0
- dantinox-0.1.0/tests/test_trainer.py +218 -0
- dantinox-0.1.0/utils/__init__.py +10 -0
- dantinox-0.1.0/utils/helpers.py +24 -0
- dantinox-0.1.0/utils/tokenizer.py +99 -0
dantinox-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dantinox
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A decoder-only Transformer built from scratch in JAX and Flax NNX
|
|
5
|
+
Author: Marco Simoni
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: jax
|
|
10
|
+
Requires-Dist: jaxlib
|
|
11
|
+
Requires-Dist: flax
|
|
12
|
+
Requires-Dist: optax
|
|
13
|
+
Requires-Dist: pyyaml
|
|
14
|
+
Requires-Dist: tokenizers
|
|
15
|
+
Requires-Dist: msgpack
|
|
16
|
+
Requires-Dist: tqdm
|
|
17
|
+
Provides-Extra: data
|
|
18
|
+
Requires-Dist: datasets; extra == "data"
|
|
19
|
+
Provides-Extra: hub
|
|
20
|
+
Requires-Dist: huggingface-hub; extra == "hub"
|
|
21
|
+
Provides-Extra: benchmark
|
|
22
|
+
Requires-Dist: pandas; extra == "benchmark"
|
|
23
|
+
Requires-Dist: matplotlib; extra == "benchmark"
|
|
24
|
+
Requires-Dist: numpy; extra == "benchmark"
|
|
25
|
+
Requires-Dist: scipy; extra == "benchmark"
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
29
|
+
Requires-Dist: ruff; extra == "dev"
|
|
30
|
+
Requires-Dist: mypy; extra == "dev"
|
|
31
|
+
Requires-Dist: types-PyYAML; extra == "dev"
|
|
32
|
+
Requires-Dist: build; extra == "dev"
|
|
33
|
+
Requires-Dist: twine; extra == "dev"
|
|
34
|
+
Requires-Dist: mkdocs-material; extra == "dev"
|
|
35
|
+
Requires-Dist: mkdocs-minify-plugin; extra == "dev"
|
|
36
|
+
Requires-Dist: mkdocs-glightbox; extra == "dev"
|
|
37
|
+
Requires-Dist: mkdocstrings[python]; extra == "dev"
|
|
38
|
+
Provides-Extra: all
|
|
39
|
+
Requires-Dist: dantinox[benchmark,data,dev,hub]; extra == "all"
|
|
40
|
+
|
|
41
|
+
<div align="center">
|
|
42
|
+
|
|
43
|
+
# DantinoX
|
|
44
|
+
|
|
45
|
+
*"Nel mezzo del cammin di nostra vita mi ritrovai per una selva oscura..."*
|
|
46
|
+
|
|
47
|
+
A decoder-only Transformer built from scratch in **JAX** and **Flax NNX** — complete with a training pipeline, autoregressive generation, hyperparameter sweeps, and a benchmarking suite.
|
|
48
|
+
|
|
49
|
+
<br>
|
|
50
|
+
|
|
51
|
+
[](https://www.python.org/)
|
|
52
|
+
[](https://github.com/google/jax)
|
|
53
|
+
[](https://github.com/google/flax)
|
|
54
|
+
[](https://opensource.org/licenses/MIT)
|
|
55
|
+
[](https://github.com/astral-sh/ruff)
|
|
56
|
+
[](http://mypy-lang.org/)
|
|
57
|
+
[](https://github.com/winstonsmith1897/DantinoX/actions)
|
|
58
|
+
[](https://winstonsmith1897.github.io/DantinoX/)
|
|
59
|
+
|
|
60
|
+
**[Documentation](https://winstonsmith1897.github.io/DantinoX/) · [Coverage Report](https://winstonsmith1897.github.io/DantinoX/coverage/) · [API Reference](https://winstonsmith1897.github.io/DantinoX/api/)**
|
|
61
|
+
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Overview
|
|
67
|
+
|
|
68
|
+
**DantinoX** is a research-grade library for building, training, and benchmarking decoder-only Transformers in pure JAX. It is designed as a transparent, modular codebase for studying how architectural choices — attention mechanism, positional encoding, MoE routing — affect convergence, memory footprint, and inference throughput.
|
|
69
|
+
|
|
70
|
+
The library ships as an installable Python package (`pip install dantinox`) with a unified CLI, a programmatic Python API, a typed configuration dataclass, and a full test suite.
|
|
71
|
+
|
|
72
|
+
### Implemented Architectures
|
|
73
|
+
|
|
74
|
+
| Component | Variants |
|
|
75
|
+
| :--- | :--- |
|
|
76
|
+
| **Attention** | Multi-Head (MHA) · Grouped-Query (GQA) · Multi-Head Latent (MLA) |
|
|
77
|
+
| **Feed-Forward** | Dense MLP (SwiGLU / GELU) · Sparse Mixture-of-Experts (Top-K) |
|
|
78
|
+
| **Positional Encoding** | Rotary (RoPE) · Absolute Sinusoidal · Learned |
|
|
79
|
+
| **Attention Masking** | Causal · Sliding Window |
|
|
80
|
+
| **Memory Optimizations** | Gradient Checkpointing (`nnx.remat`) · Weight Tying · Static KV-Cache |
|
|
81
|
+
| **Training** | Gradient Accumulation · AdamW / Adafactor / Lion · Cosine LR Schedule |
|
|
82
|
+
| **Tokenizers** | Character-level · Byte-Pair Encoding (BPE) |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Installation
|
|
87
|
+
|
|
88
|
+
### From PyPI
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pip install dantinox # core only
|
|
92
|
+
pip install "dantinox[data]" # + HuggingFace datasets
|
|
93
|
+
pip install "dantinox[benchmark]" # + pandas / matplotlib / scipy
|
|
94
|
+
pip install "dantinox[all]" # everything including dev tools
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### From Source
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
git clone https://github.com/winstonsmith1897/DantinoX.git
|
|
101
|
+
cd DantinoX
|
|
102
|
+
|
|
103
|
+
conda create -n dantinox python=3.12 -y
|
|
104
|
+
conda activate dantinox
|
|
105
|
+
|
|
106
|
+
make install # installs JAX + all extras in editable mode
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
> **GPU support:** replace the JAX CPU wheels with `pip install -U "jax[cuda12]"` after running `make install`.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Quick Start
|
|
114
|
+
|
|
115
|
+
### CLI
|
|
116
|
+
|
|
117
|
+
DantinoX registers a single `dantinox` entry-point with five subcommands:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# Train from a YAML config
|
|
121
|
+
dantinox train --config configs/default_config.yaml --data_path data/corpus.txt
|
|
122
|
+
|
|
123
|
+
# Override any config field from the command line
|
|
124
|
+
dantinox train --config configs/default_config.yaml --data_path data/corpus.txt \
|
|
125
|
+
--lr 3e-4 --use_moe true --num_blocks 8
|
|
126
|
+
|
|
127
|
+
# Generate text from a saved checkpoint
|
|
128
|
+
dantinox generate --run_dir runs/run_20260101_120000 \
|
|
129
|
+
--prompt "Nel mezzo del cammin " --max_new_tokens 200 --temperature 1.2
|
|
130
|
+
|
|
131
|
+
# Run a W&B Bayesian hyperparameter sweep
|
|
132
|
+
dantinox sweep --sweep_config configs/sweep.yaml --data_path data/corpus.txt
|
|
133
|
+
|
|
134
|
+
# Benchmark all run directories and save metrics to CSV
|
|
135
|
+
dantinox benchmark --runs_dir runs --out_csv benchmark_results.csv
|
|
136
|
+
|
|
137
|
+
# Generate plots from benchmark results
|
|
138
|
+
dantinox plot --in_csv benchmark_results.csv --out_dir plots
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Python API
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from dantinox import Trainer, Generator, BenchmarkRunner
|
|
145
|
+
from core.config import Config
|
|
146
|
+
|
|
147
|
+
# --- Training ---
|
|
148
|
+
config = Config(
|
|
149
|
+
dim=512, n_heads=16, head_size=32, kv_heads=4,
|
|
150
|
+
num_blocks=12, max_context=512,
|
|
151
|
+
use_moe=True, n_experts=4, top_k_mlp=2,
|
|
152
|
+
lr=3e-4, batch_size=64, grad_accum=4, epochs=100,
|
|
153
|
+
)
|
|
154
|
+
trainer = Trainer(config)
|
|
155
|
+
run_dir = trainer.fit("data/corpus.txt")
|
|
156
|
+
|
|
157
|
+
# --- Generation ---
|
|
158
|
+
gen = Generator(run_dir)
|
|
159
|
+
text = gen.generate(
|
|
160
|
+
"Nel mezzo del cammin ",
|
|
161
|
+
max_new_tokens=200,
|
|
162
|
+
temperature=1.2,
|
|
163
|
+
top_p=0.9,
|
|
164
|
+
use_cache=True,
|
|
165
|
+
)
|
|
166
|
+
print(text)
|
|
167
|
+
|
|
168
|
+
# --- Benchmarking ---
|
|
169
|
+
runner = BenchmarkRunner("runs")
|
|
170
|
+
df = runner.run(out_csv="benchmark_results.csv")
|
|
171
|
+
print(df[["run", "type", "params_m", "prefill_ms"]].to_string())
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Configuration
|
|
177
|
+
|
|
178
|
+
All architecture and training settings live in a single typed dataclass. YAML files are fully supported and can be partially overridden from the CLI.
|
|
179
|
+
|
|
180
|
+
```yaml
|
|
181
|
+
# configs/default_config.yaml
|
|
182
|
+
|
|
183
|
+
model:
|
|
184
|
+
dim: 512 # Hidden dimension (must equal n_heads × head_size)
|
|
185
|
+
n_heads: 16 # Query heads
|
|
186
|
+
kv_heads: 4 # Key/value heads — set < n_heads to enable GQA
|
|
187
|
+
head_size: 32 # Per-head dimension
|
|
188
|
+
num_blocks: 12 # Transformer depth
|
|
189
|
+
max_context: 512 # Maximum sequence length
|
|
190
|
+
weight_tying: true # Tie embedding ↔ LM-head weights
|
|
191
|
+
activation: gelu # Activation function (gelu | silu)
|
|
192
|
+
use_swiglu: true # Replace MLP activation with SwiGLU gate
|
|
193
|
+
gradient_checkpointing: true # Recompute activations to reduce VRAM
|
|
194
|
+
dropout_rate: 0.15
|
|
195
|
+
|
|
196
|
+
moe:
|
|
197
|
+
use_moe: false # Toggle Sparse MoE (true) vs Dense MLP (false)
|
|
198
|
+
n_experts: 4 # Total number of experts
|
|
199
|
+
top_k_mlp: 2 # Active experts per token
|
|
200
|
+
expansion: 4 # Expert hidden-dimension multiplier
|
|
201
|
+
alpha_balance: 0.1 # Load-balancing loss weight
|
|
202
|
+
|
|
203
|
+
attention:
|
|
204
|
+
use_rotary_pos: true # Rotary Positional Embedding (RoPE)
|
|
205
|
+
sliding_window: false # Restrict attention to a local window
|
|
206
|
+
context_window: 4 # Window size (if sliding_window: true)
|
|
207
|
+
no_sink: true # Sigmoid attention gate for training stability
|
|
208
|
+
|
|
209
|
+
# Multi-Head Latent Attention (MLA)
|
|
210
|
+
mla: false
|
|
211
|
+
down_dim_q: 256 # Query compression dimension
|
|
212
|
+
down_dim_kv: 256 # Key/Value compression dimension
|
|
213
|
+
rope_dim: 32 # RoPE dimensions for decoupled key encoding
|
|
214
|
+
|
|
215
|
+
tokenizer:
|
|
216
|
+
tokenizer_type: char # char | bpe
|
|
217
|
+
tokenizer_path: null
|
|
218
|
+
|
|
219
|
+
data:
|
|
220
|
+
dataset_source: local # local | huggingface
|
|
221
|
+
dataset_name: ""
|
|
222
|
+
|
|
223
|
+
training:
|
|
224
|
+
lr: 0.005
|
|
225
|
+
batch_size: 128
|
|
226
|
+
grad_accum: 16
|
|
227
|
+
optimizer: adamw # adamw | adafactor | lion
|
|
228
|
+
epochs: 1000
|
|
229
|
+
warmup_steps: 420
|
|
230
|
+
seed: 42
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Config Validation
|
|
234
|
+
|
|
235
|
+
The `Config` dataclass enforces constraints at instantiation:
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
Config(dim=512, n_heads=16, head_size=32) # OK — 16 × 32 = 512
|
|
239
|
+
Config(dim=512, n_heads=16, head_size=31) # ConfigError: dim must equal n_heads × head_size
|
|
240
|
+
Config(dim=512, n_heads=16, kv_heads=3) # ConfigError: n_heads must be divisible by kv_heads
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## CLI Reference
|
|
246
|
+
|
|
247
|
+
### `dantinox train`
|
|
248
|
+
|
|
249
|
+
| Argument | Default | Description |
|
|
250
|
+
| :--- | :--- | :--- |
|
|
251
|
+
| `--config` | `configs/default_config.yaml` | YAML config file |
|
|
252
|
+
| `--data_path` | — | Path to plain-text corpus |
|
|
253
|
+
| `--run_dir` | auto-generated | Output directory for weights and logs |
|
|
254
|
+
| `--wandb_project` | — | W&B project name for live logging |
|
|
255
|
+
| `--<field>` | config value | Override any `Config` field directly |
|
|
256
|
+
|
|
257
|
+
### `dantinox generate`
|
|
258
|
+
|
|
259
|
+
| Argument | Default | Description |
|
|
260
|
+
| :--- | :--- | :--- |
|
|
261
|
+
| `--run_dir` | **required** | Run directory with `config.yaml` + `model_weights.msgpack` |
|
|
262
|
+
| `--prompt` | `"Nel mezzo del cammin "` | Input text prefix |
|
|
263
|
+
| `--max_new_tokens` | `150` | Number of tokens to generate |
|
|
264
|
+
| `--temperature` | `1.0` | Sampling temperature |
|
|
265
|
+
| `--top_p` | `null` | Nucleus sampling threshold |
|
|
266
|
+
| `--top_k` | `null` | Top-K sampling limit |
|
|
267
|
+
| `--greedy` | `false` | Deterministic greedy decoding |
|
|
268
|
+
| `--no_cache` | `false` | Disable KV-cache (slower, for debugging) |
|
|
269
|
+
| `--seed` | `42` | RNG seed |
|
|
270
|
+
|
|
271
|
+
### `dantinox benchmark`
|
|
272
|
+
|
|
273
|
+
| Argument | Default | Description |
|
|
274
|
+
| :--- | :--- | :--- |
|
|
275
|
+
| `--runs_dir` | `runs` | Directory containing run sub-directories |
|
|
276
|
+
| `--runs` | all | Specific run names to benchmark |
|
|
277
|
+
| `--out_csv` | — | Save results to this CSV path |
|
|
278
|
+
|
|
279
|
+
### `dantinox sweep`
|
|
280
|
+
|
|
281
|
+
| Argument | Default | Description |
|
|
282
|
+
| :--- | :--- | :--- |
|
|
283
|
+
| `--sweep_config` | `configs/sweep.yaml` | W&B sweep YAML |
|
|
284
|
+
| `--config` | `configs/default_config.yaml` | Base model config (overridden by sweep) |
|
|
285
|
+
| `--data_path` | **required** | Training corpus |
|
|
286
|
+
| `--wandb_project` | `DantinoX` | W&B project |
|
|
287
|
+
| `--count` | unlimited | Maximum sweep runs |
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Project Structure
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
DantinoX/
|
|
295
|
+
├── core/ # Neural network primitives
|
|
296
|
+
│ ├── config.py # Config dataclass — single source of truth
|
|
297
|
+
│ ├── model.py # Transformer: embedding → blocks → LM head
|
|
298
|
+
│ ├── attention.py # MHA / GQA / MLA + RoPE + KV-cache
|
|
299
|
+
│ ├── block.py # Transformer block (Attention + FFN + LayerNorm)
|
|
300
|
+
│ ├── mlp.py # Dense MLP (SwiGLU / GELU)
|
|
301
|
+
│ ├── moe.py # Sparse Mixture-of-Experts with load-balancing loss
|
|
302
|
+
│ └── generation.py # Autoregressive decode loop (fori_loop + vmap)
|
|
303
|
+
│
|
|
304
|
+
├── dantinox/ # Installable library package
|
|
305
|
+
│ ├── cli.py # `dantinox` entry-point (train/generate/sweep/benchmark/plot)
|
|
306
|
+
│ ├── trainer.py # Trainer — JIT training loop, logging, checkpointing
|
|
307
|
+
│ ├── generator.py # Generator — checkpoint loading + text generation
|
|
308
|
+
│ ├── bench.py # BenchmarkRunner — latency / throughput / FLOPs
|
|
309
|
+
│ ├── plotting.py # Plotter — automated figure generation
|
|
310
|
+
│ └── exceptions.py # Exception hierarchy (DantinoXError → sub-classes)
|
|
311
|
+
│
|
|
312
|
+
├── utils/
|
|
313
|
+
│ ├── tokenizer.py # CharTokenizer · BPETokenizer · Tokenizer Protocol
|
|
314
|
+
│ └── helpers.py # Loss · batch sampling · LR schedule
|
|
315
|
+
│
|
|
316
|
+
├── configs/ # YAML configuration files
|
|
317
|
+
│ ├── default_config.yaml
|
|
318
|
+
│ └── sweep.yaml
|
|
319
|
+
│
|
|
320
|
+
├── tests/ # Pytest test suite (22 tests)
|
|
321
|
+
│ ├── conftest.py # Session-scoped Config fixtures
|
|
322
|
+
│ ├── test_model.py # Forward pass · GQA · MoE · weight tying · JIT
|
|
323
|
+
│ └── test_mla.py # MLA training · inference cache · RoPE constraints
|
|
324
|
+
│
|
|
325
|
+
├── pyproject.toml # Package metadata, deps, ruff, mypy, pytest config
|
|
326
|
+
├── Makefile # Development targets
|
|
327
|
+
└── mkdocs.yml # Documentation site configuration
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Exception Hierarchy
|
|
331
|
+
|
|
332
|
+
```
|
|
333
|
+
DantinoXError
|
|
334
|
+
├── ConfigError — invalid or inconsistent Config fields
|
|
335
|
+
├── CheckpointError — missing run directory, config, or weights
|
|
336
|
+
├── BenchmarkError — failure loading or running a benchmark
|
|
337
|
+
└── PlotError — missing CSV or plot module import failure
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## Development
|
|
343
|
+
|
|
344
|
+
All common workflows are exposed through `make`:
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
make install # Install package + all dev/doc dependencies (editable)
|
|
348
|
+
make test # Run test suite with coverage report
|
|
349
|
+
make lint # Ruff static analysis
|
|
350
|
+
make typecheck # Mypy type checking
|
|
351
|
+
make check # lint + typecheck + test (run before every push)
|
|
352
|
+
make build # Build sdist + wheel into dist/
|
|
353
|
+
make publish # Upload dist/ to PyPI via twine
|
|
354
|
+
make clean # Remove build artefacts and __pycache__
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Running Tests
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
make test
|
|
361
|
+
|
|
362
|
+
# Or directly:
|
|
363
|
+
JAX_PLATFORM_NAME=cpu python -m pytest tests/ -v
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
The suite runs on CPU (no GPU required) and covers:
|
|
367
|
+
|
|
368
|
+
- Forward-pass output shapes for MHA, GQA, and MLA
|
|
369
|
+
- KV-cache correctness and accumulation
|
|
370
|
+
- MoE load-balancing loss propagation
|
|
371
|
+
- Weight tying between embedding and LM head
|
|
372
|
+
- JIT compilation stability
|
|
373
|
+
- `Config` validation (dim constraints, GQA divisibility, MLA rope_dim)
|
|
374
|
+
- `Config` round-trip serialization (`to_dict` / `from_dict`)
|
|
375
|
+
|
|
376
|
+
Coverage output is written to `docs/coverage/` and published automatically with the documentation site.
|
|
377
|
+
|
|
378
|
+
### Code Quality
|
|
379
|
+
|
|
380
|
+
The project enforces a strict quality baseline:
|
|
381
|
+
|
|
382
|
+
| Tool | Configuration | What it checks |
|
|
383
|
+
| :--- | :--- | :--- |
|
|
384
|
+
| **ruff** | `pyproject.toml` | Style (E/W), imports (I), pyupgrade (UP), bugbear (B), simplify (SIM) |
|
|
385
|
+
| **mypy** | `pyproject.toml` | Full type annotation coverage across `dantinox/`, `core/`, `utils/` |
|
|
386
|
+
| **pytest** | `pyproject.toml` | 22 unit tests, CPU-only, session-scoped fixtures |
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Training Artifacts
|
|
391
|
+
|
|
392
|
+
Each training run writes an isolated artifact directory:
|
|
393
|
+
|
|
394
|
+
```
|
|
395
|
+
runs/run_20260101_120000/
|
|
396
|
+
├── config.yaml # Exact config used for the run
|
|
397
|
+
├── model_summary.json # Parameter counts per component
|
|
398
|
+
├── training_log.csv # step, train_loss, val_loss, bal_loss, ms_per_step
|
|
399
|
+
└── model_weights.msgpack # Serialized model state (Flax msgpack format)
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
The training loop logs to console via `tqdm` with live loss postfix, and optionally streams metrics to **Weights & Biases** when `--wandb_project` is specified.
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
## Benchmarking
|
|
407
|
+
|
|
408
|
+
`BenchmarkRunner` measures latency and throughput across a matrix of sequence lengths and batch sizes using XLA cost analysis for FLOPs:
|
|
409
|
+
|
|
410
|
+
```python
|
|
411
|
+
from dantinox import BenchmarkRunner
|
|
412
|
+
from dantinox.plotting import Plotter
|
|
413
|
+
|
|
414
|
+
df = BenchmarkRunner("runs").run(out_csv="benchmark_results.csv")
|
|
415
|
+
Plotter("benchmark_results.csv", out_dir="plots").run()
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**Reported metrics per run:**
|
|
419
|
+
|
|
420
|
+
| Metric | Description |
|
|
421
|
+
| :--- | :--- |
|
|
422
|
+
| `params_m` | Total trainable parameters (millions) |
|
|
423
|
+
| `theoretical_cache_mb` | KV-cache memory at `max_context` (MB) |
|
|
424
|
+
| `prefill_ms` | Prefill latency for a 256-token prompt |
|
|
425
|
+
| `tps_{64,128,256,512}` | Decode throughput (tok/s) at each sequence length |
|
|
426
|
+
| `tps_bs{1,4,16,64,...}` | Decode throughput at each batch size |
|
|
427
|
+
| `decode_gflops` | FLOPs per decode step (XLA cost analysis) |
|
|
428
|
+
| `prefill_arith_int` | Arithmetic intensity of the prefill kernel |
|
|
429
|
+
| `val_loss` | Final validation loss from `training_log.csv` |
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## Empirical Results
|
|
434
|
+
|
|
435
|
+
Ablation studies were conducted via W&B Bayesian sweeps over 100+ configurations. Key findings:
|
|
436
|
+
|
|
437
|
+
- **MLA vs GQA vs MHA:** MLA achieves lower KV-cache memory with comparable perplexity when `down_dim_kv ≤ dim / 4`.
|
|
438
|
+
- **SwiGLU:** Consistently outperforms GELU by ~0.05 val-loss across all model sizes.
|
|
439
|
+
- **Sliding Window:** Improves training speed on long contexts with negligible perplexity loss when `context_window ≥ 64`.
|
|
440
|
+
- **Attention Gating (`no_sink`):** Stabilizes training when combined with RoPE at high learning rates.
|
|
441
|
+
- **MoE (Top-2/4):** Matches dense perplexity at 60% of the active-parameter count.
|
|
442
|
+
|
|
443
|
+
Full charts and analysis: [Ablation Studies](https://winstonsmith1897.github.io/DantinoX/ablation_studies/)
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## Documentation
|
|
448
|
+
|
|
449
|
+
The full documentation is built with MkDocs Material and deployed to GitHub Pages:
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
# Rebuild and deploy
|
|
453
|
+
mkdocs gh-deploy --force
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
Sections:
|
|
457
|
+
|
|
458
|
+
- [Architecture](https://winstonsmith1897.github.io/DantinoX/architecture/) — attention variants, MoE, positional encodings
|
|
459
|
+
- [Training & Sweeps](https://winstonsmith1897.github.io/DantinoX/training/) — training loop internals, W&B integration
|
|
460
|
+
- [Inference & Generation](https://winstonsmith1897.github.io/DantinoX/generation/) — KV-cache, decoding strategies
|
|
461
|
+
- [Benchmarks](https://winstonsmith1897.github.io/DantinoX/benchmarks/) — throughput and FLOPs analysis
|
|
462
|
+
- [API Reference](https://winstonsmith1897.github.io/DantinoX/api/) — auto-generated from docstrings
|
|
463
|
+
- [Coverage Report](https://winstonsmith1897.github.io/DantinoX/coverage/) — line-level test coverage
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
## License
|
|
468
|
+
|
|
469
|
+
MIT — see [LICENSE](LICENSE).
|