Dialogflow - Pepperで喋らせてみる

Dialogflow（旧：api.ai）のチャットをPepperで喋らせてみます
Pepperアプリの作成にはChoregrapheというツールを使います
ChoregrapheのPythonブロックでPython(2.7)が書けるので、そこからなんでもAPI呼び出しできる（Dialogflowもそれ以外も）ということになります

Dialogflowの使い方については、
- [Dialogflow/api.aiでチャットボットをつくってみる](https://qiita.com/ume1126/private/5955a0680c430a1cf25f) (ume1126さんの投稿）
- [Dialogflow/api.aiで天気情報を呼び出す](https://qiita.com/ume1126/private/f60335179b1cee25fa2f) (ume1126さんの投稿）
- [Dialogflow/api.aiをSlackに連携させる](https://qiita.com/ume1126/private/1fa38c430fc0e6248be8) (ume1126さんの投稿）
などをご参照ください

# DialogflowのAPIキーを入手しておく
- 後述のPepperアプリから呼び出すため、DialogflowのClient API キーを入手しておきます
- Dialogflowのコンソールを開き、画面左上の使用しているAgentを選択し、Agentの右側にある「設定」（歯車のアイコン）をクリックします

<img width="381" alt="スクリーンショット 2017-12-28 16.01.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/72938530-8f51-390d-3a25-defb58828cf5.png">

- Agentコンソールの画面下部の「Client access token」の32桁(32文字）の文字列をコピーしておきます（Developer access tokenのほうではないので注意します）

<img width="598" alt="スクリーンショット 2017-12-28 15.59.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/e9bc8066-a41b-2542-93ba-459f2dc491f6.png">


# Choregrapheをインストールする
- Pepperのアプリを作るためにChoregrapheをインストールします。
- [Choregrapheのダウンロードサイト](https://developer.softbankrobotics.com/jp-ja/downloads/pepper)からダウンロードしてインストールします

<img width="1680" alt="スクリーンショット 2017-12-28 15.36.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/0fba41d6-5442-5887-7ea2-f28542320d20.png">

- [robot library](https://pepper.robo-lib.com/projects/user/bird_tomita)などを参考に、Pepper胸部タブレットからの入力を可能にするボックスを入手します
- その他さまざまなPepperの動作は[Pepper Atelier](http://pepper-atelier-akihabara.jp/archives/259)などから入手可能です

# アプリを作ります
- 「Set Language」「Say」「Table Input」「Speech Reco.」「Pythonブロック」「Say Text」の各ボックスを下記のように配置します

<img width="976" alt="スクリーンショット 2018-01-09 17.22.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/a141510d-87ed-53d2-8c51-06777f58b2f3.png">

- １つめの「Set Language」ボックスで日本語を設定します。

<img width="308" alt="スクリーンショット 2017-12-28 15.41.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/d4d5b635-825c-4a93-8d53-b54350c42d2d.png">

- またこのアプリで日本語を使用可能にするため、画面左上の「プロパティ」を開いて日本語も使えるように追加します（このとき、英語を削除してしまうとエラーになるようなので、日本語は英語へ追加するかたちで登録すると良いようです）

<img width="889" alt="スクリーンショット 2017-12-28 15.41.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/b7f52d61-a9b9-fc8c-375d-eeec7bc9f48f.png">

- 「Set Language」ボックスの「onReady」出力端子から、次の「Say」ボックスの「onStart」入力端子へ接続します

<img width="186" alt="スクリーンショット 2017-12-28 15.44.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/dfcddd14-d284-564e-4c7f-030a29d148a3.png">


- 次の「Say」ボックスでは、「こんにちは、ご質問をどうぞ」など最初の挨拶を話すようにします

<img width="358" alt="スクリーンショット 2017-12-28 15.42.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/0b87f476-3473-e9b1-dc32-ff980872e635.png">

- 「Table Input」ボックスでは、「Say」ボックスから及び「Say Text」ボックスからの線を「Table Input」ボックスの「onStart」入力端子に接続し、「onInputed」出力端子からの出力を後段のPythonブロックの「Input」入力端子へ接続します。また、入力がループに陥るのを避けるため、「onInputed」出力端子から「onStop」入力端子へ接続しておきます

<img width="194" alt="スクリーンショット 2018-01-09 17.30.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/de917ee1-673b-a7cb-ad2c-3932881db010.png">

- 同様に「Speech Reco.」ボックスも接続します。ここでは（主にPepperが耳が遠いため）このSpeech Reco.ボックスは使用していませんが、必要に応じ使用可能です
- 前項と同様に「Say」「Say Text」ボックスからおよびPythonボックスへ接続し、また入力がループに陥るのを避けるため、「onInputed」出力端子から「onStop」入力端子へ接続しておきます
- 「Speech Reco.」ボックスの「wordRecognized」出力端子から、次のPythonブロック("test"）の「input」入力端子へ接続します

<img width="408" alt="スクリーンショット 2017-12-28 16.08.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/3d466ce4-8389-dc68-2c43-f39d37a88207.png">

- 画面のなにもないところで二本指でタップ（もしくは[Cntl]を押しながらクリック）して、「ボックスの新規作成」⇢「Python」を選択してPython用のボックスを作成します

<img width="405" alt="スクリーンショット 2017-12-28 15.46.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/d27830b5-c5fd-c982-7f81-3c82cb8d6b33.png">

- 新規作成されたPythonボックスを二本指でタップ（もしくは[Cntl]を押しながらクリック）して、「ボックスの編集」を選択します

<img width="324" alt="スクリーンショット 2017-12-28 15.48.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/a71c9f0f-b500-dfcb-4582-429e6b8edaed.png">

- Pythonボックスに適当な名称（ここでは"to_dialogflow")を指定し、「インプット／アウトプット／パラメータ」欄の「入力」の右側の「＋」を押して新しい入力を追加します

<img width="422" alt="スクリーンショット 2017-12-28 15.49.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/a6e0fb86-cfed-26ce-89f9-222c5c9f2d85.png">

- 新しい入力に適当な名称（ここでは"input”）を指定し、「タイプ」を「文字列」を選択して「OK」を押して作成します

<img width="474" alt="スクリーンショット 2017-12-28 15.49.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/734e00b2-2739-6917-2afd-1508b1b80228.png">

- 同様に、新しい出力を作成（ここでは"output"）し、「タイプ」を「文字列」を選択して「OK」を押して作成します

<img width="476" alt="スクリーンショット 2017-12-28 15.53.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/dda58ebc-416e-8eb4-2242-3d282e7c62a9.png">

- 「OK」を押すとPythonブロックに新しい入力（”input”）と出力（”output"）が追加されているのが確認できます
 
- Pythonブロックをダブルクリックしてスクリプトエディタを開きます
- デフォルトで記入されている内容を下記で上書きします。下記のうち、CLIENT_ACCESS_TOKENを前節で入手した自分のDialogflowのAPIトークンで置き換えます

```py:pepper.py
class MyClass(GeneratedClass):
    def __init__(self):
        GeneratedClass.__init__(self)

    def onLoad(self):
        self.framemanager = ALProxy("ALFrameManager")
        self.folderName = None

    def onUnload(self):
        #put clean-up code here
        pass

    def onInput_input(self, p):
        self.log(p)
        #self.onStopped() #activate the output of the box
        import os.path
        import sys
        import json
        self.folderName = os.path.join(self.framemanager.getBehaviorPath(self.behaviorId), "../lib")
        if self.folderName not in sys.path:
            sys.path.append(self.folderName)
        import apiai
        CLIENT_ACCESS_TOKEN = '0123456789abcdef0123456789abcdef'
        ai = apiai.ApiAI(CLIENT_ACCESS_TOKEN)
        request = ai.text_request()
        request.lang = 'ja'  # optional, default value equal 'en'
        request.session_id = "1"
        request.query = p
        response = request.getresponse()
        r = response.read()     #can be obtained only once
        json_dict = json.loads(r)
        r2 = format(json_dict['result']['fulfillment']['speech'])
        r3 = r2.encode('utf-8')
        self.log(r3)
        self.output(r3)

    def onInput_onStop(self):
        self.onUnload() #it is recommended to reuse the clean-up as the box is stopped
        self.onStopped() #activate the output of the box
```
<img width="972" alt="スクリーンショット 2017-12-28 16.07.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/282e037c-ecbe-bb08-36b4-056c3a621ca2.png">


- Pythonブロックの「output」出力端子から、最後の「Say Text」ボックスの「onStart」入力端子へ接続します

<img width="342" alt="スクリーンショット 2017-12-28 16.09.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/8d58a4e5-592a-1358-14cc-c0bfa7cf863d.png">

# Pepperで稼働させて確認します
- Pepperを接続し、上記アプリケーションの稼働を確認します
- Pepperを接続するには同一ネットワーク（同一Wifi）内に接続されていることが必要になります
- 必要に応じてMotion（動き）などを追加します。PepperのMotionについては[pepper Atelier - モーション作成を効率化するボックスライブラリを公開](http://pepper-atelier-akihabara.jp/archives/259)などが便利です
- Pepperあんまり安定してないですね。。
- Good luck :-)