DPO doesn't break the SFT abilities — actually slightly improves preflop EM.
The CO regression that motivated this v3 retrain is fully resolved (~80 BB swing).
1from peft import PeftModel
2from transformers import AutoModelForCausalLM, AutoTokenizer
3import torch
4
5base = AutoModelForCausalLM.from_pretrained(
6 "Qwen/Qwen3-14B",
7 torch_dtype=torch.bfloat16,
8 device_map="auto",
9)
10model = PeftModel.from_pretrained(base, "ianlee1996/pokerbench-qwen3-14b-lora-dpo-v3")
11tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-14B")
12
13system_prompt = (
14 "You are a specialist in playing 6-handed No Limit Texas Holdem. "
15 "Output ONLY the optimal action with no explanation. "
16 "Valid formats: 'fold', 'check', 'call', 'bet N', 'raise N', 'all-in'."
17)
18# Inference: temp 0.1, top-p 0.95, max_tokens 16
1# 1. Self-play (~9 hours, ~$50 Bedrock)
2.venv/bin/python -m scripts.collect_selfplay --config configs/eval/rl_selfplay_5k.yaml
3
4# 2. Multi-seat counterfactual extraction (~14 hours, ~$30 Bedrock)
5.venv/bin/python -m scripts.extract_preferences \
6 --hand-logs data/rl/selfplay_5k.jsonl \
7 --out data/rl/preferences_5k.jsonl \
8 --adapter checkpoints/09_qwen3_14b_lora_mixed_v2_sized \
9 --hero-seats all --n-mc 5 --max-workers 8 \
10 --bedrock-model deepseek.v3.2
11
12# 3. DPO (~25 min)
13.venv/bin/python -m scripts.train --config configs/experiments/10_qwen3_14b_dpo_v3_on_v2_sft.yaml
The 4686 preference pairs and raw self-play logs are public at
ianlee1996/pokerbench-rl-dpo.
1@inproceedings{zhuang2025pokerbench,
2 title={PokerBench: Training Large Language Models to become Professional Poker Players},
3 author={Zhuang, Richard and Gupta, Akshat and Yang, Richard and Rahane, Aniket and Li, Zhengyu and Anumanchipalli, Gopala},
4 booktitle={Proceedings of the AAAI Conference on Artificial Intelligence},
5 year={2025},
6 url={https://arxiv.org/abs/2501.08328}
7}