9
8

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.

ChatGPT APIを用いたLINE botに音声認識機能を搭載してみた。

Last updated at Posted at 2023-05-05

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から返答があれば、成功です!

音声だと以下のようになります。
IMG_8186.jpeg

⒉音声認識機能を搭載した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が優秀なだけですが。
また何か作ってみます。

9
8
0

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
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?