Edited at

MS BotFramework(Azure Bot Service) for Node.js で使えるTips

More than 1 year has passed since last update.


はじめに



  • MS BotFrameworkはMicrosoftが提供する多チャネル対応のChatBot開発Frameworkです。

  • Node.js / C# に対応しています。

  • ユーザーの状態、セッション管理やデータ管理(永続化)などが簡単に行なえます。

  • 同MicrosoftのLUISと連携させたりすれば、イケてるChatBotが作れる気がします。

  • サーバーは自前で用意する必要があります。


BotFramework for Node.jsの基本


  • npm packageのBotBuilderによって実装されている。

  • 基本はwaterflowモデルにて実行される。


waterflowモデル


  • 基本的に上のfunctionから実行されていく


  • next(result) メソッドを呼び出すと、強制的に次のfunctionへ制御が移行する。
    resultはoptionalで指定すれば次のfunctionのargsで取得可能
    nextを使用する際はfunction自体の引数にnextを含める必要がある。(2つめのfunction)

function(session, args, next) {

session.send('次のfunctionに遷移します');
next({'status': 'ok'});
},
function(session, result) {
session.send('遷移しました');
session.send('引数は' + result.status + 'です。');
}


Prompt


  • ユーザーからの入力値(選択肢)を取得するメソッド

  • promptを出すと、BOTの制御は一旦そこで止まる

  • ユーザーが何らかのアクション(文字入力、選択肢を選ぶなど)をすると、自動的に次Functionが開始する

  • ユーザーの入力値は次functionの引数に設定されている


  • テキスト入力を受け付けるには



    • builder.Prompts.text(session, messageObject) について


      • ユーザーの自由入力を待つ

      • 次functionの引数の['response']のキーに値が格納される

      • messageObjectにattachment等を設定するとリッチなUI選択肢が表示可能






  • 選択肢を提示してユーザーの選択を受け付けるには



    • builder.Prompts.choice(session, text, 'choice1|choice2|choice3', {retryPrompt: '正しい選択肢を選んで下さい'})


      • choiceはユーザーに選択肢を与える

      • 次functionの引数の['response']['entity']に選択した値が格納される

      • 選択肢はArrayも設定可能

      • retryPromptを設定すると、ユーザーが選択肢を選ばなかった場合(直接文字入力など)に表示する文言を設定可能






session


  • session内にユーザー固有の情報や、BOTの接続チャネル、今までのメッセージ履歴など多くの情報を保持している

  • 頻繁に使用するものは以下



    • session.endConversation()


      • 会話を明示的に終了する。




    • session.dialogData


      • そのDialog(後述)内でのみ有効な一時的なデータ保存領域。

      • functionを跨いでデータを保持したい場合などに使用する。




    • session.conversationData


      • その会話内で有効なデータ領域(?)


      • session.endConversation() を呼ぶとクリアされる




    • session.userData


      • ユーザー毎にデータを永続化できる保存領域。

      • どのようにしてユーザーを特定しているかは分からないが、各ユーザー毎にデータを保存しておける。


      • session.userData.hogehoge = 'hogehoge' のようにして値を格納する。


      • delete session.userData.hogehoge 削除できる。




    • session.send(message)


      • Botにmessageを発言させる。




    • session.sendTyping()


      • Botにタイピングインジケータを表示させる

      • Botが次のアクションをしたタイミングで消える

      • プラットフォームに依る(と思う)が、一定時間経過でも自動的に消える




    • session.message.address


      • このaddressをbotの発言時に付加すると、確実に対象の相手へsendできる

      • 例えば遅延処理などで自動でreplyする際などはaddress指定しないと別のユーザーと混線する






Facebook Messenger連携


  • Facebook Messenger上で表現できるUI(jsonで記述)は以下のようにして実装可能

// FacebookAPIのQuickReplyボタン(画像カスタム)を表示

var reply = new builder.Message(session).text('カスタムボタンを出します。');

reply.sourceEvent({
facebook: {
quick_replies: [
{
content_type:"text",
title:"はい",
payload:"ANY STRINGS",
image_url:"https://hogehoge.com/images/yes.png"
},
{
content_type:"text",
title:"いいえ",
payload:"ANY_STRINGS",
image_url:"https://hogehoge.com/images/no.png"
}
]
}
});

session.send(reply);

// FacebookAPIのSendLocationボタンを表示

var reply = new builder.Message(session).text('現在地を送信するボタンを出します。');

reply.sourceEvent({
facebook: {
quick_replies: [{
content_type:"location"
}]
}
});

session.send(reply);


dialog


  • Botの今処理している場所(状態)をdialogという表現で管理する

  • 別のDialogを開始する



    • session.beginDialog('hogehoge/dialog_name', args)


      • hogehoge/dialog_nameのdialogを開始する

      • argsは任意だが、指定すれば次dialogへ値を渡すことができる

      • dialogを開始しても後続のコードは実行されるので、以下のようなコードは注意





function(session, args) {

session.send('次のDialogに遷移します');
session.beginDialog('/next/start', {'status': 'ok'});

// beginDialogの後にreturnしていないので、
// '/next/start'のDialogが開始するのとほぼ同時に以下のコードも実行される
session.send('次のDialogが終わりました。');
}



  • 別のDialogに置きかえる



    • session.replaceDialog('hogehoge/dialog_name', args)


      • hogehoge/dialog_nameのdialogを開始する

      • beginDialogとは違い、replaceDialogは今までのdialogStackがすべて消える

      • つまり、hogehoge/dialog_nameが終了しても元のdialogへは戻らない






  • Dialogを終了する



    • session.endDialog()


      • 今現在のdialogを終了する

      • 引数は渡せない

      • endDialogにより、一つ前のdialogの次functionから始まる






  • Dialogを終了し、戻り先に引数を渡す



    • session.endDialogWithResult(args)


      • endDialogの引数あり版

      • 一つ前のdialogの次functionから始まり、そのfunctionの引数としてargsが渡される






終わりに