// The project
Rukh, on one page.
Rukh is a chess language model trained from scratch, aligned with reinforcement learning from verifiable rewards, deployed on WebGPU and turned into an agent with tools. This site is the course that documents every step.
One model, every stage of the lifecycle.
A custom decoder (tens of millions of parameters) trained on Lichess games, an encoder that understands positions, instruction-style fine-tuning with target-Elo tokens, a reward model, DPO and GRPO with Stockfish as the judge, ONNX export to play in the browser and, in the second phase, RAG and agents that comment games.
- M1Data & tokenizationLichess cut, UCI vocabulary, BPE, dataloaders
- M2DecoderGPT-style MoveDecoder trained from scratch, ONNX, WebGPU demo
- M3EncoderMasked move modeling, value and blunder heads
- M4Fine-tuningMasters SFT, Elo-conditioning, LoRA, QLoRA vs Qwen3
- M5AlignmentReward model, DPO, GRPO with Stockfish as verifier
- M6EvaluationSingle results table, model cards, final demo
- A1-A6Agentic coachRAG over positions and books, LangGraph agent, MCP server
Three repositories, no shared packages.
Everything the two web apps share (CSS tokens, the TypeScript tokenizer, precomputed JSON) is copied by a script and guarded by a hash test. All trained weights and datasets live on Hugging Face, never in git.
- borja-glez/rukh
Model, data, training, evaluation and agents. Python 3.12, PyTorch, MLflow.
- borja-glez/rukh-lab
This site: the course, in Spanish. Static Astro with Preact islands.
- borja-glez/rukh-web
The demo: play against the model in the browser with onnxruntime-web.
Measured the same way, every time.
One table for every stage, always measured the same way. It fills in as the course progresses; each row links to its model card.
| Stage | Params | Legal moves, no mask (%) | Top-1 (%) | Top-3 (%) | Puzzles 1000-1500 (%) | Puzzles 1500-2000 (%) | Puzzles 2000+ (%) | Elo vs Stockfish (95% CI) | Mean loss (cp) | Hugging Face |
|---|---|---|---|---|---|---|---|---|---|---|
| medium-greedy | 115.1 M | 99.4 | 52.9 | 80.9 | 37.6 | 24.0 | 10.2 | 1091 (990 … 1194) | — | — |
| small | 39.0 M | 99.4 | 51.1 | 79.4 | — | — | — | 785 (680 … 896) | — | — |
| small-greedy | 39.0 M | 99.4 | 51.1 | 79.4 | 34.7 | 21.1 | 10.3 | 1007 (920 … 1101) | — | — |
| tiny | 5.3 M | 94.5 | 40.3 | 67.1 | — | — | — | 64 (-200 … 292) | — | — |
| Stage | Params | Blunder F1, tuned threshold (%) | Threshold (chosen on “tune”) | Blunder F1, threshold 0.5 (%) | Baseline F1 (%) | Margin (F1 points) | Blunder ROC AUC | Average precision | Blunder base rate (%) | Value: Spearman | Value: Pearson | Result (%) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| encoder | 15.1 M | 17.9 | 0.128 | 0.0 | 8.9 | +9.0 | 0.738 | 0.109 | 3.7 | 0.407 | 0.442 | 49.9 |
| encoder-squares | 14.3 M | 14.6 | 0.0446 | 0.0 | 8.9 | +5.7 | 0.696 | 0.091 | 3.7 | 0.422 | 0.688 | 50.2 |