優勝するとデロリアンがもらえるハッカソン、Gemini API デベロッパーコンペティションにチームで参加しました。
そして全世界から3000プロジェクトの応募の中から、9個の賞のうちの1つ、Best use of ARCore を受賞しました。やったー🥳🥳🥳🥳。
私達の作ったものは "everies"。身の回りのものすべてと喋ることができるアプリです。動画が短くまとまっているのでぜひ見てください。
開発チームメンバーは以下:
せっかくなので、開発の裏側的なものを書こうと思います。
仲間探し
昨年 友人の音楽家 Twothと Google’s Immersive Geospatial Challengeに参加し、幸運にも受賞することができて、ハッカソン怖くない!となった私は、今回も参加してみたいと思い、仲間を募りました。長年Co-creatorとして一緒に作っているWhatever Co.のSlack雑談チャンネルへぽちっと。
。。。1時間で最強の仲間が集まりました。みんなノリがいいな!
3000件も応募があるとは思ってなくて、謎の自信にあふれたセリフを吐いている当時の自分を殴りたい。
企画
最初の1ヶ月くらいはオンラインであつまり、企画をワイワイ考えました。そしてクリエイティブディレクターKyosuke TaniguchiとアートディレクターTaichi Itoの提案してくれた、AR上でキャラクターと喋る案を掘り進めることになりました。
今見返すと、企画書の時点で高い精度で完成形が見えてますね。素晴らしい。
リサーチ & デベロップ
企画と並行して、アプリを作るための技術調査も進めました。
APIの整備されているWebやネイティブアプリはライバルが多そうなので、私の得意分野のUnity x ARを中心にR&Dしていきました。
UnityからGemini APIを使う部分はライブラリとして公開しています。Google Generative ModelのAPIを網羅はしていませんが、今回必要になった以下のような基本的なGemini APIとの連携に対応しました:
- 生成のストリーム受信
- UnityのTexture・AudioClipをMultimodal 入力として送る
- Function Callで自動的にC#メソッドを叩く
- C#の型定義をOpenAPIのスキーマに変換して、JSONモードで受け取る
マルチモーダルが優秀なので、音声認識も画像認識もセリフ作るのも全部をLLMに投げています。音声認識も、日本語、英語、ドイツ語で話しかけましたが全部理解して返答したことに驚きました。
以下の動画は初期のプロトタイプです。オブジェクトから目が出る部分はLLMで毎秒画像を送るわけにもいかないので、TensorFlow LiteでスマホのローカルでEfficiantDetを使ったオブジェクト検出をしています。音声も当初はGoogle TTSを使っていました。
ローカルで動く軽量モデルでは認識しないオブジェクトも多々ありますが、ローカル認識していないものをタップすると、Gemini API側のマルチモーダルで画像を認識して、どんなものでもキャラクターになってくれるのがLLMのすごいところです。ローカルで動くレスポンスの早い軽量機械学習モデルと、LLMを組み合わせる実験ができたのは嬉しい成果でした。
その他の依存ライブラリとして、自作の以下3つをDogfoodingしています。
- GitHub - asus4/tf-lite-unity-sample: TensorFlow Lite Samples on Unity: 機械学習ライブラリTensorFlow LiteをUnityで使うライブラリ。
- GitHub - asus4/ARFoundationReplay: AR Record and Playback System on Unity ARFoundation:ARを録画して、UnityEditorの中でAR Foundationを動かす。
- GitHub - asus4/TextureSource: Virtual Texture Source for Unity (WebCam, Video, AR Camera):画像認識の入力を抽象化する。今回、空間にオブジェクトを配置するためARのDepth機能を追加。
これによりUnity AR FoundationをUnity Editorの中で動かして、AR内でTensorFlow Liteによる画像認識ができるようになりました。Editorと実機で(処理速度以外は)ほぼ同じ挙動が確認できることで、開発のイテレーション回数が上がります。
そして今回の肝となった、個性的なキャラクターの音声は、Makoto Matsutakeが調査を進めてくれました。
色々試す中でElevenLabsが一番個性的な声を出せるということで採用になりました。最初のプロトタイプと比較すると、個性的な声になっていますね。
プロンプトエンジニアリング
未知の分野のプロンプトエンジニアリング。普段はクリエイティブディレクターのKyosuke Taniguchiが、プロンプトエンジニアリングも担当しました。Google AI Studioでプロンプトを練って、画像を送るとキャラ設定とセリフを返してくれるところまで、一行もコードを書かずに作っています。
ちょうどこの頃、実装担当の私とMakoto Matsutakeが無謀なことに締切の被っている本業に忙殺されていました。このハッカソンもやりたいが仕事優先、全然終わらん〜となっているところに、Whatever CTOのSaqoosha が助っ人に来てくれました。心強すぎる!!嵐のような早さで残タスクを進めていってくれました。CTOに手伝ってもらうというチート技を使ってしまった。
Promptを本番と同じワークフローで詰めるためにWebでPrompt Editorを作ってくれました。最終的に使った3ステップの生成を通して、様々な画像でユニークなキャラクターになるようなプロンプトを調整していきました。
Geminiはレスポンス時間とAPI金額を考慮してGemini Falsh 1.5 を使っています。Gemini Proモデルより性能は劣りますが、レスポンスは早く、使用料も締め切り前で沢山テストした8月で500円程度に収まりました。
組み込んでいるプロンプトでは、王道のプロンプトエンジニアリングだけでは変化の幅が少ないと判断し、プロンプトのテキスト自体もランダムに入れ替わるという古典的も手法を組み合わせています。
この段階までは日本語でプロンプトを考えていましたが、コンペティションの応募はすべて英語が条件。英語にするときに困った…とSaori Nakakariyaにプロンプトを英語でも動作させるのを手伝ってもらいました。最終的にはプロデューサー業、提出から受賞のemailのやりとりまで、すべてをお任せしてしまった。
今回LLMとプログラムの連携を本格的に試してみて、JSONモードに可能性を感じました。LLMは自由にテキストを生成するので、自分の必要な情報をパースするのに一手間かかります。しかしJSONモードを使うと、まるで自分専用のAPIが存在するかのような手触りに変わります。
キャラクター作り
Taichi Itoのデザイン案を基に、キャラクターのモデリングはBlenderで行いました。キャラクターの個性である口は柔らかさを出すために、ボーンではなく、すべてShape Keyを使って作りました。
編集点を少なくするため、カーブでShape Keyをつくり、スクリプトで自動的にMeshのShape Keyに変換。FBXへ書き出しています。
FBXをUnityへ読み込んだ後、Blend Shapeの全パラメーターをAnimatorでブレンドして、様々なバリエーションの顔を作りました。
テスト!
締め切り間近。テスト、バグ取り、そしてデモ動画提出へ向け、日本と台湾のWhateverチームにアプリを配りテスト動画を撮影してもらいました。お陰で素敵なデモ動画も完成。
今後について
普段のお仕事にも色々ストーリーはあるのですが、制作の過程を包み隠さず話せるのは自主プロジェクトならでは。
こんな感じで多くの人の力を借りて作っています。
せっかく受賞もしたことだし、時間を見つけて…と言っていると絶対やらないので年明けにリリースへ向けてブラッシュアップして公開したいです。