こんにちは、岡田です!
Bot作成に興味はあるけど、なんだか難しそう……という人のためにMicrosoft Bot Frameworkを使いつつ、手とり足とり作成方法を教えるこのシリーズ。本日は、いよいよAI搭載Botを作成します!
具体的には、LUISというサービスとMicrosoft Bot Frameworkを連携することでAI搭載Botを作っていこうと思います。LUISについては前回の記事でも紹介しているので割愛します。
詳細な作成方法に入る前に、ざっくりと自然言語を理解するときにLUIS側がどんな動きをしているのか復習も兼ねて説明します!
自然言語理解AIとプログラムをつなぐ仕組み
LUISとBotを連携させるときには、前回の記事でご紹介した「インテント(意図)」と「エンティティ(意味のある単語)」が非常に重要な役割をはたします。
インテント(Intents): その発言が、どういった意図を持っているのかをカテゴリー分けしていく概念
エンティティ(Entities): その発言のなかにある、意味のある単語をカテゴリー分けしていく概念
自然言語理解AIと連携したプログラムでは、判別した「インテント」によって、実行するアクションを分岐させます。そして、そのアクションに必要となる情報を「エンティティ」から呼び出します。
この説明だけだと、何が何やらサッパリですね…。
「Siri」「OK, Google」「Cortana」のようなアシスタントアプリを例にしてみましょう!
これらのアプリに「明日の朝7時に起こして」と話しかけたときの、アシスタントアプリのAIの中の動きを例にしてみます。

そうだ、学習データをもとに、インテントとエンティティに分解してみよう。

でも何時にアラームをセットすればいいんだ……?

よし、人間が何をしたいかわかったぞ! 「明日」の「7時」に『アラームをセットする』ように、スマホに命令をだそう!
……と、このようにAIくんは自然言語(人間がふつうに使う言葉)を、インテントとエンティティに分解することで初めてスマホにアラームをセットする事ができます。
人間には簡単な事でも、機械には難しかったんですね…。
ちなみに、このインテントとエンティティに分解していく手法は、LUISだけではなく、wit.aiやapi.aiといったAIでも基本的に同じのようです。この機会に覚えておいて損はないと思います。
Botで実際にやってみよう!
さて、さきほど紹介したAIくんの思考回路を、Microsoft Bot Frameworkでも試してみましょう。
>> Bot Builder for Node.js (Bot Framework Version 3.0)で’Hello World’ Part-1
今回つかう環境は、下記の通りです。
- Node.js
- botbuilder V3 ( Microsoft Bot Framework )
botbuilderとは、Node.jsでMicrosoft Bot Framework用のBotを作成するライブラリです。
botbuilderには、LUISと連携するためにIntentDialogという便利なものが用意されています。
今回は、LUISと連携するBotのテンプレートをご用意しました。
こちらをコピペして改造するだけで、簡単にAI搭載Botを作成できるかのではないかと思います!
少し長いですが、コードと合わせて順に解説していきますね!
Botの準備
この部分では、Botの準備をしています。
var restify = require('restify');
var builder = require('botbuilder');
//=========================================================
// ボットの準備
//=========================================================
// Restifyサーバの設定
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
console.log('%s listening to %s', server.name, server.url);
});
// ボットの接続先設定
var connector = new builder.ChatConnector({
// MicrosoftBotFramework公式サイトで取得した、IDとパスワードを入力します
appId: '******************************',
appPassword: '******************************'
});
// ボットの仕組みを提供してくれるUniversalBotオブジェクトを作成
var bot = new builder.UniversalBot(connector);
// ***/api/messagesをエンドポイントとして、ボットをサーバで提供する
server.post('/api/messages', connector.listen());
ただ、この部分は特に、理解したり覚えたりする必要はありません。
Botを作成するときには毎回絶対使う部分ですので、おまじないのような物だと思っていただいて大丈夫です!
17〜18行目には、Microsoft Bot Framework公式サイトで取得したIDとパスワードを入力しましょう。
インテントと処理を結びつける「IntentDialog」
さて、ここが重要な部分です!
IntentDialogは、LUISによって判定した「インテント」と「プログラムの処理」を結びつける役割をします。
この部分を作り込むことでSiriやCortanaのような機能が実装できちゃう、ってことですね。
では、早速ソースを見てみましょう!
//=========================================================
// IntentDialogオブジェクトの用意
//=========================================================
// 認識に指定するLUIS APIのURLを指定
var recognizer = new builder.LuisRecognizer('**********************************');
// IntentDialogオブジェクトを作成
var intents = new builder.IntentDialog({
recognizers: [recognizer]
});
//=========================================================
// 会話の処理
//=========================================================
// 初期ダイアログを、intentDialogとして使用する
bot.dialog('/', intents);
// インテントと処理の結びつけ
intents
.matches('intentA', function (session, args) {
// インテントが 'intentA' だったときの処理をここに記述します。
})
.matches('intentB', function (session, args) {
// インテントが 'intentB' だったときの処理をここに記述します。
})
34行目には、作成したLUIS APIのURLを入れましょう。
さて、実際にインテントと処理の結びつけを行っているのは 49-60行目 です。
‘intentA’にマッチしたときは、その中に処理を書いて……
‘intentB’にマッチしたときは、その中に処理を書いて……
という型に当てはめていくだけです。非常にわかりやすく、シンプルですね!
「エンティティ」を抽出しよう!
IntentDialogでインテントと処理を結びつける事ができました!
これである程度の事ができそうですが、これではまだぜんぜん高度な事はできません。実用には程遠い状態です…。
どういう事でしょうか?
ここで少し、前半のAIくんの思考回路を思い出してください。

でも何時にアラームをセットすればいいんだ……?
そう、今はまさにこの状態です……。
インテントによって「どんなアクションすればいいかはわかった」のですが、「アクションをするための具体的な情報」がわからないのです……。
AIくんはどのように、それを理解したんでしたっけ? 続きを見てみましょう!

よし、人間が何をしたいかわかったぞ! 「明日」の「7時」に『アラームをセットする』ように、スマホに命令をだそう!
そうでした! 「エンティティ(意味のある単語)」によって理解していましたね!
botbuilderにも、エンティティを抽出するEntityRecognizerというものが用意されています。サンプルコードでは、下記の部分で使われています。
.matches('intentC', function (session, args) {
// インテントが 'intentC' だったときの処理をここに記述します。
// ▼ 応用 ▼
// argsの中には、LUISの認識結果が入っています。
console.log(args);
// 例えば、天気予報Botを想定したLUISの場合 : 「明日の東京の天気は?」を解析すると..
// { score: 1,
// intent: 'AskWeather',
// intents:
// [ { intent: 'AskWeather', score: 1, actions: [Object] },
// { intent: 'None', score: 0.0144235147 } ],
// entities:
// [ { entity: '東京',
// type: '場所',
// startIndex: 3,
// endIndex: 4,
// score: 0.9854452 },
// { entity: '明日',
// type: '日にち',
// startIndex: 0,
// endIndex: 1,
// score: 0.963219762 } ] }
// 上記のような結果が得られます。
// EntityRecognizerを使うと、指定したエンティティの内容を抽出できます。
var area = builder.EntityRecognizer.findEntity(args.entities, '場所');
// 「場所」エンティティが認識できた場合の処理
if (area) {
session.send("あなたが天気を知りたい場所は、" + area + "ですね!"); // この場合、「東京」が出力されます。
}
})
こちらも、思いのほか簡単ですね!
var 変数名 = builder.EntityRecognizer.findEntity(args.entities, '抽出したいエンティティ名');
で抽出するだけです。
断片的に解説しましたが、LUIS搭載Botの基本はざっと以上になります! これだけです。
じっくりご覧になりたい方は、ぜひGitHubでご覧ください!
実践編: 天気を教えてくれるAI搭載Botの作成
さてここまで、LUIS搭載Botの作り方をご紹介しました。
ただ、テンプレートだけだとすこし具体的なイメージが湧きづらいですよね……。というわけで、今回は実際にサンプルBotも作成しました!
>> okajax’s LUIS Bot Demo
「今日の東京の天気は?」
「明日の名古屋」
「大阪は明日どう?」
など、天気を尋ねると答えてくれるBotです。
日にちは、「今日」か「明日」の範囲で答えられます。もちろんAIなので、どんどん学習していきますよ。
GitHubにソースコードもご用意していますので、興味ある方はご覧ください!
>> okajax / luis-bot-demo
お天気botの中身の解説
用意している「インテント」と「エンティティ」は、以下のようになっています。
- None
- AskWeather
- 日にち
- 場所
- 天気
天気予報の機能
今回、天気予報の機能の部分は、weather-yahoo-jpというモジュールを使用しました。
「場所」エンティティを抽出し、その情報をもとにYahoo!天気からスクレイピングしています。
Botの処理
Bot内のおおまかな処理の流れは、以下の通りです。
- AskWeatherインテントと判定されたら、予報の処理開始
- 場所エンティティがあれば、それをもとにYahoo!天気から情報をスクレイピング
- 日にちエンティティがあれば、中身が「今日」か「明日」か調べる
- 「{日にち}の{場所}の天気は、{予報の結果}です!」というテキストを発言させる
割愛している部分もありますが、上記のような形です。
全貌が気になる方は、ぜひソースコードをご覧ください!
おわりに
いかがでしたでしょうか。
Microsoft Bot Frameworkに用意されているIntentDialogとEntityRecognizerを使えば、AI搭載Botがけっこうシンプルに作れそうですね!
この記事で、AI搭載Bot作成の敷居が下がればいいなと思っています!
皆さんも面白いBotを作ったら、ぜひ教えてくださいね。
それではー!