IBM Watson Conversationサービスの初心者向け講座 (3) Dialog におけるcontextの扱い

[IBM Watson Conversation](https://www.ibm.com/watson/jp-ja/developercloud/conversation.html)はチャットボットのようなUIサービスを簡単に作成できるサービスです。

サービス内容も興味深いのですが、実は、プログラミング環境としても面白いものです。また変更がすぐにチャットに反映されわかりやすいので、実はプログラミング初心者にも良い入門教材かもしれません。

##今回の内容は

前回の [講座 (2) Dialog ノードのresponseの実行条件](https://qiita.com/yamachan360/items/1f9680aa8b4680b8a691) では最初の挨拶を時間によって変える、という地味なところを説明してみました。

Intents や Entities は華麗にスルー、Dialog もいまだに2つのノードのまま、という地味な講座ですが、今回も地味にcontext(文脈)について説明していきます。

## Contextとは何か

会話においてContext(文脈)は大切です。

例えば買い物の話をしている時に「高い」と言われれば、それは「値段が高い」の略で、価格のことを言っているとわかります。もし登山の話をしているのであれば、「高い」は「山の標高が高い」の略で、長さ(距離)のことを言っているのがわかります。

その判断の基準は、いま何の話をしているか？という会話の流れに対する理解であり、それがContext(文脈)です。

このContext(文脈)がしっかりしていないと、いきなり関係のない返答をするなど会話が成り立ちません。それは単に1問1答の単純な受け答えができるだけの応答システムであり、会話システムではないでしょう。

Watson Conversationは context という内部情報をもち、このContext(文脈)に関する情報を取り扱うことができます。実際に格納される情報は Context variables と呼ばれるもので、これに関して次のセクションで見ていきます。

## Context変数とは何か

Context変数(variables) に関しては [Building a dialog](https://console.bluemix.net/docs/services/conversation/dialog-build.html#dialog-build) の [Context variables](https://console.bluemix.net/docs/services/conversation/dialog-build.html#context) というセクションに情報があります。

英語なので最初の部分を簡単に訳してみます。

>Dialogはステートレスで、これはユーザーとのやり取りに関する情報を次回に引き継げないことを意味します。必要な情報を管理し維持する責任は、(Dialogを利用する)あなたのアプリケーションにあります。しかし、アプリケーションがDialogに情報を渡し、そしてDialogはその情報を更新しアプリケーションに返すことは可能です。そのためにcontext変数があります。
>
context変数は、あなたがノードのなかで定義し、そして必要であれば初期値を指定できる変数です。それ以降、他のノードやアプリケーションロジックはcontext変数のその値をセットしたり変更したりできます。
>
あなたはcontext変数の値によって条件付けができます。例えばDialogノードのconditionでcontext変数を参照することで、そのノードを実行するかどうかを決定することができます。そしてユーザーの入力や外部サービスへのアクセスで得られた情報により、Dialogノードでの応答を変化させることもできます。

うん、だいたいの意味はわかりました。それでは、実際にはどう実装されているか、実際に試しながら見ていきましょう。

## 何もしない第3のノードを追加

また今度も「ようこそ」ノードを改造しようと思ったのですが、さすがにそろそろ怒られそうです… ちゃんと専用のノードを追加してみましょうか。

まずは準備として、何もしないノードを作成してみます。「ようこそ」ノードの右にあるメニューから「Add note below」をクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/11cbe77d-fa85-c086-266d-726d98627007.png)

「ようこそ」ノードの下に新しいノードが追加されますので、上の赤枠の部分に "デバッグ" という名称を、下の赤枠には "true" という必ず成立する条件を指定します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/c686cb70-d1ea-5def-a3e7-2a81e70747d1.png)

そして respond のセクションは空のままにしておき、finally セクションで "Jump to..." をクリックし、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/595e21ee-c5b9-365b-6f0c-7d9523cd1407.png)

Jump 先の選択になるので、「その他」ノードをクリックして選択、更にひらいたメニューから condition をクリックして選択します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/129cdfb5-9f79-cb11-2aab-22d818276191.png)

最終的に、この何もしない「デバッグ」ノードは以下のようになりました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/7e0c8033-7cd9-4c30-fdc3-16a7fd40011c.png)

さて！チャット用の領域(Try it out)を表示してみましょう。今回のノード追加が何の影響も与えていないことが確認できます。

今の「デバッグ」ノードは、condition が true のため、毎回、実行条件が成立しています。でも respond に何も指定していませんから、何もしません。そして入力動作もせず、次の「その他」ノードに処理を渡して(Jumpして)います。

このセクションでは、本当に何もしない、役立たずなノードを追加しました。

## コンテキスト情報の表示

さて、このまま何もしないノードの定義だけで終わってしまうと、さすがに怒られそうです。今回は文脈(context)が主題ですから、この「デバッグ」ノードでその情報を表示させてみましょう。

さきほど空のままスキップした「デバッグ」ノードの respond のセクションに以下のテキストを設定します。

```
コンテキスト情報 <? context ?>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/b78ce297-6b82-2a26-8718-0513871053f9.png)

[前回の講座](https://qiita.com/yamachan360/items/1f9680aa8b4680b8a691) で、&lt;? XXX ?&gt; 表記が出てきましたね。あのときの計算式などのかわりに、context という内部の情報を表示させています。

さあ、チャット用の領域(Try it out)を表示してみましょう。結果は見たほうがはやいでしょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/f69497a6-fa17-8b50-e784-cb207f953241.png)

内部の文脈(context)情報が表示されるようになりました。「デバッグ」ノードという名称にふさわしい動作になりましたね。

## Context変数を追加してみる

文脈(context)にはContext変数が格納されている、のですよね。では私たちも新しく追加してみましょう。

「ようこそ」ノードの最初の respond を開き、右側のオプションから「Open JSON editor」をクリックすると

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/0df189cf-854e-f665-0e3f-b95cd4aca961.png)

respond の入力が単なる1行のテキストから、以下のようなJSONエディタに変わります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/916721de-524f-962c-8b11-c5eb5a6b8e81.png)

このエディタで、optput の前に以下の定義を追加します。

```json
  "context": {
    "test_int": 0
  },
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/4ebca768-cff9-d9a8-da6c-88c8bc04de24.png)

そうそう、「ようこそ」には時間にあわせて2つの respond が定義されていますね。下にあるもう一方にも同様の定義、ただし初期値を 10 にして追加します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/208e9e91-047b-9e36-6ecb-da994dc9dc51.png)

さあ、チャット用の領域(Try it out)を表示してみましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/dcace56a-0691-6c1f-5097-ebc490a14d00.png)

test_int というContext変数が定義されているのがわかります。実行したのが朝でしたので、初期値は 0です。

## Context変数を変更してみる

さて、今度はContext変数の値を変更してみましょう。「デバッグ」ノードを開き、さきほどと同様に respond を JSON モードに変更します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/947a36eb-bbef-dfa8-edf7-2cfae2a93da1.png)

こちらにも以下のような context の定義を追加しましょう。

```json
  "context": {
    "test_int": "<? $test_int + 1 ?>"
  },
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/f60d7069-8306-7dde-e7da-3219c0947d66.png)

数値の計算なのに "" で囲み、更に見慣れた &lt;? XXX ?&gt; 表記を使用するなど、なかなか癖の強い記述になっています。

これはもう JSON における "&lt;? XXX ?&gt;" 表記として慣れるしかないかもしれませんね…

まあとにかく、チャット用の領域(Try it out)で実行してみましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/80d0f8cc-bfcd-a606-4e13-4c9c4650a2e0.png)

処理がループして「デバッグ」ノードを通るたび、Context変数の test_int の値が増えていくのが確認できます。

## ちょっとした注意点

今回の「デバッグ」ノードでは、Context変数 test_int の値の変更と、それを含んだ context 自体の表示、どちらも実行していました。

最初に表示された test_int の値は(朝の場合は) 1 でした。これは表示よりも、値の変更が先に実行されたことを示しています。

ノードにおいては

1. context の評価
2. output の表示

という順番で実行される、ことは覚えておくべきでしょう。

## まとめ

さて今回、はじめてノードを追加し、またContext変数を扱ってみましたが、如何でしょうか？

ノードは3つに増えましたが、処理は上から下に流れるだけ、あまり Dialog っぽくない雰囲気が続いています。そろそろ処理の分岐を試してみるべきですかね？

さて、次回もDialogの設定を試していきましょう！

## ライセンス

今回の講座シリーズに含まれる私の作成したコード・画像・文章などは全て [Creative Commons Zero](https://creativecommons.org/publicdomain/zero/1.0/deed.ja) ライセンスとします。自由にお使いください。