MTG Commander Deck Completion

Given a Commander (and optionally a partial decklist), suggests which other cards belong in the deck. Trained on 122,571 real public Commander decklists from Moxfield (dataset).

Training/evaluation code: github.com/nsaroiu/mtg-deck-completion (the tokenizer + model + training/eval pipeline that produced these weights β€” not the Moxfield data-collection pipeline or the web UI built on top of this model, which live elsewhere and aren't public).

Architecture

Every card gets a hybrid embedding: a learned per-card vector, summed with a small MLP over structured features (color identity, mana cost, type, keywords) and a semantic sentence embedding of its oracle text β€” so even a rarely-seen card starts from a meaningful representation instead of a near-random one.

A deck is treated as an unordered set: a permutation-invariant encoder (mean-pool or self-attention) pools the known cards + commander(s) into one vector, scored against the full card vocabulary via a tied dot product (word2vec-style).

Production inference is an ensemble of two specialized checkpoints, not one model β€” a single model/loss was tried and found to trade off staple recognition against synergy ranking:

  1. Synergy phase (set_transformer_softmax_checkpoint.pt, self-attention encoder): generates iteratively, a few picks at a time, re-conditioning on its own prior picks β€” this is what surfaces specific combo/synergy pieces rather than a generic "good stuff" pile.
  2. Staple backfill (deepsets_softmax_checkpoint.pt, mean-pool encoder): tops up near-universal staples (Sol Ring, Command Tower, ...) to a realistic target count, since the synergy phase alone under-recommends them.
  3. Optional pruning pass (prune_checkpoint_inject_lowdensity.pt): a separate discriminator model that re-scores the assembled deck and cuts the weakest fit, the one step no generation-only model can do.

Files

file role
deepsets_softmax_checkpoint.pt staple-recognition specialist
set_transformer_softmax_checkpoint.pt synergy-ranking specialist
prune_checkpoint_inject_lowdensity.pt optional deck-pruning pass
tokenizer.json card vocabulary + structured features
tokenizer_text_embeddings.npy cached oracle-text sentence embeddings
card_tiers.json staple / mid-tier / long-tail classification per card

All three checkpoints share the same card vocabulary and expect tokenizer.json / tokenizer_text_embeddings.npy alongside them.

Evaluation

Recall@50 / Precision@50 / MRR on held-out real decks, by how much of the deck is already known (mask ratio β€” low = mostly complete, high = mostly empty), staple-recognition checkpoint, validation split:

mask ratio Recall@50 Precision@50 MRR
0.1 (deck mostly complete) 0.60 0.10 0.132
0.5 0.51 0.44 0.068
0.9 (deck mostly empty) 0.38 0.59 0.046

Held-out-commander split (commanders never seen in training, testing generalization via card content rather than memorized co-occurrence): Recall@50 0.27–0.41 across the same ratio range β€” meaningfully above chance, confirming the hybrid content embeddings carry real signal for unfamiliar commanders. Full breakdown by card-popularity tier, plus the synergy/pruning checkpoints' own numbers, in the GitHub repo's eval output.

Usage

There's no standalone pip package yet β€” loading these checkpoints requires the tokenizer + model code from the GitHub repo above (tokenizer/ and training/; no other part of that repo is needed to run inference):

git clone https://github.com/nsaroiu/mtg-deck-completion
cd mtg-deck-completion
pip install -r requirements.txt
from huggingface_hub import hf_hub_download

repo = "nsaroiu/mtg-deck-completion"
for f in ["deepsets_softmax_checkpoint.pt", "set_transformer_softmax_checkpoint.pt",
          "prune_checkpoint_inject_lowdensity.pt", "tokenizer.json",
          "tokenizer_text_embeddings.npy", "card_tiers.json"]:
    hf_hub_download(repo_id=repo, filename=f, local_dir=".")

from training.evaluate import load_checkpoint
from training.ensemble import ensemble_complete_deck, load_tiers
from training.train import pick_device

device = pick_device()
staple_model, tok, _ = load_checkpoint("deepsets_softmax_checkpoint.pt", device)
synergy_model, _, _ = load_checkpoint("set_transformer_softmax_checkpoint.pt", device)
tiers = load_tiers(tok, path="card_tiers.json")

# (name, score, source) triples, source in {"synergy", "staple"}
results = ensemble_complete_deck(
    ["Atraxa, Praetors' Voice"], [], 20, tok, device,
    staple_model, synergy_model, tiers,
)
for name, score, source in results:
    print(f"{score:.3f}  [{source:7}]  {name}")

training/ensemble.py is also a CLI covering the same flow shown above (--commander β€” repeatable, for partner commanders β€” --card, --chunk-size/--temperature for the iterative synergy phase, --prune-checkpoint to enable the pruning pass). training/complete_deck.py exposes just one specialist checkpoint at a time, without the ensemble fusion, if that's all you need.

Limitations

  • Staple-tier ranking is imprecise in a near-empty context. The model confidently recognizes that a staple belongs (~90% precision when it predicts one) well before it reliably ranks which specific staple is the true target β€” the ensemble's backfill phase exists specifically to work around this.
  • Color-identity legality is not learned β€” it's enforced as a deterministic post-filter (see legal_mask in training/complete_deck.py). Using the raw logits without that filter can suggest illegal cards.
  • Iterative generation (the synergy phase's default mode) is an experimental setting, tuned on a sample of 11 commanders, not exhaustively validated.
  • Trained only on real, currently-popular Commander decks β€” a Commander format power-level/meta shift (new sets, ban changes) isn't reflected until retrained on fresher data.

License

The weights and code in this repository are released under the MIT license. The training data itself is a scrape of public Moxfield decklists with no asserted license (see the dataset card) β€” if that matters for your use case, that's Moxfield's terms to check, not a constraint this repo imposes.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Dataset used to train nsaroiu/mtg-deck-completion