ChatGPT APIを用いたLINE botに音声認識機能を付けてみました。
この機能を搭載する事で、LINE botはテキストだけでなく、音声を送っても返答してくれるようになります。
使用しているAWSのインスタンスのインスタンスイメージはubuntuです。
音声認識には、Openai APIのWisperを使用しています。
手順は、ChatGPT APIを用いたLINE botに音声認識機能を付けるだけです。
簡単に、音声認識機能を搭載したChatGPT APIを用いたLINE botのコード解説も付けます。
⒈ChatGPT APIを用いたLINE botに音声認識機能を付ける
まず、インスタンスにSSH接続します。
インスタンスのコンソールが開いたら以下をインストールします。
aptのアップデート
sudo apt update
pipのインストール
sudo apt install python3-pip
LINEのインストール
sudo pip install line-bot-sdk
ngrokのインストール
sudo pip install pyngrok
flaskのインストール
sudo pip install flask
openaiのインストール
sudo pip install openai
pydubのインストール
sudo pip install pydub
次にpythonのファイルを保存するディレクトリを作成します。
mkdir ディレクトリ名
作成したディレクトリに移動します。
cd ディレクトリ名
作成したディレクトリでファイルを作成します。
nano ファイル名
作成したファイルの中に下記のbotのコードを入れて、ctrl oでファイルを保存して、ctrl xでファイルを閉じます。
※LINE、ngrok、openaiのキーやトークンをコードに入れてください。これらの取得については、こちらを参考にしてください。
# LINEのチャネルシークレット
LINE_CHANNEL_SECRET = ''
# LINEのチャネルアクセストークン
LINE_ACCESS_TOKEN = ''
# ngrokのAuthtoken
NGROK_AUTHTOKEN = ''
# openaiのキー
OPENAI_API_KEY = ""
import os
import requests
from pyngrok import ngrok
from pyngrok.conf import PyngrokConfig
from flask import Flask, request, abort
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, AudioMessage, TextSendMessage, TextMessage, ImageSendMessage
from pydub import AudioSegment
import openai
# URLの生成
ngrok.set_auth_token(NGROK_AUTHTOKEN)
os.system('kill -9 $(pgrep ngrok)')
https_tunnel = ngrok.connect(addr='127.0.0.1:5000',bind_tls=True)
print(https_tunnel)
app = Flask(__name__)
openai.api_key = OPENAI_API_KEY
line_bot_api = LineBotApi(LINE_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)
@app.route("/test")
def test():
return "TEST OK"
@app.route("/", methods=['POST'])
def callback():
# get X-Line-Signature header value
signature = request.headers['X-Line-Signature']
# get request body as text
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
# handle webhook body
try:
handler.handle(body, signature)
except InvalidSignatureError:
print("Invalid signature. Please check your channel access token/channel secret.")
abort(400)
return 'OK'
assist1 = "" # 初期化
# テキストメッセージを処理
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
global assist1 # assist1をグローバル変数にする
text = event.message.text
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "任意の設定"},
{"role": "assistant", "content": assist1},
{"role": "user", "content": text},
]
)
assist1 = response["choices"][0]["message"]["content"] # assist1を更新
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=response["choices"][0]["message"]["content"]),
)
# 音声メッセージを処理
def transcribe_audio(file_path):
with open(file_path, "rb") as audio_file:
response = openai.Audio.transcribe("whisper-1", audio_file)
return response.text
# LINEの音声認識
@handler.add(MessageEvent, message=AudioMessage)
def handle_audio_message(event):
message_content = line_bot_api.get_message_content(event.message.id)
audio_data = b''
for chunk in message_content.iter_content():
audio_data += chunk
audio_format = "m4a"
audio_filename = f"audio_{event.message.id}.{audio_format}"
with open(audio_filename, "wb") as f:
f.write(audio_data)
transcript = transcribe_audio(audio_filename)
# 音声ファイルを削除する
os.remove(audio_filename)
global assist1 # assist1をグローバル変数にする
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "任意の設定"},
{"role": "assistant", "content": assist1},
{"role": "user", "content": transcript},
]
)
assist1 = response["choices"][0]["message"]["content"] # assist1を更新
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=response["choices"][0]["message"]["content"]),
)
if __name__ == "__main__":
app.run(port=int(os.getenv("PORT", 5000)))
一度、上手くファイルが作成されているか下記のコマンドで確認します。
find ~
上手くファイルが作成されていたら、screenを作成します。
screen -S スクリーン名
ルート権限で、screen内でpythonで作成したファイルを実行します。
sudo python3 ファイル名.py
実行したら、生成されたURLを取得して、LINE Developers のダッシュボードにwebhook URLを設定します。(詳しくは、こちらを参考にしてください。)
※稀にエラーが発生します。エラーが発生した場合、エラー処理して頂くか、インスタンスを再起動してください。
webhook URLを設定後、LINE Developersで検証を押します。
成功と表示されたら、上手く接続出来ています。(インスタンス側では、上手くいっている場合は200と返されます。500の場合、プログラムに問題ありなどなので、普通のエラーと同じです。)
ここまで出来たら、LINE botを友達登録してテキストと音声で、話しかけてみてください。(音声入力については、LINEのテキスト入力の右横のボタンを押すと音声入力のボタンが現れます。)
それぞれで、botから返答があれば、成功です!
⒉音声認識機能を搭載したChatGPT APIを用いたLINE botのコード解説
簡単に音声認識機能を搭載したChatGPT APIを用いたLINE botのコード解説をします。
トークンやキーの入力
LINEとngrok、openaiに必要な情報を入力します。
# LINEのチャネルシークレット
LINE_CHANNEL_SECRET = ''
# LINEのチャネルアクセストークン
LINE_ACCESS_TOKEN = ''
# ngrokのAuthtoken
NGROK_AUTHTOKEN = ''
# openaiのキー
OPENAI_API_KEY = ""
インポート
ngrokとLINEに必要なインポートを行なっています。
import os
import requests
from pyngrok import ngrok
from pyngrok.conf import PyngrokConfig
from flask import Flask, request, abort
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, AudioMessage, TextSendMessage, TextMessage, ImageSendMessage
from pydub import AudioSegment
import openai
webhook URLの生成
webhook用にngrokをインストールして、URLを作成しています。
この処理の為に管理者権限で実行する必要があります。
# URLの生成
ngrok.set_auth_token(NGROK_AUTHTOKEN)
os.system('kill -9 $(pgrep ngrok)')
https_tunnel = ngrok.connect(addr='127.0.0.1:5000',bind_tls=True)
print(https_tunnel)
LINE botを実行するにあたり必要な処理
LINE botに必要な基本的な機能等を記載します。
app = Flask(__name__)
openai.api_key = OPENAI_API_KEY
line_bot_api = LineBotApi(LINE_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)
@app.route("/test")
def test():
return "TEST OK"
@app.route("/", methods=['POST'])
def callback():
# get X-Line-Signature header value
signature = request.headers['X-Line-Signature']
# get request body as text
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
# handle webhook body
try:
handler.handle(body, signature)
except InvalidSignatureError:
print("Invalid signature. Please check your channel access token/channel secret.")
abort(400)
return 'OK'
テキストメッセージを処理する
普通のChatGPTを搭載したLINE botと同じコードです。
assist1 = "" # 初期化
# テキストメッセージを処理
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
global assist1 # assist1をグローバル変数にする
text = event.message.text
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "任意の設定"},
{"role": "assistant", "content": assist1},
{"role": "user", "content": text},
]
)
assist1 = response["choices"][0]["message"]["content"] # assist1を更新
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=response["choices"][0]["message"]["content"]),
)
音声メッセージを処理する関数
LINE botが受け取ってファイルにした音声メッセージをwisperで処理してテキストにする関数です。
# 音声メッセージを処理
def transcribe_audio(file_path):
with open(file_path, "rb") as audio_file:
response = openai.Audio.transcribe("whisper-1", audio_file)
return response.text
音声メッセージを処理
LINEが音声メッセージを受信したら、音声ファイルにして、先程の関数で音声ファイルをテキストにします。
音声をテキストにしたら、音声ファイルは削除して、テキストをChatGPTに渡して返答メッセージを作成します。
その後、作成したメッセージをLINEに返します。
# LINEの音声認識
@handler.add(MessageEvent, message=AudioMessage)
def handle_audio_message(event):
message_content = line_bot_api.get_message_content(event.message.id)
audio_data = b''
for chunk in message_content.iter_content():
audio_data += chunk
audio_format = "m4a"
audio_filename = f"audio_{event.message.id}.{audio_format}"
with open(audio_filename, "wb") as f:
f.write(audio_data)
transcript = transcribe_audio(audio_filename)
# 音声ファイルを削除する
os.remove(audio_filename)
global assist1 # assist1をグローバル変数にする
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "任意の設定"},
{"role": "assistant", "content": assist1},
{"role": "user", "content": transcript},
]
)
assist1 = response["choices"][0]["message"]["content"] # assist1を更新
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=response["choices"][0]["message"]["content"]),
)
LINE botを実行中にする
LINE botを実行中にします。
if __name__ == "__main__":
app.run(port=int(os.getenv("PORT", 5000)))
最後に
LINE botと話せると感動する方が多いですね。
openai APIが優秀なだけですが。
また何か作ってみます。