ついに日本でもAmazonEchoが発売されました!
ということで、ServerlessFrameworkでAlexaスキルを作って見ようと思います。
今回はAlexa Skills Kit for Node.js+TypeScriptで実装してみます。
前提
事前にalexa開発者ポータルに登録しておいてください。 (lambdaをデプロイするだけなら不要ですが
nodeのインストール方法やserverlessの利用方法詳細等は省略します。
環境
- node v8.9.1
- yarn v1.3.2
- serverless v1.24.1
serverlessプロジェクトを作る
まずは、lambda側の実装からやっていきます
適当なディレクトリを作ります
$ mkdir serverless-alexa-sample
$ cd serverless-alexa-sample
serverlessコマンドでプロジェクトを作成します。
$ sls create --template aws-nodejs
TypeScript環境を作る
続いてTypeScriptの環境を作っていきます
package.json作成後、typescript周りのライブラリをインストールします。
$ yarn init -y
$ yarn add typescript tslint tslint-config-standard --dev
必要な型定義を追加します
$ yarn add @types/node @types/alexa-sdk --dev
tsconfig.jsonを追加します
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"target": "es2015",
"sourceMap": false,
"outDir": "build",
"removeComments": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"allowUnreachableCode": true,
"allowUnusedLabels": true,
"alwaysStrict": true,
"noImplicitReturns": true,
"suppressImplicitAnyIndexErrors": true,
"lib": [
"es2017"
],
"types": [
"node"
]
},
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules"
]
}
tslint.jsonを追加します
{
"extends": "tslint-config-standard"
}
続いてtsファイル用のディレクトリを生成し、既存のhandler.jsをリネームして配置します。
$ mkdir src
$ mv handler.js src/handler.ts
このままではTypeScriptのビルドエラーとなるためhandler.tsを以下のように修正します。
+ module.exports.hello = (event: any, context: any, callback: any) => {
+ const response = {
+ statusCode: 200,
+ body: JSON.stringify({
+ message: 'Go Serverless v1.0! Your function executed successfully!',
+ input: event
+ })
+ }
+
+ callback(null, response)
+
+ // Use this code if you don't use the http event with the LAMBDA-PROXY integration
+ // callback(null, { message: 'Go Serverless v1.0! Your function executed successfully!', event })
+ }
ビルドが通るか確認してみます。
package.jsonにビルド用のコマンドを追加します。
{
"name": "serverless-alexa-sample",
"version": "1.0.0",
"main": "index.js",
"author": "YukiYonekura <yuki.yonekura@example.com>",
"license": "MIT",
+ "scripts": {
+ "build": "tsc"
+ },
"devDependencies": {
"@types/alexa-sdk": "^1.0.10",
"@types/node": "^8.0.53",
"tslint": "^5.8.0",
"tslint-config-standard": "^7.0.0",
"typescript": "^2.6.1"
}
}
ビルドしてみます。
$ yarn run build
yarn run v1.3.2
$ tsc
Done in 1.06s.
これでTypeScriptでの開発環境が整いました!
ビルドしたファイルは./buildディレクトリに配置されています。(tsconfig.jsonで指定
build
└── handler.js
実装
ここからlambdaの実装に入ります
今回は「開いて」と発話すると「こんにちはアレクサ」、「終了」と発話すると「さようならアレクサ」、
それ以外なら「よく分かりません」と返すだけの簡単なスキルを実装してみます。
Alexa Skills Kit for Node.jsを追加します
$ yarn add alexa-sdk
handler.tsを以下のように修正します
import * as Alexa from 'alexa-sdk'
module.exports.hello = (event: Alexa.RequestBody<any>, context: Alexa.Context) => {
const alexa = Alexa.handler(event, context)
alexa.registerHandlers({
'Unhandled': function () {
this.emit(':tell', 'よく分かりません')
},
'LaunchRequest': function () {
this.emit(':tell', 'こんにちはアレクサ')
},
'AMAZON.StopIntent': function () {
this.emit(':tell', 'さようならアレクサ')
}
})
alexa.execute()
}
実際の実装ではstate毎にhandlerを実装していくことになると思うので、
handlerは別ファイルに分けたほうがいいでしょう
serverless.ymlを以下のように編集します
handlerにビルドしたファイルを指定し、eventsにAlexaスキル用のイベントを追記します
functions:
hello:
+ handler: build/handler.hello
+ events:
+ - alexaSkill
スキルの実装は以上になります
tsファイルをビルド後にslsコマンドでデプロイします
$ yarn run build
$ sls deploy
参考
Alexaスキルの登録
ここからは、開発者コンソールからAlesaスキルの登録を行って行きます
(スキルの登録方法については、公式に詳しくのっているで、雑に説明しています
まずは、ALEXAのホームにアクセスし、
「Alexa Skills Kit」の「始める」ボタンをクリックします
登録済みのスキル一覧が表示されます
まだスキルを登録していないので何も表示されていません。
「新しいスキルを追加する」ボタンをクリックします。
スキルの作成画面に遷移します。
説明に従って項目を埋めていきます。
※ALEXAではなくカナで「アレクサ」の方がいいかも
ちゃんと日本語化されているので特に困ることはないと思います。
全て載せると 面倒くさい 長くなるのでデフォルト値から変更した箇所だけ載せます
スキル情報
言語
もちろん「Japanese」を選択します
スキル名
任意の名前を入力
呼び出し名
画像では「ハローALEXAサンプル」となっていますが、カタカナの方がいい気がします
対話モデル
インテントスキーマ
AMAZON.StopIntentだけ登録します。
LaunchRequestとUnhandleは不要です
{
"intents": [
{
"intent": "AMAZON.StopIntent"
}
]
}
サンプル発話
AMAZON.StopIntentと「終了」、「おわり」という単語を紐づけます
組み込みインテントなので「ストップ」、「停止」等の単語は登録しなくても認識されます
AMAZON.StopIntent 終了
AMAZON.StopIntent おわり
設定
サービスエンドポイントのタイプ
「AWS Lambda の ARN (Amazonリソースネーム)」を選択
デフォルト
デプロイしたlambdaのARNを入力
例 arn:aws:lambda:ap-northeast-1:123456789012:function:serverless-alexa-sample-dev-hello
テスト
ここまで項目を入力するとテスト実行が可能になります
サービスシミュレーターから以下のように動作を確認できます
追記: アプリケーションIDの設定
Alexa SDKではApplicationIDを設定してあげないと、ログに以下のようなWarningが出力されます
Warning: Application ID is not set
ApplicationIDはAlexaの開発者コンソールで確認できます。
「スキルIDの表示」をクリックするとApplicationIDが表示されます。
ApplicationIDを確認したらhandler.tsを以下のように編集します
今回はApplicationIDをLambdaの環境変数から取得するようにしています
import * as Alexa from 'alexa-sdk'
module.exports.hello = (event: Alexa.RequestBody<any>, context: Alexa.Context) => {
const alexa = Alexa.handler(event, context)
+ alexa.appId = process.env.APPLICATION_ID
alexa.registerHandlers({
'Unhandled': function () {
this.emit(':tell', 'よく分かりません')
},
'LaunchRequest': function () {
this.emit(':tell', 'こんにちはアレクサ')
},
'AMAZON.StopIntent': function () {
this.emit(':tell', 'さようならアレクサ')
}
})
alexa.execute()
}
続いてserverless.ymlに環境変数の設定を追記します
functions:
hello:
handler: build/handler.hello
+ environment:
+ # 開発者コンソールで取得したApplicationIDを設定
+ APPLICATION_ID: amzn1.ask.skill.12345678-1234-1234-1234-123456789012
events:
- alexaSkill
これでWarningは表示されなくなりました
コード
今回作成したコードは以下においています
https://github.com/YukiYonekura/serverless-alexa-sample
まとめ
招待メールはよ
申請までの流れはEchoが届いたら書くかも