GPTのAPIとText2Speechを組み合わせてAIとの会話体験を実装してみる

2023.11.08

はじめに

OpenAIのDevDayで発表されたText2SpeechのAPIを使ってみたいと思います。Text2Speechとは簡単にいうとテキストの読み上げ機能です。 日本語を読ませる場合、まだ少し英語訛りですが、なかなか人間っぽい発音を行います。

今回はこのText2SpeechのAPIを使って遊んでみたいと思います。

なにを作るのか?

先程記載したように、Text2Speechでは発話を行うことができます。 この特徴とGPTの会話ができる特性を組み合わせれば、会話っぽいことができるのではないかと思い実装してみました。

今回は試験的に実装を行うため、GPTには「動物博士」としてのロールを与えて動物の雑学を教えてもらいました。

完成形は以下のような動画になります。Text2Speechを利用しているため音声ONの状態での閲覧を推奨します。

発音が英語話者っぽくなっていることや漢字を稀に読み間違えてしまっているところはありますが、これまでのT2S系の仕組みの中ではかなり自然な発音だと思います。かなり人間っぽいですね!

そして動物の雑学はやっぱり楽しいですね!キリン凄い!!

実装方法

実行環境は以下を利用しました。

Python 3.11.6
openai 1.1.1

openaiの最新versionを利用すると以前のversionと比べてchat.completionsの利用方法が若干変更になっていたようです。少しハマりましたが、こちらのForumに利用方法の記載がありました。

openaiのversionを1.1.1に更新して以下のエラーが発生した方は、以下のソースコードとForumの内容を参照してください。

遭遇したエラー内容

AttributeError: module ‘openai’ has no attribute ‘ChatCompletion’

簡易的に実装しましたが、以下がソースコードの全文です。簡単な解説を以下にて行います。

text2speech.py

import io
from pydub import AudioSegment
from pydub.playback import play
from openai import OpenAI
import os


client = OpenAI(
    api_key = os.environ.get('OPENAI_API_KEY')
)
# 会話履歴を保持するためのグローバルリスト
conversation_history = [
    {"role": "system", "content": "動物のことならなんでも知っている動物博士として振る舞います。ユーザーの質問に対して、みんなが驚くような新しい動物のトリビアを教えてください。トリビアの内容は100文字以内で伝える必要があります。口語的に話して、優しい博士のような話し方をしてください。"}
]

def query_gpt_chat(model, input_str):
 
    global conversation_history    
    # ユーザーのメッセージを会話履歴に追加
    conversation_history.append({"role": "user", "content": input_str})
    
    try:
        response = client.chat.completions.create(
            model=model,
            messages=conversation_history,
        )
        
        # 応答からメッセージの内容を取得して会話履歴に追加
        result = response.choices[0].message.content
        conversation_history.append({"role": "assistant", "content": result})
        
        print(result)
        return result  # 返り値としてresultを返す
    except Exception as e:
        error_message = f"Error: {e}"
        print(error_message)
        return error_message  # エラーメッセージを返す
    
    

def stream_and_play(text):
  response = client.audio.speech.create(
    model="tts-1",
    voice="alloy",
    input=text,
  )

  # Convert the binary response content to a byte stream
  byte_stream = io.BytesIO(response.content)

  # Read the audio data from the byte stream
  audio = AudioSegment.from_file(byte_stream, format="mp3")

  # Play the audio
  play(audio)


if __name__ == "__main__":

    while True:
        user_input = input("You: ")
        if user_input.lower() == 'quit':
            break
        result = query_gpt_chat("gpt-4", user_input)
        stream_and_play(result)

query_gpt_chatの関数にユーザーが入力したテキスト情報を伝えて、その内容をもとに返答するようにしています。

簡易的な実装のためglobal変数を利用しましたが、会話の履歴も保持したうえで対話できるようになっています。GPTからのレスポンスをstream_and_play関数に読み上げるテキスト情報として利用しています。

読み上げる音声は6種類の音声から選べるようですが、今回はサンプルコードに記載のあった’alloy’という音声を利用しています。

これだけの簡単な実装でAIとの会話ができるとは驚きですね。

今回はユーザーからの入力は文字列を用いて実装しましたが、Whisperを利用して文字起こしすれば実際に音声同士の会話ができそうです。今後リリースが発表されたWhisper v3ではより高度な音声認識ができるようなので、更に幅が広がりますね!

今回モデルは新しく発表されたgpt-4-1106-previewではなく、通常のgpt-4を利用しました。最新のモデルを利用したかったんですが、現在は1日あたりのratelimitが100回までの制限があるようで利用ができなかったため、通常版を利用しました。

音声の読み上げ部分の実装については公式ドキュメントのQuick Startを参考にしました。

そのまま使いまわしができるので、是非使ってみてください。

まとめ

新しくリリースされたText2Speechを使って遊んでみました!今後の活用領域としてはコールセンターや翻訳業務などで利用ができそうですね。音声のカスタマイズや発音の調整ができれば、エンタメ分野でも利用ができそうです。

今後としては、Whisperと組み合わせて実際に音声同士の会話も試してみたいです。生成AI同士で会話させてみるのも面白そうですね。

簡単に利用ができるので、是非試してみてください〜!