Open chess model · plays the style you describe

Tell a chess model how to play.

CHSM8 is a 210M-parameter chess transformer that picks its moves from a free-text description of a playing style. It plays without search, and every move is legal by construction. Weights, datasets, labels and demos are open.

1837Elo of the pretrained model against Stockfish at UCI_Elo 2000, no search
1.07Bfiltered Lichess games for pretraining
30.1Mgame sides with five style descriptions each
53→67%early queen trades when asked, before and after DPO

What it does

Chess models trained on human games now play well without search, but none of them lets you simply say how they should play. Rating-conditioned models control strength and player-specific models control identity; CHSM8 accepts an open-ended request. It is built for sparring and fun rather than grandmaster-level play, and it stays strong without search.

trade queens as early as possible castle queenside and storm the enemy king with your pawns go for the Sicilian Defense solid, safe, risk-free chess play like Magnus Carlsen

Text in, move out

A frozen EmbeddingGemma-300m encodes the prompt. Gated cross-attention in the top 6 of 12 decoder layers reads every token of it.

Legal by construction

Each move is a tuple (source, destination, piece, promotion) with one output head per field. The model scores only the legal moves of the position.

No search

One forward pass per move: the model plays its highest-scoring legal move. That is fast enough to run in a browser tab.

Try it

Play against CHSM8, give each side a style prompt, and see the probabilities behind every move.

The move tokenizer, live

Any notation in (SAN, LAN, UCI, numbered PGN with comments and variations, mixed within one game), the exact model input out. Each move becomes a 15-bit id (6 bits from-square, 6 bits to-square, 3 bits promotion) and a model row (kind, src, dst, piece, promo). This box runs the Rust tokenizer compiled to WebAssembly, the same code the demos use.

Use it

The models are project-specific PyTorch checkpoints on Hugging Face; the inference code is one file, chsm8.py, in the code repository.

Score moves from Python

# needs a Rust toolchain for the tokenizer (https://rustup.rs)
git clone https://github.com/nov3o/llm_chess-demo
cd llm_chess-demo && pip install -r requirements.txt
hf auth login   # once: the prompt encoder is gated
from chsm8 import CHSM8

model = CHSM8.from_pretrained()   # LegumMagister/chsm8
moves = model.score("1. e4 e5 2. Nf3",
    "castle queenside and storm the enemy king with your pawns")
print(moves[:3])   # legal moves with log-probabilities, best first

An empty prompt gives the model's own play. Other weights: CHSM8.from_pretrained("LegumMagister/chsm8-sft"), or filename="full_pass/model.pt" for the full-pass DPO model. Accept the EmbeddingGemma-300m license on Hugging Face first.

Tokenizer and data

pip install "git+https://huggingface.co/LegumMagister/chsm8-tokenizer"
import chsm8_tok
chsm8_tok.tokenize("1. e4 e5 2. Nf3")   # [1804, 2356, 1350]
chsm8_tok.convert("1. e4 e5 2. Nf3", dst="lan", type="text")
# 'e2-e4 e7-e5 Ng1-f3'
from datasets import load_dataset
games = load_dataset("LegumMagister/chsm8-pre-training",
                     split="train", streaming=True)
labels = load_dataset("LegumMagister/chsm8-post-training",
                      split="validation")

Games join their style labels on (month, row_idx), the stable game id of every CHSM8 dataset.

How it is built

Standard components at every stage: a Llama-style decoder, GPT-3 style schedules, Flamingo-style gated cross-attention, distilled labels and DPO. Design choices at each stage were made by fixed-budget automated search loops in the style of autoresearch. Elo is without a prompt, against Stockfish at UCI_Elo 2000. Select a stage.

style branch, from chsm8-pt
games-only branch, from chsm8-pt

Key results

Greedy legal moves against Stockfish 17.1 limited to UCI_Elo 2000, colors alternating. The Elo scale is a reproducible engine calibration, not a FIDE or Lichess rating. Style results use 2,000 games per prompt (95% precision about ±1 to 2 points for shares and ±21 Elo).

Prompts change play, and DPO sharpens it

The targeted behavior of the model's own side with no prompt, with the matching prompt, and under the three other main prompts (6,000 games).

Main comparison

modelqueens traded by ply 40pawn moves per movequeenside castlingElo, no prompt
chsm8-sft53.0%.29097.3%1792
chsm866.5%.31999.7%1797
chsm8, full pass58.7%.31799.6%1812

Each metric is measured under its own prompt; queenside castling is the share of castling. The main model is a 20-minute DPO run on 1 GPU; a full pass over the data did not improve on it. Strength without a prompt is unchanged.

The cost of following risky prompts

Told to attack at all costs and sacrifice material, chsm8 does, and without search it loses about 150 Elo against an accurate engine (SFT: about 40). Training games labeled as sacrificial were not lost more often.

Strong without search

chsm8-pt against other public models trained without preference tuning, rewards or search: 200 games each, from 100 openings with colors swapped. Elo advantage with 95% CI. It wins every match, including against a 2.8B model.

Strength during pretraining

200 games per checkpoint (±50 Elo); final model 999 games, 1837 Elo (95% CI 1817 to 1856). The pass was restarted at 60% with the remaining data reshuffled, after a loss bump tied to the 2021-09 to 2022-05 Lichess months.

Against strong public models, 1,000 games per match

Score of each CHSM8 model (wins plus half the draws), both sides playing their most likely legal move from book openings with both colors. Every opponent was also rated against Stockfish under the same protocol, where chsm8-pt rates 1837, chsm8-player-base 1890 and the Carlsen fine-tune 1903.

opponentits Elochsm8-ptplayer-baseplayer-carlsen
public models trained by supervised prediction
Maia-2 blitz165765.3%71.8%71.7%
ChessLFM168791.5%93.3%92.8%
Kempner ChessFormer 50M173386.5%90.0%93.9%
chess-gpt2-uci178482.2%88.8%91.0%
Chess-GPT (Karvonen)187375.1%83.3%81.1%
ChessGPT-base 2.8B173188.0%93.7%94.3%
strong recent models, no search
Otter 15M202149.1%56.1%61.1%
Allie 2.0223213.5%21.2%19.8%
Maia-3 79M227114.0%15.7%21.3%
Searchless 9M240314.9%13.0%16.7%
Searchless 136M258410.2%10.3%6.3%
with search
Matilda (Maia-3 + Stockfish)30091.9%4.1%1.6%

CHSM8 wins every match against the older public models, is about even with Otter, and loses clearly to Allie 2.0, Maia-3 and DeepMind's searchless transformers, which are trained on far more data or on engine evaluations. None of the opponents takes a text prompt.

Player prompts

On about 1,000 held-out games for each of the 20 top players with the most data, "play like {player}" with the right name makes the player's real moves more likely than the same wording with another top player's name, for all 20 players.

chsm8, paired on 20,508 gamesanother nameright name
probability of the player's move47.1%48.7%
top-1 move match53.7%55.5%
top-3 move match77.4%78.8%

Across all 99 players, the right name wins in cross-entropy for 94 (SFT) and 96 (DPO). The effect is modest because top players differ little in their moves.

Labels that agree with the board

Gemma-4-31B described 3.02M game sides from their moves plus a card of features measured on the board. A Gemma-3-1B student, distilled from the 2.4M teacher sets that contradict nothing on the board, labeled the rest.

labelerlabels contradicting the boardsides per second, 4-GPU node
Gemma-4-31B teacher4.7%7.5
Gemma-3-1B student0.5%520

The student carries as much signal about the game as its teacher. A second teacher, Apertus-70B, wrote vivid labels that carried 4 to 5 times less signal, so it was dropped.

Models and datasets

Everything is public on Hugging Face. You are welcome to reproduce the results, build on the models and use the data and labels in your own work. The training code and search logs will follow.

modelwhatElo, no promptlicense
chsm8final style model (DPO; called chsm8-dpo in the report), full-pass variant, browser ONNX export1797MIT
chsm8-sftstyle-conditioned SFT model, evaluation prompts1792MIT
chsm8-ptpretrained model, no text input1837MIT
chsm8-player-basegames-only continuation, no cross-attention; recommended base for new work1890MIT
chsm8-player-*14 player models: the FIDE top 10, plus Fischer, Kasparov, Karpov and Polgar1850 to 1910MIT
chsm8-labeler-gemma3-1bstyle labeler distilled from Gemma-4-31BGemma
chsm8-tokenizerRust move tokenizer and notation converter, Python and WebAssemblyMIT
datasetwhatsizelicense
chsm8-pre-trainingfiltered Lichess games, 2013-01 to 2026-06, with conversion scripts1.07B gamesCC0
chsm8-post-traininggame sides with five style descriptions, the SFT and DPO splits30.1M sidesApache-2.0
chsm8-labeler-distillthe clean Gemma-4-31B label sets the labeler was distilled from2.40M setsApache-2.0
chsm8-teacher-labelsevery teacher label (Gemma-4-31B, Apertus-v1.5-70B), raw and repaired7.77M setsApache-2.0
chsm8-top-playersgames of the 14 modeled players with their held-out splits, crawler and prompt templates119,618 gamessee card

Code: github.com/nov3o/llm_chess-demo (inference, ONNX export, both demos; MIT). The prompt encoder, EmbeddingGemma-300m, is downloaded at run time under the Gemma Terms of Use.

Limitations

  • No search. The model can miss tactics an engine would see, and risky prompts cost strength against an accurate opponent.
  • An alignment tax. Style SFT costs about 45 Elo without a prompt (1792 against 1837), because the decoder learns to fit the description as well as the move.
  • No weak-play conditioning. Every described player is rated 2200 or higher, so asking for weaker or stronger play does not change strength.
  • Modest player effect. Player prompts work for 94 of 99 players, but move match rises by only about one point.
  • Proxy metrics. Style adherence is measured on a handful of prompts with hand-written metrics, not a validated judgment of style.
  • English prompts only; standard chess only.

Cite

@techreport{badanin2026chsm8,
  title  = {CHSM8: A Chess Transformer that Follows Natural-Language Style Prompts},
  author = {Badanin, Ilia},
  year   = {2026},
  month  = oct,
  url    = {https://llmchess-demo-web.vercel.app}
}