Skip to main content

Train lightweight chess personas from PGN files.

Project description

persona-chess

persona-chess is a Python library for training lightweight chess personas from PGN files. The goal is not to find the strongest move. The goal is to predict how a specific player is likely to move.

The current foundation includes PGN ingestion, player filtering, neural persona training, legal move masking, checkpoint inference, baseline comparison models, profile reports, JSON artifacts, and a CLI.

Install

pip install persona-chess
pip install "persona-chess[ml]"
pip install "persona-chess[evaluation]"
pip install "persona-chess[formats]"

CUDA is handled through PyTorch. persona-chess uses CUDA automatically when the installed PyTorch build can see a compatible GPU; otherwise it safely trains on CPU. If CUDA is requested but unavailable, install the PyTorch wheel that matches your NVIDIA driver/CUDA runtime.

For local development:

pip install -e ".[dev]"

Python API

The normal workflow is train once, then load the checkpoint as a bot.

from persona_chess import PersonaChess

result = PersonaChess().train(
    "games.pgn",
    player="Target Player",
    epochs=3,          # optional
    batch_size=32,     # optional
    device="cuda",     # optional; auto uses CUDA when PyTorch can see it
)

print(result.checkpoint_dir)
print(result.model_state_path)  # .../model.pt

bot = PersonaChess.load_neural(result.checkpoint_dir)
move = bot.move("startpos")
print(move.move_uci, move.san)

By default, persona checkpoints are tagged against malcouffe/chessgpt, a 432M-parameter UCI-move ChessGPT model trained on Lichess move sequences under Apache-2.0. This is the selected upstream base model direction for persona-chess because it treats chess as move language instead of engine evaluation. The native checkpoint trainer remains compatible with local init_checkpoint files while the Hugging Face base adapter path is hardened.

For large PGNs, keep the same API and switch on streaming. This writes training records under the checkpoint folder and trains batch by batch instead of keeping the whole dataset in memory:

persona = PersonaChess()
result = persona.train(
    "large-games.pgn.zst",
    player="Target Player",
    streaming=True,
    validation_ratio=0.1,
)

Baseline personas are still available for quick comparison:

from persona_chess import PersonaChess

persona = PersonaChess().fit_pgn("games.pgn", player="Target Player", model_type="blend")
persona.save("target-player.persona.json")

CLI

persona-chess profile games.pgn "Target Player"
persona-chess model-card games.pgn "Target Player" --out target-player.model-card.json
persona-chess train games.pgn "Target Player" --model-type blend --out target-player.persona.json
persona-chess move target-player.persona.json --fen "startpos"
persona-chess export-training games.pgn "Target Player" --out target-player.train.jsonl
persona-chess export-training-stream games.pgn "Target Player" --out target-player.train.jsonl
persona-chess export-base-training-stream public-games.pgn --out base.train.jsonl
persona-chess split-training-stream target-player.train.jsonl --train-out target-player.fit.jsonl --validation-out target-player.valid.jsonl
persona-chess split games.pgn "Target Player" --train-out train.jsonl --test-out test.jsonl
persona-chess benchmark games.pgn "Target Player" --model-type blend --out benchmark.json
persona-chess prepare-neural games.pgn "Target Player" --manifest-out adapter.manifest.json --move-vocab-out moves.vocab.json --position-vocab-out positions.vocab.json
persona-chess prepare-neural-stream target-player.train.jsonl "Target Player" --manifest-out adapter.manifest.json --move-vocab-out moves.vocab.json --position-vocab-out positions.vocab.json
persona-chess recommend-neural-config --training-examples 100000 --device cuda
persona-chess validate-neural adapter.manifest.json moves.vocab.json positions.vocab.json
persona-chess train-neural games.pgn "Target Player" --checkpoint-dir checkpoints/player --use-lora
persona-chess train-neural-stream target-player.train.jsonl --manifest adapter.manifest.json --move-vocab moves.vocab.json --position-vocab positions.vocab.json --checkpoint-dir checkpoints/player --init-checkpoint checkpoints/base
persona-chess neural-move checkpoints/player --fen "startpos"
persona-chess engine-move target-player.persona.json --engine-path /path/to/stockfish --fen "startpos"
persona-chess persona-report target-player.persona.json games.pgn "Target Player" --baseline-model baseline.persona.json --out persona-report.json
persona-chess download-model persona-chess/base-small --registry models.json

Built-in model backends:

  • blend: weighted baseline combining exact position memory, opening book, and phase priors.
  • frequency: exact position memory with global legal fallback.
  • opening_book: early-game repertoire memory.
  • phase: game-phase move prior for opening, middlegame, and endgame positions.

Persona Model Cards

Model cards turn a PGN collection into a portable style and data-quality report. They include style tags, move and phase breakdowns, data warnings, and a recommended inference path.

persona-chess model-card games.pgn "Target Player" --out target-player.model-card.json
persona-chess model-card games.pgn "Target Player" --format markdown --out target-player.model-card.md

Persona Evaluation

persona-report is the main product-level evaluation command. It keeps the project-specific persona metrics in persona-chess, while optionally using common scientific Python tooling through persona-chess[evaluation] when available.

The report includes move-match top-1/top-k, MRR, baseline deltas, phase metrics, piece metrics, style similarity, opening similarity, score confidence, optional SciPy distribution distances, and optional UCI-engine centipawn/blunder metrics.

persona-chess train games.pgn "Target Player" --model-type blend --out target.persona.json
persona-chess train games.pgn "Target Player" --model-type frequency --out baseline.persona.json
persona-chess persona-report target.persona.json games.pgn "Target Player" --baseline-model baseline.persona.json --out persona-report.json
persona-chess persona-report target.persona.json games.pgn "Target Player" --engine-path /path/to/stockfish --out engine-report.json

Engine-Guided Persona Moves

persona-chess can rerank persona candidates with an external UCI engine such as Stockfish or Lc0. The engine is not bundled and the persona model still supplies the candidate style; the UCI engine only acts as a quality signal.

persona-chess engine-move target-player.persona.json --engine-path /path/to/stockfish --fen "startpos" --engine-weight 0.35

Large PGN Training

For large PGN collections, use the streaming commands. They keep the training records on disk and only materialize the active batch during neural training. Input can be plain .pgn or compressed .pgn.gz, .pgn.bz2, .pgn.xz, and .pgn.zst files. Zstandard support is optional:

pip install "persona-chess[formats]"
persona-chess export-training-stream games.pgn "Target Player" --out target-player.train.jsonl
persona-chess split-training-stream target-player.train.jsonl --train-out target-player.fit.jsonl --validation-out target-player.valid.jsonl
persona-chess prepare-neural-stream target-player.train.jsonl "Target Player" --manifest-out adapter.manifest.json --move-vocab-out moves.vocab.json --position-vocab-out positions.vocab.json
persona-chess train-neural-stream target-player.fit.jsonl --manifest adapter.manifest.json --move-vocab moves.vocab.json --position-vocab positions.vocab.json --checkpoint-dir checkpoints/player --validation-records target-player.valid.jsonl --use-lora

To build a general chess policy foundation before persona adaptation, export every move from a large public PGN instead of filtering by one player:

persona-chess export-base-training-stream public-games.pgn --out base.train.jsonl
persona-chess split-training-stream base.train.jsonl --train-out base.fit.jsonl --validation-out base.valid.jsonl
persona-chess prepare-neural-stream base.fit.jsonl "persona-chess-base" --manifest-out base.manifest.json --move-vocab-out base.moves.json --position-vocab-out base.positions.json --config-profile large
persona-chess train-neural-stream base.fit.jsonl --manifest base.manifest.json --move-vocab base.moves.json --position-vocab base.positions.json --checkpoint-dir checkpoints/base --validation-records base.valid.jsonl --full-finetune
persona-chess train-neural-stream target-player.fit.jsonl --manifest adapter.manifest.json --move-vocab base.moves.json --position-vocab base.positions.json --checkpoint-dir checkpoints/player --validation-records target-player.valid.jsonl --init-checkpoint checkpoints/base --use-lora

Neural preparation uses a stable chess-wide position vocabulary by default so base checkpoints and persona adapters can share the same embedding shapes. Use --data-position-vocab only for isolated experiments that will not initialize from another checkpoint.

There are two training modes:

  • PersonaChess().fit_pgn(...) and persona-chess train ... fit a fast baseline persona artifact. This is the quickest way to create a playable opponent.
  • export-training-stream plus prepare-neural-stream plus train-neural-stream runs the neural Transformer/LoRA path. Use this for a base model and stronger per-player adaptation.

Neural Auto Configuration

Neural commands use hardware-aware defaults when training settings are omitted. persona-chess inspects CPU memory and optional CUDA memory, then chooses a small, balanced, or large Transformer + LoRA profile. Users can still override training knobs directly:

persona-chess recommend-neural-config --training-examples 500000 --device cuda
persona-chess prepare-neural-stream target-player.train.jsonl "Target Player" --manifest-out adapter.manifest.json --move-vocab-out moves.vocab.json --position-vocab-out positions.vocab.json --config-profile balanced --epochs 3 --batch-size 32 --gradient-accumulation-steps 4
persona-chess train-neural-stream target-player.train.jsonl --manifest adapter.manifest.json --move-vocab moves.vocab.json --position-vocab positions.vocab.json --checkpoint-dir checkpoints/player --validation-records target-player.valid.jsonl --epochs 2 --batch-size 16

For very large datasets, keep the streaming path: export once, prepare the neural artifacts from JSONL, then train from the manifest. This avoids loading the full PGN or training set into memory at once.

The neural trainer reports train loss, optional validation loss, legal top-1 accuracy, legal top-3 accuracy, optimizer steps, active mixed precision mode, and trainable parameter counts. Training uses AdamW, learning-rate warmup plus cosine decay, gradient accumulation, gradient clipping, and CUDA mixed precision when available.

Long neural runs can save resumable checkpoints:

persona-chess train-neural-stream target-player.fit.jsonl --manifest adapter.manifest.json --move-vocab moves.vocab.json --position-vocab positions.vocab.json --checkpoint-dir checkpoints/player --validation-records target-player.valid.jsonl --save-best --checkpoint-every-epoch
persona-chess train-neural-stream target-player.fit.jsonl --manifest adapter.manifest.json --move-vocab moves.vocab.json --position-vocab positions.vocab.json --checkpoint-dir checkpoints/player-resumed --resume-checkpoint checkpoints/player/best

Remote base checkpoints can be distributed as zip archives through a registry JSON. Each archive must contain a checkpoint.json at or below its root.

{
  "schema_version": "persona-chess/model-registry/v1",
  "models": [
    {
      "name": "persona-chess/base-small",
      "version": "0.1.0",
      "url": "https://example.com/persona-chess-base-small.zip",
      "sha256": "..."
    }
  ]
}

Project Direction

The planned model path is:

  1. A clean PGN-to-position dataset pipeline.
  2. Deterministic train/test splitting at game level.
  3. Strong baseline models for honest comparison.
  4. A chess-native base Transformer trained on large public PGN data.
  5. A training JSONL schema with legal move masks and target move indexes.
  6. Per-player LoRA adapters trained from personal PGNs.
  7. Legal move masking through python-chess.
  8. Evaluation by move-match accuracy and style similarity metrics.

The neural command currently prepares versioned adapter manifests, move vocabularies, and position vocabularies. The package also includes an optional PyTorch Transformer policy skeleton behind the ml extra, with PEFT-powered LoRA, legal-masked policy batches, checkpoint helpers, and checkpoint inference. It is not enabled for standard installs.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

persona_chess-0.2.0.tar.gz (74.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

persona_chess-0.2.0-py3-none-any.whl (88.7 kB view details)

Uploaded Python 3

File details

Details for the file persona_chess-0.2.0.tar.gz.

File metadata

  • Download URL: persona_chess-0.2.0.tar.gz
  • Upload date:
  • Size: 74.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for persona_chess-0.2.0.tar.gz
Algorithm Hash digest
SHA256 ee9c8d526f41f57c0a81b685be9e786fcdf27c59c1b6652e2297947bd08568be
MD5 5dd559d2873a7de28f237eb7f987efc0
BLAKE2b-256 88f83115be23e3af958eb2b658e2969a7ab5ace125f8d50a7bdc70f5bdc03f44

See more details on using hashes here.

Provenance

The following attestation bundles were made for persona_chess-0.2.0.tar.gz:

Publisher: publish.yml on brutalstein/persona-chess

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file persona_chess-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: persona_chess-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 88.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for persona_chess-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f1d68a01aef99d16bdcd37d151bbe77bb77095deea7193da200768784a299ff9
MD5 c2952e45df7bd74e9a9581411cd12368
BLAKE2b-256 8cfb4f8a6e4e721789a2ca7cda3845d18c12b9a7f41d121431a3c780993a4779

See more details on using hashes here.

Provenance

The following attestation bundles were made for persona_chess-0.2.0-py3-none-any.whl:

Publisher: publish.yml on brutalstein/persona-chess

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page