Miscellaneous notes

主に技術的な雑記的な

Alexa Skillの開発をServerless Frameworkだけで完結するための「Serverless Alexa Skills Plugin」の紹介

この記事は、Serverless Advent Calendar 13日目の記事です。

qiita.com

今回は拙作ですがオススメのServerless FrameworkのPluginを紹介したいと思います。

概要

Serverless Alexa Skills Pluginは、Serverless FrameworkでAlexa Skill用のLambda Functionを開発しながら、スキル周辺の設定も serverless.yml および serverless(sls) コマンドから管理できるようにすることで、Alexa Skillの開発をServerless Frameworkで統合管理するためのPluginです。

github.com

経緯など

Alexa Skillの開発にはLambda Functionの開発がセット

Alexaのカスタムスキルを作る場合、基本的にはLambda Functionの開発がセットになります。もちろん、Lambdaを使わずに特定のHTTP Endpointとやり取りすることで実行することもできますが、HTTPサーバを作って運用したりする手間とコストを考えるとLambdaを使う方が大抵の場合楽ですし、コストメリットも高いです。

developer.amazon.com

Lambda Functionの開発はServerless Frameworkでやりたい

最近は専らLambda Functionの開発はServerless Frameworkでやっています。以前は独自のデプロイツールを作って使っていたりもしましたが、v1.0からFrameworkの内部構造がそれ以前より段違いで良くなり、足りない機能はpull requestを送ったりpluginを作ったりして補えるようになったため、フルタイムで会社まで作ってメンテしていて、良い感じにエコシステムが確立しつつある製品に対抗してもしょうがないので乗っかる方針でやっています。

Alexa Skillの設定管理がめんどくさい

対して、Alexa Skillの設定はAlexa Skill Kitのコンソール画面から行うか、ack-cliを使う方法が公式で提唱されています。このack-cliがまた設定をJSONで書かないといけなかったり、公式ツールなのでしょうがないのですが、APIに忠実に作られているので必要なコマンド数が多かったりするわけです。

developer.amazon.com

Serverless Frameworkで全部良い感じにやりたい

そんな思いから生まれたのがServerless Alexa Skills Pluginというわけです。

使い方

インストール

インストールはnpmにリリースされてるのでこれだけです。

$ npm install -g serverless
$ serverless plugin install -n serverless-alexa-skills

認証情報の取得

利用するためにはLambda FunctionをデプロイするためのAWSの認証情報もそうですが、Alexa Skills Kit APIを実行するための認証情報も必要になります。AlexaはAWSではなくAmazon本体の管轄であり、Login with Amazon というAmazon本体アカウントを使ったOAuth2.0によるシングルサインオンで認証を受ける必要が有るため、認証情報の扱いが異なるのでそこを説明したいと思います。AWSの認証情報の取得方法についてはここでは触れません。

まず、Amazon Developer Consoleへログインします。

developer.amazon.com

APPS&SERVICES タブから Login with Amazon へ移動し、 Create a New Security Profile からセキュリティプロファイルを作成します。

f:id:FumblePerson:20171213225925p:plain

各入力項目は適当で良いです。

f:id:FumblePerson:20171213230336p:plain

作成したら、出来上がったセキュリティプロファイルの Web Settings を設定します。

f:id:FumblePerson:20171213230629p:plain

Allowed Origins は空で良いです。 Allowed Return URLshttp://localhost:3000 を入力します。このポート番号は設定(serverless.yml)で変更可能なので、変えたい場合は変えても良いです。

f:id:FumblePerson:20171213230810p:plain

ここまでできたら、できあがったセキュリティプロファイルの Client IDClient Secret を控えておきましょう。併せてもう一つ、 Vendor ID というものも必要になるので、Developer Consoleへログインした状態でコチラへアクセスして控えておきましょう。

ちょっと面倒ですが、この作業は初回だけです。同じアカウントを使う限りは今後いくつスキルを作ろうと同じ情報が使えます(漏洩などして入れ替えが必要にならなければw)

面倒な画面ポチポチはここまでです!!ここから先はみんな大好きの黒い画面をメインに進みます!!

認証情報をセット

取得した認証情報を serverless.yml へ書き込みます。直接書き込むのに抵抗がある場合は下記のように環境変数を利用すると良いでしょう。また、 Allowed Return URLs でポート番号を買えた場合は localServerPort という設定を追加してポート番号を書き込んでください。

provider:
  name: aws
  runtime: nodejs6.10

plugins:
  - serverless-alexa-skills

custom:
  alexa:
    vendorId: ${env:YOUR_AMAZON_VENDOR_ID}
    clientId: ${env:YOUR_AMAZON_CLIENT_ID}
    clientSecret: ${env:YOUR_AMAZON_CLIENT_SECRET}

そして、以下のコマンドを実行します。

$ serverless alexa auth

このコマンドを実行するとブラウザが開かれAmazonへのログイン画面が出てきます。そこでログインに成功すると localhost:3000 へリダイレクトされ、認証に成功していれば Thank you for using Serverless Alexa Skills Plugin!! とデザイン皆無の味も素っ気もないメッセージが表示されているはずです!w

ちなみにこれによって取得した認証トークンの有効期限は1時間となっています。今後、トークンの自動リフレッシュなど実装予定ですが、現状では認証エラーが出たら再度上記コマンドの実行をお願いします。

スキルの作成

それではスキルを作ってみましょう。以下のコマンドを実行します。

$ serverless alexa create --name $YOUR_SKILL_NAME --locale $YOUR_SKILL_LOCALE --type $YOUR_SKILL_TYPE

それぞれオプションは以下の通りです。

  • name(n): スキルの名前
  • locale(l): スキルのロケール。日本語なら ja-JP, 英語なら en-US
  • type(t): スキルのタイプ。 custom or smartHome or video

スキルマニフェストの更新

スキルを作ったら、スキルの基本的な設定を表すスキルマニフェストを設定する必要があります。今作成したスキルに初期設定されているマニフェストは以下のコマンドで確認できます。

$ severless alexa manifests

Serverless: 
----------------
[Skill ID] amzn1.ask.skill.xxxxxx-xxxxxx-xxxxx
[Stage] development
[Skill Manifest]
skillManifest:
  publishingInformation:
    locales:
      ja-JP:
        name: sample
  apis:
    custom: {}
  manifestVersion: '1.0'

実行すると上記のような出力が出るので、 [Skill ID][Skill Manifest] をコピーして serverless.yml へ以下のように貼り付けます。

custom:
  alexa:
    vendorId: ${env:AMAZON_VENDOR_ID}
    clientId: ${env:AMAZON_CLIENT_ID}
    clientSecret: ${env:AMAZON_CLIENT_SECRET}
    skills:
      - id: ${env:ALEXA_SKILL_ID}
        skillManifest:
          publishingInformation:
            locales:
              ja-JP:
                name: sample
          apis:
            custom: {}
          manifestVersion: '1.0'

この serverless.yml の設定を更新後、下記のコマンドを実行するとマニフェストが更新されます。ちなみに恒例?の --dryRun/-d オプションで実際に更新は行わずに更新内容だけ確認できます。

$ serverless alexa update

マニフェストの設定構文についてはAPIに準じているので、こちらで確認できます。

developer.amazon.com

対話モデルの構築

Alexaスキルを動かすためには、対話モデルの構築が必要です。これもマニフェストとほぼ同じ流れでできますが、作成しただけのスキルは対話モデルを持っていないのでまず先に serverless.yml に対話モデルの設定を書き込む所から始まります。

custom:
  alexa:
    vendorId: ${env:AMAZON_VENDOR_ID}
    clientId: ${env:AMAZON_CLIENT_ID}
    clientSecret: ${env:AMAZON_CLIENT_SECRET}
    skills:
      - id: ${env:ALEXA_SKILL_ID}
        skillManifest:
          publishingInformation:
            locales:
              ja-JP:
                name: sample
          apis:
            custom: {}
          manifestVersion: '1.0'
        models:
          ja-JP:
            interactionModel:
              languageModel:
                invocationName: PPAP
                intents:
                  - name: PineAppleIntent
                    slots:
                    - name: Fisrt
                      type: AMAZON.Food
                    - name: Second
                      type: AMAZON.Food

このような形で models.ロケール.interactionModel という構造で下記に準じた対話モデルを設定します。

developer.amazon.com

そして、下記のコマンドで対話モデルを更新し、構築します。ここでも --dryRun が利用可能です。

$ serverless alexa build

構築した対話モデルは下記のコマンドで確認可能です。

$ serverless alexa models

Serverless: 
-------------------
[Skill ID] amzn1.ask.skill.xxxx-xxxx-xxxxx
[Locale] ja-JP
[Interaction Model]
interactionModel:
  languageModel:
    invocationName: PPAP
    intents:
      - name: PineAppleIntent
        slots:
        - name: Fisrt
          type: AMAZON.Food
        - name: Second
          type: AMAZON.Food

現段階では以上です

ここから実際にスキルを公開するまではもう少しステップがありますが、一番変更が多く試行錯誤が必要でバージョン管理しておきたいマニフェストと対話モデルが統合管理できるのは大きいのではないかと思います。今後Alexa Skills Kitを通したテストや公開まで統合できるよう開発は進めていきたいと思っています。

また、ここでは触れなかったServerless FrameworkでAlexa Skill用のLambda Functionを実装する方法についてはこちらをご確認ください。

serverless.com

良かったら今後Alexaスキルを作る際にご利用いただき、フィードバックやStarをいただけると励みになりますので、よろしくお願いします。

github.com