Commit 061b508
authored
Adopt searchless_chess 1968-action vocabulary (#52)
* Adopt searchless_chess 1968-action vocabulary as primary token representation
Replace PAWN's dense 4284-token vocabulary (64×64 grid + promotions + outcomes)
with DeepMind's searchless_chess 1968-action vocabulary. Actions 0-1967 are 1:1
with searchless_chess — no offset, no remapping.
New token layout:
0-1967: searchless_chess actions (reachable moves only)
1968: PAD
1969-1979: outcome tokens (11 total)
Key changes:
- Generate engine/src/searchless_vocab.rs from canonical JSON via codegen script
- Rewrite vocab.rs: lookup-table tokenization replaces formula-based approach
- board.rs: move_to_token builds UCI string and looks up action index
- batch.rs: PAD initialization uses 1968 instead of 0
- Add pawn_to_searchless/searchless_to_pawn conversion functions
- Update all test assertions for new token ranges
All 304 Rust tests pass.
* Add prepend_outcome flag and fix PAD initialization in Rust engine
- generate_clm_batch() gains prepend_outcome parameter (default false)
- false: pure moves [m1, m2, ..., mN, PAD], max_ply = seq_len
- true: [outcome, m1, ..., mN, PAD], max_ply = seq_len - 1
- Fix PAD initialization: input_ids/targets use PAD_TOKEN (1968)
instead of 0 (which is now action "a1b1")
- Fix sparse legal mask PAD insertion to use vocab::PAD_TOKEN
- Expose pawn_to_searchless/searchless_to_pawn to Python
- Update all test assertions for new token ranges
304 Rust tests pass. Python smoke test verified.
* Update Python config and model for searchless_chess vocabulary
config.py:
- New defaults: PAD_TOKEN=1968, OUTCOME_TOKEN_BASE=1969, vocab_size=1980,
max_seq_len=512
- Add LegacyVocab class for loading old checkpoints (vocab_size=4284)
- TrainingConfig.max_ply defaults to 512 (matches seq_len)
model.py:
- CLMEmbedding derives pad_token, outcome_base, n_actions from
cfg.vocab_size — works with both new (1980) and legacy (4284) vocab
- _build_decomposition_table(n_actions) is parameterized: builds from
engine vocab for new, from old formula for legacy
- Factored embeddings produce identical (src, dst, promo) decomposition
for the same UCI move regardless of vocab
Both PAWNCLM(CLMConfig()) and PAWNCLM(CLMConfig(vocab_size=4284)) produce
correct output shapes and decomposition tables.
* Update Python data pipeline for searchless_chess vocabulary
data.py:
- pack_clm_sequences uses torch.full(PAD_TOKEN) instead of torch.zeros
- CLMDataset passes prepend_outcome flag to engine (default false)
- create_validation_set gains prepend_outcome parameter
lichess_data.py:
- LegalMaskBuilder default vocab_size: 4278 → 1968
- LegalMaskCollate default vocab_size: 4278 → 1968
- compute_legal_indices default vocab_size: 4278 → 1968
generation.py:
- Use model.cfg.vocab_size instead of class default for legal mask size
* Update all tests and remaining Python code for searchless_chess vocabulary
Tests (14 files, 1328 pass):
- test_config.py: new constants (PAD=1968, outcomes at 1969+, vocab_size=1980)
- test_model.py: decomp table shape [1968,3], token ranges [0,1967]
- test_data.py: PAD=1968 in pack_clm_sequences assertions
- test_clm_format.py: engine calls use prepend_outcome=True for
outcome-format tests, new token ranges for all assertions
- test_512_token.py: updated for new vocab + no-outcome default
- test_rosa.py, test_specialized_clm.py: token range fixes
- test_lichess_data.py: remove hardcoded vocab_size=4278
- test_trainer.py: updated for new defaults
Python source:
- probes.py: no_outcome_token defaults to True (no stripping needed)
- specialized_clm.py: handle PAD_TOKEN > vocab_size gracefully
- generation.py: get_legal_token_masks_batch default vocab_size=1980
- trainer.py: updated by background agent for new vocab defaults
* Add --legacy-vocab flag and resume validation to training scripts
train.py:
- PretrainConfig.max_seq_len defaults to 512 (was 256)
- --legacy-vocab flag sets vocab_size=4284, max_seq_len=256
- Resume path validates checkpoint vocab_size matches model
train_all.py:
- --legacy-vocab flag applies to all variant configs
- max_ply derived from model_cfg.max_seq_len (512 or 256)
* Add backward compatibility tests and update CLAUDE.md
tests/model/test_backward_compat.py (10 tests):
- Old/new model instantiation and forward pass
- Factored embedding equivalence across vocabs
- pawn_to_searchless/searchless_to_pawn roundtrips
- Impossible move conversion returns -1
- CLM batch format verification for both vocab modes
CLAUDE.md:
- Token vocabulary: 1968 actions + 1 PAD + 11 outcomes = 1980
- Sequence format: pure moves (512 tokens), outcome prefix optional
- max_seq_len: 256 → 512
- Document prepend_outcome flag and conversion functions
* Remove VOCAB_TRANSITION.md planning document
* Fix review issues: legacy decomp off-by-one, data corruption, legality metric
Bug fixes:
- Legacy decomp table: allocate n_actions+1 rows so token 4272 (last promo)
is reachable. Fix clamp in forward() to use decomp_table.shape[0]-1.
Add test for token 4272 vs 4271 aliasing.
- strip_outcome_token: guard with `prepend_outcome` check to prevent
silently dropping first move when --no-outcome-token is used with the
new default (prepend_outcome=False).
- Legality metric: parameterize compute_legal_move_rate_from_preds by
n_actions so legacy-vocab predictions use the correct grid index mapping.
Cache grid index tensors per (n_actions, device).
- --legacy-vocab: set config.max_seq_len=256 before the override block
so it doesn't get clobbered to 512.
- SpecializedCLM: derive padding_idx from vocab_size (0 for legacy, 1968
for new, None for toy).
Performance:
- move_to_token: use stack [u8; 5] buffer instead of String allocation.
Eliminates ~1.3M heap allocs/sec on the hot game generation path.
Rust:
- Add test_clm_batch_seq_len_consistency_no_outcome asserting
max_ply == seq_len when prepend_outcome=false.
305 Rust tests, 1339 Python tests pass.
* Pass n_actions to legality metric in train_all.py and backfill_metrics.py
- train_all.py: pass model.embed.n_actions to compute_legal_move_rate_from_preds
- backfill_metrics.py: pass model.embed.n_actions to compute_legal_move_rate
- compute_legal_move_rate wrapper: forward n_actions parameter
- train.py: fix misleading comment on --legacy-vocab max_seq_len override
* Deprecate no_outcome_token flag, fix stale docstring
- CLMTrainer: emit DeprecationWarning when no_outcome_token is set,
stop passing it to CLMDataset/create_validation_set (it was a no-op
since prepend_outcome defaults to False)
- pack_clm_sequences docstring: remove hardcoded "(256)" from seq_len1 parent 805548c commit 061b508
File tree
40 files changed
+8360
-1078
lines changed- engine
- python/chess_engine
- src
- pawn
- eval_suite
- scripts
- tests
- adapters
- core
- model
- training
40 files changed
+8360
-1078
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| |||
55 | 55 | | |
56 | 56 | | |
57 | 57 | | |
| 58 | + | |
58 | 59 | | |
59 | 60 | | |
60 | 61 | | |
61 | 62 | | |
62 | | - | |
63 | | - | |
| 63 | + | |
| 64 | + | |
64 | 65 | | |
65 | | - | |
| 66 | + | |
66 | 67 | | |
67 | 68 | | |
68 | 69 | | |
| |||
373 | 374 | | |
374 | 375 | | |
375 | 376 | | |
376 | | - | |
| 377 | + | |
377 | 378 | | |
378 | 379 | | |
379 | 380 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
| 41 | + | |
| 42 | + | |
41 | 43 | | |
42 | 44 | | |
43 | 45 | | |
| |||
73 | 75 | | |
74 | 76 | | |
75 | 77 | | |
| 78 | + | |
| 79 | + | |
76 | 80 | | |
77 | 81 | | |
78 | 82 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
281 | 281 | | |
282 | 282 | | |
283 | 283 | | |
284 | | - | |
285 | | - | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
286 | 289 | | |
287 | 290 | | |
288 | 291 | | |
289 | 292 | | |
290 | 293 | | |
291 | 294 | | |
| 295 | + | |
292 | 296 | | |
293 | | - | |
| 297 | + | |
294 | 298 | | |
295 | 299 | | |
296 | 300 | | |
297 | 301 | | |
298 | 302 | | |
299 | | - | |
300 | | - | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
301 | 306 | | |
302 | 307 | | |
303 | 308 | | |
304 | 309 | | |
305 | | - | |
306 | | - | |
307 | | - | |
308 | | - | |
309 | | - | |
310 | | - | |
311 | | - | |
312 | | - | |
313 | | - | |
314 | | - | |
315 | 310 | | |
316 | 311 | | |
317 | | - | |
318 | | - | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
319 | 338 | | |
320 | | - | |
321 | | - | |
322 | | - | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
323 | 343 | | |
324 | | - | |
325 | 344 | | |
326 | 345 | | |
327 | 346 | | |
328 | 347 | | |
329 | 348 | | |
330 | | - | |
331 | | - | |
332 | | - | |
333 | | - | |
334 | | - | |
335 | | - | |
336 | 349 | | |
337 | 350 | | |
338 | 351 | | |
| |||
408 | 421 | | |
409 | 422 | | |
410 | 423 | | |
411 | | - | |
| 424 | + | |
412 | 425 | | |
413 | 426 | | |
414 | 427 | | |
| |||
419 | 432 | | |
420 | 433 | | |
421 | 434 | | |
422 | | - | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
423 | 438 | | |
424 | 439 | | |
425 | 440 | | |
426 | 441 | | |
427 | | - | |
| 442 | + | |
428 | 443 | | |
429 | 444 | | |
430 | | - | |
431 | | - | |
| 445 | + | |
| 446 | + | |
432 | 447 | | |
433 | 448 | | |
434 | | - | |
| 449 | + | |
435 | 450 | | |
436 | | - | |
| 451 | + | |
437 | 452 | | |
438 | 453 | | |
439 | 454 | | |
| |||
442 | 457 | | |
443 | 458 | | |
444 | 459 | | |
445 | | - | |
| 460 | + | |
446 | 461 | | |
447 | 462 | | |
448 | | - | |
| 463 | + | |
449 | 464 | | |
450 | 465 | | |
451 | 466 | | |
| |||
461 | 476 | | |
462 | 477 | | |
463 | 478 | | |
464 | | - | |
465 | | - | |
| 479 | + | |
| 480 | + | |
466 | 481 | | |
467 | 482 | | |
468 | 483 | | |
| |||
471 | 486 | | |
472 | 487 | | |
473 | 488 | | |
474 | | - | |
| 489 | + | |
475 | 490 | | |
476 | 491 | | |
477 | 492 | | |
| |||
503 | 518 | | |
504 | 519 | | |
505 | 520 | | |
506 | | - | |
507 | | - | |
| 521 | + | |
| 522 | + | |
508 | 523 | | |
509 | 524 | | |
510 | 525 | | |
| |||
685 | 700 | | |
686 | 701 | | |
687 | 702 | | |
688 | | - | |
689 | | - | |
| 703 | + | |
| 704 | + | |
690 | 705 | | |
691 | | - | |
| 706 | + | |
692 | 707 | | |
693 | 708 | | |
694 | 709 | | |
695 | 710 | | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
696 | 720 | | |
697 | 721 | | |
698 | 722 | | |
699 | | - | |
| 723 | + | |
700 | 724 | | |
701 | 725 | | |
702 | 726 | | |
| |||
708 | 732 | | |
709 | 733 | | |
710 | 734 | | |
711 | | - | |
| 735 | + | |
712 | 736 | | |
713 | 737 | | |
714 | 738 | | |
| |||
726 | 750 | | |
727 | 751 | | |
728 | 752 | | |
729 | | - | |
| 753 | + | |
730 | 754 | | |
731 | 755 | | |
732 | 756 | | |
| |||
794 | 818 | | |
795 | 819 | | |
796 | 820 | | |
797 | | - | |
798 | | - | |
| 821 | + | |
| 822 | + | |
799 | 823 | | |
800 | 824 | | |
801 | 825 | | |
802 | 826 | | |
803 | 827 | | |
804 | 828 | | |
805 | 829 | | |
806 | | - | |
| 830 | + | |
807 | 831 | | |
808 | 832 | | |
809 | 833 | | |
| |||
0 commit comments