o3 miniにボードゲームやらせてみたら役に立ちそうだった話

## コードネームをやってみよう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1977360/81088fa7-338e-40b8-ab2c-a6d79873a7b8.png)

コードネーム（codenames）は2チームで自チームの色のカードを取り合うボードゲームです。
各チームから一人抜擢されたスパイマスターにのみカードの色が公開されるので、簡単な単語と数字をヒントにチームメンバーがカードを選択します。
神経衰弱のように、自チームのカードを選択できると続けてカードを選択できます。
黒いカードは選択すると即敗北になります。

https://codenames.game


## 実装
1. ブラウザからテキストを取得
1. LLMに推論させる


### テキスト取得


ゲーム画面はHTMLで構成されているので、各カードのテキストはconsoleからDOM APIで取得できます。

```js
JSON.stringify({alliesCards: Array.from(document.getElementsByClassName('card red')).map(e => e.innerText).filter(e => e), opponentsCards: Array.from(document.getElementsByClassName('card blue')).map(e => e.innerText).filter(e => e), grayCards: Array.from(document.getElementsByClassName('card gray')).map(e => e.innerText).filter(e => e), blackCards: Array.from(document.getElementsByClassName('card black')).map(e => e.innerText).filter(e => e)})
```


### LLMに投げる

プロンプトを書きます。
reasoning model用のプロンプト指南がOpenAIから出ているので、それに従います。

https://platform.openai.com/docs/guides/reasoning-best-practices#how-to-prompt-reasoning-models-effectively



````
あなたはcode nameのスパイマスターとしてプレイしています。
チームのメンバーに的確なヒントを出し、可能な限り多くのalliesCardsを選択させることが目的です。
alliesCardsをチームメンバーが選択し続ける限りターンは続行でき、多くのカードを選択できます。
grayCardsは相手の得点にはなりませんが、ターンが終了してしまいます。
opponentsCardsをメンバーが選択すると、相手の得点となりターンが終了するので避けてください。
blackCardsはメンバーが選択すると即敗北になるので絶対に避けられるよう、このワードとは関連のないヒントを出力してください。

出力は
- 選択させたいカードの名前（1つ以上）
- ヒントとする単語
とすること。

```json
{"alliesCards":["グリーン","タワー","ケーブル","カバー","かまくら","マーク","ポンド","ビタミン","パーティー"],"opponentsCards":["チョーク","サロン","枕","鎧","昼","クイーン","紙","マーチ"],"grayCards":["風呂","劇場","ミルク","タイガー","くすり","弁護士","海岸"],"blackCards":["オリーブ"]}
```
````

このプロンプトでは
- 直接的な指示
- 理由を出力させない
- 区切り文字の使用
- ゼロショット
- 制約（ゲームルール）の説明
- 最終出力形式の指定
をシンプルに行いました。

### いざ推論
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1977360/628baaba-3468-4711-98d3-c963e41e1dba.png)
貧乏過ぎて残高がありませんでした。
いずれにしてもAPIのo1 previewではreasoningの取得ができないのでChatGPTサービスを利用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1977360/0b576764-8ad2-4b3e-a4eb-9c1394029fab.png)
いろいろ考えてくれていい感じです。


<details>
<summary>全文</summary>

```
「グリーン」、「パーティー」、「ケーブル」、「タワー」など、チームメンバーに選んでもらいたいカードを考えています。これらは全て、"自然" や "環境" といったテーマに関連付けて出すことができるかも。だとしても、一番注意したいのは黒カード「オリーブ」を絶対に避けること。ヒントとしては「自然」や「イベント」などどうだろうか？でも「昼」や「海岸」もグレーゾーンなので、それらと無関係にしておく必要がある。

「グリーン」、「タワー」、「ケーブル」、「かまくら」など、いくつかのカードが関連しそう。でも、「オリーブ」を絶対に避けなければならない。これはどうしても関わりたくない。だから、例えば「自然」を使ってヒントを出すのがいいかも。でも、他のカード、例えば「昼」や「海岸」は注意が必要。グレーや相手チームのカードと誤解されないように気をつける必要がある。

「グリーン」や「パーティー」、「ケーブル」など、異なる印象のカードが多い。でも、これらを関連付ける言葉が必要だ。色や環境で「グリーン」、建物で「タワー」、コネクションで「ケーブル」や「カバー」、冬のイメージで「かまくら」など。それでも、印象がバラバラだな…かなり難しい。カバーやケーブルが「テレビ」に関連しそうだけど、他のカードにも適用できる言葉が見つからない。

最適なヒントを考えていますが、色を使うのは危険。特に「グリーン」は「オリーブ」に繋がる可能性があるからです。それで、「ロンドン」「イギリス風」などのヒントを試してみるが「クイーン」へのリスクが残ります。代わりに、少なくとも他のカードと強く関連するヒントを見つける必要があります。「タワー」「カバー」「マーク」など、新しいグループを試しながら慎重に進めています。

「タワー」「ケーブル」「ポンド」を「橋」に関連付けようとしているんだけど、とにかく「グリーン」を使いたくはない。橋に関するヒントが最適かもだけど「カバー」はやや当てはまりにくい。代わりに「タワー」「ポンド」「ケーブル」で「ロンドン」といったヒントを試すことも考慮中。でも、「ロンドン」は「クイーン」を連想する危険もある。やっぱり慎重に選ばないと。

「ロンドン」をヒントにしたいけど、「クイーン」のリスクがある。おそらく「ロンドン」で「タワー」「ポンド」「ケーブル」に絞れるけど、「クイーン」が連想される可能性が高い。これが一番良さそうな選択肢かもしれないが、リスクがあるため警戒が必要。「グリーン」も絡む可能性があるが、選ばれるならそれでもOK。でも「クイーン」は避けたい。
```
</details>

### 結果

```
{"cards": ["タワー", "ポンド", "ケーブル"], "hint": "ロンドン"}
```
うーん？


### 感想
reasoningの頑張りはめちゃくちゃ伝わってきます。
特に禁忌である「オリーブ」を避ける強い意思をreasoningから感じました。
しかし、最終的なヒントである「ロンドン」に対し、「ケーブル」はあまり関連を見いだせず、「ロンドン、3」でヒントを出すと味方を混乱させてしまうでしょう。「ロンドン、2」なら妥当だと思います。

とはいえ、この性能のモデルが無料で使えるのはいい時代になりました。

### おまけ

Reasoningの日本語訳、「推論」ではない別の単語にしませんか？
推論はモデルの出力全般を指す単語に感じます。
個人的には「推測」を推しています。