#初めに
この記事はDialogflowでチャットボットを作成する練習としてELIZAもどきが作れないか試してみた記録です。
チャットボットが好きなだけの非プログラマがいい加減な知識で書いていることを予めご了承ください。
#ELIZAとは
ELIZA(イライザ)は人口無能の起源と言われるチャットボットプログラムです。
中でもセラピストとしてのキャラクター付けをされたDOCTORスクリプトが有名です。
単純なパターンマッチ技法(特定のキーワードが入力文にあればそれに対応した応答文を返す)で作られてはいますが、相手の使った言葉を応答文に取り入れたり、話が途切れないよう質問を返すような応答をしたり、ELIZA自体への質問は躱すような反応をするなどの会話らしい会話を続けるための工夫が凝らされており、当時はプログラムではなく人間が応答していると信じた人も多かったそうです。
#ELIZAの仕組み
ELIZAの応答を作る中核的な仕組みは次の三つで出来ています。
- key キー。マッチするキーワードと優先度(ランク)を設定
- decomp 分解。入力文中のキーワード前後の要素を抜き出す。
- reasmb 再構成。キーに対応する応答文に、必要に応じて抜き出した要素をはめ込み応答文を完成させる。
他にも、応答文をストックしておいて会話が続かないときに思い出したようにその話をするという素晴らしい仕組みもあるのですが(reasm_for_memory)、ノーコードでは厳しそうだったので割愛。
#Dialogflowについて
DialogflowはGoogleが提供している、チャットボットやAIアシスタントを作るためのサービスです。面倒な言語処理部分を良い感じにやってくれます。
"Dialogflow ES"というスタンダード版なら基本無料で利用できます。
Dialogflowの始め方~使い方の説明はこちらの記事がわかりやすいかと思います。
[『Googleの無料サービス「Dialogflow」を使ってノーコードでチャットボットを作ってみた』]
(https://ledge.ai/dialogflow-try/ "Googleの無料サービス「Dialogflow」を使ってノーコードでチャットボットを作ってみた")
一つ注意点を書いておきますと、左上のロゴの横の地域選択をTokyo,JapanではなくUSにしておかないと、LINEや他サービスに接続するためのメニュー"Integrations"が表示されなくて困ることになります。というか私はなりました。
#Dialogflowの基本
Dialogflowでは基本的に
- Intents(インテント・意図)
- Entities(エンティティ・実体)
- Contexts(コンテキスト・文脈)
の三つを使って会話を作っていきます。
ELIZAにはコンテキストに類する機能は無いので、前二つの機能である程度再現できそうです。
##インテント
こう話しかけられたらこう返事をする、という会話の根幹部分を設定する部分です。
初期状態では
- Default Fallback Intent(デフォルトフォールバックインテント)
- Default Welcome Intent(デフォルトウェルカムインテント)
の二つのインテントが存在します。
「デフォルトフォールバックインテント」は他に該当するインテントが無かった時に呼び出されるインテントなので、無いとまずいです。
「デフォルトウェルカムインテント」は音声アシスタントなどで使う時に初めに呼び出されるインテントらしいので、今回のようなチャットボットの場合は無くても多分大丈夫。
ですがせっかくあるので「こんにちは」等会話の初めになりそうな挨拶が入力された時用のインテントとして使っていこうと思います。
"Training phrases"に入力例を設定し、"Responses"に応答文を設定します。
例えば"Training phrases"に
「こんにちは」「こんにちわ」「今日は」「やあ!」「ごきげんよう」
など、想定される入力例を複数設定することで、言い回しの違いや表記ゆれにも対応できます。
応答文はShift+Enterキーで改行できます。
"Responses"は"Text Responses"というグループに各30個まで応答文を登録でき、その中からランダムで選んで応答します。
"Text Responses"グループ自体を複数作ることが出来ますが、応答フレーズが30個以上になるわけではなく、各グループから一つずつランダムで応答文を選んで、その全てを一度の応答文として出力します。
##エンティティ
反応したい語句や取得したい語句を登録する部分です。
本来、予約や購入といったシーンで予約日時や商品名などの必要な情報を入力文から取得するといった用途が想定されている機能のようですが、言葉の揺らぎを吸収したり、入力語句を言い換えるのにも使えます。
先ほどのインテントでの例のように、各インテントのトレーニングフレーズでマッチさせたい語句を登録しても良いのですが、エンティティで設定したほうが認識されやすくなりますし、複数のインテントから使いまわせて便利です。
何より、エンティティに設定した語句が入力文中にあった場合、それを取得して応答文の中で使うことが出来るので、ELIZA風チャットボットを作るには重要な機能です。
##コンテキスト
インテント同士の前後関係を設定する機能です。会話のルート・フラグ管理。
アウトプットコンテキストで「これ以降この話題に入る」(最大5ターン ・インテント毎に更新可能)というのをフラグ立てし、インプットコンテキストで「このインテントはどのフラグを受け継いでいるか」を設定します。
インテントに排他的な親子関係(一本道ルート)を設定するフォローアップインテントという機能もあります。
今回は使わないのでこれ以上の説明は割愛。
#インテントとエンティティを使ってELIZAっぽい応答を作ってみる
ELIZAの応答の一例として、入力文中に「母・父・娘・息子」等の家族を表す単語があった場合、
- 「あなたのご家族についてもう少しお聞かせください」
- 「あなたの(取得した入力語句)について考えるとき、他に何が思い浮かびますか?」
と返すものがあります。
これをDialogflowで再現していきます。
##エンティティで設定した語句をインテントのキーワードマッチに使う
まず、エンティティーでマッチさせたい語句を登録します。
次に、家族についての会話をするインテントを作成します。
画像のようにトレーニングフレーズを入力していくと、語句が自動でハイライトされる場合があります。
既存のエンティティとして認識されたということです。
画像の例の場合、「父・母」は先ほど設定した"familymember"として認識されているので問題ありませんが、特に認識して欲しいわけではない「仲」も登録した覚えのないエンティテイとして認識されています。
これはDialogflowが初めから持っているシステム・エンティティで、日時・場所・数字などのエンティティがあります。
今回はそこは特に認識して欲しくないので、ハイライト部分をドラッグしたり、認識エンティティ一覧の右端のバツ印をクリックすることで、ハイライトを消去します。
ハイライトしてほしい範囲がずれている場合も同様にドラッグで範囲を変更できます。
ハイライト範囲は問題ないけれどエンティティが意図したものでない場合は、ハイライト上をクリックし、別のエンティティに変更することが出来ます。
トレーニングフレーズ中にエンティティ名を入れたい場合は「@エンティティ名(例の場合"@familymember")」と書きます。
これで、入力文中に家族を表す語句があった場合このインテントが呼び出されるようになりました。
あとはレスポンス欄に
「あなたのご家族について、もう少し聞かせてください。」
「ご家族の中で他には誰がそういったことを?」
といった応答文を書いて、インテント名右横のセーブボタンでセーブしたら完了です。
(応答文はオリジナルのELIZAのものを私が意訳したものなので、ELIZAの応答と完全に同じというわけではないことをご了承ください)
ELIZAでは複数ある応答文をランダムで選ぶのではなく、上から順番に使っていくのですが、Dialogflowではノーコードでは無理そうだったのでランダムで妥協しました。
##さらに応答文にエンティティーで取得した語句をはめ込んで使う
先ほどの応答文でも十分会話っぽくはなっていますが、さらに相手の使った単語を応答文に取り入れることで、より相手の話を聞いている感を演出できます。ELIZAの得意技です。
応答文に
あなたの**$familymember**が?
と、「$エンティティ名」をはめ込むだけで、入力文から取得された語句を使用できます。
この時、エンティティを作るときに見出しに設定した語句が使われるので、
ユーザー「親父が頑固で話を聞かないんだ」
ボット「あなたの親父が?」
といった微妙に失礼な感じにはならずに、
ボット「あなたのお父さんが?」
と言い換えてくれます。
逆に、入力された語句をそのまま使いたいときは「$エンティティ名.original」(例の場合は$familymember.original)で使用できます。
Responsの上にあるAction and parametersのVALUE欄で、デフォルトでどちらを使うかを設定することもできます。
余談ですが、Action and parametersのREQUIREDにチェックを入れると、その要素が全て埋まるまで質問を返してくれるインテントが作れます。(リストの右に質問する文章を登録する欄が表示される)
グーグルホームさんとかにカレンダーへの予定の登録を頼むと「何日に登録しますか」とか必要事項を追加質問してくれる感じのやつです。
##エンティティに登録してない語句も取得してみる
ユーザー「よく怖い夢を見るんです」
bot「怖い夢ですか?」
という会話ができるようにしたいと思います。
「怖い」の部分が「面白い」でも「水の」でもなんでも取得できることを目指します。
「夢を見た」や「夢見た」といった共通する部分はエンティティに登録しておきます。
トレーニングフレーズを色んなパターンで登録し、取得したい夢の内容部分をドラッグでハイライトし、クリックしてシステムエンティティの一つである**@sys.any**を選択しておきます。
これで、応答文に
$any夢ですか?
と書くことで
怖い夢ですか?
と話せるようになりました。運が良ければ。
トレーニングフレーズに無い未知の入力文からDialogflowさんがどこを@sys.anyとして切り出してくるかは謎なので、「よく怖い夢ですか?」「こないだ悲しい夢ですか?」など不自然な感じになることも多いです。
ひたすら地道に後述のトレーニングで調整します。
構文解析APIなどを使えばもっと正確に切り出せるのかもしれませんが、面倒なので今回はこれで良しとします。
#トレーニングで調整
こうしてエンティティとインテントをどんどん作っていけばチャットボットはできるのですが、テスト(コンソール画面右上の**"Try it now"からテスト**できます)してみると、登録した語句を入力しているのに該当無しの時用のフォールバックインテントに飛ばされたり、意図したのとは全然違うインテントが呼び出されることが多々あります。
DialogflowさんはAIでいい感じに学習して柔軟にやってくれるので、気を利かせてか勝手に違うことをやってくれるっぽいのです。
なので、こまめに"Training"メニューから「この場合はこっちのインテントやで」「このエンティティは使わんでええで」と教えてあげなくてはいけません。
「がんばれ森川君2号」でpitの教育をする感じです。伝わらない例えですみません。
Trainingの他にHistoryというメニューもあり、実際の会話履歴を確認することもできます。
そちらでは使われたインテントへのリンクもあるのでインテントを確認したいときにも便利です。
#優先度設定
インテント編集画面でインテント名左横の色付きドットをクリックすることで、そのインテントの呼び出し優先度を変更できます。
オリジナルELIZAさんは「コンピューター」とか「プログラム」とか「ボット」と言われた場合最優先で反応するように設定されていたので、このELIZAもどきボットでもそうしてみました。
#ELIZAもどきのサンプルボットELIZAA
こうしてできたボットがこちらです。
日本語の性質上本家ELIZAさんのように自然に語句が切り出せなかったり、あちこち妥協した部分があったりで、出来の良いチャットボットになったとは言い難いですが、Dialogflowの使い方に慣れるという目的は果たせたので良しとします。
#作ったボットをLINEボットにする
本題でないため書くのが後回しになりましたが、この工程はボットが完成してからじゃなくても良いというか、むしろ始めのほうにやったほうがLINE上での挙動も随時確認出来て良い気がします。
大まかな手順としては、
- 「LINE for Business」のアカウントを作る
- ボット用のLINE公式アカウントを作成
- DialogflowのIntegrationsメニューからLINEと連携する
といった感じです。
LINE以外にもツイッターやSlackなど色んなサービスと連携できます。
細かい手順はこちらの記事が詳しいです。
Googleの無料サービス「Dialogflow」ノーコードでLINEチャットボットを作ってみた
#最後に
今回のELIZAもどきはLINEボットにしていないのですが、「WANDERLUST」という別のLINEボットもDialogflowで作っているので良かったら遊んでみてください。
会話とルーン占いができます。
(ELIZAもどきより会話部分を頑張って作り込んでます!)
Dialogflowを使っていませんが、占いと挨拶機能だけのツイッターボット版もあります。
https://twitter.com/WLbot
最後までお読みいただきありがとうございました。