Python(オセロ01_Geminiでの対戦相手)
■Geminiでオセロの対戦相手を作る。
前にやったPythonのオセロのコードを少し修正して、Geminiへの問い合わせから石を置く場所を求める。
久しぶりなので、前回のコードの中身を思い出しながら修正。前回はランダム同士で対戦させていたけど、ロジックは次のようなものだった。
置くことができる場所をリストにして、その中からランダムで場所をチョイス(このときリストから削除)。その場所で相手の石をひっくり返すことができたら、それを採用。できなかったら、残ったリストから再度ランダムでチョイス。これを繰り返して最後までひっくり返せなかったらパス。
下のように"○"の場合はランダム(このロジック)、それ以外("●")の場合はGeminiへの問い合わせで場所を取得する。
while len(leftBlankList) > 0:
if turn_ == "○":
stone_pos = rd.choice(tempBlankList)
tempBlankList.remove(stone_pos)
else:
stone_pos_str = gemini(board)
print("gemini:"+str(stone_pos_str))
if stone_pos_str == None:
tempBlankList = ""
stone_pos = ast.literal_eval(stone_pos_str)
stoneList_tobeChanged = checkReversible(board, stone_pos)
if len(stoneList_tobeChanged) > 0:
<以下省略>
肝心のGeminiのコードが下(まだ試行錯誤中だけど)。
def gemini(board):
# 優先順位が高い順にモデルをリスト化
models_to_try = ["gemini-2.5-flash"]
max_retries = 3
client = genai.Client(api_key="(省略、APIキー部分)")
for model_id in models_to_try:
for i in range(max_retries):
try:
print(f"モデル {model_id} で試行中... ({i + 1}/{max_retries})")
response = client.models.generate_content(
model=model_id,
contents=f"盤面: {board}",
config=types.GenerateContentConfig(
system_instruction=(
"オセロAI。回答は[行,列]形式のみ。例:[3,5]。"
"回答は-が入っているところから選択すること。"
"解説不要。1-8の範囲で選択。あなたは●。あなたはプロのオセロプレイヤーです。"
"置くところがないときはNoneを返却"
),
temperature=0.1,
),
)
# 正常に取得できたら返却
if response and response.text:
return response.text.strip()
except exceptions.ResourceExhausted:
print(f"モデル {model_id} の制限に達しました。")
if model_id == models_to_try[-1]:
# 最後のモデルでも制限なら待機
print("全モデル制限中。60秒待機します...")
time.sleep(60)
else:
# 次のモデル(1.5 Flash等)へ切り替え
print("次のモデルへ切り替えます。")
break
except Exception as e:
print(f"予期せぬエラー ({model_id}): {e}")
break
return None
回答のフォーマットを指定しないと出てきた回答をうまく処理できないので、[3, 5]のように回答を指定。これで何手かはうまくいった。下の実行結果では[5, 3] の回答が返ってきて、置くことができた(赤丸部分)。

ただ、画面から分かる通り、先に[4, 7]と置くことができない回答もしている。また、既に石が置いてあるところを回答したりもする。この辺りは、質問の工夫でもう少し何とかなるかも。
上の実行では、gemini-2.5-flashのモデルを使っているけど、現在RPD(1日のリクエスト数)は無料枠では20が上限になっている。オセロの対戦では盤の状態を送って適切な場所を求めるなら、30のリクエストは必要で明らかに不十分。Google AI Studioでは、Gemini 2 Flashとか他のバージョンの記載もあるけど、実際にAPIで使おうとすると、上限が0に設定されているといった例外が発生して使えない。この辺りは、有料枠の設定とかすれば何とかなるかな。
とりあえずの目標は、どれかのモデルでオセロの1ゲームを達成することにする。
