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してやればよいでしょう。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark