33
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

エンジニア作業飲み集会Advent Calendar 2022

Day 23

ChatGPTが出たのでVRChatに音声対話型AI Botを作った。

Last updated at Posted at 2022-12-23

どうも、GesonAnkoです。ChatGPTが出たので GPTベースであるOpenAIの言語処理エンジンAPIとその他諸々を組み合わせて VRChatに音声対話型 ChatBotを作りました。

今回はこれについて書いていこうかなと思います。なお、ソースや詳しい使い方はGithubに公開していますので、詳細はそれを参照願います。

インストール

環境

仮想オーディオインターフェースをインストール

VB Cableなどを用いるとVRChat上にマイクを接続する行為を簡単にすることができます。
https://vb-audio.com/Cable/

コマンド

依存関係をインストールします。

pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu117

pip install git+https://github.com/openai/whisper.git@main

このリポジトリをクローンし、プロジェクトのルートフォルダで次のコマンドを実行してください。

pip install .

使い方

OpenAIのAPI KEY 取得

OpenAIのAPIKEYをここから取得してください
取得したAPI KEYは data/API_KEY.txt を作成しその中に書き込んでください。

オーディオデバイスの確認

次のコマンドを実行して、利用するスピーカとマイクを探します。

python -m vrchatbot audio-devices
  • output
--- Microphones ---
Index: 0, Name: CABLE Output (VB-Audio Virtual Cable)
Index: 1, Name: ヘッドホン (Oculus Virtual Audio Device)

--- Speakers ---
Index: 0, Name: Name: CABLE Input (VB-Audio Virtual Cable)
Index: 1, Name: ヘッドホン (Oculus Virtual Audio Device)

使用するマイクとスピーカの名前をbotconfig.tomlの中の mic_index_or_nameおよびspeaker_index_or_nameにしてしてください。Indexによる指定も可能ですが、よくその値は変更されるため名前による指定が望ましいです。

VRChatに実装する場合は、 マイクにループバックとしてスピーカーの名前を指定し、スピーカーにCABLE Input (VB-Audio Virtual Cable)といった仮想オーディオインターフェースを指定すると良いでしょう。そしてVRChat上のマイクにCABLE Output (VB-Audio Virtual Cable)などを指定することによって他のプレイヤーと対話できるようになります。

実行

それでは実行してみましょう!

python -m vrchatbot run
  • output
Setting up...
Ready.
Recongnized: <話した声>

Responce: <AIのレスポンス>

...

テキストチャットのみのモード

音声認識を使用せずに、テキストチャットのみも使用できます。

python -m vrchatbot chat
  • output
Setting up...
Ready.
人間: こんばんわ
人工知能:   「こんばんわにゃあ」
人間: <入力待ち>  
...

文字起こしのみのモード

言語処理を行わず、音声認識モデルのみを使用することもできます。

python -m vrchatbot recognize 
  • output
Setting up...
Ready.
ja: 文字認識は始まっています。
ja: このようにして文字を認識できます。
...

仕組み

みなさん一番最初に気になるのが仕組みでしょう。一番シンプルなシーケンシャルな対話アルゴリズムを採用しました。

この方式なので、Botが喋り終わってから話す必要があったり、録音タイミングが絶妙にわかりにくかったりしますが、そこはご愛嬌ということで今回は済ませました。

main関数にはこのように定義されています。詳細はGithubリポジトリ内のvrchatbot/__main__.pyを参照ください。 

def main(args, config: dict) -> None:
    print("Setting up...")
    recorder = Recorder(**config["Recorder"])
    speech_recognizer = SpeechRecongition(
        options=DecodingOptions(**config["DecodingOption"]), **config["SpeechRecognition"]
    )
    chatbot = ChatBot(**config["ChatBot"])
    speaker = TextSpeaker(**config["Speaker"])
    print("Ready.")

    log_file_name = datetime.now().strftime("%Y-%m-%d %H-%M-%S.log")

    with open(os.path.join(args.log_dir, log_file_name), "a", encoding="utf-8") as logf:
        while True:
            wave = recorder.record_audio_until_silence(5)
            if wave is None:
                continue
            _, text = speech_recognizer.recongnize(wave)
            if text == "":
                continue

            rec_txt = f"Recongnized: {text}\n"
            logf.write(rec_txt)
            print(rec_txt)
            responce = chatbot.responce(text)
            rsp_txt = f"Responce: {responce}\n"
            logf.write(rsp_txt)
            print(rsp_txt)

            speaker.speak_text(responce)  

材料

今回は録音アルゴリズムのみ自作で、あとは外部のツールやAPIを用いました。

  • 自作録音アルゴリズム
  • OpenAI Whisper (文字起こし)
  • OpenAI Text Davinci 003 (言語処理)
  • OpenJTalk (音声合成)

録音アルゴリズム

波形を録音し、音量が一定以上に鳴ったら録音を開始し、一定時間無音が続いたら録音を終了するというとてもシンプルなアルゴリズムです。無音の判別には波形のルート自乗平均を用いました。実際のソースでは波形のチェックチャンクサイズとストライドが存在し、 細かく無音判別をできるようなアルゴリズムになっています。
$$ \sqrt{\frac{1}{N} \sum_i^N{wave[i]^2}} $$

OpenAI Whisper

OpenAIが公開している非常に高品質な音声認識モデルです。このモデル単体で文字起こしだけでなくさまざまなタスクを解くことができます。

使用するに当たって、このサイトを参考にしました。
PCで再生中の音声をWhisperでリアルタイムに文字起こしする

  • Note:
    GPUを使用した処理を行わせたい場合は、事前にGPU版のPyTorchをインストールしておく必要があります。

OpenAI Text Davinci 003

これはOpenAI が公開している GPT3ベースの言語モデルのクラウドAPIです。非常に今品質なテキスト補完が可能であり、この補完機能を利用して対話を生成して行きます。

使用するに当たって、このサイトを参考にしました。
【GPT-3】PythonでGPT-3を用いてChatGPT風のコマンドラインツールを作ろう!

import openai
openai.api_key = "<API KEY>"  


resp = openai.Completion.create(
    engine="text-davinci-003",
    prompt="Your input prompt",
    max_tokens=4000,
    temperature=0.9,
    stop=[]
)

text = resp["choices"][0]["text"]

会話分を生成するには

会話を行わせたい場合は、次のようなプロンプトを送信する必要があります。これは会話という行為をテキスト補完タスクとして扱うためによく使われる手段です。

次の会話は人工知能と人間の会話です。人工知能はとても知的で、創造的で、気さくで、日本語を話します。
また人工知能の語尾は「にゃあ」です。話題をよく変えます。

人間: 君は僕と話すために生まれた人工知能だ。
人工知能: よろしくにゃあ
人間: 君の自己紹介をしてくれないか?  
人工知能: 

この方法から、一貫した会話を生成するには、常に会話の履歴を全て入力プロンプトとして送信しなければならないことがわかります。VRChat Botの ChatBotクラスはそういった履歴の処理も内部で行うように作られています。

参考: https://beta.openai.com/docs/guides/completion/conversation
注意: 出力停止ワードをstop=["人工知能:", "人間:" ]といった形で書き込む必要があります。これにより、人間側まで文章を生成してしまうことを防ぐことができます。

OpenJTalk

名古屋工業大学が開発した日本語の音声合成システムです。Pythonで扱うため pyopenjtalkを用います。
インストール時にビルドが走るので、以下の項目がインストールされている必要があります。

  • C/C++ compilers (to build C/C++ extentions)
  • cmake
  • cython

使い方は非常に簡単です。

import pyopenjtalk
from scipy.io import wavfile

x, sr = pyopenjtalk.tts("おめでとうございます")
wavfile.write("test.wav", sr, x.astype(np.int16))

余談

今回Chat Botを作ってみて思ったことは、真の対話とは 何か?です。

私たちは普段から人と流暢に言語を使ってコミュケーションをとることができます。しかし、対話そのものは言語のみのコミュニケーションで説明できるものではありません。ジェスチャーといった非言語コミュニケーションが存在し、もっとさまざまな要因が有機的に絡み合っていることが想像されます。
もはや、世界の状態遷移・観測の遷移そのものを近似せざるを得ないのではとさえ思わされます。

今回作成した言語のみでのBotシステムは、実装が比較的容易で、何かアシスタントAIとして動くには十分かもしれません。人間とさして変わらない知能を実現する上で非常に重要なマイルストーンではありますが、何か決定的に欠けているものがあり、これからも研究しがいのある領域だと深く感じる結末でした。

参考資料

33
13
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?