|
| 1 | +# Nanochat in Plato |
| 2 | + |
| 3 | +Plato includes a Nanochat integration for federated training plus optional CORE evaluation. |
| 4 | +This guide documents the **working end-to-end setup** for the current repository state. |
| 5 | + |
| 6 | +Reference files: |
| 7 | + |
| 8 | +- `configs/Nanochat/synthetic_micro.toml` |
| 9 | +- `configs/Nanochat/parquet_micro.toml` |
| 10 | +- `examples/nanochat/README.md` |
| 11 | +- `external/nanochat/` |
| 12 | + |
| 13 | +## What you need to know first |
| 14 | + |
| 15 | +There are two separate pieces of setup: |
| 16 | + |
| 17 | +1. **Running Nanochat training inside Plato** |
| 18 | +2. **Running Nanochat CORE evaluation** |
| 19 | + |
| 20 | +The current `synthetic_micro.toml` configuration already enables: |
| 21 | + |
| 22 | +```toml |
| 23 | +[evaluation] |
| 24 | +type = "nanochat_core" |
| 25 | +``` |
| 26 | + |
| 27 | +So if you run that config as-is, you need **both**: |
| 28 | + |
| 29 | +- the Nanochat Rust tokenizer extension (`rustbpe`) |
| 30 | +- a trained tokenizer under `~/.cache/nanochat/tokenizer/` |
| 31 | + |
| 32 | +The CORE evaluation bundle itself is downloaded automatically on first use, but the tokenizer is **not**. |
| 33 | + |
| 34 | +## Step 1: Clone Plato and initialize submodules |
| 35 | + |
| 36 | +From a fresh checkout: |
| 37 | + |
| 38 | +```bash |
| 39 | +git clone git@github.com:TL-System/plato.git |
| 40 | +cd plato |
| 41 | +git submodule update --init --recursive |
| 42 | +``` |
| 43 | + |
| 44 | +The Nanochat code lives in the submodule: |
| 45 | + |
| 46 | +- `external/nanochat` |
| 47 | + |
| 48 | +If this step is skipped, Nanochat imports and build steps will fail. |
| 49 | + |
| 50 | +## Step 2: Install Plato with the Nanochat extra |
| 51 | + |
| 52 | +From the repository root: |
| 53 | + |
| 54 | +```bash |
| 55 | +uv sync --extra nanochat |
| 56 | +``` |
| 57 | + |
| 58 | +This installs the Python dependencies needed by Plato's Nanochat integration. |
| 59 | + |
| 60 | +## Step 3: Install `maturin` |
| 61 | + |
| 62 | +The Rust tokenizer build step uses `maturin`. Install it once if it is not already available on your machine: |
| 63 | + |
| 64 | +```bash |
| 65 | +uv tool install maturin |
| 66 | +``` |
| 67 | + |
| 68 | +If you already have `maturin`, you can skip this step. |
| 69 | + |
| 70 | +## Step 4: Build the Nanochat Rust tokenizer extension for Plato's environment |
| 71 | + |
| 72 | +From the repository root: |
| 73 | + |
| 74 | +```bash |
| 75 | +uv run --extra nanochat maturin develop --release --manifest-path external/nanochat/rustbpe/Cargo.toml |
| 76 | +``` |
| 77 | + |
| 78 | +This builds and installs the `rustbpe` extension into the environment used by `uv run` in the Plato repository. |
| 79 | + |
| 80 | +### Troubleshooting: `Both VIRTUAL_ENV and CONDA_PREFIX are set` |
| 81 | + |
| 82 | +If `maturin` fails with a message like this: |
| 83 | + |
| 84 | +```text |
| 85 | +Both VIRTUAL_ENV and CONDA_PREFIX are set. Please unset one of them |
| 86 | +``` |
| 87 | + |
| 88 | +run: |
| 89 | + |
| 90 | +```bash |
| 91 | +unset CONDA_PREFIX |
| 92 | +uv run --extra nanochat maturin develop --release --manifest-path external/nanochat/rustbpe/Cargo.toml |
| 93 | +``` |
| 94 | + |
| 95 | +## Step 5A: Run the training-only synthetic smoke test |
| 96 | + |
| 97 | +If you only want to verify that Nanochat training works and do **not** need CORE evaluation yet, first make a local copy of the config and disable the evaluation block there: |
| 98 | + |
| 99 | +```bash |
| 100 | +cp configs/Nanochat/synthetic_micro.toml /tmp/nanochat_synthetic_train_only.toml |
| 101 | +``` |
| 102 | + |
| 103 | +Edit `/tmp/nanochat_synthetic_train_only.toml` and comment out: |
| 104 | + |
| 105 | +```toml |
| 106 | +# [evaluation] |
| 107 | +# type = "nanochat_core" |
| 108 | +# max_per_task = 16 |
| 109 | +``` |
| 110 | + |
| 111 | +Then run: |
| 112 | + |
| 113 | +```bash |
| 114 | +uv run --extra nanochat python plato.py --config /tmp/nanochat_synthetic_train_only.toml --cpu |
| 115 | +``` |
| 116 | + |
| 117 | +This launches a 1-round synthetic training smoke test on CPU without requiring tokenizer setup for CORE evaluation. |
| 118 | + |
| 119 | +## Step 5B: Prepare the tokenizer required by CORE evaluation |
| 120 | + |
| 121 | +If you want to run `configs/Nanochat/synthetic_micro.toml` **without editing it**, you must prepare a tokenizer first. |
| 122 | + |
| 123 | +### Why this extra step is needed |
| 124 | + |
| 125 | +Nanochat's CORE evaluator expects these tokenizer artifacts under: |
| 126 | + |
| 127 | +- `~/.cache/nanochat/tokenizer/tokenizer.pkl` |
| 128 | +- `~/.cache/nanochat/tokenizer/token_bytes.pt` |
| 129 | + |
| 130 | +Plato can auto-download the CORE evaluation bundle, but it does **not** auto-create the tokenizer. |
| 131 | + |
| 132 | +### 5B.1 Download Nanochat base data shards |
| 133 | + |
| 134 | +Run this from the Plato repository root: |
| 135 | + |
| 136 | +```bash |
| 137 | +PYTHONPATH=external/nanochat:$PYTHONPATH \ |
| 138 | +uv run --extra nanochat python external/nanochat/nanochat/dataset.py -n 2 |
| 139 | +``` |
| 140 | + |
| 141 | +This downloads data into: |
| 142 | + |
| 143 | +- `~/.cache/nanochat/base_data/` |
| 144 | + |
| 145 | +!!! warning "Download at least 2 shards" |
| 146 | + Do not download just one shard. |
| 147 | + |
| 148 | + Nanochat's tokenizer training script uses all but the last shard for the training split and reserves the last shard for validation. With only one shard, the training split is empty and tokenizer training produces an unusable tokenizer. |
| 149 | + |
| 150 | +### 5B.2 Train the tokenizer |
| 151 | + |
| 152 | +For the micro config, use a small vocabulary size matching the smoke-test setup: |
| 153 | + |
| 154 | +```bash |
| 155 | +PYTHONPATH=external/nanochat:$PYTHONPATH \ |
| 156 | +uv run --extra nanochat python external/nanochat/scripts/tok_train.py --max_chars 1000000 --vocab_size 512 |
| 157 | +``` |
| 158 | + |
| 159 | +This should create: |
| 160 | + |
| 161 | +- `~/.cache/nanochat/tokenizer/tokenizer.pkl` |
| 162 | +- `~/.cache/nanochat/tokenizer/token_bytes.pt` |
| 163 | + |
| 164 | +## Step 6: Run the synthetic Nanochat config with CORE evaluation |
| 165 | + |
| 166 | +Once the tokenizer exists, run: |
| 167 | + |
| 168 | +```bash |
| 169 | +uv run --extra nanochat python plato.py --config configs/Nanochat/synthetic_micro.toml --cpu |
| 170 | +``` |
| 171 | + |
| 172 | +What to expect: |
| 173 | + |
| 174 | +- training runs on CPU |
| 175 | +- one client participates in one round |
| 176 | +- the CORE evaluation bundle is downloaded automatically on the first run if missing |
| 177 | +- some CORE examples may be skipped when they exceed the tiny micro model's `sequence_len` |
| 178 | + |
| 179 | +That last point is expected for this micro configuration. |
| 180 | + |
| 181 | +## Step 7: Run the Parquet micro config |
| 182 | + |
| 183 | +The repository also includes: |
| 184 | + |
| 185 | +- `configs/Nanochat/parquet_micro.toml` |
| 186 | + |
| 187 | +Run it with: |
| 188 | + |
| 189 | +```bash |
| 190 | +uv run --extra nanochat python plato.py --config configs/Nanochat/parquet_micro.toml |
| 191 | +``` |
| 192 | + |
| 193 | +Notes: |
| 194 | + |
| 195 | +- this config is set up for `mode = "parquet"` |
| 196 | +- it reuses Nanochat's cached base data under `~/.cache/nanochat/base_data/` |
| 197 | +- it also requires the tokenizer prepared in [Step 5B](#step-5b-prepare-the-tokenizer-required-by-core-evaluation), because Parquet tokenization and CORE evaluation both depend on it |
| 198 | +- by default it will reuse the tokenizer trained in Step 5B; if you train a different tokenizer or vocabulary, keep the tokenizer, cached data flow, and model settings aligned |
| 199 | +- it defaults to `device = "cuda"` |
| 200 | +- it performs many more rounds than the synthetic smoke test |
| 201 | +- it is intended for a more realistic run than the CPU micro smoke test |
| 202 | + |
| 203 | +You may need to adjust device, batch counts, rounds, and data volume for your hardware. |
| 204 | + |
| 205 | +## Common failure modes |
| 206 | + |
| 207 | +### `ModuleNotFoundError: No module named 'nanochat'` |
| 208 | + |
| 209 | +This usually happens when running upstream Nanochat scripts directly. |
| 210 | + |
| 211 | +Use the commands in this guide from the **Plato repository root** and include: |
| 212 | + |
| 213 | +```bash |
| 214 | +PYTHONPATH=external/nanochat:$PYTHONPATH |
| 215 | +``` |
| 216 | + |
| 217 | +when calling upstream scripts such as: |
| 218 | + |
| 219 | +- `external/nanochat/nanochat/dataset.py` |
| 220 | +- `external/nanochat/scripts/tok_train.py` |
| 221 | + |
| 222 | +You do **not** need this extra `PYTHONPATH` prefix when running `plato.py`, because Plato's Nanochat integration adds the submodule path internally. |
| 223 | + |
| 224 | +### `AttributeError: module 'rustbpe' has no attribute 'Tokenizer'` |
| 225 | + |
| 226 | +The Rust extension was not built for Plato's active Python environment. |
| 227 | + |
| 228 | +Re-run: |
| 229 | + |
| 230 | +```bash |
| 231 | +uv run --extra nanochat maturin develop --release --manifest-path external/nanochat/rustbpe/Cargo.toml |
| 232 | +``` |
| 233 | + |
| 234 | +### `FileNotFoundError: ... ~/.cache/nanochat/tokenizer/tokenizer.pkl` |
| 235 | + |
| 236 | +The tokenizer has not been trained yet. |
| 237 | + |
| 238 | +Follow the steps in: |
| 239 | + |
| 240 | +- [Step 5B: Prepare the tokenizer required by CORE evaluation](#step-5b-prepare-the-tokenizer-required-by-core-evaluation) |
| 241 | + |
| 242 | +### CORE evaluation crashes on long prompts |
| 243 | + |
| 244 | +The `synthetic_micro.toml` model uses a very small sequence length. |
| 245 | +Some CORE prompts can exceed that limit. |
| 246 | + |
| 247 | +Plato now skips examples that do not fit into the model context window during Nanochat CORE evaluation, instead of aborting the entire run. |
| 248 | + |
| 249 | +## Recommended command summary |
| 250 | + |
| 251 | +### Minimal training-only smoke test |
| 252 | + |
| 253 | +1. `git submodule update --init --recursive` |
| 254 | +2. `uv sync --extra nanochat` |
| 255 | +3. `uv tool install maturin` |
| 256 | +4. `uv run --extra nanochat maturin develop --release --manifest-path external/nanochat/rustbpe/Cargo.toml` |
| 257 | +5. `cp configs/Nanochat/synthetic_micro.toml /tmp/nanochat_synthetic_train_only.toml` |
| 258 | +6. comment out `[evaluation]` in `/tmp/nanochat_synthetic_train_only.toml` |
| 259 | +7. `uv run --extra nanochat python plato.py --config /tmp/nanochat_synthetic_train_only.toml --cpu` |
| 260 | + |
| 261 | +### Full synthetic run with CORE evaluation |
| 262 | + |
| 263 | +1. `git submodule update --init --recursive` |
| 264 | +2. `uv sync --extra nanochat` |
| 265 | +3. `uv tool install maturin` |
| 266 | +4. `uv run --extra nanochat maturin develop --release --manifest-path external/nanochat/rustbpe/Cargo.toml` |
| 267 | +5. `PYTHONPATH=external/nanochat:$PYTHONPATH uv run --extra nanochat python external/nanochat/nanochat/dataset.py -n 2` |
| 268 | +6. `PYTHONPATH=external/nanochat:$PYTHONPATH uv run --extra nanochat python external/nanochat/scripts/tok_train.py --max_chars 1000000 --vocab_size 512` |
| 269 | +7. `uv run --extra nanochat python plato.py --config configs/Nanochat/synthetic_micro.toml --cpu` |
| 270 | + |
| 271 | +## Related documentation |
| 272 | + |
| 273 | +- [Installation](../../install.md) |
| 274 | +- [Quick Start](../../quickstart.md) |
| 275 | +- [Evaluation configuration](../../configurations/evaluation.md) |
0 commit comments