chess-gpt-pgn-char (A)

A 50.9M-parameter GPT that plays chess by predicting the next move token. There is no search and no evaluation function: one forward pass per move. It is model A of three models trained the same way and differing only in their tokenizer:

Model Tokenizer A token is Vocab
A pgn-char one character of 1.e4 e5 2.Nf3 34
B uci-move one move, g1f3 1971
C uci-square one square (+ promotion piece), g1 f3 71

Write-up: blog.wezn.dev/chess-gpt ยท Code: github.com/wezn/chess-gpt

This model

  • Architecture: decoder-only transformer, 16 layers, 8 heads, width 512, context 1024 tokens, tied embeddings
  • Training data: 35M Lichess games (rapid and slower, all ratings), each seen once
  • Training: 206,934 steps on one NVIDIA GB10
  • Validation loss per move: 1.564

Mean over the final 11 snapshots, from the write-up:

A B C
Elo (Lichess scale, estimated from self-play scored by Stockfish) 1,940 1,908 1,792
Legal moves on held-out human games 99.75% 99.45% 99.71%
Average centipawn loss 56 58 61

The Elo figures are estimates, not results from rated play. The write-up describes how they were measured.

Usage

git clone https://github.com/wezn/chess-gpt && cd chess-gpt && uv sync
uv run hf download ftaz/chess-gpt-pgn-char --local-dir models/chess-gpt-pgn-char
import chess
from chessgpt.eval.player import ModelPlayer

player = ModelPlayer("models/chess-gpt-pgn-char", device="cpu")
board = chess.Board()
for san in ["e4", "e5", "Nf3", "Nc6", "Bb5", "a6"]:
    board.push_san(san)
print(player.choose_moves([board])[0].move)                         # the model's move
print([(board.san(m), round(p, 3)) for m, p in player.rank_legal_moves(board)[:3]])

config.json holds the architecture and tokenizer. model.safetensors holds the weights only.

Downloads last month
-
Safetensors
Model size
50.9M params
Tensor type
F32
ยท
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support