Alexa虎の巻(9)Alexa-hostedスキルでセッション永続性を使用する(1)

記事タイトルとURLをコピーする

Alexa虎の巻(9)Alexa-hostedスキルでセッション永続性を使用する(1) こんにちは、サーバーワークスのこけしの人、坂本(@t_sakam)です。

 さて、前回の「Alexa虎の巻」の第8回目ではスロットを使って「豆知識スキル」の手直しを行いました。スロットを使うことでインテントを増やすよりも少ないコードでユーザーからの指示(「宇宙」と「こけし」)に対応することができましたね。

 今回は、ユーザーがスキルを開始したときの挨拶を変更したいと思います。最初の挨拶に「こんにちは。○回目のご利用ありがとうございます。」と入れてみます。そうなると、スキルを使うのが何回目かどうかをどこかに保存しておかないといけませんね。通常Alexaスキルでデータを保存しておく場合は、DynamoDBが使われることが多いですが、Alexa-hostedスキルの場合は、DynamoDBは付いていません。どうしたらよいでしょうか?

 そんな時、Alexa-hostedスキルの場合はS3を使います。Alexa-hostedスキルにはS3が付いてくるので、今回はS3を使ってデータを保存して使う方法「Session Persistence(セッション永続性)」を試してみたいと思います。

 ※Alexaでもスキルを起動してから終了するまでは1セッションと表現されます。

1. Alexa開発者コンソールのトップページ

 Alexa開発者コンソールにログインします。「豆知識スキル」リンクをクリックします。

Alexa虎の巻(9)キャプチャ001

2. 「豆知識スキル」のトップページ

 「豆知識スキル」のトップページが表示されたら、画面上メニューから「コードエディタ」を選択します。

Alexa虎の巻(9)キャプチャ002

3. コードエディタ

 画面左下の「メディアストレージ: S3[0.4/5GB]」リンクをクリックします。

Alexa虎の巻(9)キャプチャ003

4. S3の「Media」フォルダ

 Alexa-hostedスキルに付属するS3バケットの「Media」フォルダが表示されました。Pollyで作成した音声データなどを使いたい時はここにデータを置いて利用することができます。

 今回利用したいデータは「Media」フォルダより上のS3バケットのルートに作成されます。ユーザーがスキルを起動した時に、何回目の起動かどうかがわかるファイルです。次回の手順の中でファイルが作成されたかどうかやファイルの中身を確認したいので、現時点で空になっているかを確認します。

 画面上の「911xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx22-us-east-1」リンクをクリックします。

Alexa虎の巻(9)キャプチャ004

5. S3バケットのルート

 現時点で存在するのは「Media」フォルダのみなのが確認できます。

Alexa虎の巻(9)キャプチャ005

6. Alexa-hostedスキルでセッション永続性を使用する

 S3バケットが空であることが確認できたので「コードエディタ」に戻ります。これからコードの修正をしていきます。Alexa虎の巻(9)キャプチャ006

 修正する内容は、公式ページの「Alexa-hostedスキルでセッション永続性を使用する」に詳しく記載されていますので、そちらも合わせてご確認ください。

developer.amazon.com

7. 「package.json」ファイルを開く

 「package.json」ファイルを開きます。

Alexa虎の巻(9)キャプチャ012

8. 「ask-sdk-s3-persistence-adapter」パッケージを追加

 「package.json」ファイルに次のパッケージを追加します。

"ask-sdk-s3-persistence-adapter": "^2.9.0"

 ついでに"ask-sdk-core"と"ask-sdk-model"も現時点での最新版に変更しておきます。

"ask-sdk-core": "^2.9.0"
"ask-sdk-model": "^1.29.0"

 追加と変更ができたら、画面上の「保存」ボタンを押します。

Alexa虎の巻(9)キャプチャ008

9. ask-sdk-s3-persistence-adapterの読み込み

 「index.js」ファイルを開き、以下のコードを追加して「ask-sdk-s3-persistence-adapter」を読み込みます。

const persistenceAdapter = require('ask-sdk-s3-persistence-adapter');

Alexa虎の巻(9)キャプチャ007

10. 画面を下にスクロール

 画面を下にスクロールして「index.js」ファイルの一番下のコードを表示します。

Alexa虎の巻(9)キャプチャ010

11. withPersistenceAdapterでS3PersistenceAdapterを追加

 skillBuilderに以下のコードを追加します。

.withPersistenceAdapter(
new persistenceAdapter.S3PersistenceAdapter({ bucketName: process.env.S3_PERSISTENCE_BUCKET })
)

Alexa虎の巻(9)キャプチャ011

12. 「LaunchRequestHandler」を変更

 次は「LaunchRequestHandler」のコードを変更します。

Alexa虎の巻(9)キャプチャ008

13. 「LaunchRequestHandler」の変更内容

 「LaunchRequestHandler」のコードを以下のように変更します。

const LaunchRequestHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    // checks request type
    return request.type === 'LaunchRequest';
  },
  async handle(handlerInput) {
    const requestAttributes = handlerInput.attributesManager.getRequestAttributes();

    const attributesManager = handlerInput.attributesManager;
    const s3Attributes = await attributesManager.getPersistentAttributes() || {};
    console.log('s3Attributes is: ', s3Attributes);

    let counter = s3Attributes.hasOwnProperty('counter')? s3Attributes.counter : 0;
    counter = counter + 1;
    
    let s3Attributes2 = {"counter":counter}
    attributesManager.setPersistentAttributes(s3Attributes2);
    await attributesManager.savePersistentAttributes();
    
    const message = `こんにちは。${counter}回目のご利用ありがとうございます。`;
    const speakOutput = message + requestAttributes.t('START_MESSAGE');

    return handlerInput.responseBuilder
      .speak(speakOutput)
      .reprompt(requestAttributes.t('HELP_REPROMPT'))
      .withSimpleCard(requestAttributes.t('SKILL_NAME'), speakOutput)
      .getResponse();
  },
};

Alexa虎の巻(9)キャプチャ009

14.  S3に保存されたデータを取得する

  少し細かくコードを見てみます。以下の辺りは、S3に保存されたデータを取得するコードになります。

const attributesManager = handlerInput.attributesManager;
const s3Attributes = await attributesManager.getPersistentAttributes() || {};

15.  ログ

 以下は、S3に保存されたデータをログに残して後で確認するために追加してあります。

console.log('s3Attributes is: ', s3Attributes);

 ログの確認方法は別の機会に触れたいと思いますが、確認すると以下のようなキーバリュー形式でS3のファイルに保存されていることがわかります。

s3Attributes is: { counter: 2 }

16.  存在を確認

 以下の箇所でS3にデータが存在するかを確認し、無ければ変数に「0」を入れています。存在していた場合は、データを入れています。取得したデータに今回のアクセスの分の「1」を追加します。

let counter = s3Attributes.hasOwnProperty('counter')? s3Attributes.counter : 0;
counter = counter + 1;

17.  S3にデータを保存する

 最後にデータ保存周りのコードです。「1」を追加した変数「counter」を、またS3のファイルに保存し直しておきます。ユーザーに返す挨拶にもその変数「counter」を使って、いままでアクセスした数をお知らせします。

let s3Attributes2 = {"counter":counter}
attributesManager.setPersistentAttributes(s3Attributes2);
await attributesManager.savePersistentAttributes();
    
const message = `こんにちは。${counter}回目のご利用ありがとうございます。`;

 すべて変更できたら、変更箇所を保存しておきます。画面右上の「保存」ボタンを押します。

18. 「languageStrings.js」ファイルを修正

 最後に「languageStrings.js」ファイルを修正します。「START_MESSAGE」に「こんにちは」という挨拶が重複するので、取ります。画面右上の「保存」ボタンを押します。

Alexa虎の巻(9)キャプチャ014

19. デプロイ

 すべて修正し終わったら「デプロイ」ボタンを押します。デプロイが完了したら、動作確認テストを行います。画面上の「テスト」を選択します。

Alexa虎の巻(9)キャプチャ015

20. テスト

 画面左上辺りの入力ボックスに「豆知識を実行して」と入力して、マシンの「Enter」ボタンを押します。

 「こんにちは。1回目のご利用ありがとうございます。豆知識スキルへようこそ…」から始まる返事が返ってきたので成功です。手順が長くなってきたので、実際のS3のデータの確認等は、次回にしたいと思います。

Alexa虎の巻(9)キャプチャ016

まとめ

 今回は、ユーザーがスキルを開始したときの挨拶を変更してみました。「Session Persistence(セッション永続性)」を使って「こんにちは。○回目のご利用ありがとうございます。」とAlexaがスキルの利用回数を言ってくれるようになりましたね。次回は実際にS3に保存されたデータの確認等を行っていきたいと思います!

 いや〜、「Alexa」って本当にいいものですね!

坂本 知子(記事一覧)

サーバーワークスのこけしの人(@t_sakam)。2020 APN AWS Top Engineers。