[Minecraft] ChatGPTを使ったマイクラ建築に挑戦!

Minecraft

ChatGPTはOpenAI社が開発した自然言語生成に特化した生成AIサービスです。
既に利用されている方も多いと思います。
マイクラの世界でもChatGPTを使って建築できないかを確認したくて、
マイクラ x Minescript Mod(Python実行環境) x ChatGPTでの組み合わせを試してみました。

本ページでは具体的な実現方法から実際動かしてみた結果までを解説していきます。

Python実行環境準備

マイクラ上でPythonスクリプトを実行できる環境を用意します。
設定についてはこちらを確認します。

ChatGPT API実行環境準備

PythonからChatGPT APIを利用するため準備を行います。
設定についてはこちらを確認します。

Pythonスクリプト作成

ここでは「my_gpt.py」としてファイルを作成します。
場所は%appdata%\.minecraft\minescriptフォルダに保存します。

スクリプト全体

今回のソースコードは以下です。
まずはこちらをmy_gpt.pyに貼り付けて保存します。
api_key="XXXXXXXX"部分は、ChatGPT APIで取得したAPI KEYに書き換えてください。

import minescript
import sys
from openai import OpenAI

if __name__ == "__main__":
    user_content = sys.argv[1]
    (px, py, pz) = minescript.player_position()
    blockpacker = minescript.BlockPacker()

    client = OpenAI(api_key="XXXXXXXX")
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role":"system", "content":"あなたは優秀なマインクラフターです。"},
            {"role":"system", "content":"あなたのプレイヤーは、x座標:%d、y座標:%d、z座標:%d の場所にいます。" % (int(px), int(py), int(pz))},
            {"role":"system", "content":"回答はPython言語で、配置ブロックの(x座標(整数),y座標(整数),z座標(整数),ブロックID(文字列))のタプルの集合を返すchatgpt_work()関数のみを定義してください。"},
            {"role":"system", "content":"回答はできるかぎりfor文やwhile文などを使って効率化してください。"},
            {"role":"system", "content":"回答文にはコメント文を含めないでください。"},
            {"role":"system", "content":"ブロックIDは質問に対して最適なマインクラフト上のブロックID(oak_logなど)を返してください。"},
            {"role":"user",   "content":user_content}
        ]
    )
    r = response.choices[0].message.content
    myf = r.replace("```python\n", "").replace("```", "")
    minescript.echo(myf)
    exec(myf)

    blockpacker = minescript.BlockPacker()
    for d in chatgpt_work():
        if d[3] == "oak_plank":
            blockpacker.setblock((int(d[0]), int(d[1]), int(d[2])), "oak_planks")
        elif d[3] == "door":
            blockpacker.setblock((int(d[0]), int(d[1]), int(d[2])), "oak_door")
        elif d[3] == "leaves" or d[3] == "leaf":
            blockpacker.setblock((int(d[0]), int(d[1]), int(d[2])), "oak_leaves")
        else:
            blockpacker.setblock((int(d[0]), int(d[1]), int(d[2])), d[3])
    blockpacker.pack().write_world()

スクリプト解説

簡単にスクリプトを解説していきます。

解説
    user_content = sys.argv[1]

プログラム引数として、ChatGPTに入力する文章を渡します。
半角スペースが含まれてしまうとsys.argv[1]に含まれなくなってしまうので繋げて入力します。
(このあたりは横着してます。。)

解説
    (px, py, pz) = minescript.player_position()

プレイヤーの現在地(x座標、y座標、z座標)を取得します。

解説
    client = OpenAI(api_key="XXXXXXXX")
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role":"system", "content":"あなたは優秀なマインクラフターです。"},
            {"role":"system", "content":"あなたのプレイヤーは、x座標:%d、y座標:%d、z座標:%d の場所にいます。" % (int(px), int(py), int(pz))},
            {"role":"system", "content":"回答はPython言語で、配置ブロックの(x座標(整数),y座標(整数),z座標(整数),ブロックID(文字列))のタプルの集合を返すchatgpt_work()関数のみを定義してください。"},
            {"role":"system", "content":"回答はできるかぎりfor文やwhile文などを使って効率化してください。"},
            {"role":"system", "content":"回答文にはコメント文を含めないでください。"},
            {"role":"system", "content":"ブロックIDは質問に対して最適なマインクラフト上のブロックID(oak_logなど)を返してください。"},
            {"role":"user",   "content":user_content}
        ]
    )

ChatGPTのプロンプト文を設定しています。
“role”:”system”に前提条件を指定した上で、
ユーザから受け取った情報から建物に変換するchatgpt_work()関数を作ってくれます。
配置ブロックの集合を返す関数として定義させています。

解説
    r = response.choices[0].message.content
    myf = r.replace("```python\n", "").replace("```", "")
    minescript.echo(myf)
    exec(myf)

chatgpt_work()関数として受け取ったソースコードを、execコマンドで評価しています。
評価することで、プログラム内でchatgpt_work()関数を利用可能になります。

解説
    blockpacker = minescript.BlockPacker()
    for d in chatgpt_work():
        if d[3] == "oak_plank":
            blockpacker.setblock((int(d[0]), int(d[1]), int(d[2])), "oak_planks")
        elif d[3] == "door":
            blockpacker.setblock((int(d[0]), int(d[1]), int(d[2])), "oak_door")
        elif d[3] == "leaves" or d[3] == "leaf":
            blockpacker.setblock((int(d[0]), int(d[1]), int(d[2])), "oak_leaves")
        else:
            blockpacker.setblock((int(d[0]), int(d[1]), int(d[2])), d[3])
    blockpacker.pack().write_world()

chatgpt_work()関数からブロックの集合が返ってきますので、
指定された座標にブロックを配置していきます。

一部ChatGPTから、現在のマイクラでは存在しないブロックIDを返してくることがあり、
if文で正しいブロックIDを返すようにしています。

ChatGPTを使って建築してみる

実際にマイクラのワールド上で建築してみます。
実行方法は「my_gpt」の後に、どのような建築物を作りたいかを入力します。
例えば、以下のように入力します。

\my_gpt ログハウスを作って。屋根、玄関、窓、明かりなども配置してね。

現在のプログラム上、半角スペースが含まれてしまうと切れてしまうので繋げて入力します。
(もちろんプログラムを変更することで対応可能です)

色々試しているなかで、ChatGPTのモデルが「gpt-4o」か「gpt-4o-mini」かで、
自動的に作られる建物の精度にもかなりの違いが出ることが分かりました。
参考までに比較の結果も載せておきます。

結果「ログハウスを作って。屋根、玄関、窓、明かりなども配置してね。」

明らかに建築精度に違いが出ています。
gpt-4oは精度が高く、様々な建築にも応用できそうです。

gpt-4o
gpt-4o-mini
りお
りお

かなり使えることが分かりました!
もっと細かい指示を与えたら、より精度の高い建築物を作ってくれそうですね。

まとめ

マイクラ x ChatGPTということで試してみました。
思ったものを自動的に建築してくれるのは新鮮な体験でした。
もちろん自分の手で建築することも、とても楽しいのですが、
マイクラを楽しむ一つの方法になるかと思っています。

コメント

タイトルとURLをコピーしました