この記事では、Uezoさん製作のAIAvatarKitを使用し、音声対話AIアバターをVRChat上に実装する方法を紹介します。
完成系は下記の動画の通り。
AIアバターはユーザの質問を分類、下記の3通りの選択肢の中から適切なものを選択し回答を行うように定義しています。
①ニュースに関する質問、またはweb検索を求められる時事問題
⇨ Web検索を行い、検索結果を要約して回答(RAG)
②マレーシア観光に関する質問
⇨あらかじめロードしたPDFを使用して回答(RAG)
③その他
⇨生成AIにて通常に回答
本会話ロジックはDifyのChatflowにて開発を行なっています。
ノーコード、ロードコードツールを中心に使用されているため、プログラミング初学者でも試しやすい内容となっております。
AIAvatarkit... Uezoさん製作。AIベースの音声対話アバターを高速で開発するアセット。(Apache 2.0ライセンス)
https://github.com/uezo/aiavatarkit
Dify... LLMアプリ開発プラットフォーム。大規模言語モデルを用いて、AI機能を持ったアプリをプログラミング不要で開発することができる。
https://dify.ai/
1 全体概要
実装の全体イメージは下記の通りです。(図はAIAvatarKit Architeture Overviewを元に作成)
ユーザからの質問を一度テキスト化し、Difyアプリに提供。Difyアプリ側にてAIで生成された回答を音声化し回答します。
下記の通り、さまざまな機能間での接続、ファイルのやり取りが発生し複雑そうに見えますが、この接続周りはほとんどAIAvatarkitが行なってくれます。
そのため我々は下記のDify Chatflow配下に該当する、AIアバターの回答ロジックの開発に注力できます。
実装手順については下記AIAvatarkit製作者様の記事が非常にわかりやすいですが、
私の記事では迷いがちなAPIキーの取得手順及びDifyを使用した場合の実装方法を中心に実装手順全体を記載することとします。
2 事前準備
実装にあたり、下記の事前準備が必要です。
- Google Text-to-Speech :アカウント作成及びAPIキー取得(クレカ登録要、無料枠有)
- Open AI: アカウント作成及びAPIキー取得(クレカ登録要、無料枠無)
- Dify:アカウント作成及びAPIキー取得(無料プラン)
- VOICEVOX:予めインストールし、自端末で起動しておく
- Python 3.10以上の環境
- VRChatアカウント(AIアバター用にご自身のものとは別に1アカウント)
各サービスのAPIキーは取得場所が分かりづらく混乱しがちなため、以降それぞれの取得場所をキャプチャ付で説明します。なお、各サービスのUIは都度アップデートにより変更される可能性があります。本解説は2024/12月時点のものであることをご留意ください。
Dify APIのみ、Dify側でアプリを作成しないと発行できないため、4章で解説します。
2.1 Google cloud Speech-To-Text APIキー取得
1.Googleクラウドコンソールにアクセスし、お持ちのGoogleアカウントでログインします。(ない場合は事前作成してください)。
2.Googleクラウド未登録の場合はGoogle Cloud Platform の無料トライアルの登録画面にて、登録を行なってください。
3.画面左上の「My First Project」を選択 、「新しいプロジェクト」を選択。任意のプロジェクト名を入力し、作成をクリックします。
4.再度画面左上の「My First Project」を選択し、3.で作成したプロジェクトを選択します。(「My First Project」でなくすでに3.で作成されたプロジェクトが左上に表示されている場合は実施なし)
5.画面上部の検索ボックスに「speech to text」と入力し検索。表示されたspeech to textをクリックし、有効化されていることを確認する。有効化されていない場合は「有効化する」ボタンをクリックします。
6.画面左上のナビゲーションメニュー(3本線)をクリックし、展開された左メニューから APIとサービス>認証情報 を選択します。
7.画面上部の 認証情報を作成>APIキー を選択。表示されたAPIキーをメモしておいてください。
2.2 OpenAI APIキー取得
1.OpenAI製品ページにアクセスし、ページ上部の「製品」部分の箇所にカーソルを合わせると、メニューが展開されます。その中から「APIログイン」を選択してください。
2.画面右上の「Sign up」を選択し、アカウント登録を進めてください。
3.ログイン後、右上タブからDashboardを選択し、左メニューからAPI keysを選択します。
4.画面中央の「Create new secret key」を選択、任意のNameを設定し、「Create secret key」を選択します。表示されたAPIキーをメモしておいてください。
8.OpenAI APIの無料クレジットは廃止されたため、APIクレジットが必要です。
右上の歯車(Setting) -> 左側メニューのBilling -> Overview -> Add payment method を選択し、任意の金額のチャージを行なってください。5ドルもあれば十分です。(クレジットカード情報の入力が求められます。
3 AIAvatarKit導入、動作確認
AIAvatarKitを導入し、VRchatに接続する前の状態でのAIAvatarKitの動作確認を行います。
Python 3.10以上の環境でpipコマンドにてAIAvatarKitをインストールします。
$ pip install aiavatar
動作確認のためにAIAvaterKitのReadMeを参考に実行ファイルを作成します。
from aiavatar import AIAvatar
GOOGLE_API_KEY = "YOUR_API_KEY" #2章で取得したGoogle APIキーを入力
OPENAI_API_KEY = "YOUR_API_KEY" #2章で取得したOpenAI APIキーを入力
VV_SPEAKER = 54 #VOICEVOXのキャラクタを選択 例 14=冥鳴ひまり
app = AIAvatar(
openai_api_key=GOOGLE_API_KEY,
google_api_key=OPENAI_API_KEY,
voicevox_speaker_id=VV_SPEAKER,
)
app.start_listening_wakeword()
実行してみます。
$ python run.py
PCに向かって「こんにちは」と話しかけてみます。(「こんにちは」が起動用語になっています。)
お使いの端末のマイク、スピーカが有効な状態であればそのまま会話が進められているはずです。
[INFO] 2024-12-25 17:42:02,578 : Input device: [0] MacBook Proのマイク
[INFO] 2024-12-25 17:42:02,578 : Output device: [1] MacBook Proのスピーカー
[INFO] 2024-12-25 17:42:02,675 : Measuring noise levels...
Noise level: -35.71dB
[INFO] 2024-12-25 17:42:05,820 : Set volume threshold: -15.0dB
[INFO] 2024-12-25 17:42:05,823 : Listening... (WakewordListener)
[INFO] 2024-12-25 17:42:10,366 : User: こんにちは
[INFO] 2024-12-25 17:42:10,366 : AI:
[INFO] 2024-12-25 17:42:13,123 : こんにちは!
[INFO] 2024-12-25 17:42:15,207 : 今日はどんなことをお話ししましょうか?
[INFO] 2024-12-25 17:42:18,523 : Listening... (VoiceRequestListener)
[INFO] 2024-12-25 17:42:23,704 : Stopped listening (VoiceRequestListener)
[INFO] 2024-12-25 17:42:23,705 : User: マレーシアのおすすめの観光地教えて
[INFO] 2024-12-25 17:42:23,705 : AI:
[INFO] 2024-12-25 17:42:26,582 : マレーシア南部地域では、
[INFO] 2024-12-25 17:42:30,009 : マラッカ市のサンチャゴの砦やジョホールの美しい島々が特におすすめです。
[INFO] 2024-12-25 17:42:35,987 : 歴史や自然を楽しめる場所がたくさんありますので、
[INFO] 2024-12-25 17:42:40,126 : ぜひ訪れてみてください!
***
4 Difyを使用したChatflow作成
この章ではLLMアプリ開発プラットフォームであるDifyを使用したアプリケーションの作成を解説します。Difyを使用することで外部情報の検索結果を使用した回答(RAG)したり、質問の内容によって回答する方法を分岐させることができたりなど、高度なAIチャットを簡単に開発することができます。
4.1準備
1.Difyにアクセスし、「Get started」を選択してアカウント登録を進めてください。プランがいくつかありますが、今回は無料のもので問題ありません。
2.新規アプリを作成します。トップページより、スタジオ>チャットボット>最初から作成 を選択します。
3.チャットフローを選択し、任意のアプリ名を設定し、「作成する」を選択します。
4.作成が完了すると、下記のようなチャットフローが表示されます。デフォルトで設定されている「LLM」と「回答」のブロックは使用しないので消しておきます。
5.DifyにOpen AIのAPIを設定します。画面右上のユーザ名(デフォルトはDify)をクリックし、設定を選択します。 表示されたポップアップから モデルプロバイダー > Open Ai > セットアップ を選択し、2章で取得したOpen AI のAPIを設定します。
4.2 質問分類機の作成
ここからチャットフローの作成を開始します。本記事の冒頭で述べたとおり、質問の内容に応じて下記の処理を行うAIチャットをDifyで開発します。
①ニュースに関する質問、またはweb検索を求められる時事問題
⇨ Web検索を行い、検索結果を要約して回答(RAG)
②マレーシア観光に関する質問
⇨あらかじめロードしたPDFを使用して回答(RAG)
③その他
⇨生成AIにて通常に回答
最終的なフローは以下のイメージになります。次から各ブロックの解説を行います。
まず、質問の内容に応じて処理を分岐させるために、質問分類機を作成します。
質問部類機とは、ユーザの質問の分類条件を定義することで、LLMが分類条件を元にユーザ質問の振り分けを行い、選択肢ごとの後続処理に繋げることができる機能です。
1.「開始」ブロックの右にある+をクリックし、質問分類機を選択します。
2.任意のGPTモデルを選択し、クラスに分類条件を定義します。
ニュースに関する質問、またはweb検索を求められる時事問題
マレーシア観光に関する質問
その他
4.3 Web検索フローの作成
チャットフローのうち、下記に該当する部分を作成します。
①ニュースに関する質問、またはweb検索を求められる時事問題
⇨ Web検索を行い、検索結果を要約して回答(RAG)
1.ここではユーザからの質問を元にweb検索で使用する検索ワードを生成AIに抽出するブロックを作ります。質問分類機のクラス1右隣の+ を選択し、LLMのブロックを選択、作成します。
2.ブロック名、モデル名、コンテキスト、SYSTEMフォームを入力します。
フォームには「/」を入力することでパラメータをプルダウンから選択できます。
ここではコンテキスト(入力情報)としてユーザの質問、SYSTEM(会話の命令)に下記プロンプト及びコンテキストを入力します。
「***」以下はユーザの質問です。ユーザの質問に回答できるように、web検索に使用可能な語句を抽出、生成してください。語句は3つ以内にしてください
***
/CONTEXT
3.検索ブロックを作成します。このブロックでは検索語句生成ブロックで作成された検索用語でweb検索を実施し、検索結果が文字列で返却されます。「検索語句生成」ブロック右隣の+ を選択し、DuckDuckGo Searchのブロックを選択、作成します。作成後、入力変数フォームに検索語句生成ブロックの結果を設定します。
4.検索語句要約ブロックを作成します。このブロックではDuckDuckGo Searchの検索結果をLLMにより要約します。DuckDuckGo Search右隣の+を選択し、LLMのブロックを選択、作成します。作成後、
下記画像通りに必要項目を設定します。
「***」以下はユーザの質問に対する検索結果である。検索結果を下記の制約に遵守する形でユーザがわかる形で要約すること。また、本コミュニケーションは口頭で行われていることを意識してください。
制約:
- わからない場合は、わからないと答えればよい。
- わからない場合、不明な場合は、明確にするよう依頼する。
-検索結果に含まれない情報について言及しない
-ユーザーの質問の言語に合わせて回答する
***
/CONTEXT
5.回答ブロックを作成します。このブロックではユーザへの回答項目を定義します。回答ブロックを設定しないとDify Chatフローが処理を完了できません。ここでは前ブロックのLLMが出力した回答を回答として定義します。「WEB検索結果を要約」ブロック右隣の+を選択し、回答のブロックを選択、作成します。作成後、下記画像通りに必要項目を設定します。
4.4 PDFを使用した回答フローの作成
チャットフローのうち、下記に該当する部分を作成します。
②マレーシア観光に関する質問
⇨あらかじめロードしたPDFを使用して回答(RAG)
1.Difyアプリに対象データ(PDF)をナレッジとしてインポートします。画面上部のナレッジメニューを選択、ナレッジを作成をクリックします。
2.テキストファイルからインポート を選択し、対象のPDFをアップロードします。マレーシア政府観光局の観光パンフレットを使用します。(私が行きたいので)
※容量が大きいのでPDFの後半を事前に削除しています。
3.設定は全てデフォルトで取り込みを実施します。右側でチャンクされた取り込み情報を確認できます。取り込み後に必要な情報だけ絞ることも可能です。
4.スタジオ画面に戻り、知識取得ブロックを作成します。このブロックで先ほど取り込んだPDFを指定し、後続のLLMがユーザの質問から本PDFの情報を参照し回答できるようにします。
「質問分類機」ブロックのクラス2右隣の+を選択し、知識取得のブロックを選択、作成します。作成後、下記画像通りに必要項目を設定します。
5.「検索設定」クリックし、「ウェイト設定」を選択します。
※Rerankモデルを使用するとRAGの品質が向上しますが、別途RerankモデルのAPIが必要になるため今回は使用しません。
6.PDF内容要約ブロックを作成します。このブロックではユーザの質問とPDFの内容をLLMにより回答を生成します。マレーシアPDFブロック右隣の+を選択し、LLMのブロックを選択、作成します。作成後、
下記画像通りに必要項目を設定します。
「***」以下の情報を使用してユーザの質問に回答してください。回答時は以下の制約を遵守してください。本コミュニケーションは口頭で行われていることを意識してください。
制約:
- わからない場合は、わからないと答えればよい。
- わからない場合、不明な場合は、明確にするよう依頼する。
-検索結果に含まれない情報について言及しない
-回答は必ず200文字以内で簡潔に
***
/CONTEXT
7.回答ブロックを作成します。このブロックではユーザへの回答項目を定義します。ここでは前ブロックのLLMが出力した回答を回答として定義します。「PDF内容を要約」ブロック右隣の+を選択し、回答のブロックを選択、作成します。作成後、下記画像通りに必要項目を設定します。
4.5 その他質問の回答フロー(汎用回答)の作成
チャットフローのうち、下記に該当する部分を作成します。
※特にデータ参照を行わず、質問をそのままAIに回答させます
③その他
⇨生成AIにて通常に回答
1.「質問分類機」ブロックのクラス3右隣の+を選択し、LLMのブロックを選択、作成します。作成後、下記画像通りに必要項目を設定します。
「***」以下の情報を使用してユーザの質問に回答してください。回答時は以下の制約を遵守してください。本コミュニケーションは口頭で行われていることを意識してください。
制約:
- わからない場合は、わからないと答えればよい。
- わからない場合、不明な場合は、明確にするよう依頼する。
-検索結果に含まれない情報について言及しない
-回答は必ず200文字以内で簡潔に
***
/CONTEXT
2.回答ブロックを作成します。このブロックではユーザへの回答項目を定義します。ここでは前ブロックのLLMが出力した回答を回答として定義します。「汎用的な質問対応」ブロック右隣の+を選択し、回答のブロックを選択、作成します。作成後、下記画像通りに必要項目を設定します。
4.6 動作確認
プレビューを押すことで、チャットの動作確認を行えます。作成した各フローを通るような質問を入力して回答を確認してみてください。リアルタイムでどのフローを通過し回答が生成されているかを確認できるとともに、各フローでの入出力も確認することができます。
質問例:
「2024年の今年の漢字は」
「マレーシアで子供でも楽しめる観光スポットは」
「腰の疲れが取れないのですが」
※DuckDuckGoのweb検索は無料ですが、1日の利用量に制限があります。rate limit errorが表示される場合は利用量制限を突破しています。
4.7 Dify APIキー取得
AIAvatarkitで使用するために、先ほど作成したDifyアプリのAPIキーを取得します。
- 画面右上の「公開する」を選択し、作成したアプリを外部から実行できるようにします。
2.左側 APIアクセス を選択し、 右上の APIキー を選択します。表示されたAPIキーをメモしておきます。
5 VRChatにAIアバターを導入
AIアバターをVRChatに導入する際はトラブル防止のため、Uezoさん側の記事記載にもある通り、必ず下記利用規約を遵守してください。
https://qiita.com/uezo/items/e74aea629a217cf6e4c4
(Uezoさん記事引用)
※超重要 利用規約を遵守してください
この仕組みは平たく言うとプログラムを介してワールド内の会話を録音する行為になります(ファイルなどには残しませんが)。そのため、例外なくワールド内にいる全員の同意が必要です。Invite Onlyのワールドで動かすか、自作のワールドで同意を取り付けないと進めないようにするなど、あらそいのない対策が必要です。絶対に守りましょう。
1.音声設定
AIAvatarkitはVRChatアバターのマイク、スピーカーを通して他アバターとのコミュニケーションを行う仕組みです。そのため、AIAvatarkit実行環境のマイク、スピーカーを仮装オーディオデバイス経由でVRChatと繋ぎます。
下記サイトのVB-Cableという仮想デバイスを使用します。 A+Bの2本セットのものを購入してください。(5ユーロほど)
仮装オーディオケーブル導入後、AIAvatarkit導入端末で以下の設定を行なってください。
-OS標準スピーカーをVB-Cable-Bに設定
-VRChatのAIAvatarのマイク設定をVB-Cable-Aに設定
-AIAvatarのオーディオ設定で、ユーザ音声以外の音量を0にしておく。(効果音、ワールド音等)
2.実行ファイル作成
3章で作成したOpenAI APIを直接呼び出すrun.pyをベースに、Dify対応版のrun.py(実行ファイル)を作成します。
作成前に、端末の仮装オーディオIDを確認します。下記コマンドを実行し、Cable A,BのIDを確認してください。
$ % python
>>> from aiavatar import AudioDevice
>>> AudioDevice.list_audio_devices()
0 MacBook Proのマイク, Core Audio (1 in, 0 out)
1 MacBook Proのスピーカー, Core Audio (0 in, 2 out)
> 2 VB-Cable A, Core Audio (2 in, 2 out)
< 3 VB-Cable B, Core Audio (2 in, 2 out)
この端末ではCalbeAが2, Cable Bが3でした。
実行ファイルを作成します。
AIAvatarKitのプロセッサーにDifyを指定し、APIキーを提供します。
また、inputデバイスがCalbe B, outputデバイスが Cable Aになるように先ほど確認したデバイスのIDを提供します。
from aiavatar import AIAvatar
from aiavatar.processors.dify import DifyProcessor
GOOGLE_API_KEY = "YOUR_API_KEY" #2章で取得したGoogle APIキーを入力
DIFY_API_KEY = "YOUR_API_KEY" #4章で取得したDify APIキーを入力
DIFY_USER = "aaa-123" #difyのユーザ名。ログ管理用のため任意のものを設定
BASE_URL = "https://api.dify.ai/v1" #DifyのURL。左記の通りで問題なし
VV_SPEAKER = 8
#14 冥鳴ひまり
#8 春日部つむぎ
chat_processor_dify = DifyProcessor(
api_key=DIFY_API_KEY,
user=DIFY_USER,
base_url=BASE_URL
)
app = AIAvatar(
google_api_key=GOOGLE_API_KEY,
chat_processor=chat_processor_dify,
voicevox_speaker_id=VV_SPEAKER,
input_device=3, # Listen sound from VRChat
output_device=2, #Speak to VRChat microphone
)
app.start_listening_wakeword()
run.pyを実行し、実行端末でAIアバター用のアカウントでVRChatにログインします。
AIアバター側からinviteするなどして、ご自身のVRChatアカウントで同じワールドにジョインできれば、AIアバターと対面できます。コミュニケーションを楽しんでみてください。
動画を視聴された方なら分かる通り、Difyを使用したAIアバターは直接Open AIを呼び出すよりも回答に時間を要しています。特に、Dify Chatflowの処理ブロックが多い時に顕著であり、web検索フローで15秒以上回答に時間がかかることがあります。(トレースを見る限り、Dify側が最も処理時間を占めているように見える)
AIAvatarkitはVCCによるアバターの表情変更に対応しているため、表情によって待ち時間を感じさせない工夫をするとともに、Dify,LLMをローカルに構築するなどして処理時間改善を図るなどの工夫を今後やっていきたいと思います。