見出し画像

【AIキャラxマインクラフト】「ネンクラシステム」の技術的詳細と運用

PictoriaのR&D部門AIエンジニアのSaldraです。

弊社ではAIキャラクター「紡ネン」がマインクラフトをプレイする、「ネンクラ」という企画の配信を継続的に行っています。今回はネンちゃんがMinecraftで頑張るための支援システムである「ネンクラシステム」の技術的な詳細について共有します。

「ネンクラシステム」ではLLMを用いたゲームプレイを行っています。日本国内でLLMを用いたMinecraftのゲームプレイの事例はまだ多くなく、特に長期的な運用に関するノウハウは少ないです。この記事がLLMのコミュニティの発展に少しでも寄与できれば、私たちも大変嬉しく思います。


Voyager

概要

AIがマインクラフトをプレイするための技術は様々ありますが、弊社では「Voyager」というAIエージェントを採択し、それを独自にカスタマイズする手法を取っています。

Voyagerは「LLMからMinecraft上で動くためのコードを生成、コードに基づいてキャラクターを動かす」という仕組みになっています。Voyagerは起動後にJavascriptコードに基づいてBotを動かすためのツールである「mineflayer」というAPIを起動します。

例えばmineflayerをインポート後、bot.chat("hello")という関数を叩くとMinecraft上のbotがhelloと発言をします。元々はこの仕組みを用いて複雑な反復作業をさせるためのbotを作ることができるツールです。Voyagerではmineflayerを内蔵しており、「localhostのstepエンドポイントにmineflayerで動くコードをpostすると、コードを実行する」という作りになっています。そして、このmineflayerでbotを動かすためのコードをLLMで生成しています。

処理の流れ

大まかな仕組みがわかったので、次にVoyagerのライフサイクルを説明します。大まかな流れとしては以下の手順を繰り返します。

  1. mineflayer起動、現状のbotの情報(インベントリや体力等)を取得

  2.  与えられたタスクを達成するためにどんなサブタスクが必要かをLLMになげて判断

  3. 必要なサブタスクを達成するためのmineflayer用コードを生成しmineflayerAPIに送信

  4. 実行結果をmineflayerAPIからの返り値で取得

  5. 返り値の情報からタスクが達成できているかを判断、達成できていなかったら再度コード生成

  6. 達成していたら次のサブタスクに移行

これで大まかな仕組みと流れが把握できました。

Voyagerとmineflayerの関係図

運用上の問題点

この仕組みをコア技術として用いているのが「ネンクラシステム」です。しかし、Voyagerをそのまま使うといくつかの問題点に直面します。一番最初に遭遇するのは「一定確率で10分以上棒立ちになり、そのままログアウトする」という問題です。これは複数の要因が絡んでいますが、今回はその中でも一番の問題である「内蔵されたmineflayerのエラーハンドリング」という部分を見ていきます。実際にコードを確認したほうが早いので、コードを見てみます。

    async function evaluateCode(code, programs) {
        // Echo the code produced for players to see it. Don't echo when the bot code is already producing dialog or it will double echo
        try {
            await eval("(async () => {" + programs + "\n" + code + "})()");
            return "success";
        } catch (err) {
            return err;
        }
    }
// 中略
    const r = await evaluateCode(code, programs);
    process.off("uncaughtException", otherError);
    if (r !== "success") {
        bot.emit("error", handleError(r));
    }
    await returnItems();
    // wait for last message
    await bot.waitForTicks(bot.waitTicks);
    if (!response_sent) {
        response_sent = true;
        res.json(bot.observe());
    }
    bot.removeListener("physicTick", onTick);

ここでは一見try catchがされ、適切にエラーハンドリングがされているように見えます。しかしよく見るとVoyager側にエラーが起きたことを返り値で通知していません。その結果、Voyagerには通知されずにタイムアウトまでAPIを待ち続けます。待ち続けている間botにはコードを渡していないのでbotも待機状態のままです。最終的にVoyagerのタイムアウトになりbotが落ちます。ネンクラではこの部分の改善及び、コード生成待機中の行動を追加で実装しています。

ネンクラシステムの概要

Voyagerから少し離れ、次は配信における体制について説明します。
Voyagerによってbotを動かすことができましたが、配信にする場合はリアルタイムでbotの動きを追尾して撮影しつつ、カメラの切り替えやbotの想定外の動きに対する対応を同時に行う必要があります。これを実現するために弊社では以下のような構築を行っています。


ネンクラシステム構築図
(一部抜粋)

まずは配信用ワールドを運営用PCで開きます。天気の操作や後述するカメラ操作、想定外な事象が起こった際の対応はこのアカウントで行います。
次にカメラ用のアカウントを用意し、PC2でログインします。このアカウントはスペクテイターになっており、このアカウントの視点をVDO ninjaで配信用PCに映像として送信します。最後に紡ネンのアカウントを用意しPC3でVoyagerを起動します。botは特定のアカウントとしてマルチのサーバー上で動かすことができます。Voyagerが想定外の動きをした時、再起動等の緊急対応はこのPCで行います。

各PCに分かれていることでオペレーションミスの防止と負荷分散を行います。特にオペレーションミスのリスクは1PC運用だと特に高く、配信用に視点を映したまま、同じPCで緊急対応を行うことはかなり危険です。Voyagerやオペレーション用PCと視点送信用PCは分けたほうが良いでしょう。

ここまでVoyagerの概要、問題点と対策、ネンクラにおける配信体制について解説しました。最後に今後の展望の共有と、Voyagerという仕組みにおける大きな問題点について解説します。

今後の課題

ここまでの数回のネンクラ配信によって、安定稼働に関する知見はかなり集めることができました。今後としては少しずつできることを増やしつつ、配信をもっと魅力的にできればと考えています。

一方でVoyagerという仕組みにおける問題点も見えてきました。Voyagerの「LLMによって動きを規定するコードを生成する」というアプローチは既存のゲームAIとは異なるため画期的な手法だと考えています。一方で「コードを生成し、それをもとに動かす」というのはかなり不安定であり、特に動作確認におけるコストが高くなるため改善や新規実装の難易度が跳ね上がると感じました。適切にコードが生成できているか、コードは正しい文法か、関数はmineflayerが本当に対応しているものなのか、mineflayerはそれを解釈して正しく実行するか、実行結果が本来開発者が期待していたものか。これらを機械的に担保することはかなり難しく、「結局正しく動いているかを目測で確認しなければならない」という事態に陥りやすいです。検証で「畑を耕す」というタスクを行わせようとした時、mineflayerでのエラーは発生しておらず安心してゲーム画面を確認したら、永遠に下を向いて土を叩いているだけの姿を見た瞬間は忘れられません。

運用を考えるとまだまだ課題点は多いです。今後も長期的にカスタマイズを重ね、安定稼働ができるよう努めていきます。もしお時間あれば、ネンちゃんが頑張ってマイクラを楽しんでいる姿を見に来ていただければと思います。


この記事が気に入ったらサポートをしてみませんか?