このトレーニングは6回のシリーズで、Alexaスキルの基礎、仕組み、スキルの開発と認証まで、幅広い内容を解説します。第4回では、Alexaスキルにおけるデータの保存についてご紹介します。また、参考としてデバイスアドレス機能についてもご紹介します。(第1回、第2回、第3回の記事もご覧ください)
- スキルで扱うデータの保存
- Alexa SDKのAmazon DynamoDB連携
- (参考) デバイスアドレスの利用
- 実習 : サンプルスキルへの処理の追加
まずは、今回学習する内容を簡単に説明するビデオを見てみましょう。
4-1. スキルで扱うデータの保存
第3回の状態管理では、ユーザーが発声した内容などスキルで扱うデータを引き継ぐセッションを紹介しました。しかしながらセッションはスキルが終了するとデータが破棄されてしまうため、次回スキルを実行するときにもデータを続けて利用したい場合は、データの保存を検討しましょう。
何か問い合わせを行うようなスキルでのデータ保存を考えてみましょう。問い合わせの条件を保存しておくことで、同じ条件でスキルを実行するときに毎回ユーザーに条件を聞く必要がなくなり、スキルの使い勝手を大幅にアップさせることができます。
ユーザー : 「アレクサ、お天気スキルで明日の天気を教えて」
Alexa : 「どこの天気をお知らせしますか」
ユーザー : 「東京」
Alexa : 「明日の東京の天気は晴れ、最高気温は25度、最低気温は15度でしょう」 (「東京」を保存してスキル終了)
ユーザー : 「アレクサ、お天気スキルで明日の天気を教えて」
Alexa : (前回の「東京」を読み出して都市の問いかけをスキップ)「明日の東京の天気は晴れ、最高気温は25度、最低気温は15度でしょう」
4-2. Alexa SDKのAmazon DynamoDB連携
Alexa SDKには、データ保存先としてAWSのデータベースサービスであるAmazon DynamoDBと連携する機能があります。使い方は非常にシンプルで、Lambda関数のプログラム内でalexa.dynamoDBTableNameメンバにDynamoDBのテーブル名を指定すると、Lambda関数の初回実行時にDynamoDBのテーブルが自動で作成され、セッション終了時に以下の形式でセッションデータのコピーをDynamoDBに保存します
列名 | データ型 | 説明 |
userId (プライマリキー) | 文字列 | ユーザーID。AlexaアプリのAmazonアカウントごとに一意だが、スキルを無効化すると変化する |
mapAttr | マップ | セッションアトリビュートのコピー |
保存後は毎回のスキル実行時にDynamoDBのデータがセッションアトリビュートへ自動でロードされるため、Lambda関数のプログラムではセッションアトリビュートを参照することで保存したデータを扱うことができます。
注意 : Amazon開発者コンソールのサービスシミュレーターでは、スキルが終了する場合でも別ページに移動するか[Reset]ボタンをクリックするまでセッションが終了しないため、それまではDynamoDBへのデータ保存が行われないことに注意しましょう。(別途、Alexa SDKの設定でデータ保存を行うこともできます)
また、実行のためには、Lambdaの実行ロールにDynamoDBの権限を付与する必要があります。任意のデータを保存する場合はLambdaのプログラムで他のライブラリを利用することで、DynamoDBをはじめとするAWSの各サービスやインターネットで提供される様々なWeb サービスをデータの保存先として利用することもできます。Web サービスとの連携では、第5回で紹介するアカウントリンク機能も参考になるでしょう。
4-3. (参考) デバイスアドレスAPIの利用
Echoデバイスでは、Alexaアプリからデバイスの設置場所を設定する項目があります。ASKのデバイスアドレスAPIを利用すると、デバイスの設置場所を取得することができます。これを使ってデバイスの設置場所に応じた処理を行うことができます。デバイスアドレスAPIで取得できる情報は以下の2つです。
- 国、郵便番号
- 住所
Echoデバイスからデバイスアドレスを取得するには、スキルの構成とAlexaアプリのそれぞれで以下の設定が必要です。
- スキルの構成でデバイスアドレスの許可を有効にする
- Alexaアプリのスキル設定で、デバイスアドレスへのアクセスを許可する
これらの設定を行うと、AlexaサービスからのリクエストにデバイスアドレスAPIにアクセスするための情報が追加され、Lambda関数内でそれらを用いたデバイスアドレスAPIへのHTTPリクエストを発行し、レスポンスから設置場所の情報を取得することができます。
デバイスアドレスAPIによって、例えばピザの注文スキルで配達先住所を取得し、注文に利用することができます。実際のプログラムは公開しているサンプルスキルを参照してください。
今回の実習
第3回で作成した星占いスキルのうちユーザーの星座をDynamoDBで保存し、DynamoDBに星座のデータがある場合は、ユーザーにもう一度星座を尋ねるアクションを省略するように改良します。
1回目の実行
ユーザー : 「アレクサ、うらないでうお座の運勢を教えて」
Alexa : 「今日のうお座の運勢は星みっつで良いでしょう。相性を占いますので、相手の星座を教えてください」
ユーザー : 「みずがめ座」
Alexa : 「うお座とみずがめ座の相性は普通です。仲良くなるために頑張りましょう」(セッションが終了し、「うお座」を保存する)
2回目の実行
ユーザー : 「アレクサ、うらないで相性を占って」
Alexa : (保存した「うお座」を読み込む)「あなたの星座はうお座ですね。相性を占いますので、相手の星座を教えてください」
ユーザー : 「かに座」
Alexa : 「うお座とかに座の相性は良いです。仲良くなれるかもしれません」
- スキルの変更点の確認
- 対話モデルの変更
- AWS Lambda関数の変更
- 動作確認
ステップ1 スキルの変更点の確認
ユーザーの星座を保存し読み込むために、相性占いのためのインテント(SynastryIntent)を対話モデルおよびAWS Lambda関数に追加します。追加後のLambda関数を以下に示します。
"use strict";
const Alexa = require('alexa-sdk');
const fortunes = [
{ 'score' : 'good', 'description' : '星みっつで良いでしょう' },
{ 'score' : 'normal', 'description' : '星ふたつで普通でしょう' },
{ 'score' : 'bad', 'description' : '星ひとつでイマイチでしょう' }
];
// ステートの定義
const states = {
SYNASTRYMODE: '_SYNASTRYMODE'
};
// 相性占い結果の定義
const synastries = [
{ 'score' : 'good', 'description' : '良いです。仲良くなれるかもしれません' },
{ 'score' : 'normal', 'description' : '普通です。仲良くなるために頑張りましょう' },
{ 'score' : 'bad', 'description' : '悪いです。仲良くなるためには努力が必要かもしれません' }
];
exports.handler = function(event, context, callback) {
var alexa = Alexa.handler(event, context);
alexa.dynamoDBTableName = 'HoroscopeSkillTable'; // ユーザーの星座を保存するDynamoDBのHoroscopeSkillTableテーブルを定義
// alexa.appId = process.env.APP_ID;
alexa.registerHandlers(handlers, synastriesHandlers); // 既存のハンドラに加えてステートハンドラ(後半で定義)も登録
alexa.execute();
};
var handlers = {
'LaunchRequest': function () {
this.emit('AMAZON.HelpIntent');
},
'AMAZON.HelpIntent': function () {
this.emit(':ask', '今日の運勢を占います。' +
'たとえば、うらないでふたご座の運勢を教えてと聞いてください');
},
'HoroscopeIntent': function () {
var sign = this.event.request.intent.slots.StarSign.value;
var fortune = fortunes[Math.floor(Math.random()*3)];
this.handler.state = states.SYNASTRYMODE; // ステートをセット
this.attributes['sign'] = sign; // 星座をセッションアトリビュートにセット
var message = '今日の' + sign + 'の運勢は' + fortune.description + '。' +
'相性を占いますので、お相手の星座を教えてください';
var reprompt = 'お相手の星座を教えてください';
this.emit(':ask', message, reprompt); // 相手の星座を聞くためにaskアクションに変更
console.log(message);
},
'SynastryIntent': function () {
if (this.attributes['sign']) {
this.handler.state = states.SYNASTRYMODE;
var sign = this.attributes['sign']; // DynamoDBから読み込んだデータを参照
var message = 'あなたの星座は' + sign + 'ですね。' +
'相性を占いますので、お相手の星座を教えてください';
var reprompt = 'お相手の星座を教えてください';
this.emit(':ask', message, reprompt);
} else {
this.emit('AMAZON.HelpIntent');
}
},
// スキルの中断時にもDynamoDBへのデータ保存を実行する設定
// https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs#making-skill-state-management-simpler
'SessionEndedRequest': function () {
this.emit(':saveState', true);
}
};
// ステートハンドラの定義
var synastriesHandlers = Alexa.CreateStateHandler(states.SYNASTRYMODE, {
'HoroscopeIntent': function() {
// ハンドラの実行後、スキルの初期状態に戻すためステートをリセット
this.handler.state = '';
this.attributes['STATE'] = undefined;
var yourSign = this.attributes['sign']; // セッションアトリビュートsignを参照
var hisSign = this.event.request.intent.slots.StarSign.value; // スロットから相手の星座を参照
var synastry = synastries[Math.floor(Math.random()*3)]; // ランダムに相性を決める
var message = yourSign + 'と' + hisSign + 'の相性は' + synastry.description;
this.emit(':tell', message);
console.log(message);
},
'Unhandled': function() {
var reprompt = 'お相手の星座を教えてください';
this.emit(':ask', reprompt, reprompt);
}
});
ステップ2 対話モデルの変更
ステップ1の変更に従い、対話モデルにインテント(SynastryIntent)とそのインテントのサンプル発話を追加します。
- Amazon開発者コンソールにサインインし、「ALEXA」メニューをクリック
- Alexa Skills Kitの「始める >」をクリック
- スキル一覧から第2回で作成したスキル「星占い」を選択
- 画面左側のメニューから[対話モデル]を選択し、以下を入力する
4-1.[インテントスキーマ]には、以下のJSONデータをコピー&ペーストで入力する。(SynastryIntentを追加しています)
{
"intents": [
{
"slots": [
{
"name": "StarSign",
"type": "ListOfSign"
}
],
"intent": "HoroscopeIntent"
},
{
"intent": "AMAZON.CancelIntent"
},
{
"intent": "SynastryIntent"
}
]
}
4.2 [サンプル発話]には、以下のテキストデータをコピー&ペーストで入力する。(SynastryIntent に対応するサンプル発話を追加しています)
HoroscopeIntent {StarSign} を 占って
HoroscopeIntent {StarSign} の 運勢 を 教えて
HoroscopeIntent {StarSign} の 運勢 は どう
HoroscopeIntent {StarSign} の 運勢 は
HoroscopeIntent {StarSign} の 運気 を 教えて
HoroscopeIntent {StarSign} の 運気 は どう
HoroscopeIntent {StarSign} の 運気 は
HoroscopeIntent {StarSign}
SynastryIntent 相性 を 占って
SynastryIntent 相性 を 教えて
SynastryIntent 相性 を 知りたい
SynastryIntent 相性 は どう
SynastryIntent 相性 が 知りたい
SynastryIntent 相性 が 聞きたい
SynastryIntent 相性
5. [保存]ボタンをクリックして、対話モデルの更新が完了するまで待ちます。
ステップ3 AWS Lambda関数の変更
ステップ1の変更をLambda関数のプログラムに適用します。また、LambdaからDynamoDBが操作できるよう、Lambdaの実行ロールにDynamoDBの操作権限を付与します。
- AWSマネジメントコンソールにログインし、画面左上の[サービス]をクリック、テキストボックスに「lambda」と入力して候補として表示されるLambdaを選択しAWS Lambdaの管理画面を表示する
- 関数のリストから「HoroscopeSkill」をクリックします
- 関数コードにステップ1のプログラムをコピー&ペーストで貼り付け、[保存してテスト]ボタンをクリックする
- 画面右上の[テスト]ボタンをクリックしてHoroscopeSkill関数の実行をテストする
- 「実行結果: 成功」と表示され、[詳細]をクリックし結果を確認する
- 画面左上の[サービス]をクリック、テキストボックスに「iam」と入力して候補として表示されるIAMを選択しIdentity and Access Managementの管理画面を表示する
- 画面左のメニューから[ロール]を選択し、検索フォームに 「lambda」と入力、リストから第1回で作成した「lambda_basic_execution」ロールを選択
- [ポリシーのアタッチ]ボタンをクリックし、アタッチするポリシーの検索フォームに「dynamodb」と入力、リストから「AmazonDynamoDBFullAccess」のチェックをオンにして画面右下の[ポリシーのアタッチ]ボタンをクリックする
ステップ4 動作確認
サービスシミュレーターで相性占いの動作を確認しましょう。2回目の実行時に、ユーザーの星座が保存される様子を確認します。
- Amazon開発者コンソールを開き、星占いスキルを選択、[テスト]タブを表示する
- サービスシミュレーターの[発話を入力してください]にユーザーの星座を入力し [星占いを呼び出す]ボタンをクリック、[サービスレスポンス]に星占い結果が出ることを確認する
- サービスシミュレーターの[発話を入力してください]に別の星座を入力し [Ask 星占い]ボタンを再度クリック、[サービスレスポンス]に相性占いの結果が出ることを確認する
- [リセット]ボタンをクリックしてセッションを終了する
- サービスシミュレーターの[発話を入力してください]に「相性を占って」と入力し [Ask 星占い]ボタンをクリックする。[サービスレスポンス]に手順2で入力した星座が含まれる(保存され、読み込まれた)ことを確認する
- サービスシミュレーターの[発話を入力してください]に別の星座を入力し [Ask 星占い]ボタンを再度クリック、[サービスレスポンス]に相性占いの結果が出ることを確認する
- AWSマネジメントコンソールにログインし、画面左上の[サービス]をクリック、テキストボックスに「dynamodb」と入力して候補として表示されるDynamoDBを選択し管理画面を表示する
- 画面左側のメニューから[テーブル]を選択する
- テーブル一覧から「HoroscopeSkillTable」(Lambdaから作成したテーブル)があることを確認しクリック、[項目]タブに表示されるリストから「amzn1.ask.acc...」のリンクをクリックする
- mapAttr列(セッションデータのコピー)があることを確認して左隣にある三角マークをクリックして開き、セッションデータ(ユーザーの星座)が保存されていることを確認する
これで今回の実習は完了です。星占いスキルにデータ保存機能を追加してユーザーの星座をスキルに記憶させる様子を確認しました。
まとめ
第4回ではスキルでのデータの保存について学習しました。次回はスキルと外部のWebシステムとの連携に利用するアカウントリンクについてご紹介します。
Source: Alexa Developer Blog