前回、Amazon Echo Alexaのカスタムスキルを作る入門をやってみました。今回は少しコードやインテントをいじってカスタマイズして、Alexaちゃんにゴミ出しの曜日を教えてもらうスキルを開発してみます。
【Amazon Echo入門】Alexaちゃんに今日履いているパンツの色を答えさせる

ぼくはNode.jsよりPythonの方がいくらか得意なので、LambdaのPython3.6で開発してみます。
Lambdaの開発
AWSのLabmdaダッシュボード画面から「Create Function」します。
Blueprintsからalexaで検索したが、Python3.6のものがなかった。仕方ないので今回もAuthor from scratchで実装します。

前回はどうもAlexaとやりとりするための規定のリクエストとレスポンスのフォーマットがわからなかったのだけど、そこまで複雑なものではなく、単にレスポンスでJSONを返せばいいだけみたい。
参考:https://medium.com/@jacquelinewilson/amazon-alexa-skill-recipe-1444e6ee45a6
def lambda_handler(event, context):
intent = event['request']['intent']
value = intent['slots']['TrashType']['value']
if value == '燃える':
day = '燃えるゴミの日は火曜日です。'
elif value == '燃えない':
day = '燃えないゴミの日は水曜日です。'
elif value == '資源':
day = '資源ごみの日は木曜日です。'
response = {
'version': '1.0',
'response': {
'outputSpeech': {
'type': 'PlainText',
'text': day
}
}
}
return response

前回同様にTriggersにAlexa Skills Kitを指定します。

ちゃんと動作するか確認したいので、Lambda Functionのテストを設定してみます。リクエスト内容は、intentのslots配下のみ書き換えます。
- Event template: Alext Intent - GetNewFact
- Event name: GetNewFact
{
"session": {
"new": false,
"sessionId": "amzn1.echo-api.session.[unique-value-here]",
"attributes": {},
"user": {
"userId": "amzn1.ask.account.[unique-value-here]"
},
"application": {
"applicationId": "amzn1.ask.skill.[unique-value-here]"
}
},
"version": "1.0",
"request": {
"locale": "en-US",
"timestamp": "2016-10-27T21:06:28Z",
"type": "IntentRequest",
"requestId": "amzn1.echo-api.request.[unique-value-here]",
"intent": {
"slots": {
"TrashType": {
"name": "TrashType",
"value": "燃えない"
}
},
"name": "GetNewFactIntent"
}
},
"context": {
"AudioPlayer": {
"playerActivity": "IDLE"
},
"System": {
"device": {
"supportedInterfaces": {
"AudioPlayer": {}
}
},
"application": {
"applicationId": "amzn1.ask.skill.[unique-value-here]"
},
"user": {
"userId": "amzn1.ask.account.[unique-value-here]"
}
}
}
}

実行すると、outputSpeechのtextに「燃えないゴミの日は水曜日です。」と返ってきていることが確認出来る。

Alexa Skill側の設定
開発者コンソールから前回同様に新しいSkillを登録していきます。
- スキル名: TrashDay
- 呼び出し名: ゴミ出しの日

{
"intents": [
{
"slots": [
{
"name": "TrashType",
"type": "LIST_OF_TRASH_TYPE"
}
],
"intent": "GetNewFactIntent"
}
]
}
カスタムスロットタイプにゴミの種別を設定する。
- タイプ: LIST_OF_TRASH_TYPE
- 値:
- 燃える
- 燃えない
- 資源
サンプル発話に以下を設定。
GetNewFactIntent {TrashType} ゴミの日
GetNewFactIntent {TrashType} ゴミの日教えて
GetNewFactIntent {TrashType} ごみの日
GetNewFactIntent {TrashType} ごみの日教えて

前回同様に、エンドポイントのデフォルトにLambdaのARN IDを指定する。
シミュレータでテストしてみる。
「燃えるゴミの日教えてください」と入力して呼び出すと、インテントのTrashTypeが「燃える」と認識され、レスポンスで「燃えるゴミの日は火曜日です。」と返って来ていることが確認出来る。

まとめ
無事できました!
インテント周りの概念がちょっと慣れるまでわかりづらいですが、一度やってみると感覚的に理解できるようになりますね。
今回もLambdaで実装しましたが、どうやら普通にエンドポイントを指定して、HTTPでリクエストしてもいけるみたいです。これを利用すれば外部のサーバーにリクエストしたりできるので、既存のサービスとの連携も色々できそうですね。
次回はゴミ出しの日を、プログラムに直接入れるのではなく、どこか別のデータソースから取ってくる実装をしてみたいなーと思ってます。