Genaro Poker 0.6B

A phone-sized poker player. Genaro is a full fine-tune of Qwen3-0.6B built to be the opponents in PokerSI, an Android poker game where every seat is a small language model running on the phone with llama.cpp. It is PokerSI's recommended model.

v3 learns its poker from a search solver running on PokerSI's own engine (Monte Carlo rollouts of every legal move, with Bayesian opponent-range inference), the teacher that beats PokerSI's House Bot by +256 bb/100. v2 learned from House Bot itself.

Given PokerSI's prompt for one decision (a persona, the rules, what the seat can see, the legal moves), Genaro answers with one JSON object: a legal move and, on talk turns, a short line in the character's voice that never gives its cards away.

{"action": "call", "amount": 55, "say": "The pot looks like it's brewing a little sunshine."}
{"action": "check", "amount": 0, "say": "Ahoy, these doubloons are worth a fortune!"}
{"action": "raise", "amount": 240, "say": "Get those reps in, I see potential!"}
File Use
genaro-poker-0.6b-v3-Q4_K_M.gguf (397 MB) On-device / llama.cpp. What PokerSI downloads. Chat template embedded.
model.safetensors + config/tokenizer (bf16) transformers, further fine-tuning, other quantizations
genaro-poker-0.6b-Q4_K_M.gguf v2, kept so app versions that point at it keep working. Revision v2 has the v2 weights.

Bigger sibling for 6 GB+ phones: predbrad/Genaro-poker-1.7B. Code, solver, data pipeline and evals: github.com/bradflaugher/genaro-poker. Training data: predbrad/genaro-poker-sft.

Results

600 held-out PokerSI decisions over all six variants (Texas Hold'em, Omaha, Five-Card Draw, Seven-Card Stud, Short Deck, Crazy Pineapple), each model run through llama.cpp exactly as the app runs it (same prompt, GBNF grammar and sampling); plus 3,600+ live hands.

model GGUF EV regret (bb/decision) big mistakes /100 leaks card talk repeats >12 words live bb/100 (same 1,200 deals) live vs House Bot, paired (3,600 hands)
Qwen3 0.6B (base) 484 MB 1.75 19.5 10.5% 39.8% 23.9% 22.7% — —
LFM2.5 1.2B (PokerSI's previous default) 731 MB 1.31 16.0 2.6% 29.8% 8.5% 9.4% -80 ± 80 —
Genaro Poker 0.6B v2 (House Bot labels) 397 MB 1.41 18.5 0.0% 0.3% 0.0% 0.0% -84 ± 52 —
Genaro Poker 0.6B v3 397 MB 1.24 13.2 0.3% 0.6% 0.0% 0.0% +61 ± 59 +44 ± 46
  • EV regret: big blinds a move gives up against the solver's best move, by the solver's own EV estimate of every move (the solver's labels themselves score 0.08). Big mistakes: moves giving up more than 2 bb.
  • Leak: a line PokerSI's own HandBlur would censor. Card talk: any card or hand word.
  • Live play: one seat against three House Bots through PokerSI's engine, paired against House Bot playing the same seat on the same deals (which cancels most of the card luck).

All results, including the solver itself: results.

Use

In PokerSI: MODELS → Genaro Poker 0.6B → download. That's it.

llama.cpp: PokerSI-style messages, with a grammar and thinking off:

llama-server -m genaro-poker-0.6b-v3-Q4_K_M.gguf --jinja -c 4096

The prompt format is PokerSI's (llm/PokerPrompt.kt); real examples are in the dataset. Outside that format Genaro is just a small, poker-obsessed Qwen3; it is not a general chat model.

transformers:

from transformers import AutoModelForCausalLM, AutoTokenizer
tok = AutoTokenizer.from_pretrained("predbrad/Genaro-poker")
model = AutoModelForCausalLM.from_pretrained("predbrad/Genaro-poker", dtype="auto")
text = tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True, enable_thinking=False)

Training

  • Prompts: self-play hands of PokerSI's own Kotlin engine and prompt builder, compiled into a bridge, so every prompt is byte-for-byte what the app sends.
  • Moves: a decision-time search solver (bridge/Solver.kt). For each legal move, including several raise sizes and every discard choice, it samples 480 worlds (unseen cards reshuffled; each world weighted by how likely the opponents' past actions were with those cards), replays the hand, makes the move and plays out with opponent policies drawn from House Bot styles plus sticky-caller and sound-regular populations, so it doesn't learn to exploit any one of them. It picks the move with the best lower confidence bound on EV (noise can't buy a shove), with a bet-size abstraction that rules out giant overbets, and lets the persona's style break near-ties. It beats House Bot by +256 ± 49 bb/100.
  • Table talk: written by Gemma 4 E4B for the chosen move, kept only if it passes the grammar's rules, 2-12 words, no card or hand vocabulary, PokerSI's repeat rules and PokerSI's HandBlur.
  • Recipe: 35,756 decisions, repeated by how much EV is at stake (52,792 rows), full fine-tune, bf16, 2 epochs, lr 3e-5 cosine, effective batch 64, loss on the reply only. ~2.5 h on one NVIDIA RTX Spark N1X laptop. See training_config.yaml.

Limits

  • Genaro distills the solver but doesn't match it: it gives up about 1.2 bb per decision against it; the solver is far ahead of every Genaro in live play.
  • The solver best-responds to House-Bot-like play (made robust with other populations); it is not a game-theoretic equilibrium solver.
  • Trained only for PokerSI's prompt format, in English; lines are family-friendly by construction.

License

Apache 2.0, inherited from Qwen3-0.6B. Training data was generated with PokerSI (MIT) and Gemma 4 (Apache 2.0).

Downloads last month
558
Safetensors
Model size
0.6B params
Tensor type
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for predbrad/Genaro-poker

Finetuned
Qwen/Qwen3-0.6B
Finetuned
(1425)
this model

Dataset used to train predbrad/Genaro-poker