1. はじめに
OpenAIのWhisperを使った音声入力のチャットポッドを、Googleコラボ上でGradioを使って簡単に作ってみましょう。OpenAIは、2024年1月23日現在で最新の1.8.0を使います。
この実装を応用することで生成AIを使った英会話や料理レシピ検索等、自分好みのアプリが簡単に作れると思います。
@2024 NPO法人AI開発推進協会
作成するチャットポッド
画面の構成は以下の通りです。
$①チャットポッドエリア$
$②テキスト入力エリア$
$③音声入力エリア$
$④クリアボタン(履歴のクリア)$
このサンプルの特徴としては、音声でもテキストでも入力できるようにしています。
2. 動作環境
Googleコラボで動かしています。
動作検証済みのリソースは下記の通りです。
T4 GPU
、V100 GPU
、A100 GPU
3. 実装コード
では、下記の手順に従って早速作ってみましょう。
3.1 ライブラリィのインストール
!pip install openai==1.8.0 # 2024.1.22現在最新
!pip install gradio=4.15.0 # 2024.1.22現在最新
!pip install fastapi==0.103.2
3.2 OpneAIのキーを指定
自身のOpenAIのキーを指定してください(GPT4のAPIキーと同じです)。
%env OPENAI_API_KEY=XXX
3.3 メソッドの定義
- OpenAIのWhisperは0.xと1.x以降でコンポーネントのインターフェースが変わっているものもあるので注意してください(今回は最新の1.8.0で実装)。
- このサンプルでは、生成AIの応答部分はダミー化しています(固定で「レスポンス」と表示)。実際に生成AI(GPT4)を使って応答をさせる場合、
response = str(query_engine.query(query))
の部分を実装してください。
GPT4 APIの使い方に不慣れな方は筆者の下記の記事を参考に実装してみてください。
import gradio as gr
import os
import openai
# 会話履歴の保存
def add_text(history, text):
history = history + [(text, None)]
return history, gr.Textbox(value="", interactive=False)
# chatbot処理
def bot(history):
query = history[-1][0]
response = "レスポンス" # 実際はGPT APIで問い合わせましょう response = str(query_engine.query(query))
history[-1][1] = ""
for character in response:
history[-1][1] += character
yield history
# 音声変換
def speech_to_text(input_audio):
audio_file = open(input_audio, "rb")
# OpenAPI 1.x以上でのAPIを使用
response = openai.audio.transcriptions.create(model="whisper-1", file=audio_file)
return response.text
# Audio領域の初期化
def reset_audio(_):
return None
3.4 画面の定義(レイアウト&イベント)
- 音声でもテキストでも自由に入力ができ、チャットポッドエリアに応答とともに(履歴)表示されます。テキストエリアでの入力時はリターンキーを押すことでチャットポッド処理が開始します(
txt.submit()
)。 - 音声入力時は終了ボタンを押したタイミング(
stop_recording()
)でチャットボット処理を開始します。Whisperを使って文字起こししたテキストを一旦テキストエリアに入力させ、テキストエリアのデータをチャットボット処理に渡すようにしています。 - チャットボット実行(データを表示)後に、入力エリアを初期化しています。
-
Clear
ボタンを押すことで履歴をクリアします。
# 画面レイアウト、イベント定義
with gr.Blocks() as demo:
gr.Label("サンプル画面にようこそ")
with gr.Row():
chatbot = gr.Chatbot([], bubble_full_width=False,
# チャットボットに表示させるアバター画像を指定
avatar_images=("dog.gif", "cat.jpeg")
)
# テキストボックス
txt = gr.Textbox(scale=4, placeholder="問い合わせを入れてください", container = False)
# 音声入力エリア
audio_data = gr.components.Audio(sources=["microphone"], type="filepath")
# Clearボタン
clear = gr.Button("Clear")
# テキストエリアの処理
txt_msg = txt.submit(add_text, [chatbot, txt], [chatbot, txt], queue = False).then(bot, chatbot, chatbot)
txt_msg.then(lambda: gr.Textbox(interactive = True), None, [txt], queue = False)
# 音声入力エリアの処理
audio_msg = audio_data.stop_recording(speech_to_text, inputs=audio_data, outputs=txt).then(add_text, [chatbot, txt], [chatbot, txt], queue = False).then(bot, chatbot, chatbot)
audio_msg2= audio_msg.then(lambda: gr.Textbox(interactive = True), None, [txt], queue = False)
audio_msg2.then(reset_audio, inputs=[], outputs=[audio_data])
# クリアボタン処理
clear.click(lambda: None, None, chatbot, queue=False)
demo.queue()
# 画面の起動、デバックをオン&エラー発生時の画面表示をオン、不要の場合は`demo.launch()`
demo.launch(debug=True, show_error=True)
その他、Gradioでのチャットポッド開発時のポイントは下記の通りです。
エラー発生時に画面にポップアップでエラー通知するには、launch(show_error=True)
とします。
Gradioコードのデバックを行うには、print()文を入れるのが便利です。ただし、デフォルトではprint()はどこにも表示されません。 launch(debug=True)
を入れることでGoogleコラボのセル出力エリアに表示させることができます。
詳細はGradioのマニュアルを参照してください。
4. 終わりに
Gradioを使うことで、比較的簡単に音声入力のチャットボット処理が作れることがわかると思います。また、Whisperの日本語テキスト変換能力の高さも実感できると思います(著者も想定以上でした)。
今回は入力のみを音声にしていますが、出力も音声化することも簡単にできます。
今後、Whisperのような精度が良い日本語の文字起こしを使い、生成AIやプロンプトエンジニアリング(RAG等)を活用し様々なオリジナルアプリを作っていけたらと思います。
[補足]
今回掲載しましたサンプルコードについて更に良いコードがあればご教授いただければと思います(思考錯誤しながらGradioの制約の中で実装したため)。継続してブラッシュアップしていきます。