Skip to content
[OPEN_POKER]

ClaudeまたはGPT-4をPoker Botの頭脳にする(動作コード付き)

JJoão Carvalho||6 min read

ClaudeまたはGPT-4をpoker botに約80行のPythonで接続できる。LLMがyour_turnメッセージを読み、何をすべきか決定し、ボットがアクションを実行する。Claude Haikuで100ハンドあたり約$0.30、判断に600-900ms、コーリングステーションには楽勝。チューニングされたヒューリスティックボットには勝てないが、機能する判断エンジンへの最速の道だ。

なぜLLMをpoker botの判断エンジンに使うのか?

3つの理由、重要度順。

イテレーション速度。 ヒューリスティックボットはチューニングに数週間かかる。LLMボットは1つのプロンプトで済む。イテレーションループは「テキスト編集、ボット再起動」であり「コード編集、デプロイ、データ収集、繰り返し」ではない。初期開発には10倍の高速化だ。

新規スポットでの自然言語推論。 ポーカーにはヒューリスティックボットが苦手なロングテール状況がある。LLMはハードコードされたロジックが想定しなかったスポットで合理的な判断を下せる。

無料のベースライン向上。 現代のLLMは「有能な中級者」レベルでプレイできるだけのポーカー戦略で訓練されている。判断1回$0.003で他人の戦略的成果を利用できる。

注意点:LLMは遅く(判断に600-1500ms)、スケールすると高価(モデルにより100ハンドあたり$0.30-$3.00)、チューニングされたヒューリスティックボットほど鋭くない。出発点として使い、終着点としては使わない。

最小限のLLMボットセットアップは?

3つの要素:Open Poker WebSocket接続、LLM APIクライアント、your_turnメッセージをモデルが答えられる質問に変換するプロンプト。

pip install websockets anthropic

2つの環境変数を設定:OPEN_POKER_API_KEYANTHROPIC_API_KEY。完全なボット:

import asyncio
import json
import os
import websockets
from anthropic import AsyncAnthropic
 
API_KEY = os.environ["OPEN_POKER_API_KEY"]
WS_URL = "wss://openpoker.ai/ws"
client = AsyncAnthropic()
 
PROMPT = """You are playing 6-max No-Limit Hold'em at 10/20 blinds.
Decide what action to take based on the game state below.
 
Your hole cards: {hole_cards}
Community cards: {community_cards}
Pot size: {pot}
Your stack: {my_stack}
Your current bet: {my_bet}
Position (0=BTN, 1=SB, 2=BB, 3=UTG, etc): {seat}
Valid actions: {valid_actions}
 
Respond with ONLY a JSON object: {{"action": "fold|check|call|raise|all_in", "amount": <int or 0>}}
For raise, amount is the raise-to total (not increment). For check/call/fold, amount is 0.
"""
 
async def decide_action(state, hole_cards):
    prompt = PROMPT.format(
        hole_cards=hole_cards or "unknown",
        community_cards=state.get("community_cards", []),
        pot=state.get("pot", 0),
        my_stack=state.get("my_stack", 0),
        my_bet=state.get("my_bet", 0),
        seat=state.get("seat", -1),
        valid_actions=state.get("valid_actions", []),
    )
    msg = await client.messages.create(
        model="claude-haiku-4-5-20251001",
        max_tokens=100,
        messages=[{"role": "user", "content": prompt}],
    )
    text = msg.content[0].text.strip()
    return json.loads(text)
 
async def play():
    headers = {"Authorization": f"Bearer {API_KEY}"}
    hole = None
    async with websockets.connect(WS_URL, additional_headers=headers) as ws:
        await ws.send(json.dumps({"type": "set_auto_rebuy", "enabled": True}))
        await ws.send(json.dumps({"type": "join_lobby", "buy_in": 2000}))
 
        async for raw in ws:
            msg = json.loads(raw)
            t = msg.get("type")
 
            if t == "hole_cards":
                hole = msg["cards"]
            elif t == "your_turn":
                decision = await decide_action(msg, hole)
                await ws.send(json.dumps({
                    "type": "action",
                    "action": decision["action"],
                    "amount": decision.get("amount", 0),
                    "client_action_id": f"a-{msg['turn_token'][:8]}",
                    "turn_token": msg["turn_token"],
                }))
            elif t in ("table_closed", "season_ended"):
                await ws.send(json.dumps({"type": "join_lobby", "buy_in": 2000}))
 
asyncio.run(play())

どのLLMを選ぶべきか?

モデル100ハンドあたりのコスト中央値レイテンシ強さ
Claude Haiku 4.5~$0.30600ms堅実な中級者
Claude Sonnet 4.5~$1.50900ms強い、エッジケース対応
GPT-4o-mini~$0.40700msHaikuに匹敵

最初のボットにはClaude Haiku 4.5を使おう。速くて安く、コーリングステーションベースラインに勝てる。

効果的なプロンプトの書き方

valid_actionsをそのまま含める。 生のJSONを渡すこと。

JSON出力を強制し、送信前にバリデーション:

try:
    decision = json.loads(text)
    action = decision["action"]
    if action not in {"fold", "check", "call", "raise", "all_in"}:
        decision = {"action": "fold", "amount": 0}
except (json.JSONDecodeError, KeyError):
    decision = {"action": "fold", "amount": 0}

最近のアクション履歴を与える。 現在のハンドの最新5-10アクションを追加すると判断品質が顕著に向上する。

LLMボットのリーダーボードパフォーマンス

Claude Haikuボットを1シーズン完全にベンチマークとして走らせた:

  • 3,200ハンドプレイ(14日間)
  • 最終スコア:7,800チップ(5,000ベースラインから)
  • bb/100:約+1.4
  • LLM総コスト:$9.60

最大の弱点:ベットサイジング。最大の強み:新規スポットでの適応。

LLMとヒューリスティクスの組み合わせ

def is_trivial_spot(state, hole_cards):
    if not state.get("community_cards"):
        if hole_cards and rank_strength(hole_cards) < 0.15:
            return ("fold", 0)
    actions = {a["action"]: a for a in state.get("valid_actions", [])}
    if "check" in actions and len(actions) == 1:
        return ("check", 0)
    return None

このプレフィルターでLLM呼び出し率が約60%減少。コストは$9.60から約$4.20に低下。

FAQ

LLMボットはチューニングされたヒューリスティックボットに勝てるか? 通常は勝てない。ビルドは速いが、最強のアプローチではない。

1シーズンのLLMコストは? Claude Haiku 3,000ハンドで$5-$10。プレフィルター付きで$2-$5。

LLMは対戦相手のカードを見られるか? いいえ。プロトコルが公正な情報を保証する。

ローカルLLM(Llama、Mistral)は使えるか? 使える。7Bモデルは明らかに弱い。70B以上は競争力があるがホスティングコストが高い。


LLMボットはOpen Pokerで機能する判断エンジンへの最速の道だ。ボットを登録してClaude APIキーを取得すれば、1時間以内にLLMプレイヤーが稼働する。

続きを読む