Alexaと自社サーバーの連携

最近話題のAlexaと自社サーバーを連携させてみました。
具体的には、自社の社員専用サイト(社員アンケート等が実施されてる)があるので、社員アンケートの状況などをAlexaに問い合わせると回答してくれるスキルを作成してみました。

#イメージ
![AlexaArch.jpg](https://qiita-image-store.s3.amazonaws.com/0/200860/73ff7e4e-ecf8-66f0-fc87-04a2c395fb1d.jpeg)
※吹き出しが日本語ですがAlexaは現在英語のみ対応です。

#Fire TabletでAlexaを使えるように
日本のアカウントでサインインしていると使用できないが、実はアメリカのアカウントでサインインするとAlexaの機能が使えるようになる。
詳細は[こちら](http://www.itmedia.co.jp/pcuser/articles/1707/31/news092.html)を参照して下さい。
後述のAlexaSkillの登録に使用するアカウントと同じアカウントでサインインして下さい。

#AlexaSkillの登録
[開発コンソール](https://developer.amazon.com/edw/home.html#/)にサインインして、「Alexa Skills Kit」からスキルを登録する。
[こちら](http://dev.classmethod.jp/etc/alexa-skill-with-lambda-sample/)を参考に登録していく。
↑はLambdaと連携する事が想定されているのでLambdaファンクションの作成は気にしない。
そしてEndpointを自社サーバーのPostしてほしいURLに設定しておく。

Intent SchemaとSample Utterancesの関係が最初良くわからない(私は分からなかった)と思うが、Intent Schemaが命令や意図のようなものを表し、Sample Utterancesがその命令や意図を発動させるため言葉集である。
IntentがEndpoint(この場合自社サーバーに)渡ってくる。
例えば下記のような感じ。

| Sample Utterances | Intent            |
|:------------------|:------------------|
| あなたは誰？        | WhoAreYouIntent   |
| あなたは何が出来るの？| WhoAreYouIntent  |
| 君の名は？          | WhoAreYouIntent  |
| 現在のステータスは？  | WhatsStatusIntent  |
| ステータスは？       | WhatsStatusIntent  |
| 調子はどうや？       | WhatsStatusIntent  |

上記は日本語で書いてますが、本当は英語で書きます。
Sample Utterancesは多ければ多いほど認識精度があがるとのこと。ユーザが発する言葉はSample Utterancesに設定した通りの言葉である必要はなくAIが意味を解釈してくれるので多少違う言い回しでも反応します。AIが意味を解釈する時に例が多い程制度が上がるという事だと思われる。

#サーバー側実装
Endpointとして呼ばれる側の実装。
AlexaからPostされてくる情報はログでも出せばわかると思うが一応[こちら](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/handling-requests-sent-by-alexa#intentrequest)に書いてあります。
ポイントとしては設定したIntentに応じて処理を振り分けることです。

```ruby:sample.rb
  # Alexa EndPoint.
  def alexap
    intent_type = params[:request][:type]

    if intent_type == "LaunchRequest"
      respond_alexa("Hi I am knox data portal manager. You can ask me my status.")
    elsif intent_type == "IntentRequest"
      intent_name = params[:request][:intent][:name]
      if intent_name == "WhoAreYouIntent"
        respond_alexa("Hi I am knox data portal manager. You can ask me my status.")
      elsif intent_name == "WhatsStatusIntent"
        # ★★★ステータス問い合わせIntentの場合は現状のステータスを返す★★★
        spk = get_current_status()
        respond_alexa(spk)
      else
        respond_alexa("I don't under stand what you are saying.")
      end
    else
      respond_alexa("I don't under stand what you are saying.")
    end
  end
```

振り分けた内容に応じて読み上げて欲しい文章を返します。
返すフォーマットは[こちら](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#response-format)に書いてあります。
outputSpeechがポイントですね。

```ruby:sample.rb
    def respond_alexa(speak_str)
      respond_to do |format|
        msg = {
          :version => "1.0",
          :sessionAttributes => {
          },
          :response => {
            :outputSpeech => {
              :text => speak_str,    # ★喋る内容★
              :type => "PlainText",
            }
          },
          :shouldEndSession => true
        }
        format.json  { render :json => msg }
      end
    end
```

ちなみにCard要素に情報を設定するとFireTabletの画面にメッセージを表示することも出来ます。
詳細は[こちら](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/providing-home-cards-for-the-amazon-alexa-app)

#感想
簡単なSkillの作成は１日もあれば出来てしまう。
もちろんマーケットに公開するには審査等が必要でありそれなりに時間を要すると思われる。

今回はアンケートの実施数等というあまりVUIで問い合わせるメリットの無いものだったが、例えば社内サイトに個人の予定まで入っている場合には、↓のようなユースケース等で使えるかもしれない。

1. 会社に電話がかかってくる
2. 総務が出る。社長宛だった
3. 電話を保留する
4. 総務「アレクサ。社長は今どこ？」
5. アレクサ「社長は、XXへ外出中です。戻りは17時です。」
6. 総務が電話の相手に伝える

というかむしろ電話を担当のものに転送するまで基本的に雛形対応が多いので、AIが電話番でもいいような気もする。

早く日本でAmazon Echo発売されないかな。