コードネームをやってみよう
コードネーム(codenames)は2チームで自チームの色のカードを取り合うボードゲームです。
各チームから一人抜擢されたスパイマスターにのみカードの色が公開されるので、簡単な単語と数字をヒントにチームメンバーがカードを選択します。
神経衰弱のように、自チームのカードを選択できると続けてカードを選択できます。
黒いカードは選択すると即敗北になります。
実装
- ブラウザからテキストを取得
- LLMに推論させる
テキスト取得
ゲーム画面はHTMLで構成されているので、各カードのテキストはconsoleからDOM APIで取得できます。
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から出ているので、それに従います。
あなたはcode nameのスパイマスターとしてプレイしています。
チームのメンバーに的確なヒントを出し、可能な限り多くのalliesCardsを選択させることが目的です。
alliesCardsをチームメンバーが選択し続ける限りターンは続行でき、多くのカードを選択できます。
grayCardsは相手の得点にはなりませんが、ターンが終了してしまいます。
opponentsCardsをメンバーが選択すると、相手の得点となりターンが終了するので避けてください。
blackCardsはメンバーが選択すると即敗北になるので絶対に避けられるよう、このワードとは関連のないヒントを出力してください。
出力は
- 選択させたいカードの名前(1つ以上)
- ヒントとする単語
とすること。
```json
{"alliesCards":["グリーン","タワー","ケーブル","カバー","かまくら","マーク","ポンド","ビタミン","パーティー"],"opponentsCards":["チョーク","サロン","枕","鎧","昼","クイーン","紙","マーチ"],"grayCards":["風呂","劇場","ミルク","タイガー","くすり","弁護士","海岸"],"blackCards":["オリーブ"]}
```
このプロンプトでは
- 直接的な指示
- 理由を出力させない
- 区切り文字の使用
- ゼロショット
- 制約(ゲームルール)の説明
- 最終出力形式の指定
をシンプルに行いました。
いざ推論
貧乏過ぎて残高がありませんでした。
いずれにしてもAPIのo1 previewではreasoningの取得ができないのでChatGPTサービスを利用します。
全文
「グリーン」、「パーティー」、「ケーブル」、「タワー」など、チームメンバーに選んでもらいたいカードを考えています。これらは全て、"自然" や "環境" といったテーマに関連付けて出すことができるかも。だとしても、一番注意したいのは黒カード「オリーブ」を絶対に避けること。ヒントとしては「自然」や「イベント」などどうだろうか?でも「昼」や「海岸」もグレーゾーンなので、それらと無関係にしておく必要がある。
「グリーン」、「タワー」、「ケーブル」、「かまくら」など、いくつかのカードが関連しそう。でも、「オリーブ」を絶対に避けなければならない。これはどうしても関わりたくない。だから、例えば「自然」を使ってヒントを出すのがいいかも。でも、他のカード、例えば「昼」や「海岸」は注意が必要。グレーや相手チームのカードと誤解されないように気をつける必要がある。
「グリーン」や「パーティー」、「ケーブル」など、異なる印象のカードが多い。でも、これらを関連付ける言葉が必要だ。色や環境で「グリーン」、建物で「タワー」、コネクションで「ケーブル」や「カバー」、冬のイメージで「かまくら」など。それでも、印象がバラバラだな…かなり難しい。カバーやケーブルが「テレビ」に関連しそうだけど、他のカードにも適用できる言葉が見つからない。
最適なヒントを考えていますが、色を使うのは危険。特に「グリーン」は「オリーブ」に繋がる可能性があるからです。それで、「ロンドン」「イギリス風」などのヒントを試してみるが「クイーン」へのリスクが残ります。代わりに、少なくとも他のカードと強く関連するヒントを見つける必要があります。「タワー」「カバー」「マーク」など、新しいグループを試しながら慎重に進めています。
「タワー」「ケーブル」「ポンド」を「橋」に関連付けようとしているんだけど、とにかく「グリーン」を使いたくはない。橋に関するヒントが最適かもだけど「カバー」はやや当てはまりにくい。代わりに「タワー」「ポンド」「ケーブル」で「ロンドン」といったヒントを試すことも考慮中。でも、「ロンドン」は「クイーン」を連想する危険もある。やっぱり慎重に選ばないと。
「ロンドン」をヒントにしたいけど、「クイーン」のリスクがある。おそらく「ロンドン」で「タワー」「ポンド」「ケーブル」に絞れるけど、「クイーン」が連想される可能性が高い。これが一番良さそうな選択肢かもしれないが、リスクがあるため警戒が必要。「グリーン」も絡む可能性があるが、選ばれるならそれでもOK。でも「クイーン」は避けたい。
結果
{"cards": ["タワー", "ポンド", "ケーブル"], "hint": "ロンドン"}
うーん?
感想
reasoningの頑張りはめちゃくちゃ伝わってきます。
特に禁忌である「オリーブ」を避ける強い意思をreasoningから感じました。
しかし、最終的なヒントである「ロンドン」に対し、「ケーブル」はあまり関連を見いだせず、「ロンドン、3」でヒントを出すと味方を混乱させてしまうでしょう。「ロンドン、2」なら妥当だと思います。
とはいえ、この性能のモデルが無料で使えるのはいい時代になりました。
おまけ
Reasoningの日本語訳、「推論」ではない別の単語にしませんか?
推論はモデルの出力全般を指す単語に感じます。
個人的には「推測」を推しています。