Chess APO Bench: Chess Puzzles for Automatic Prompt Optimization
8
3 commits
1 linked in READMEs
updated Oct 5, 2026
The exact chess puzzle train/test splits used in the paper Benchmarking Prompt Optimization of Large Language Models With Chess (Lesort et al., 2026). The puzzles come from the Lichess puzzle database (CC0 1.0).
from datasets import load_dataset
ds = load_dataset("imecai/chess-apo-bench")
print(ds) # train: 559 rows, test: 559 rows
print(ds["test"][0]["FEN"], ds["test"][0]["Moves"])
test = load_dataset("imecai/chess-apo-bench", split="test") # a single split
| Split | File | Puzzles | Independent positions |
|---|---|---|---|
train | data/puzzle_train.csv | 559 | 1,439 |
test | data/puzzle_test.csv | 559 | 1,439 |
These files are the frozen splits used in the paper, published byte-for-byte:
| File | SHA-256 |
|---|---|
data/puzzle_train.csv | cddc48ba72b255b4bf7f607bf4c9a914f37ad927ae72198f66bd1f1ac547c87c |
data/puzzle_test.csv | 91f832bc242a4829da7aa8f75d131967faa500a0a18c94a515e5cc5f329e7c55 |
The splits share no puzzle IDs, starting positions, or (FEN, Moves) lines.
In the paper, optimizers see only train. In each run, train is divided into
419 training and 140 validation puzzles, keeping all positions of a puzzle
together. test is held out for the final evaluation.
Both splits have the same stratified composition:
mate theme.NumMoves): 1 β 159, 2 β 160, 3 β 80, 4 β 80, 5 β 80.Each puzzle is expanded into independent positions, one per solver turn. The reference line is replayed, and the model sees the position (FEN, side to move and the sorted legal moves) and must return the reference move. Unparseable or illegal answers count as wrong. The paper's main metric is puzzle-level accuracy: a puzzle counts as solved only if every one of its positions is answered correctly.
The first ten columns are the original Lichess puzzle fields. The last five record how the paper's splits were built.
| Column | Type | Description |
|---|---|---|
PuzzleId | string | Lichess puzzle ID (https://lichess.org/training/<PuzzleId>). |
FEN | string | Position before the opponent's move that sets up the puzzle. |
Moves | string | Space-separated UCI moves. The first is the opponent's setup move. After that, solver and opponent moves alternate, so solver moves are the 2nd, 4th, β¦. |
Rating | int | Lichess puzzle rating (Glicko-2). |
RatingDeviation | int | Rating deviation. |
Popularity | int | Lichess popularity score (β100 to 100). |
NbPlays | int | Number of times the puzzle was played on Lichess. |
Themes | string | Space-separated Lichess themes (e.g. mate mateIn1 endgame). |
GameUrl | string | Source game and ply on Lichess. |
OpeningTags | string, nullable | Space-separated opening tags. Empty for most puzzles. |
NumMoves | int | Number of solver moves, i.e. independent positions (1β5). |
RatingBin | string | 100-point rating bin used for stratification, e.g. (1800, 1900]. |
Mate | bool | True if Themes contains mate. |
GameId | string | Lichess game ID, taken from GameUrl. |
GameSAN | string | SAN moves of the source game, leading to FEN. |
The puzzle records come from the Lichess puzzle database, released under CC0 1.0. This dataset is released under CC0 1.0 as well. Thanks to Lichess and its community for making the puzzle database freely available.
@article{lesort2026chessapo,
title = {Benchmarking Prompt Optimization of Large Language Models With Chess},
author = {Lesort, Timoth{\'e}e and L{\'o}pez de Aberasturi G{\'o}mez, Alejandra and Karch, Tristan and Veniat, Tom and Modard, Philippe and Tuyls, Karl and Denoyer, Ludovic},
journal = {arXiv preprint arXiv:2610.00416},
year = {2026}
}
Chess APO Bench: Chess Puzzles for Automatic Prompt Optimization
8
3 commits
1 linked in READMEs
updated Oct 5, 2026
The exact chess puzzle train/test splits used in the paper Benchmarking Prompt Optimization of Large Language Models With Chess (Lesort et al., 2026). The puzzles come from the Lichess puzzle database (CC0 1.0).
from datasets import load_dataset
ds = load_dataset("imecai/chess-apo-bench")
print(ds) # train: 559 rows, test: 559 rows
print(ds["test"][0]["FEN"], ds["test"][0]["Moves"])
test = load_dataset("imecai/chess-apo-bench", split="test") # a single split
| Split | File | Puzzles | Independent positions |
|---|---|---|---|
train | data/puzzle_train.csv | 559 | 1,439 |
test | data/puzzle_test.csv | 559 | 1,439 |
These files are the frozen splits used in the paper, published byte-for-byte:
| File | SHA-256 |
|---|---|
data/puzzle_train.csv | cddc48ba72b255b4bf7f607bf4c9a914f37ad927ae72198f66bd1f1ac547c87c |
data/puzzle_test.csv | 91f832bc242a4829da7aa8f75d131967faa500a0a18c94a515e5cc5f329e7c55 |
The splits share no puzzle IDs, starting positions, or (FEN, Moves) lines.
In the paper, optimizers see only train. In each run, train is divided into
419 training and 140 validation puzzles, keeping all positions of a puzzle
together. test is held out for the final evaluation.
Both splits have the same stratified composition:
mate theme.NumMoves): 1 β 159, 2 β 160, 3 β 80, 4 β 80, 5 β 80.Each puzzle is expanded into independent positions, one per solver turn. The reference line is replayed, and the model sees the position (FEN, side to move and the sorted legal moves) and must return the reference move. Unparseable or illegal answers count as wrong. The paper's main metric is puzzle-level accuracy: a puzzle counts as solved only if every one of its positions is answered correctly.
The first ten columns are the original Lichess puzzle fields. The last five record how the paper's splits were built.
| Column | Type | Description |
|---|---|---|
PuzzleId | string | Lichess puzzle ID (https://lichess.org/training/<PuzzleId>). |
FEN | string | Position before the opponent's move that sets up the puzzle. |
Moves | string | Space-separated UCI moves. The first is the opponent's setup move. After that, solver and opponent moves alternate, so solver moves are the 2nd, 4th, β¦. |
Rating | int | Lichess puzzle rating (Glicko-2). |
RatingDeviation | int | Rating deviation. |
Popularity | int | Lichess popularity score (β100 to 100). |
NbPlays | int | Number of times the puzzle was played on Lichess. |
Themes | string | Space-separated Lichess themes (e.g. mate mateIn1 endgame). |
GameUrl | string | Source game and ply on Lichess. |
OpeningTags | string, nullable | Space-separated opening tags. Empty for most puzzles. |
NumMoves | int | Number of solver moves, i.e. independent positions (1β5). |
RatingBin | string | 100-point rating bin used for stratification, e.g. (1800, 1900]. |
Mate | bool | True if Themes contains mate. |
GameId | string | Lichess game ID, taken from GameUrl. |
GameSAN | string | SAN moves of the source game, leading to FEN. |
The puzzle records come from the Lichess puzzle database, released under CC0 1.0. This dataset is released under CC0 1.0 as well. Thanks to Lichess and its community for making the puzzle database freely available.
@article{lesort2026chessapo,
title = {Benchmarking Prompt Optimization of Large Language Models With Chess},
author = {Lesort, Timoth{\'e}e and L{\'o}pez de Aberasturi G{\'o}mez, Alejandra and Karch, Tristan and Veniat, Tom and Modard, Philippe and Tuyls, Karl and Denoyer, Ludovic},
journal = {arXiv preprint arXiv:2610.00416},
year = {2026}
}