元消防士の川俣涼氏

川俣涼氏:久しぶりのリアルの勉強会で緊張していますが、発表します。

「Minecraft × ChatGPTで、マイクラで作りたいものを伝えると魔法のように作成してくれるコマンドを作る」です。

自己紹介です。川俣涼といいます。このアイコンで「Twitter」をやっています。LAPRASという会社でエンジニアをやっています。2児の父で、先月子どもが生まれたので、今は1年間の有休を取得中です。6年ほど前まではリアルな炎上案件の火消しをずっとやっていて、そこからエンジニアになるという、少し変わった経歴を持っています。趣味は懸垂と個人開発です。

「Minecraft」上で作りたいものを伝えると作ってくれるコマンドを作成

今日は、先ほどのタイトルでお話ししたコマンドの実装の紹介と、その中で学んだ「ChatGPT API」のエラーハンドリングについてお話しします。

「Minecraft」とPythonの連携についての説明は省略しているので、興味がある方がいれば、懇親会などで聞いてください。

作ったものです。これですね、Minecraft上で作りたいものを伝えると、実際に作ってくれるコマンド。

どんなものかというと、例えば「空に丸い月を作って!」とMinecraft上でコマンドを打つと、こんな感じで実際に月が出来上がるんですね。

ほかにもいろいろできます。例えば「ビルを作って!」と言ったら、ビルっぽいものができたり、「国旗を作って!」と言ったら国旗っぽいものが出来上がる。ChatGPTが毎回作るので、同じコマンドでも別の物ができてけっこうおもしろいです。

なぜ作ったかというと、息子が好きなMinecraftで「ええかっこ」したいなと思って作りました。実際に、(父に対する)尊敬度がアップして、エンジニアの仕事に少し興味を持ってくれたのでよかったなと思っています。

デモ

ということで、デモです。ここがちょっと緊張の瞬間です。本当に動くかが心配なんですけど(笑)、やります。

これが、マイクラの世界ですね実際にコマンドを打ちます。「py magic」と打って、じゃあ「豪華な」……今日は勉強会なので、「勉強会の会場を作って」。こんなアバウトな指示です。

しばらく待たなくてはいけないので、ちょっとスライドに戻ります。待つ間に仕組みについて話します。

構成と実装イメージを解説

どのように実現しているか。どうなっているかというと、「Minecraft With Raspberryjammod」というものがあって、マイクラでPythonを動かします。コマンドとChatGPT APIという構成になっていて、マイクラ上で「/py magic 空に月を作って!!」というコマンドを実行すると、コマンドの中でプロンプトを組み立てて送信します。ざっくり、「空に月をMinecraftで作るPythonコードを書いて!!」みたいな感じです。

そうすると、コードと説明を返信してくれます。「はい。こちらです。hogehoge」。そこからコードを抽出してEvalすると、実際に建物が出来上がる感じです。めっちゃシンプルです。

実装イメージも、こんな感じで簡単です。

これは疑似コードですが、mainのところで、引数で受け取った指示をプロンプトに埋め込んで、「Chat Completion API」に送信します。

「あなたは優れたPythonプログラマーであり、優れたMinecraftビルダーでもあります」みたいなことを英語で書きます。そして、「教えてください」として、APIの戻り値から、コードブロックのみを抽出します。その後にEvalする感じですね。

ここがちょっと緊張するタイミングですが……あっ、できている。できている(笑)。リアルに出来上がっています。

(会場拍手)

ありがとうございます。箱が出来上がっています。ちょっと入り口を探すのが面倒なので、箱の中に入ります。

ゾンビがいっぱいいる。これが勉強会会場です(笑)。

(会場笑)

ありがとうございます。よかった。

一応、失敗していたら見せる版も作っておいたのでお見せします。これは早送りをしていますが、「豪華な家を作って」「窓は広めで」とやると、ドドンと出来上がります。今回は、成功例が見せられたのでよかったです。

よく起こるエラーその1 「コードが抽出できない」

続きです。「工夫したポイントは何か?」というと、ChatGPTならではのエラーハンドリングというものがあります。

このコードは単純ですが、けっこう最初にエラーが起きたんですよ。1つ目が、「コードが抽出できない」です。ChatGPT APIがコードを返してくれないというやつですね。

Web UIでもけっこうあると思いますが、「申し訳ありません、私たちはMinecraftとPythonを組み合わせた実務」みたいな感じで、「書いて」と言っても書いてくれないというパターンがあります。これが1つ目。

よく起こるエラーその2 「Evalでエラーが発生する」

もう1つが、「Evalでエラーが発生する」です。これは、ChatGPTが間違ったコードを書いてきて、実行時エラーが発生するというものです。

Minecraftの変数を間違えている、ブロックのナンバーが違うなどでよく失敗しています。

「コードが抽出できない」の解決策

じゃあこれをどう解決するかと考えました。

「そうだ! ChatGPTに任せよう!」ということでやってみた感じですね。

1つ目が、「コードが抽出できない」の解決策です。イメージですが、APIリクエストの流れが、こんな感じになっています。

「空に大きな丸い月を作ってください」みたいなことを最初に投げます。そうすると、「申し訳ありません」と返ってきます。コードが書かれていないんですね。

ここでの2回目のリクエストがポイントで、(スライドを示して)こういう感じで、最初のリクエスト、返してきたものがありますが、リトライで前回のやりとり+依頼文を送ります。それを自動化してやると、きちんと書いてくれます。

これをどう実装するかというと、ChatGPT API呼び出しの関数を修正します。think_codeという関数なんですが、extra_messagesを配列で受け取って、その中で展開するように修正します。

main関数を修正します。だいぶざっくりしていますが、追加のメッセージの配列を最初に初期化した上で、retry_countを超えない限りは、失敗した場合にループするようにします。

その上で、コードが抽出できない場合は、APIの返答とコード生成の依頼文を追記して再度問い合わせます。retry_countは、maxにならない限りはずっと繰り返すので、いずれは作ってくれる場合が多かったです。

「Evalでエラーが発生する」の解決策

もう1つ、Evalで実行時エラーの解決ですね。これも同じなのですが、「空に大きな丸い月を作ってください」、「はい、こちらです」で、実行時エラーが発生します。エラー文と一緒に、「実行したところ、hogehogehogeというエラーが発生しました」と出るので、前回のやりとり+エラー文を送ります。

そうすると、「申し訳ございません。コードが間違っていました。以下が修正済みのコードです」と、エラーを修正したコードを書いてくれます。そうすると、実際に動くんですね。

これが、main関数の修正です。先ほど紹介したコードは省略していますが、ここでEvalをtry/exceptで囲み、発生した例外をキャッチします。

キャッチした上で、エラー内容を次のAPI呼び出しのプロンプトにそのまま埋め込みます。「実行したところ、{e}というエラーが発生しました。修正してください」ですね。

そうすると、先ほどのAPI呼び出しになるので、修正したコードを書いて戻してくれるという感じです。これで解決です。

まとめ

まとめです。Minecraftは楽しい! ChatGPTのコードをEvalする際のエラーは、ハンドリングしてChatGPTに直してもらうとよいよ、です。今回は記事に書いているので、もしよかったら見てください。

個人開発した「IME Submit Blocker」を紹介

最後に宣伝です。MacでChatGPT関連の海外サービスを使う時に困るアレを解決するツールを最近個人開発しました。

どんなものかというと、「IME Submit Blocker」。ちなみにこれはたぶんMacの方しか対象じゃないので(笑)、LinuxとかWindowsの方はそもそも困っていないと思います。

「Bing」は最近直ったのですが、前は変換した時に、変換で送信されることがあったと思うんですよ。僕の拡張機能を入れると、これがぜんぜん大丈夫になるよというやつです。

今、Bingをお見せしていますが、Bing以外の、どんなWebサービスでもできます。今、これですね、変換しても大丈夫です。誤送信されません。Auto Applyなどいろいろなものが入っています。

ちょっと実際にデモをしてみようと思います。「ChatPDF」を使ったことがある方はいますか? 多いですよね。ChatPDFも、日本語だと変換確定のEnterで送られちゃうんですよ。

こういう感じで変換で送られてしまうと、まともに問い合わせできないじゃないですか。この時に、「APPLY」とやると、変換しても送られません。

どのサービスでも、この拡張機能はだいたい動くので、ぜひ使ってみてください。(スライドを示して)こちらにあるので、ぜひ使ってみて、良かったら、評価とリポジトリにスターをお願いします(笑)。

以上です、ありがとうございました。

(会場拍手)