Skip to main content

SightRead

Can your vision-language model read the board at first sight?

SightRead is a benchmark for exact game-state extraction from screenshots. Not whether a model can play chess or mahjong — whether it can see the board: every seat, every tile, every piece, every number, exactly.

Existing game benchmarks (GameWorld, LMGame-Bench, MET-Bench) score agents playing games, confounding perception with policy. SightRead removes policy entirely and audits perception: field-by-field, run-by-run, dollar-by-dollar.


Why this matters

In the original mahjong benchmark run that seeded this project (6 models × 6 screenshots × 3 runs, 22 fields, hand-verified ground truth):

Model Field accuracy Hand-tile F1 $/call
qwen3.8-27b (API) 89.4% ± 7.3% 90.3% $0.035
qwen3.8-27b (local Q5_K_M, free) 84.8% ± 9.6% 95.2% free
glm-5.3-flash (API) 74.7% ± 13.8% 85.1% $0.008

The headline findings are more interesting than the leaderboard:

  • Exact hands are the hardest field by 2× (25.7% exact) — but per-tile F1 shows models are close; all-or-nothing scoring hides it.
  • Seat winds flip between runs while seat points score 100% — a clean dissociation between reading numbers (OCR) and spatial relational reasoning (which badge belongs to which seat). This is SightRead's central question.
  • Populated discard piles: ~19% correct for every model. Unsolved.
  • A decoy example in the prompt catches models that echo the prompt instead of looking at the image — now a first-class metric: grounding fidelity.
  • A free local model beats every paid API on the hardest component metric.

What SightRead measures

Metric What it tells you
Field accuracy (mean ± sd over k runs) exact-match rate per state field
Component F1 closeness on multisets (hands, piece lists) — not all-or-nothing
Grounding fidelity decoy-echo rate: did the model read the image or the prompt?
Flip rate which fields change between identical runs — instability, per field
Cost & latency $/call and accuracy-per-dollar, cached-token aware, local = $0

Architecture

A core (game-agnostic) + packs (per-game contributions):

sightread-bench/
├── src/sightread/        # core: comparators, scorer, runner, cost, reports
├── packs/
│   ├── mahjong/          # complete: parser ported from the original benchmark
│   │   ├── pack.yaml     #    field spec + grounding traps
│   │   ├── extract.py    #    format-agnostic response parser
│   │   ├── prompt.md     #    the extraction prompt
│   │   ├── gt/           #    hand-verified ground truth (JSON)
│   │   └── images/       #    screenshots stay LOCAL (gitignored - copyrighted)
│   └── chess/            # scaffold: FEN-driven GT generation, contamination notes
├── models.example.yaml   # OpenAI-compatible endpoints; llama-server works as-is
└── results/              # calls.jsonl -> results.csv + leaderboard.md

Adding a game = adding a directory. See docs/adding-a-game.md. Scoring runs identically across games; the leaderboard is generated, not hand-edited.

Quickstart

pip install -e .

# validate a pack (schema, GT completeness, enum values)
sightread check --pack packs/mahjong

# run models (resume-safe; safe to kill and re-run)
cp models.example.yaml models.yaml   # add API keys via env vars
sightread run --pack packs/mahjong --models models.yaml --runs 3 --out results

# score + leaderboard
sightread score --pack packs/mahjong --calls results/calls.jsonl --out results

Local models: llama-server --port 5006 and point base_url at http://127.0.0.1:5006/v1 — the same OpenAI-compatible path, $0/call.

Packs

Pack Status Ground truth Visual difficulty
mahjong (riichi/MahjongSoul) ready hand-verified, 22 fields tiny tiles, spatial seat rotation
chess scaffold programmatic (FEN) requires non-standard skins: models memorize standard diagrams
card games planned programmatic (deck state) occlusion, deduced hidden state
go planned programmatic (SGF) counting; near-empty boards need careful design

Roadmap

  • port remaining parser unit tests from the original harness (68 total)
  • chess pack: contamination-resistant renderer (random piece sets/skins)
  • held-out private packs per game (submission-time evaluation)
  • HuggingFace dataset + leaderboard Space
  • prompt-scaffolding ablation: does describing the seat layout fix wind flips?

Citation

@software{sightread2026,
  title  = {SightRead: Exact Game-State Extraction Benchmark for Vision-Language Models},
  author = {ansteinhuynh},
  year   = {2026},
  url    = {https://github.com/ansteinhuynh/sightread-bench}
}

License

MIT. Screenshots from game platforms are not included in this repository — packs ship ground truth + prompts; capture images locally per the pack README.

Metadata

Release files for sightread-bench 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sightread-bench 0.1.0
File Size Uploaded
sightread_bench-0.1.0.tar.gz 31.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sightread-bench 0.1.0
File Interpreter ABI Platform
sightread_bench-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 48.5 kB

Release files / sightread_bench-0.1.0.tar.gz

Download URL sightread_bench-0.1.0.tar.gz
Size 31.4 kB
Tags Source
SHA-256 checksum
How to use checksums
6a3f22d5c4484d9b19914451ce28daf0621f850c0db0b83b65de7f784c106df0
BLAKE2b-256 checksum
How to use checksums
5f2d75d97486dfae54cef24b81e606279c4e7e5b44ad4e3e6a23615f6961bb67
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / sightread_bench-0.1.0-py3-none-any.whl

Download URL sightread_bench-0.1.0-py3-none-any.whl
Size 17.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
07aa799f33f473e0c17ee88b42d0bfcb439cfe108296619efdbbee4ce34854f9
BLAKE2b-256 checksum
How to use checksums
cbc7d8331556cc100431557e485dfb2a500a8160d8b640b30f3896550b0aca3a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page