gemma-unity-pluginをUnityで動かす

初めに

先日 Google がgemmaをゲーム領域で使っていく発表がありました。その中で以下のライブラリが公開されていたので動かしていきます

github.com

動かすと以下のようになります。レスポンスの精度は2bだったのでそれなりです

記事内容は以下のRepositoryで公開しています

github.com

開発環境

  • Unity 6000.1.1f1
  • UniTask 2.5.10
  • Gemma.cpp for Unity 1.0.5

ライブラリのインストール

はじめに必要なライブラリをインストールしていきます。

まずは PackageManager 経由で UniTaskをインストールします。

URL: https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask

次に gemma-unity-pluginをインストールします。

URL: https://github.com/google/gemma-unity-plugin.git

モデルのダウンロード

次にモデルのダウンロードを行います。

手元で動作確認ができたものが google/gemma-2b-sfp-cppだったため、こちらのモデルをダウンロードして StreamingAssets に以下のように配置します

Gemmaライブラリ用の設定ファイルの作成

ライブラリを動かすために Craete > Gemma > Settins から 設定ファイルを再生します

設定ファイルの項目は以下のように設定します

スクリプトの作成と設定

ライブラリ側が用意している Gemma Manager を適当なオブジェクトにアタッチします

以下のようなスクリプトを作成してアタッチします。

using System;
using Cysharp.Threading.Tasks;
using GemmaCpp;
using UnityEngine;

namespace GemmaTest
{
    public class GemmaTest : MonoBehaviour
    {
        private GemmaManager _gemmaManager;

        private void Awake()
        {
            _gemmaManager = GetComponent<GemmaManager>();
            Debug.Log("GemmaManager initialized.");
        }

        private async void Start()
        {
            await UniTask.WaitUntil(() => _gemmaManager.Initialized,cancellationToken:destroyCancellationToken);
            Debug.Log("GemmaManager initialized.");
            GenerateResponseAsync("Hello, Gemma! Tell me a short story.").Forget();
        }

        private async UniTask GenerateResponseAsync(string prompt)
        {
            try
            {
                Debug.Log($"Sending prompt: {prompt}");

                Debug.Log("Generating response...");
                bool OnTokenReceived(string token)
                {
                    Debug.Log($"Token received: {token}");
                    return true;
                }

                string response = await _gemmaManager.GenerateResponseAsync(prompt, OnTokenReceived);
                Debug.Log($"Gemma's response: {response}");
            } catch (Exception e)
            {
                Debug.LogError(e);
            }
        }
    }
}

上記のスクリプトを以下のようにアタッチします。

こちらを実行すると以下のようになります。

レスポンスにはそれなりに時間がかかります。

備考

なぜか二回目を実行するとクラッシュしています。Domain Reloadの設定も変更しても解決したなかったのでライブラリ側のバグなのかもしれないですが、そこまでは調査できず...