A Laya checkpoint fine-tuned to build the 40-card maindeck from a finished Magic: The Gathering draft pool for The Hobbit (HOB) Premier Draft. Given the whole pool, it answers one typed question per card, "how many copies go in the maindeck?", plus one question per basic land type (0β17 copies).
The labels are the decks that 17Lands users actually registered. The model imitates human deckbuilding; it does not search for the strongest possible deck.
Status: experimental. The numbers below come from the validation split recorded during training (epoch 3 of 4). A full held-out test run has not finished yet (see Benchmark status).
| Question type | Laya HOB deckbuild (val) | Always the majority class |
|---|---|---|
| Non-basic cards (0β¦N copies, N = copies drafted) | 80.88% | n/a |
| Basic lands (0β17 of each of the 5 types) | 71.49% | n/a |
| All 12,440 questions | 79.56% | ~55% |
Validation loss is 1.49, which means the model is overconfident. Temperatures were not fitted
([1.2, 1.2, 1.2]), so top-1 agreement is unaffected but the probabilities are poorly calibrated.
A test-split run (split == "test", 345 builds) was started on 2026-09-28 on an Apple M-series Mac (MPS).
The OS stopped it at 141/345 builds because it ran out of memory, before it saved any results. It
takes about 12 s per build (roughly 28k input tokens), so a complete run needs about 70 minutes on a machine with
more free memory than a 16 GB Mac. Until that run finishes, treat the validation figures as optimistic.
We found no published benchmark for maindeck selection from a drafted pool. Published MTG work covers pick prediction (UrzaGPT, DraftFM, Ward et al.) or deck strength (DraftEncoder), so there is no external number to compare against. The majority-class baseline above is the only reference point.
| Base | convaiinnovations/laya (English, ModernBERT-large encoder, 421M params) |
| Data | 17Lands draft_data_public.HOB.PremierDraft.csv (pool = all picks of a draft_id) + game_data_public.HOB.PremierDraft.csv (registered deck_ / sideboard_ columns), same 3,000 strong-player drafts as the pick model |
| Builds | 3,457 exact-40-card builds: 2,762 train / 350 val / 345 test, split by draft_id |
| Card text | MTGJSON HOB.json, compact type/cost/colors/P-T/rarity/keywords/rules text |
| Checkpoint | epoch 3 of 4 (checkpoint_epoch3) |
| Lengths | max_len=1280, head_max_len=768 |
One request per build. state holds the whole pool (no basics, alphabetical). questions has one key per
distinct non-basic card, followed by Forest, Island, Mountain, Plains, Swamp.
state = {
"game": "Magic: The Gathering", "format": "Booster Draft", "event_type": "PremierDraft",
"expansion": "HOB", "set_name": "The Hobbit",
"pool": [{"name": "Bilbo Baggins, Burglar", "count": 2}, {"name": "Smaug's Fury", "count": 1}],
"pool_size": 3,
}
PREFIX = ("Booster Draft deckbuild decision for the Magic: The Gathering set 'The Hobbit' (HOB). "
"The player's full drafted pool of picked cards is already fixed; you are now choosing the "
"40-card maindeck versus sideboard. ")
questions = {
"Bilbo Baggins, Burglar": {
"type": "choice",
"instructions": PREFIX + (
"This card was drafted 2 time(s) (copies beyond that number were never in the pool and are "
"not valid options). How many copies of this card does the maindeck include? "
"Bilbo Baggins, Burglar: Legendary Creature β Halfling Rogue, {2}{U}, U, 2/1, common, Scry. "
"Text: When Bilbo Baggins enters, draw a card."),
"criteria": {"0": "0 copies (sideboard only)", "1": "1 copy", "2": "2 copies (all drafted copies played)"},
},
# ... one entry per pool card ...
"Plains": {
"type": "choice",
"instructions": PREFIX + (
"Basic lands are unlimited and free to add while deckbuilding, so this count is not limited by "
"the pool. How many copies of this basic land does the maindeck include (0 to 17)? "
"Plains: Basic Land β Plains, mana value 0, colorless, common. Text: ({T}: Add {W}.)"),
"criteria": {str(i): f"{i} cop{'y' if i == 1 else 'ies'}" for i in range(18)},
},
# ... Forest, Island, Mountain, Swamp ...
}
Label rules for non-basic cards: "0" β "0 copies (sideboard only)", middle values β "1 copy" /
"i copies", and the last value (= copies drafted) gets the suffix " (all drafted copies played)".
import laya
from huggingface_hub import snapshot_download
path = snapshot_download("FabioCeleste/laya-mtg-deckbuild")
agent = laya.load(path, device="cuda") # or "mps" / "cpu"
answers = agent.predict(state, questions)["answers"]
deck = {name: int(a["choice"]) for name, a in answers.items() if int(a["choice"]) > 0}
print(sum(deck.values()), deck)
The model does not guarantee 40 cards. Each question is answered independently. To close the deck,
add or remove copies from the answers with the lowest answer_confidence (usually basics) using
probabilities. That repair step is your own logic, and it has not been evaluated.
Tested with laya==0.3.20. A full 37-question build took about 12 s on MPS.
FabioCeleste/laya-mtg-draft-picks β picks one card from a HOB pack.FabioCeleste/laya-mtg-deck-evaluator β scores the finished 40-card deck (per-game win probability).Labels from 17Lands public datasets (CC BY 4.0). Card data from MTGJSON. The base model is Apache-2.0.
A Laya checkpoint fine-tuned to build the 40-card maindeck from a finished Magic: The Gathering draft pool for The Hobbit (HOB) Premier Draft. Given the whole pool, it answers one typed question per card, "how many copies go in the maindeck?", plus one question per basic land type (0β17 copies).
The labels are the decks that 17Lands users actually registered. The model imitates human deckbuilding; it does not search for the strongest possible deck.
Status: experimental. The numbers below come from the validation split recorded during training (epoch 3 of 4). A full held-out test run has not finished yet (see Benchmark status).
| Question type | Laya HOB deckbuild (val) | Always the majority class |
|---|---|---|
| Non-basic cards (0β¦N copies, N = copies drafted) | 80.88% | n/a |
| Basic lands (0β17 of each of the 5 types) | 71.49% | n/a |
| All 12,440 questions | 79.56% | ~55% |
Validation loss is 1.49, which means the model is overconfident. Temperatures were not fitted
([1.2, 1.2, 1.2]), so top-1 agreement is unaffected but the probabilities are poorly calibrated.
A test-split run (split == "test", 345 builds) was started on 2026-09-28 on an Apple M-series Mac (MPS).
The OS stopped it at 141/345 builds because it ran out of memory, before it saved any results. It
takes about 12 s per build (roughly 28k input tokens), so a complete run needs about 70 minutes on a machine with
more free memory than a 16 GB Mac. Until that run finishes, treat the validation figures as optimistic.
We found no published benchmark for maindeck selection from a drafted pool. Published MTG work covers pick prediction (UrzaGPT, DraftFM, Ward et al.) or deck strength (DraftEncoder), so there is no external number to compare against. The majority-class baseline above is the only reference point.
| Base | convaiinnovations/laya (English, ModernBERT-large encoder, 421M params) |
| Data | 17Lands draft_data_public.HOB.PremierDraft.csv (pool = all picks of a draft_id) + game_data_public.HOB.PremierDraft.csv (registered deck_ / sideboard_ columns), same 3,000 strong-player drafts as the pick model |
| Builds | 3,457 exact-40-card builds: 2,762 train / 350 val / 345 test, split by draft_id |
| Card text | MTGJSON HOB.json, compact type/cost/colors/P-T/rarity/keywords/rules text |
| Checkpoint | epoch 3 of 4 (checkpoint_epoch3) |
| Lengths | max_len=1280, head_max_len=768 |
One request per build. state holds the whole pool (no basics, alphabetical). questions has one key per
distinct non-basic card, followed by Forest, Island, Mountain, Plains, Swamp.
state = {
"game": "Magic: The Gathering", "format": "Booster Draft", "event_type": "PremierDraft",
"expansion": "HOB", "set_name": "The Hobbit",
"pool": [{"name": "Bilbo Baggins, Burglar", "count": 2}, {"name": "Smaug's Fury", "count": 1}],
"pool_size": 3,
}
PREFIX = ("Booster Draft deckbuild decision for the Magic: The Gathering set 'The Hobbit' (HOB). "
"The player's full drafted pool of picked cards is already fixed; you are now choosing the "
"40-card maindeck versus sideboard. ")
questions = {
"Bilbo Baggins, Burglar": {
"type": "choice",
"instructions": PREFIX + (
"This card was drafted 2 time(s) (copies beyond that number were never in the pool and are "
"not valid options). How many copies of this card does the maindeck include? "
"Bilbo Baggins, Burglar: Legendary Creature β Halfling Rogue, {2}{U}, U, 2/1, common, Scry. "
"Text: When Bilbo Baggins enters, draw a card."),
"criteria": {"0": "0 copies (sideboard only)", "1": "1 copy", "2": "2 copies (all drafted copies played)"},
},
# ... one entry per pool card ...
"Plains": {
"type": "choice",
"instructions": PREFIX + (
"Basic lands are unlimited and free to add while deckbuilding, so this count is not limited by "
"the pool. How many copies of this basic land does the maindeck include (0 to 17)? "
"Plains: Basic Land β Plains, mana value 0, colorless, common. Text: ({T}: Add {W}.)"),
"criteria": {str(i): f"{i} cop{'y' if i == 1 else 'ies'}" for i in range(18)},
},
# ... Forest, Island, Mountain, Swamp ...
}
Label rules for non-basic cards: "0" β "0 copies (sideboard only)", middle values β "1 copy" /
"i copies", and the last value (= copies drafted) gets the suffix " (all drafted copies played)".
import laya
from huggingface_hub import snapshot_download
path = snapshot_download("FabioCeleste/laya-mtg-deckbuild")
agent = laya.load(path, device="cuda") # or "mps" / "cpu"
answers = agent.predict(state, questions)["answers"]
deck = {name: int(a["choice"]) for name, a in answers.items() if int(a["choice"]) > 0}
print(sum(deck.values()), deck)
The model does not guarantee 40 cards. Each question is answered independently. To close the deck,
add or remove copies from the answers with the lowest answer_confidence (usually basics) using
probabilities. That repair step is your own logic, and it has not been evaluated.
Tested with laya==0.3.20. A full 37-question build took about 12 s on MPS.
FabioCeleste/laya-mtg-draft-picks β picks one card from a HOB pack.FabioCeleste/laya-mtg-deck-evaluator β scores the finished 40-card deck (per-game win probability).Labels from 17Lands public datasets (CC BY 4.0). Card data from MTGJSON. The base model is Apache-2.0.