Given the cards in a booster pack and the cards you have already picked, this model ranks which card to take next. It generalizes to unseen sets: a card it has never seen during training still receives a representation for zero-shot inference.
The model was trained on processed draft data from 30 different sets from 17Lands. SOS and MSH were excluded from training and evaluated as chronological holdouts.
Results for the validation-selected seed 42 checkpoint. Lower NLL is better; SOS and MSH did not participate in training or checkpoint selection.
| Split | Top-1 | Top-3 | NLL |
|---|---|---|---|
| Known test | 68.26% | 95.17% | 0.8184 |
| SOS holdout | 50.49% | 85.41% | 1.3349 |
| MSH holdout | 51.50% | 85.95% | 1.2839 |
from mtgda import MtgDraftAssistant
assistant = MtgDraftAssistant.from_pretrained("pier97/mtgda")
draft = assistant.new_draft()
for recommendation in draft.see([
"Lightning Bolt",
"Llanowar Elves",
"Cancel",
]):
print(recommendation.name, recommendation.probability)
draft.pick("Lightning Bolt")from mtgda import DraftStep, MtgDraftAssistant
assistant = MtgDraftAssistant.from_pretrained("pier97/mtgda")
history = [
DraftStep(
pack=("Lightning Bolt", "Llanowar Elves", "Cancel"),
pick="Lightning Bolt",
)
]
recommendations = assistant.rank(
history,
["Shock", "Giant Growth", "Murder"],
)Cards can be passed as names from the bundled catalog or as Scryfall-style dictionaries for custom, preview, or newly released cards.
custom = {
"name": "Made-Up Card",
"type_line": "Creature - Goblin",
"mana_cost": "{1}{R}",
"power": "3",
"toughness": "1",
"oracle_text": (
"Haste. When this creature enters, "
"it deals 2 damage to any target."
),
"layout": "normal",
}
recommendations = assistant.rank(
[],
[custom, "Giant Growth", "Cancel"],
)Card representations are cached by the assistant after their first encoding.
- The card encoder combines a 320-dimensional MPNet text representation, 16 numeric features, and 207 deterministic mechanic flags into a 543-dimensional card vector.
- The draft model is a two-layer causal encoder-decoder transformer with 320-dimensional hidden states, eight attention heads, pooled pack memory, and a candidate scorer.
- The Python API resolves card names, encodes uncached cards in batches, maintains draft history, and returns ranked recommendations with probabilities.
