LoginSignup
1
2

More than 3 years have passed since last update.

PythonでAlexa Hello World

Last updated at Posted at 2019-08-17

GitHub.com のASK SDK for Python (JA)のチュートリアルの補足

初めてのスキル開発AWS Lambda用にコードを準備するのセクションで、SkillのLambdaコードをパッケージ化してデプロイする手順があるのですが、この手順が少し説明不足なので補足。

  1. ローカルでskillという作業用のフォルダを作る。
  2. skillフォルダ内に移動し、hello_world.py 新規で作成する。

    skill
    └── hello_world.py 
    
  3. Pythonのスキルのコードは、クラスベースとデコレーターベースの二つの作り方があるが、どちらでも良い。クラスベースの方が、ASK SDK for Node.jsの書き方に似てるので、個人的にはわかりやすいと思う。

  4. 手順通り hello_world.pyの中身を記述。こちらのコードを丸ごとコピペでもOK。

  5. さて、ここで「AWS Lambda用にコードを準備する」の手順に入るが、ここでは特定のフォルダへのSDKセットアップを詳しく解説

  6. ターミナルを開き、skillフォルダに移動する。

    $ cd Skill
    
  7. pipコマンドで、ask-sdk-core SDKライブラリをダウンロードする。必要な依存ライブラリも一緒にダウンロードされる。

    $ pip install ask-sdk-core -t .
    

    現時点で中身はこんな感じになる。

    .
    ├── __pycache__
    ├── ask_sdk_core
    ├── ask_sdk_core-1.10.2.dist-info
    ├── ask_sdk_model
    ├── ask_sdk_model-1.14.0.dist-info
    ├── ask_sdk_runtime
    ├── ask_sdk_runtime-1.10.2.dist-info
    ├── bin
    ├── certifi
    ├── certifi-2019.6.16.dist-info
    ├── chardet
    ├── chardet-3.0.4.dist-info
    ├── dateutil
    ├── hello_world.py
    ├── idna
    ├── idna-2.8.dist-info
    ├── python_dateutil-2.8.0.dist-info
    ├── requests
    ├── requests-2.22.0.dist-info
    ├── six-1.12.0.dist-info
    ├── six.py
    ├── urllib3
    └── urllib3-1.25.3.dist-info
    
  8. ここからAWS Lambdaのエンドポイントにデプロイするためのパッケージ(ZIPファイル)を作成する。zipファイルの中身にはskillフォルダを含めてはいけないことに注意。直下にライブラリ群が入っている必要がある。また、ライブラリ群とhello_world.pyファイルも同じ階層でなければならない。

    $ zip ../skill.zip -r .
    

    これで一つ上の階層にskill.zipファイルが作成される。

    ├── skill
    │   ├── __pycache__
    │   ├── ask_sdk_core
    │   ├── hello_world.py
    │   <省略>
    └── skill.zip
    
  9. 作成したzipファイルをAWS LambdaにアップロードすればOK

    UploadZip.png

オマケ

公式のhello_world.pyを日本語で動くようにしたソースです。

hello_world.py

from ask_sdk_core.dispatch_components import AbstractExceptionHandler
from ask_sdk_model.ui import SimpleCard
from ask_sdk_model import Response
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_request_type, is_intent_name
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.skill_builder import SkillBuilder


class LaunchRequetHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return is_request_type("LaunchRequest")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
        speech_text = "ようこそ、アレクサスキルキットへ、こんにちは、と言ってみてください。"

        handler_input.response_builder.speak(speech_text).ask(speech_text).set_card(
            SimpleCard("ハローパイソン", speech_text)).set_should_end_session(False)

        return handler_input.response_builder.response


class HelloWorldIntentHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
        return is_intent_name("HelloWorldIntent")(handler_input)

    def handle(self, handler_input):
        speech_text = "こんにちは"

        handler_input.response_builder.speak(speech_text).set_card(
            SimpleCard("ハローパイソン", speech_text)).set_should_end_session(True)

        return handler_input.response_builder.response


class HelpIntentHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
        return is_intent_name("AMAZON.HelpIntent")(handler_input)

    def handle(self, handler_input):
        speech_text = "こんにちは、と言ってみてください。"

        handler_input.response_builder.speak(speech_text).ask(speech_text).set_card(
            SimpleCard("ハローパイソン", speech_text)).set_should_end_session(False)

        return handler_input.response_builder.response


class CancelAndStopIntentHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
        return is_intent_name("AMAZON.CancelIntent")(handler_input) or is_intent_name("AMAZON.StopIntent")(handler_input)

    def handle(self, handler_input):
        speech_text = "さようなら"

        handler_input.response_builder.speak(speech_text).set_card(
            SimpleCard("ハローパイソン", speech_text)).set_should_end_session(False)

        return handler_input.response_builder.response


class SessionEndedRequestHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
        return is_request_type("SessionEndedRequest")(handler_input)

    def handle(self, handler_input):

        # Nothing to do

        return handler_input.response_builder.response


class AllExceptionHandler(AbstractExceptionHandler):
    def can_handle(self, handler_input, exception):

        return True

    def handle(self, handler_input, exception):
        # CloudWatch Logsに例外を書き出す
        print(exception)

        speech_text = "すみません。もう一度言ってください"
        handler_input.response_builder.speek(speech_text).ask(speech_text)
        return handler_input.response_builder.response


# Lambda Handlers
sb = SkillBuilder()
sb.add_request_handler(LaunchRequetHandler())
sb.add_request_handler(HelloWorldIntentHandler())
sb.add_request_handler(HelpIntentHandler())
sb.add_request_handler(CancelAndStopIntentHandler())
sb.add_request_handler(SessionEndedRequestHandler())
sb.add_exception_handler(AllExceptionHandler())

handler = sb.lambda_handler()

モデル ja-JP.json

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "ハローパイソン",
            "intents": [
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": []
                },
                {
                    "name": "HelloWorldIntent",
                    "slots": [],
                    "samples": [
                        "ハロー",
                        "こんにちは",
                        "ハローと言って",
                        "こんにちはと言って"
                    ]
                },
                {
                    "name": "AMAZON.NavigateHomeIntent",
                    "samples": []
                }
            ],
            "types": []
        }
    }
}
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2