AlexaSkillの作り方

時間があくとやり方を忘れるのでメモ

ゴール

  • たようならというと起動し、どんばんはというとよなかんばってやっぱりというと猫が好きと返すスキルを作る

Alexaスキルを作成

  • Amazon Alexa Voice AI | Alexa Developer Official Siteにアクセス
  • Alexaスキル開発をクリック。ページ遷移後コンソールをクリック
  • alexa developer consoleが表示されるので、スキルの作成をクリック
  • 新しいスキルを作成画面になるので、以下のように入力
    • スキル名
      • たようなら
        • ここがスキル起動のワードとなります
    • プライマリロケール
      • 日本語(日本)
    • 1.スキルに追加するモデルを選択
      • カスタム
    • 2.スキルのバックエンドリソースをホスティングする方法を選択
      • Alexa-hosted (Python)
  • スキルを作成ボタンを押す
  • スキルに追加するテンプレートを選択スクラッチで作成を選んでテンプレートで続けるボタンを押す
  • 少し待つと作成が完了します

Alexaスキルの設定

  • 画面左の対話モデルからインテントを選択しインテントを追加ボタンを押す
  • インテントを追加画面で以下のように入力
    • カスタムインテントを作成Donbanwaと入力してカスタムインテントを作成ボタンを押しサンプル発話どんばんわ,どんばんはを追加(プラス記号をクリック)
    • カスタムインテントを作成Yappariと入力してカスタムインテントを作成ボタンを押しサンプル発話やっぱりを追加
  • 画面左からエンドポイントを選択しAWS LambdaのARNスキルIDをコピーしておきます
  • 画面左の対話モデルからインテントを選択しモデルを保存ボタンを押して、モデルをビルドボタンを押します

Serverless FrameworkでLambdaの作成

  • 任意のディレクトリでtayounaraディレクトリを作成してディレクトリに移動

  • serverless create --template aws-python3

  • serverless.ymlを以下のようにする

    service: tayounara
    
    provider:
      name: aws
      runtime: python3.9
      region: ap-northeast-1
    
    functions:
      tayounara:
        handler: handler.handler
        role: TayounaraRole
        events:
          - alexaSkill: 【メモしておいたAlexaスキルのID】
    
    resources:
      Resources:
        TayounaraRole:
          Type: AWS::IAM::Role
          Properties:
            RoleName: TayounaraRole
            AssumeRolePolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Principal:
                    Service:
                      - lambda.amazonaws.com
                  Action: sts:AssumeRole
            Policies:
              - PolicyName: LambdaBasicPolicy
                PolicyDocument:
                  Version: '2012-10-17'
                  Statement:
                    - Effect: Allow
                      Action:
                        - logs:CreateLogGroup
                        - logs:CreateLogStream
                        - logs:PutLogEvents
                      Resource:
                        - 'Fn::Join':
                          - ':'
                          -
                            - 'arn:aws:logs'
                            - Ref: 'AWS::Region'
                            - Ref: 'AWS::AccountId'
                            - 'log-group:/aws/lambda/*:*:*'
    
    plugins:
      - serverless-python-requirements
    
  • handler.pyを以下のようにする

    # -*- coding: utf-8 -*-
    
    import logging
    import boto3
    
    from ask_sdk_core.skill_builder import SkillBuilder
    from ask_sdk_core.utils import is_request_type, is_intent_name
    from ask_sdk_core.handler_input import HandlerInput
    
    from ask_sdk_model.ui import SimpleCard
    from ask_sdk_model import Response
    
    sb = SkillBuilder()
    
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
    
    # 起動直後
    @sb.request_handler(can_handle_func=is_request_type("LaunchRequest"))
    def launch_request_handler(handler_input):
        speech_text = "どんばんわ、か、やっぱり、といってください"
    
        return handler_input.response_builder.speak(speech_text).set_card(
            SimpleCard("たようなら", speech_text)).set_should_end_session(
            False).response
    
    @sb.request_handler(can_handle_func=is_intent_name("Donbanwa"))
    def donbanwa_intent_handler(handler_input):
        speech_text = f'よなかんばって'
    
        return handler_input.response_builder.speak(speech_text).set_card(
            SimpleCard("たようなら", speech_text)).set_should_end_session(
            True).response
    
    @sb.request_handler(can_handle_func=is_intent_name("Yappari"))
    def donbanwa_intent_handler(handler_input):
        speech_text = f'猫が好き'
    
        return handler_input.response_builder.speak(speech_text).set_card(
            SimpleCard("たようなら", speech_text)).set_should_end_session(
            True).response
    
    @sb.request_handler(can_handle_func=is_intent_name("AMAZON.HelpIntent"))
    def help_intent_handler(handler_input):
        speech_text = "どんばんわ、か、やっぱり、というと返答します"
    
        return handler_input.response_builder.speak(speech_text).ask(
            speech_text).set_card(SimpleCard(
                "たようなら", speech_text)).response
    
    @sb.request_handler(
        can_handle_func=lambda handler_input:
            is_intent_name("AMAZON.CancelIntent")(handler_input) or
            is_intent_name("AMAZON.StopIntent")(handler_input))
    def cancel_and_stop_intent_handler(handler_input):
        speech_text = "さようなら"
    
        return handler_input.response_builder.speak(speech_text).set_card(
            SimpleCard("たようなら", speech_text)).response
    
    @sb.request_handler(can_handle_func=is_intent_name("AMAZON.FallbackIntent"))
    def fallback_handler(handler_input):
        speech = (
            "The たようなら skill can't help you with that.  "
            "You can say hello!!")
        reprompt = "You can say hello!!"
        handler_input.response_builder.speak(speech).ask(reprompt)
        return handler_input.response_builder.response
    
    @sb.request_handler(can_handle_func=is_request_type("SessionEndedRequest"))
    def session_ended_request_handler(handler_input):
        speech_text = "終了"
        return handler_input.response_builder.response
    
    @sb.exception_handler(can_handle_func=lambda i, e: True)
    def all_exception_handler(handler_input, exception):
        logger.error(exception, exc_info=True)
    
        speech = "問題が発生しました。時間をおいて、再度実行してみてください"
        handler_input.response_builder.speak(speech).ask(speech)
        return handler_input.response_builder.response
    
    handler = sb.lambda_handler()
    
  • requirements.txtを作成し内容を以下のようにする

    ask-sdk-core==1.17.1
    ask-sdk-model==1.34.2
    ask-sdk-runtime==1.17.1
    boto3==1.24.26
    botocore==1.27.26
    certifi==2022.6.15
    cffi==1.15.0
    chardet==4.0.0
    charset-normalizer==2.1.0
    cryptography==36.0.1
    idna==3.3
    jmespath==1.0.1
    pdfminer.six==20211012
    pycparser==2.21
    python-dateutil==2.8.2
    requests==2.28.1
    s3transfer==0.6.0
    six==1.16.0
    urllib3==1.26.10
    
  • serverless plugin install -n serverless-python-requirements

  • sls deploy

  • Mangagement Consoleにログインし、Lambdaの画面に移動

  • 関数のARNをひかえる

  • alexa developer consoleエンドポイントを選択

  • AWS LambdaのARNデフォルトの地域に、ひかえたLambda関数のARNを入力する

  • エンドポイントの保存ボタンを押す

Alexaスキルのテスト

  • alexa developer consoleで画面上部のテストを選択
  • 画面上部のプルダウンを開発中に変更
  • Alexaシミュレータでたようならどんばんはやっぱりを入力して応答を確認

Alexaスキルを実機で動作させる

  • 一般リリースはできないので、βテストという機能を使用して自分のEchoデバイスに紐づくAmazonアカウントに対してAlexaスキル使用を許可します
  • Alexa Icon Builderにアクセス
  • 適当なアイコンを選んでダウンロードボタンを押す
  • ダウンロードされたzipファイルを展開
  • alexa developer consoleの上部の公開をクリック
  • 以下のように入力する(必須な最低限の入力しかしません)
    • 公開名
      • たようなら
    • 説明
      • たようならスキルです
    • 詳細な説明
      • たようならスキルです
    • 最新情報
      • 入力不要
    • サンプルフレーズ
      • どんばんわ
    • 小さなスキルアイコン
      • 先程ダウンロードしたファイルをドラッグアンドドロップ
    • 大さなスキルアイコン
      • 先程ダウンロードしたファイルをドラッグアンドドロップ
    • カテゴリー
      • Social - Communication
        • 適当です
  • 保存して続行をクリック
  • プライバシーとコンプライアンスが表示されるので以下のように入力
    • このスキルを使って何かを購入をしたり、実際にお金を支払うことができますか?
      • いいえ
    • このスキルはAlexaショッピングアクションを使用しますか?
      • いいえ
    • このAlexaスキルはユーザーの個人情報を収集しますか?
      • いいえ
    • このスキルは13歳未満のお子様を対象としていますか?
      • いいえ
    • このスキルで広告は表示されますか?
      • いいえ
    • 輸出コンプライアンス
  • 保存して続行をクリック
  • 公開範囲が表示されるので以下のように入力
    • このスキルにアクセスできるユーザー
      • 公開
    • ベータテスト
      • ベータテスト管理者用Eメールアドレス
        • 自分のEchoデバイスに紐づくAmazonアカウントのメールアドレス
      • スキルのベータテスト(計0人 、アクティブ0人)のアクセスを管理
        • 自分のEchoデバイスに紐づくAmazonアカウントのメールアドレス
  • ベータテストの有効化をクリック
  • メールが飛んでおり、Enableリンクがあるが、パソコンからは有効化できないので、スマホからEnableのリンクをクリック
  • Alexaアプリが開くので、スキル一覧から対象アプリを選んで有効にするをクリック
  • echoデバイスからたようならでスキルが使えることを確認