🤖

ChatGPT APIとVOICEVOX、LangChainを使ってAITuberを作ってみた

2023/08/17に公開

こんにちは!
今回は、OpenAIのChatGPT API、VOICEVOX、そしてLangChainを使って、独自のAITuberを作成する方法を紹介します。この記事を読むことで、AI技術を活用して、リアルタイムの会話を音声出力する仮想キャラクターを作成する方法を学べます。

必要なツールとライブラリ

まず、以下のツールとライブラリが必要です:

  • OpenAIのChatGPT API
  • VOICEVOX
  • Pythonの仮想環境(venv)
  • LangChain(なくてもOK)

仮想環境のセットアップ

Pythonの仮想環境を使用して、必要なライブラリをインストールします。これにより、プロジェクトの依存関係が他のプロジェクトやシステム全体と干渉することなく、独立して管理できます。

python -m venv voicevox_env
voicevox_env\Scripts\activate

ChatGPT APIのセットアップ

OpenAIのAPIキーを取得し、.envファイルに保存します。
これにより、APIキーを安全に管理できます。

https://platform.openai.com/overview

パッケージのインストール

pip install openai requests

VOICEVOXのセットアップ

VOICEVOXを使用して、テキストを音声に変換します。さらに、音声ファイルを再生するための関数も実装します。

以下からVOICEVOXをダウンロードし、インストールします。

https://voicevox.hiroshiba.jp/

パッケージのインストール

pip install pyaudio SpeechRecognition

LangChainのセットアップ

LangChainは、ChatGPT APIの会話の履歴を保存するためのツールです。
LangChainのPostgresChatMessageHistoryを使用して、会話の履歴をPostgreSQLデータベースに保存します。

必須ではありませんが、これにより、ChatGPT APIの記憶を保持することができます。

PostgreSQLのインストール

以下のサイトからPostgreSQLをダウンロードし、対応するOSのファイルをインストールします。

https://www.postgresql.org/download/

インストール手順は以下のサイトが参考になります。

https://python-work.com/install-postgresql/

インストール中に、postgresユーザーのパスワードを設定するプロンプトが表示されます。このパスワードは後でデータベースにアクセスする際に必要となるので、忘れないようにしてください。

また、ポート番号(デフォルトは5432)やロケールなどの設定も求められます。デフォルトの設定で問題ない場合は、そのまま進めてください。

インストールが完了すると、pgAdminというPostgreSQLの管理ツールもインストールされます。
pgAdminを起動して、左側のツリービューで「Servers」を展開し、PostgreSQLサーバーに接続します。

pgAdmin内で、PostgreSQLサーバーを右クリックし、「Create」>「Database...」を選択します。
新しいデータベースの名前を入力し、OKをクリックしてデータベースを作成します。

パッケージのインストール

pip install langchain[llms] psycopg psycopg-binary

コードの実装

自ボイスからテキストに変換

def voice_to_text():
    r = sr.Recognizer()
    with sr.Microphone(sample_rate=16000) as source:
        print("なにか話してください")
        audio = r.listen(source)
        audio_data = BytesIO(audio.get_wav_data())
        audio_data.name = 'from_mic.wav'
        transcript = openai.Audio.transcribe('whisper-1', audio_data)
        return transcript['text']

ChatGPT APIを使用して返答を取得

def chat(messages: list) -> str:
    result = openai.ChatCompletion.create(
        model='gpt-3.5-turbo',
        messages=messages
    )
    response_text = result['choices'][0]['message']['content']
    return response_text

VOICEVOXを使用してテキストを音声に変換

def post_audio_query(text: str) -> dict:
    params = {'text': text, 'speaker': 1}
    res = requests.post('http://localhost:50021/audio_query', params=params)
    return res.json()

def post_synthesis(audio_query_response: dict) -> bytes:
    params = {'speaker': 1}
    headers = {'content-type': 'application/json'}
    audio_query_response_json = json.dumps(audio_query_response)
    res = requests.post(
        'http://localhost:50021/synthesis',
        data=audio_query_response_json,
        params=params,
        headers=headers
    )
    return res.content
    
def text_to_voice(text: str):
    audio_query_response = post_audio_query(text)
    audio_data = post_synthesis(audio_query_response)
    play_wavfile(audio_data)

音声ファイルの再生

def play_wavfile(wav_file: bytes):
    wr: wave.Wave_read = wave.open(io.BytesIO(wav_file))
    p = pyaudio.PyAudio()
    stream = p.open(
        format=p.get_format_from_width(wr.getsampwidth()),
        channels=wr.getnchannels(),
        rate=wr.getframerate(),
        output=True
    )
    chunk = 1024
    data = wr.readframes(chunk)
    while data:
        stream.write(data)
        data = wr.readframes(chunk)
    sleep(0.5)
    stream.close()
    p.terminate()

メイン関数

def main():
    EXIT_PHRASE = 'exit'
    messages = [
        {'role': 'system', 'content': 'You are a helpful assistant.'},
        {'role': 'user', 'content': f'終了やストップなどの会話を終了する内容で話しかけられた場合は{EXIT_PHRASE}のみを返答してください。'}
    ]
    exit_flag = False
    while not exit_flag:
        text = voice_to_text()
        messages.append({'role': 'user', 'content': text})
        response = chat(messages)
        if response == EXIT_PHRASE:
            exit_flag = True
            response = 'またね!'
        messages.append({'role': 'assistant', 'content': response})
        print(f'User : {text}')
        print(f'ChatGPT: {response}')
        audio_data = post_synthesis(post_audio_query(response))
        play_wavfile(audio_data)

if __name__ == '__main__':
    main()

(LangChain)Postgresを使用してチャットメッセージの履歴を保存

PostgresChatMessageHistoryクラスを使用して、Postgresデータベースに接続し、メッセージを追加および取得をします。

connection_stringには、Postgresデータベースへの接続情報を指定します。
こちらのコードでは、ユーザー名postgres、パスワードmypassword、ホストlocalhost、データベース名chat_historyを使用していますが、実際の環境に合わせて変更する必要があります。

https://python.langchain.com/docs/integrations/memory/postgres_chat_message_history

class ChatHistory:
    def __init__(self):
        self.history = PostgresChatMessageHistory(
            connection_string = DB_CONNECTION_STRING,
            session_id="foo",
        )

    def add_user_message(self, message):
        self.history.add_user_message(message)

    def add_ai_message(self, message):
        self.history.add_ai_message(message)

    def get_messages(self):
        return self.history.messages

実装とトラブルシューティング

実際のコードの実装中には、さまざまな問題やエラーが発生することがあります。

psycopgではなく、psycopg2をインストールするとエラーになる。
ModuleNotFoundError: No module named 'psycopg'

https://github.com/langchain-ai/langchain/issues/3290

まとめ

ChatGPT API、VOICEVOX、そしてLangChainを使用して、独自のAITuberを作成する方法を紹介しました。不明なところはChatGPTに聞けばある程度、解決できます。この記事を参考にして、自分のAITuberを作成してみてください!

参考記事

https://zenn.dev/umyomyomyon/articles/5f07abe67a289b
https://github.com/VOICEVOX/voicevox_core
https://laboratory.kazuuu.net/install-psycopg3-the-latest-implementation-of-the-postgresql-adapter-for-python/

Discussion