AlexaのAMAZON.RepeatIntentをシンプルに実装する方法
Alexaスキルは、「もう一度言って」のように話しかけた際に先ほど話した内容を復唱できるように作れます。この際、AMAZON.RepeatIntentというインテントを利用すると、よくある復唱をお願いする言い回しをビルト […]
目次
Alexaスキルは、「もう一度言って」のように話しかけた際に先ほど話した内容を復唱できるように作れます。この際、AMAZON.RepeatIntent
というインテントを利用すると、よくある復唱をお願いする言い回しをビルトインのモデルでハンドルできるようになります。
で、このインテントの実装で問題なのが「前のレスポンスを復元する」という実装です。
いろいろ試してみたのですが、おそらく一番シンプルな方法はこれかなと思ったので紹介します。
ResponseInterceptorでレスポンスをまるごとキャプチャする
これまではインテント別にコンテンツをsessionAttributesに保存して、RepeatIntentが来たらもう一度そのハンドラーのhandleメソッドを実行したりしていました。が、これでは実装したインテントでしかリピートができません。
一方でResponseInterceptor
を使えば、すべてのレスポンスをキャプチャすることができます。
import { ResponseInterceptor } from 'ask-sdk-core'
import {
updateSessionAttributes,
} from 'ask-utils'
const RecordTheResponseInterceptor:ResponseInterceptor = {
process(handlerInput, response) {
// No response text
if (!response) return
// Session should be closed
if (response.shouldEndSession === true) return
// Skill will be closed
if (!response.reprompt) return
updateSessionAttributes(handlerInput, {
lastResponse: response
})
}
}
このようにすると、会話が継続する状態=AMAZON.RepeatIntentが呼ばれる可能性がある状態の時のみレスポンスのオブジェクトをまるごとキャプチャできます。
今回はsessionAttributesに保存していますが、セッションが切れた状態から復元したいという場合は、persistantAttributesの方に保存すればよいでしょう。
RepeatIntentHandlerを実装する
あとはハンドラーを作成して、先ほどのレスポンスを復元するだけです。
import { RequestHandler } from 'ask-sdk-core';
import { Response } from 'ask-sdk-model'
import {
getSessionAttribute,
isMatchedIntent
} from 'ask-utils'
const RepeatIntentHandler: RequestHandler = {
canHandle(handlerInput) {
return isMatchedIntent(handlerInput, 'AMAZON.RepeatIntent')
},
handle(handlerInput) {
const lastResponse = getSessionAttribute(handlerInput, 'lastResponse') as Response | null
if (!lastResponse) throw new Error('No repeat content')
return lastResponse
}
}
これなら余計なステート更新が発生したり、ランダムなコンテンツが入れ替わってしまったりすることもありません。
万が一リピートしてほしくない内容がある場合は、キャプチャする側で除外するか、RepeatIntentHandler側でthrow new Errorしてやればよいでしょう。