LoginSignup
9
9

More than 5 years have passed since last update.

Visual StudioからAlexaスキルをデプロイする。C#で。

Last updated at Posted at 2018-10-31

はじめに

Alexaスキルの実際の処理を行うエンドポイントの作成には、一般的にはNode.jsかPythonが使われます。
これらの言語はAmazonよりSDKが提供されており、それを使うことで効率的に開発を行うことができますし、情報も多いのでAlexaスキルを作りたい場合はぜひNode.jsかPythonを選んでください。
情報量で言ったらNode.jsのほうが多いのでNode.jsがおすすめです。

しかし、ここではC#で関数を作成してデプロイする方法を紹介します。
なぜ、わざわざC#なのか、というと、Visual Studioのインテリセンスなどの便利機能の恩恵を目一杯受けられるからです。

素晴らしいですね!!

でもまあそのかわりネットでの情報量がものすごく少なくなってしまうのですが。

環境

  • Windows 10 Pro ver.1809
  • Visual Studio Community 15.8

手順概要

手順はざっくり以下のとおりです。

  1. Visual StudioからAWSにアクセスする用のIAMユーザーの作成
  2. AWS Toolkit for Visual Studioのインストール(拡張機能)
  3. Alexa.NETのインストール(Nuget)
  4. C#で実装
  5. AWS Lambdaへデプロイ

IAMユーザーの作成

以下の画像はAWS Toolkitをインストールしたあとのものですが、Visual StudioからはLambdaだけではなく様々なサービスにアクセスできるので、ここで作成するユーザーにはかなり大きな許可を与えることになります。

image.png

まずはAWSコンソールの「ユーザー」から、ユーザーを追加しましょう。

image.png

ユーザー名を入力し、次のステップへ進みます。

image.png

そうしたら既存のポリシーから「AdministratorAccess」にチェックをつけて、次のステップに進みます。

image.png

最後に設定を確認してユーザーを作成します。

image.png

これで大きな権限持ったユーザーが作成されました。
このときに発行されるアクセスキーやシークレットアクセスキーを大事に保管しておきましょう。

補足

ユーザーにポリシーを直接アタッチするのではなく、グループは作ってそこにポリシーをアタッチしておき、ユーザーをそのグループに所属させれば同じことになります。

AWS Toolkit for Visual Studioのインストール

Visual StudioからAWSサービスにアクセスするための拡張機能がAmazonから提供されています。
それがAWS Toolkit for Visual Studioです。

まず、Visual Studioを起動します。
次に、ツールから拡張機能と更新プログラムを選択します。
image.png

ウィンドウの左側のカラムからオンラインをクリックし、検索窓にawsと入力すると、目的のAWS Toolkit for Visual Studioが見つかります。
ダウンロードボタンを押すと、ダウンロードが行われ、ダウンロード完了後にVisual Studioを閉じると拡張機能がインストールされます。

image.png

初回起動時の設定

インストール後の初回起動時には以下の設定タブが表示されます。
このAccess KeySecret Keyにそれぞれ、先程作成したIAMユーザーのアクセスキーシークレットアクセスキーを入力すると、「Save and Close」ボタンが有効になるのでクリックすると設定完了です。
Profile Nameはそのままでも良いですし、好きな名前をつけても良いです。これはIAMユーザー名とは関係ないので、好きにして大丈夫です。
Account Numberは空欄のままでOKです。

image.png

メニューの表示からAWS Explorerを表示することができます。
image.png

AWS Explorerは冒頭でも示したとおりです。
image.png

Alexa.NETのインストール

Alexa.NETというのはC#でAlexaスキルのリクエストとレスポンスを扱いやすくしてくれる便利なライブラリで、NuGetで配布されています。
これはAmazonではなく有志の方が作成してくれているものです。ありがたや。

これはNuGetパッケージとしてされており、プロジェクトにライブラリとして追加して使用するものなので、まずはVisual Studioのプロジェクトを作成する必要があります。

Lambdaプロジェクトの作成

ファイル新規作成プロジェクトを選択します。
image.png

プロジェクトの種類としてAWS Lambda Project(.NET Core)を選択して、名前を決めたら「OK」ボタンを押します。
image.png

次にテンプレートを選択します。
Alexaスキルのテンプレートはないので、ここではEmpty Functionを選択し、「Finish」ボタンを押します。
これでプロジェクトが作成されます。
image.png

作成直後のLambda関数本体であるFunction.csは以下のとおりです。

Function.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using Amazon.Lambda.Core;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]

namespace MyFirstCSharpSkill_Lambda
{
    public class Function
    {

        /// <summary>
        /// A simple function that takes a string and does a ToUpper
        /// </summary>
        /// <param name="input"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public string FunctionHandler(string input, ILambdaContext context)
        {
            return input?.ToUpper();
        }
    }
}

本当にAlexa.NETのインストール

プロジェクトが作成できたら、次はAlexa.NETをプロジェクトにインストールします。
ツールNuGetパッケージマネージャーソリューションのNuGetパッケージの管理を選択します。

image.png

NuGetタブの「参照」で検索窓に「alexa.net」と入力すると「Alexa.NET」が見つかります。
右カラムのインストール先プロジェクトにチェックをつけて、「インストール」ボタンを押してインストールします。
image.png

C#での実装

いよいよC#でコーディングしていきます。
Function.csにはLambda関数の雛形が作られています。
この中のFunctionクラスのFunctionHandlerメソッドがAlexaからのリクエストを受け取り、レスポンスを返す役割を担います。
しかし、この時点ではstring型を入力として受け取り、string型を返すものになっています。

まずはこの引数と返り値をAlexaスキル用に変更します。
具体的には、SkillRequest型を受け取り、SkillResponse型を返すようにします。

Function.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Alexa.NET.Request;//追加しました。
using Alexa.NET.Response;//追加しました。
using Amazon.Lambda.Core;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]

namespace MyFirstCSharpSkill_Lambda
{
    public class Function
    {

        /// <summary>
        /// A simple function that takes a string and does a ToUpper
        /// </summary>
        /// <param name="input"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public SkillResponse FunctionHandler(SkillRequest input, ILambdaContext context)
        {
            var skillResponse=new SkillResponse();

            //ここでレスポンスを構築する

            return skillResponse;
        }
    }
}

Alexa.NETの便利なところは、Alexaから受け取ったJSON形式のリクエストが自動的に.NETのクラスにデシリアライズされ、それを返すときにJSON形式にシリアライズされる点です。
これによって入出力におけるデータ形式を考える必要がなく、Requestオブジェクトから必要なデータを取得し、最終的に必要なResponseオブジェクトを構築してreturnするだけですみ、コーディングがとてもシンプルになります。

一番シンプルなAlexaスキルを作成

このままだとデプロイしたとしてもAlexaスキルとしての動作を確認できないので、最低限の応答を返すようにします。

FunctionHandlerメソッド
        public SkillResponse FunctionHandler(SkillRequest input, ILambdaContext context)
        {
            //ResponseプロパティにAlexaに喋らせる内容などを突っ込んでいく
            var skillResponse = new SkillResponse
            {
                Version = "1.0",//お約束
                Response = new ResponseBody()//お約束
            };


            //リクエストタイプが「LaunchRequest」かそれ以外の「IntentRequest」か判別する
            //今回はスキル起動時に送られる「LaunchRequest」のときとそれ以外のときで異なるレスポンスを返すようにした。
            if (input.Request.Type == nameof(Alexa.NET.Request.Type.LaunchRequest))
            {
                skillResponse.Response.OutputSpeech = new PlainTextOutputSpeech
                {
                    Text = "スキルを起動しましたよ。"
                };
            }
            else
            {
                skillResponse.Response.OutputSpeech = new PlainTextOutputSpeech
                {
                    Text = "スキルを起動できませんでしたよ。"
                };
            }


            //セッション終了させる。
            skillResponse.Response.ShouldEndSession = true;

            return skillResponse;
        }

スキルが呼び出し名によって起動されたとき、リクエストのタイプはLaunchRequestになります。それ以外の場合はIntentRequestになります。

今回はLaunchRequestかどうかでAlexaに喋らせる内容を変えるシンプルな構成にしました。

AWS Lambdaにデプロイ

ソリューションエクスプローラからプロジェクト名(ここでは「MyFirstCSharpSkill_Lambda」)の上で右クリックして、コンテキストメニューから「Publish AWS Lambda...」を選択します。

image.png

以下のウィンドウが表示されるので、Function Nameにお好みの名前を入力して、お好みのリージョンを選択して「Next」ボタンを押してください。

image.png

次に表示されるウィンドウでは、Role Nameの欄にプルダウンからNew role based on AWS managed policy: AWSLambdaBasicExecutionRoleを選択します。
ここでは今回デプロイするLambda関数に許可する権限を指定しています。
今回はAWSの他のサービスを呼び出すことはないので、「AWSLambdaBasicExecutionRole」を指定していますが、もしDynamoDBなどを使用する場合はDynamoDBの権限を与える必要があります。

「Upload」ボタンを押すとデプロイが始まり、進捗を表示するウィンドウが表示されます。
image.png

デプロイが完了すると進捗ウィンドウが自動的に閉じて、Visual Studioに以下のタブが表示されます。
ここで、Example Requestsの欄のプルダウンからAlexa Start Sessionを選択し、「Invoke」ボタンを押してください。
右側のResponse欄に「スキルを起動しました」を含むJSON形式のデータが表示されれば、デプロイしたAlexaスキルが正しく動作しています。
image.png

AWSコンソールのLambda関数のリストも確認してみましょう。
デプロイした関数が表示されています。
image.png

あとはAlexa開発者コンソール側での対話モデルの作成です。

対話モデルの作成

「スキルの作成」ボタンを押します。
image.png

スキル名を入力し、カスタムスキルを作成します。

image.png

呼び出し名を決めます。
image.png

少なくとも1つ以上のインテントを作らなければならないので、何かインテントを作成します。
image.png

少なくとも1つ以上の発話も登録しなければならないので、何かサンプル発話を登録します。

image.png

次にモデルをビルドします。
image.png

エンドポイントの設定を行います。
このエンドポイントというのが、先程C#で作成したLambda関数になります。
デフォルトの地域の欄にそのLambda関数のARN(AWSにおける一意の識別子)を指定することで、この対話モデルとLambda関数が結び付けられます。
dadjoiasesoifjaso.png

この対話モデルにも当然ARNがありまして、まずは対話モデルのARNをLambda関数側に登録する必要があります。
ちょっとややこしいですが、このエンドポイントのページ内の「クリップボードにコピー」をクリックしてこの対話モデルのARNをコピーします。
そして、一旦このまま開いたままにして、AWSのコンソールへ移ります。
AWS Lambdaの先程作成した関数を開き、この関数のトリガーとして「Alexa Skills Kit」を選択します。
image.png

次に、その下に「トリガーの設定」と表示されるので、「スキルID検証」を「有効」にして、スキルIDの欄に対話モデルのARNを貼り付けて、「追加」ボタンを押します。
image.png

ページ右上の「保存」ボタンを押して変更を保存します。
これでLambda関数側に対話モデルのARNを設定できました。
そして、今度は対話モデルにこのLambda関数のARNを設定するので、この「保存」ボタンの上のARNを選択してコピーしておきます。
塗りつぶしていますが、「arn:」で始まる部分です。
adjfalsdfjweioajflask.png

では、開きっぱなしにしておいた対話モデル側のエンドポイントのページで、デフォルトの地域の欄にLambda関数のARNを貼り付け、「エンドポイントを保存」ボタンを押してください。
image.png

これで対話モデルとLambda関数を結びつけることができました。

スキルのテスト

対話モデルの方で、「テスト」タブを開いてスキルのテストを有効にして、入力欄に「サンプル呼び出し」と入力してスキルを呼び出してみましょう。
image.png

すると、以下のようにAlexaが応答します。
C#で作成したLambda関数が正しく動いているようですね。

image.png

ちなみに、LaunchRequestに対するレスポンスではセッションを終了するように指定しているので、ここでスキルは終了します。

じゃあ形式上仕方なく作ったインテントはどうやって呼び出すのかというと、スキルの呼び出しとインテントの指定を一度にやるとOKです。
「サンプル呼び出し」が呼び出し名で、「サンプルを呼び出して」がSampleIntentを呼び出す発話になります。
そうすると、リクエストのタイプがLaunchRequestではなくIntentRequestになり、もう一方のレスポンスが帰ってきます。

image.png

Lambda関数に送られるリクエストの内容を見てみると、typeIntentRequestIntentnameSampleIntentになっていることがわかります。

image.png

おわりに

これでC#でAlexaスキルを実装するはじめの一歩を踏み出せるのではないかと思います。
慣れ親しんだC#で、Visual Studioのインテリセンスの恩恵を受けて開発するのもいいのではないでしょうか。

今回はLaunchRequestかそれ以外かで応答を変えていましたが、次回は複数のインテントに対して、異なる応答を返すようにしてみます。

次回はこちら

9
9
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
9
9