Bluemix
Watson
node-red
linebot

Watson ConversationでLINEのチャットボットを作ってみる(後編)

More than 1 year has passed since last update.

はじめに

さて、Watson ConversationでLINEのチャットボットを作ってみる(前編)で、LINE@によるチャットボットのフレームができました。今回は中身となるロジックに、WatsonのConversationを仕込んでみようと思います。

参考

Conversationについてはたくさんの記事が見つかりますし、IBM公式のテンプレートもちゃんとしているので、中の説明はそちらに譲ろうと思います。見た目や機能が変わりすぎるので記事にするのが辛いという側面もあります。下記以外にも素晴らしい記事がたくさんあるので検索してみてください。ただし古い記事は見た目や名称が違うことがあり、読み替えが必要です。

IBM Watson Conversationサービスの初心者向け講座 (1) 環境設定とDialogの基本
IBM公式ドキュメント

Node-REDとConversationとの接続(バインド)

Bluemixを利用する利点の一つに、この『バインド』という概念があります。今回のようにWatsonなどのAPIを呼び出す場合に、本来は前編でLINEで接続したときのような、複雑な認証情報を入力したり、管理する必要があるのですが、バインドを使うことで非常に簡単な管理になります。まずはBluemix Consoleにログインして、ダッシュボードから前編で用意したNode-REDの、接続を開きます。
IMG_0250.PNG

色々試しているので汚いですが気にしないでください。通常はCloudantのみが接続されているはずです。ここで『新規』をクリックするとBluemixカタログが表示されます。左のメニューからWatsonを選択すると絞り込まれますので、Conversationを選択します。
IMG_0251.PNG

ライトプランを選択して、『作成』をクリックすると、Conversationのインスタンスが作成され、同時にNode-REDにバインドされた状態になります。なおバインドには再ステージが必要になりますので、起動までしばらく待ちます。
IMG_0252.PNG

接続済一覧にConversationが表示されていることを確認して、Conversationをクリックします。

Conversationの開発

Conversationを開くと下記の画面になりますので、『Launch tool』をクリック、Conversationのツールに移動します。
IMG_0253.PNG

Createから新規作成していくのですが、説明端折ります。
IMG_0254.PNG

Intentsにはこんな感じ
IMG_0248.PNG

Dialogにはこんな感じです。
IMG_0247.PNG

Watsonがもう少し汲み取ってくれると思いIntentsでの登録にしたのですが、ほぼキーワード一致条件になって残念です。入力が短文すぎる挨拶という、テーマが悪かったですね。
IMG_0249.PNG

作成が終わったら、左のメニュー最下部にある窓のようなアイコンを押すと、Workspace一覧に戻るので、・・・からView detailsを選択し、Workspace IDをコピーしてください。
IMG_0255.PNG

なんとなく挨拶ボットができたということで、次に移ります。

Node-REDでの接続

ようやく本番ですね。ConversationをNode-REDで接続してみます。フローエディタのパレットでWatsonと検索するとConversationが出てきます。
IMG_0256.PNG

これを適当に、ドンと配置してみます。
IMG_0258.PNG

そして開いてみると先ほどコピーしたWorkspace IDを入れる欄がありますので、貼り付けます。
IMG_0257.PNG

このまま繋いで動くといいのですが、ちょっと加工する必要があります。前編で調べたように、LINE@からの入力は"msg.payload.events[0].message.text"に格納されていました。これに対しWatson Conversationへの入力は曾祖父である"msg.payload"に直接格納してやる必要があります。複数のやり方がありますが、今回はChangeノードを使って実装してみます。
IMG_0259.PNG

開いて、下記のとおり書きます。
IMG_0260.PNG

そしてまた乱暴に、これらを接続してしまいます。最後、終端にDebugノードを配置しています。
IMG_0262.PNG

デプロイし、携帯から『こんにちは』と入力してみてください。デバッグノードには下記のようにメッセージが飛び込んでくるはずです。
IMG_0261.PNG

これは、正常にConversationにメッセージが飛び、返り値として『intentは昼の挨拶』なので返答として『こんにちは。いい天気ですね。』と、それぞれ格納されている場所とともに返却されたことを示します。今回はこれをそのままLINE@に返却できればよいので、前編でfunctionノードに設定した"text"の値だけを変えてやればいいことになります。
IMG_0263.PNG

function
msg.headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer {ここにアクセストークンを貼り付け}"
};

msg.payload = {
    "replyToken": msg.replyToken,
    "messages":[
        {
            "type": "text",
            "text": msg.payload.output.text[0]
        },
    ]
};
return msg;

"msg.payload.events[0].message.text + "?""としていた箇所を、"msg.payload.output.text[0]"と書き換えてください。
IMG_0264.PNG

これで準備が整ったはずだったのですが、漏れがありました。7行目のreplyTokenが、先ほどConversationのために"msg.payload"を上書きしたので、破棄されてしまっています。破棄される前にreplyTokenを退避させる必要がありますので、再度先ほどのChangeノードを開き、以下のように設定します。
IMG_0265.PNG

ここで重要なのは、Changeノードの中での順番です。上から順に処理されますので、Payloadが上書き(破棄)されるより前に配置してやる必要があります。三本線を引っ張って、上位に配置しましょう。
IMG_0267.PNG

全て接続したら、忘れずに『デプロイ』して、テストに進みましょう。

できあがりのフロー図

IMG_0270.PNG

LINE2
[{"id":"fdeca679.e6ed08","type":"http in","z":"407ee723.987178","name":"line_hook[POST]","url":"/line_hook","method":"post","upload":false,"swaggerDoc":"","x":100,"y":40,"wires":[["45704fcf.56b148"]]},{"id":"be576634.686ad8","type":"http request","z":"407ee723.987178","name":"send_result","method":"POST","ret":"txt","url":"https://api.line.me/v2/bot/message/reply","tls":"","x":570,"y":160,"wires":[["f252fab3.cff5d8"]]},{"id":"f252fab3.cff5d8","type":"http response","z":"407ee723.987178","name":"","statusCode":"","headers":{},"x":710,"y":160,"wires":[]},{"id":"d22cd584.c0ae6","type":"function","z":"407ee723.987178","name":"Set MSG","func":"msg.headers = {\n    \"Content-Type\": \"application/json\",\n    \"Authorization\": \"Bearer {ここにアクセストークンを貼り付け}\"\n};\n\nmsg.payload = {\n    \"replyToken\": msg.replyToken,\n    \"messages\":[\n        {\n            \"type\": \"text\",\n            \"text\": msg.payload.output.text[0]\n        },\n    ]\n};\nreturn msg;","outputs":1,"noerr":0,"x":420,"y":160,"wires":[["be576634.686ad8"]]},{"id":"5b5d4899.336878","type":"watson-conversation-v1","z":"407ee723.987178","name":"","workspaceid":"287b0831-c454-46d4-9667-e0d5829b27d5","multiuser":false,"context":true,"empty-payload":false,"default-endpoint":true,"service-endpoint":"https://gateway.watsonplatform.net/conversation/api","x":350,"y":100,"wires":[["d22cd584.c0ae6"]]},{"id":"45704fcf.56b148","type":"change","z":"407ee723.987178","name":"Set MSG","rules":[{"t":"set","p":"replyToken","pt":"msg","to":"payload.events[0].replyToken","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"payload.events[0].message.text","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":200,"y":100,"wires":[["5b5d4899.336878"]]}]

テスト

これで、無事replyTokenが渡されたはずですので、携帯から飽きずに『こんにちは』と送ってみましょう。
IMG_0269.PNG

動きました!途中少しだけjavascriptが出てきますが、これもChangeノードのみで表現することは可能です。ノンプログラムでLINEチャットボットができることがわかって、スッキリしました。ただし、conversationの本流であるcontextて振り分けたり、entityを抜き出したりという使い方をするにはもう少し工夫が必要ですので、それはまた次回ということで。

おわりに

上記の宿題もありますがSlackの記事が途中なので、時間を見つけてどちらも投稿していこうと思います。