[Alexa] Responseオブジェクトを利用した応答の作成

2017.09.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

テレビとラジオで比較できるように、Echo (Dot)のような音声のみのデバイスと、Echo Showのような、表示装置を持ったデバイスでは、やはり応答は、違ったものになるかもしれません。

また、スキルの質を高める目的で、スロットの入り具合によってユーザーへの問いかけをきめ細かく調整するような事を考え始めると、応答を構築する作業は、どんどん複雑になっていきます。

そして、このような複雑な応答に対応するためには、Responseオブジェクトの利用が有効であると、下記のブログで紹介されていました。

How to Teach Your Alexa Skill to Detect a Screen

Responseオブジェクトは、当初から、Alexa Skills Kit SDK for Node.jsに存在していましたが、簡易な応答には、そのラッパーである :tell:ask を利用し、AudioPlayerなどのようにラッパーが存在しない場合だけ利用方法が記載されていました。

しかし、最近のバージョン(v1.0.10以降)では、Responseオブジェクトの利用方法についても、詳しくREADMEに記載されるようになりました。

今回は、このRersponseオブジェクトの利用方法について整理して見ました。

2 :tell :ask の違い

まずは、簡単に、:tell:askの記述要領と、Responseオブジェクトを使用した場合との違いを比較してみます。

:tellは、ユーザーのレスポンスを待たない発話でした。

let outputSpeech = 'My favorite color is red.'; 

this.emit(':tell', outputSpeech)

そして、これをResponsオブジェクトで記述すると次のようになります。

this.response.speak(outputSpeech);
this.emit(':responseReady');

生成されるレスポンスは、どちらも全く同じで、shouldEndSessiontrueにセットされていることを確認できます。

{
  "version": "1.0",
  "response": {
    "outputSpeech": {
      "ssml": "<speak> My favorite color is red. </speak>",
      "type": "SSML"
    },
    "speechletResponse": {
      "outputSpeech": {
        "ssml": "<speak> My favorite color is red. </speak>"
      },
      "shouldEndSession": true
    }
  },
  "sessionAttributes": {}
}

:askは、ユーザーのレスポンスを待つ場合に利用されていました。 ユーザーが8秒間黙っていた場合、さらなるプロンプトを発話します。

let outputSpeech = 'My favorite color is red.'; 
let reprompt = 'for example, my favorite color is green.'

this.emit(':ask', outSpeech, outSpeech + ' ' + reprompt)

こちらは、Responseオブジェクトでは、次のようになります。

this.response.speak(outputSpeech).listen(outputSpeech + ' ' + reprompt);
this.emit(':responseReady');

shouldEndSessionがfalseになっていることを確認できます。

{
  "version": "1.0",
  "response": {
    "outputSpeech": {
      "ssml": "<speak> My favorite color is red. </speak>",
      "type": "SSML"
    },
    "reprompt": {
      "outputSpeech": {
        "ssml": "<speak> My favorite color is red. for example, my favorite color is green. </speak>",
        "type": "SSML"
      }
    },
    "speechletResponse": {
      "outputSpeech": {
        "ssml": "<speak> My favorite color is red. </speak>"
      },
      "reprompt": {
        "outputSpeech": {
          "ssml": "<speak> My favorite color is red. for example, my favorite color is green. </speak>"
        }
      },
      "shouldEndSession": false
    }
  },
  "sessionAttributes": {}
}

この比較から、発話するメッセージついては、常に speak() で設定し、ユーザーの応答を待つ場合に、listen() を追加するという基本的な利用方法が分かります。

3 カードの追加

カードを追加する場合は、cardRenderer() を使用します。

this.response.cardRenderer('card title', 'card body', 'https://hostname/image.jpg');
this.response.speak(outputSpeech);
this.emit(':responseReady');
{
  "version": "1.0",
  "response": {
    "outputSpeech": {
      "ssml": "<speak> Hello </speak>",
      "type": "SSML"
    },
    "card": {
      "content": "card body",
      "title": "card title"
    },
    "speechletResponse": {
      "outputSpeech": {
        "ssml": "<speak> Hello </speak>"
      },
      "card": {
        "content": "card body",
        "title": "card title"
      },
      "shouldEndSession": true
    }
  },
  "sessionAttributes": {}
}

4 組み立て自由

Responseオブジェクトは、自由な順序で動的に組み立てが可能です。

以下の例は、全て同じレスポンスを生成します。

// 例1)
this.response.listen(reprompt).speak(question).cardRenderer(CARD_TITLE, question);

// 例2)
this.response.speak(question).listen(reprompt).cardRenderer(CARD_TITLE, question);

// 例3)
this.response.cardRenderer(CARD_TITLE, question);
this.response.speak(question).listen(reprompt);

// 例4)
this.response.speak(question);
this.response.listen(reprompt);
this.response.cardRenderer(CARD_TITLE, question);

How to Teach Your Alexa Skill to Detect a Screenより

組み立ての順番は、全く自由で、また、連結も可能です。 最後に this.emit(':responseReady'); をコールした時点で、レスポンスが生成されます。

全てをまとめて this.emit(':tell'..) に送るような必要がありません。 この利用方法が、複雑なレスポンスを作成する作業では、一番威力を発揮するでしょう。

5 その他

Responseオブジェクトには、上記以外にも、各種のオブジェクトが利用可能ですが、詳しくは各ドキュメントをご参照下さい。

Link Account cardの表示

this.response.linkAccountCard()

AudioPlayer関連 参考 : AudioPlayer Interface Reference

this.response.audioPlayer(directiveType, behavior, url, token, expectedPreviousToken, offsetInMilliseconds)
this.response.audioPlayerPlay(behavior, url, token, expectedPreviousToken, offsetInMilliseconds)
this.response.audioPlayerStop()
this.response.audioPlayerClearQueue(clearBehaviour)

Echo Show用のテンプレート表示 参考 : Display Interface Reference

this.response.renderTemplate(template)

Echo Showでのヒント表示 参考 : Include Hint Directives in Responses

this.response.hint(hintText)

Echo Showでのビデオ再生 参考 : VideoApp Interface Reference

this.response.playVideo(url, metadata)

6 最後に

:tell 及び、:ask 関連の記述は、ラッパーだけあって記述は表示に簡単です。しかし、今後、デバイスが多様化していく中、より優れたUXをスキルに求める場合、Responseオブジェクトの利用は、重要な選択になるかも知れません。

7 参考リンク

How to Teach Your Alexa Skill to Detect a Screen
https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs