LoginSignup
72
71

More than 3 years have passed since last update.

実用レベルのLINE BOTを爆速開発する(前編)

Last updated at Posted at 2019-04-20

LINE BOT、作ってますか?おうむ返しで終わってないですか?

この記事は"おうむ返しは作ったけどその後実用的なBOTの開発運用には至っていない"という方をメインの対象に、linebot-project-templateを利用して高機能なチャットボットを爆速開発できるようになることを目指したものです。(もちろん、初心者も大丈夫な内容のはずです!)

前後編の2回に分けて、前編ではテンプレートを利用してスキルを追加するまで、後編では翻訳スキルと天気予報スキルの作り方について解説していきます。

LINEBOT Project Templateとは

本格的なLINEBOTを爆速で開発するためのプロジェクトテンプレート。コンテキスト管理やユーザー管理、自然言語解析処理、メッセージログ閲覧といった機能が最初から組み込まれているほか、LIFFやリッチメニューのサンプル、翻訳スキルと天気予報スキルのサンプルコードも同梱しています。

事前準備

本手順を実施する前に、インターネットからアクセスできる環境を準備するのと、LINE Messaging APIの利用に必要な手続きを完了する必要があります。既にLINE BOTを運用していて適当なChannel SecretChannel Access Tokenをお持ちの方は依存ライブラリのインストールのみでOKです。

PCをインターネットからアクセスできるようにする

LINEからリクエストを受信するため、ngrokを導入してPCにインターネット経由でアクセスできるようにします。Azureの仮想マシンやAWSのEC2インスタンスなど既にお持ちの場合は本手順は必須ではありませんが、お手元のPCで実機デバッグできる方が便利です。

ngrokのダウンロードページからご自身の環境に適したバイナリをダウンロードしてパスを通してください。Macの場合は以下のコマンドでもインストールできます。

$ brew install ngrok

インストールが完了したら以下のコマンドを実行して動作確認します。Ctrl+Cで終了できますが、URLが都度変わりますのでチャットボットを動作させるまで終了しないようにしてください。

$ ngrok http 21212

以下のように表示されたら起動成功です。この例では、https://9b41ad02.ngrok.ioにアクセスすると、あなたのPCのlocalhost:21212にリクエストがトンネルされることを意味しています。

ngrok by @inconshreveable                                       (Ctrl+C to quit)

Session Status                online                                            
Account                       Yuji Ueki (Plan: Pro)                             
Update                        update available (version 2.3.25, Ctrl-U to update
Version                       2.2.8                                             
Region                        United States (us)                                
Web Interface                 http://127.0.0.1:4041                             
Forwarding                    http://9b41ad02.ngrok.io -> localhost:21212       
Forwarding                    https://9b41ad02.ngrok.io -> localhost:21212      

Connections                   ttl     opn     rt1     rt5     p50     p90

LINE Messaging APIの準備

APIを利用するためのアカウントを作成し、各種設定を行います。ゴールはChannel SecretChannel Access Tokenを取得し、先ほど作成したURLをWebhookに設定することです。

依存ライブラリのインストール

PyPIからLINE公式のPythonSDKとチャットボットフレームワークのMinetteをインストールします。今回のプロジェクトテンプレートはMinette for Pythonというチャットボットフレームワークを活用するものです。
依存ライブラリはrequirements.txtに定義してありますので、以下の通り一括インストールしましょう。

pip install -r requirements.txt

プロジェクトテンプレートの入手と設定

linebot-project-templateのリポジトリをCloneするか、ZIPでダウンロードして解凍したら適当なディレクトリ(ユーザーホーム直下とか)に配置してください。配置が完了したらディレクトリ内に移動して設定ファイルminette.iniを編集します。ここにLINE Developersで取得したChannel SecretとChannel Access Tokenを設定してください。

minette.ini
[line_bot_api]
channel_secret = YOUR_CHANNEL_SECRET
channel_access_token = YOUR_CHANNEL_ACCESS_TOKEN

実行

これで準備は完了しました。チャットボットを起動してLINEアプリから話しかけてみましょう。

$ python run.py

2019-04-17 21:48:01,443 - minette.core - WARNING - Do not use MeCabService tagger for the production environment. This is for trial use only. Install MeCab and use MeCabTagger instead.
2019-04-17 21:48:01,444 - minette.core - INFO - Create 16 worker thread(s)
 * Serving Flask app "run" (lazy loading)
 * Environment: production
 * Debug mode: off
 * Running on http://0.0.0.0:21212/ (Press CTRL+C to quit)

おうむ返しに加えて、前回発話内容の表示、ユーザー名の表示、そして発話に含まれる名詞の抽出をしてくれると思います。つまり、コンテキスト情報の管理や自然言語解析処理(形態素解析)がすぐに利用できるということをお分かりいただけたかと思います。

実行結果

なおMinetteでは1つの話題ごとに1つの処理部品(クラス)を用意するような構造になっています。今回のおうむ返し+αのコードの中身は以下の通りです。

SpecialEchoDialog.py
# リクエスト情報やセッション情報を使ったおうむ返し
class SpecialEchoDialogService(DialogService):
    def compose_response(self, request, context, connection):
        # 前回の発話内容をセッションから取得
        previous_text = context.data.get("previous_text", "")

        # 今回の発話内容をセッションに格納
        context.data["previous_text"] = request.text

        # 発話内容から名詞を抽出
        noun = [w.surface for w in request.words if w.part == "名詞"]

        # この対話を継続することでセッション情報を維持
        context.topic.keep_on = True

        # 応答メッセージの組み立て
        ret = "こんにちは、{}さん。今回は'{}'って言ったね。前回は'{}'って言ってたよ".format(
            request.user.name, request.text, previous_text
        )
        ret += "\n含まれる名詞: {}".format("、".join(noun)) if noun else ""
        return ret

自分でスキルを追加する

MinetteではDialogRouterと呼ばれる部品でユーザーの意図を解釈し、コンテキストを踏まえて適切と思われる話題にリクエストを振り分けます。そして、DialogServiceと呼ばれる話題毎の処理部品でリクエストを処理し、応答メッセージをユーザーに返します。

ここでは純粋なおうむ返し対話処理部品のDialogServiceを作成し、それをDialogRouterに登録するという流れで説明していきます。

DialogServiceの作成

このテンプレートではdialogsフォルダの中に各対話処理部品をまとめていますので、ここにecho.pyを追加したら、以下の通りコードを追加してください。

echo.py
from minette import DialogService

class EchoDialogService(DialogService):
    def compose_response(self, request, context, connection):
        return "You said: {}".format(request.text)

簡単に解説すると、compose_responseメソッドは応答メッセージを組み立てる処理で、定型文にrequestオブジェクトのtextプロパティの値を埋め込んだものを戻り値としています。

DialogRouterへの登録

作成したおうむ返しスキルをどのようなときに呼び出すか、ということを設定します。プロジェクトの最上位ディレクトリに戻って、dialog_router.pyを開いて以下の通りコードを追加します。

まずは冒頭に先ほど作成したEchoDialogServiceのインポート文を追加。

dialog_router.py
from dialogs.echo import EchoDialogService      # ⭐ ️追加 1

続いて、register_intentsメソッドでインテントEchoIntentEchoDialogServiceを紐づけるように設定。

dialog_router.py
    # ルーティングテーブルの設定
    def register_intents(self):
        self.intent_resolver = {
            "TranslationIntent": TranslationDialogService,
            "WeatherIntent": WeatherDialogService,
            "EchoIntent": EchoDialogService     # ⭐ ️追加 2
        }

最後に、発話内容が「おうむ」で始まっているときにEchoIntentとして解釈するよう、extract_intentメソッドの末尾に追加。戻り値の2つ目はエンティティ、3つ目はこのインテントの処理優先度を示しています。今回はHighestを指定していますので、いかなる話題も中断されておうむ返しをしてくれるようになります。

echo.py
        # ⭐ ️以下、追加 3

        # 「おうむ」から始まるときおうむ返し
        if request.text.startswith("おうむ"):
            return "EchoIntent", {}, Priority.Highest

なおこのextract_intentメソッドからLUISなどを呼び出し、その結果をそのままリターンすることでインテリジェントチャットボットを作ることができます。個人的見解としては、ルールベースとそれら自然言語処理サービスとを組み合わせることで、シナリオ進行に制御をきかせつつ柔軟な解釈も可能にするというのがオススメです。

動作確認

これで準備は整いました。Ctrl+Cでチャットボットを停止し、run.pyを実行して再起動したらLINEアプリで会話を試してみてください。

実行結果

メッセージログの確認

品質のよいチャットボットに育て上げていくためには、ユーザーの発話に対して適切な回答を返せているか、冗長な対話シナリオになっていないかということを確認し、日々改善を行っていくことがとても重要です。

そういった取り組みを支援するため、このテンプレートでは対話のログをブラウザベースでいつでもどこでも確認できるような仕組みを提供しています。チャットボットが起動した状態で、今回の例だと https://9b41ad02.ngrok.io/messagelog?key=password にアクセスすることで閲覧できます。アクセスキーのパラメータkeyminette.iniで変更することができますので、必ず変更しましょう。

メッセージログ

ユーザーとチャットボットそれぞれの発話内容に加えて、インテント、話題とそのステータス、処理時間などが表示されます。エンティティが抽出された場合はその内容も記録されるため、発話内容をどのように解釈し、どのような処理を行ったかがわかるようになっています。

タスクスケジューラーの利用

チャットボットのリソースを活用しつつ定期的にタスクを実行するための機能があります。サンプルでは同梱のscheduler.pyを実行すると5秒毎にメッセージが表示されます。タスクの実装はtasksパッケージ内のSecondsTaskです。

さいごに

作例として、翻訳スキルと天気予報スキルの対話処理部品のサンプル実装を同梱しますので参考にしてみてください。後編ではこれらの中身について解説していきます。

またデータベースはデフォルトでSQLiteになっていますが、SQL DatabaseとMySQLにも対応していますので処理負荷などを考慮してそれらのデータベースを利用することをお勧めします。利用方法はMinetteのexamplesの設定ファイルを参照してください。

その他解説はしょりすぎな部分が多々あるかと思いますので、不明点がありましたらIssueに投げていただくかTwitter: @uezochanまでお気軽にお問い合わせください。

なおMinetteを使って以下のチャットボットを開発しました。よかったらお友だちになってください!あにBOTはこのテンプレートで実質2〜3日くらいで作ったものです。荒削りなのでこれから育てます。

それでは、Enjoy creating awesome LINEBOT!

参考: Minetteの主な特長

このプロジェクトテンプレートのベースとなるフレームワークMinette for Pythonの主な特長は以下の通りです。

  • コンテキスト管理 発話をまたいで情報を引き継ぐ機能。インタラクティブな対話を可能にします
  • ユーザー管理 LINEのユーザーIDをキーに自動的にユーザー情報を保存し、スキル内で利用することができます
  • 形態素解析 発話内容は自動的にMeCabによる形態素解析が行われ、スキルの中で利用することができます
  • メッセージログ ユーザーとBOTの話した内容やその際のトピック、コンテキスト情報、エンティティなどが記録されます
  • スケジューラ 定期的なタスクを実行する機能。Cron等を利用することなくすべてチャットボットのリソースで完結します。
  • 並列処理 長時間かかる処理を行っていても他のユーザーのリクエストに応答することができます(LINE等。メッセージングサービスの仕様とWebサーバ等の仕様にもよる)
  • 統一的なアーキテクチャ LINEもClovaも同じアーキテクチャで開発することができます
72
71
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
72
71