Alexa Skills KitのAMAZON.RepeatIntentをためす
元記事:Alexa Skill Recipe: Using Session Attributes to Enable Repeat Responses 面白そうだったので試してみました。 AMAZON.RepeatInt […]
目次
元記事:Alexa Skill Recipe: Using Session Attributes to Enable Repeat Responses
面白そうだったので試してみました。
AMAZON.RepeatIntent
とは?
Amazonが提供するビルトインインテントの1つで、最後のアクションを繰り返すようにAlexaへ求めることができるインテントです。ドキュメントによると、日本語では「もう一度言って」や「繰り返して」と話しかけることで利用できます。
インテントを登録する
このインテントはビルトインなので、「アレクサのビルトインライブラリから既存のインテントを使用」で検索して追加することで自分のスキルに追加できます。
Fact Skill(豆知識スキル)で利用する
Fact SkillはAWS Lambdaを新規作成時に利用できる設計図の1つです。alexa-sdkを含むLambdaファンクションをちょっと試したい時などに便利ですので、今回もこれを実験材料にします。日本語での作り方は、公式のドキュメントが参考になります。
そのままで使ってみる
想定する会話の流れは以下のようになります。
ユーザー「アレクサ、豆知識を開いて」
アレクサ「(豆知識について話す)」
ユーザー「もう一度言って」
アレクサ「(先程の内容を繰り返す)」
実装前の素の状態で試すと以下のようになりました。
これはデフォルトではレスポンスを返した段階でセッションが終了するようになっているからです。以下がLambdaからのレスポンスですが、body.response.shouldEndSession
がtrue
になっている場合はここでスキルが終了してしまいます。
{
"body": {
"version": "1.0",
"response": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak> Here's your fact: On Mars, the Sun appears about half the size as it does on Earth. </speak>"
},
"card": {
"type": "Simple",
"title": "Space Facts",
"content": "On Mars, the Sun appears about half the size as it does on Earth."
},
"shouldEndSession": true
},
"sessionAttributes": {},
"userAgent": "ask-nodejs/1.0.25 Node/v6.10.3"
}
}
ということで、Lambdaのソースコードを変更して、もう一度繰り返してもらえるようにしていきましょう。
LambdaをAMAZON.RepeatIntent
に対応させる
ここからはLambdaのソースコードを変更します。
1: セッションを継続させる
まずは豆知識をアレクサが話した後にセッションが継続している状態にする必要があります。以下は豆知識を話すための処理部分をLambdaからとってきたものです。
'GetNewFactIntent': function() {
var factArr = data;
var factIndex = Math.floor(Math.random() * factArr.length);
var randomFact = factArr[factIndex];
var speechOutput = GET_FACT_MESSAGE + randomFact;
this.emit(':tellWithCard', speechOutput, SKILL_NAME, randomFact)
},
:tellWithCard
はshouldEndSession
をtrue
で返しますので、false
で返す:askWithCard
に変更しましょう。また、ask
の場合は一定時間ユーザーが返事をしなかった場合にもう一度だけ話しかけることができますので、その際の発話内容も追加する必要があります。
this.emit(':askWithCard', speechOutput, repromptSpeech, cardTitle, cardContent, imageObj);
// via: https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs/blob/master/Readme.jp.md#%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9-vs-responsebuilder
ということで以下のように変更しましょう。var
がconst
に変わっているのはそういうものだと思ってください。
'GetNewFactIntent': function() {
const factArr = data;
const factIndex = Math.floor(Math.random() * factArr.length);
const randomFact = factArr[factIndex];
const speechOutput = GET_FACT_MESSAGE + randomFact + '他に聞きたいことはありますか?';
const reprompt = 'もう一度聞きたい場合は、「もう一度言って」と話しかけてください。終了する場合は、「ストップ」と言ってください。'
this.emit(':askWithCard', speechOutput, reprompt, SKILL_NAME, randomFact)
},
これでレスポンスが以下のように変わりました。body.response.reprompt
が追加され、body.response.shouldEndSession
がfalse
に変わっています。
{
"body": {
"version": "1.0",
"response": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak> 知ってましたか?金星は水星と比べて太陽より遠くにありますが、気温は水星よりも高いです。他に聞きたいことはありますか? </speak>"
},
"card": {
"type": "Simple",
"title": "豆知識",
"content": "金星は水星と比べて太陽より遠くにありますが、気温は水星よりも高いです。"
},
"reprompt": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak> もう一度聞きたい場合は、「もう一度言って」と話しかけてください。終了する場合は、「ストップ」と言ってください。 </speak>"
}
},
"shouldEndSession": false
},
"sessionAttributes": {},
"userAgent": "ask-nodejs/1.0.25 Node/v6.10.3"
}
}
ビルドツールでのテストでも会話が継続していることがわかります。
2: AMAZON.RepeatIntent
に対応させる
それではいよいよ繰り返しに対応させましょう。まずはGetNewFactIntent
で取得した豆知識の内容をattributesに保存して再利用できるようにします。
'GetNewFactIntent': function() {
const factArr = data;
const factIndex = Math.floor(Math.random() * factArr.length);
const randomFact = factArr[factIndex];
this.attributes.lastSpeech = randomFact;
const speechOutput = GET_FACT_MESSAGE + randomFact + '他に聞きたいことはありますか?';
const reprompt = 'もう一度聞きたい場合は、「もう一度言って」と話しかけてください。終了する場合は、「ストップ」と言ってください。'
this.emit(':askWithCard', speechOutput, reprompt, SKILL_NAME, randomFact)
}
続いて、AMAZON.RepeatIntent
でのリクエストを処理するコードを追加します。
'AMAZON.RepeatIntent': function () {
const reprompt = 'もう一度聞きたい場合は、「もう一度言って」と話しかけてください。終了する場合は、「ストップ」と言ってください。'
this.response.speak(this.attributes.lastSpeech + " 他に聞きたいことはありますか?").listen(reprompt);
this.emit(':responseReady');
},
これでAMAZON.RepeatIntent
がリクエストされた場合、その前のGetNewFactIntent
でattributesに追加された内容を繰り返すようになります。
ちなみにthis.attributes
の値は、Lambdaの中ではevent.session.attributes
の中にオブジェクト形式で送信されてきます。
{
"version": "1.0",
"session": {
"new": false,
"sessionId": "amzn1.echo-api.session.XXXXX",
"application": {
"applicationId": "amzn1.ask.skill.XXXXX"
},
"attributes": {
"lastSpeech": "太陽の質量は全太陽系の質量の99.86%を占めます。"
},
"user": {
"userId": "amzn1.ask.account.XXXXX"
}
},
"request": {
"type": "IntentRequest",
"requestId": "amzn1.echo-api.request.xxxxx",
"timestamp": "2018-04-07T06:57:05Z",
"locale": "ja-JP",
"intent": {
"name": "AMAZON.RepeatIntent",
"confirmationStatus": "NONE"
}
},
...
Lambdaのテストを書かれる場合の参考になればです。
会話をより続けやすくする
最後に「他に聞きたいことはありますか?」という返答を処理できるようにしておきましょう。「はい」か「いいえ」の返答が想定されますので、AMAZON.YesIntent
とAMAZON.NoIntent
の2つを追加しておきます。
'AMAZON.YesIntent': function () {
this.emit("GetNewFactIntent");
},
'AMAZON.NoIntent': function () {
this.response.speak(STOP_MESSAGE);
this.emit(':responseReady');
}
これで繰り返したい場合も他の豆知識が聞きたい場合も両方サポートできるようになりました。
終わりに
予約システムやスケジュールの照会などを行うスキルを作る場合、AMAZON.RepeatIntent
をサポートするとユーザーにとってより使いやすいスキルになるでしょう。
日本ではまだ使えない便利なビルトインインテントなどもありますので、またそちらもトライしてみます。