初めてのスキル開発



初めてのスキル開発

このガイドでは、ASK SDK v2 for Javaを使ったスキル開発の手順を説明します。

前提条件

  • Amazon開発者アカウント。Alexaスキルの作成と設定に必要です。
  • アマゾンウェブサービス(AWS)アカウント。このガイドでは、AWS Lambdaでスキルをホスティングする手順を確認できます。
  • SDKとの依存関係を持つMavenプロジェクト。ASK SDK v2 for Javaのセットアップをご覧ください。サンプルスキルには、標準SDK配布パッケージが必要です。依存関係をカスタマイズする場合は、コアSDKおよびAWS Lambdaのサポートモジュールを含める必要があります。

リクエストハンドラーを実装する

まず、スキルで受信するさまざまなタイプのリクエストを処理するのに必要なリクエストハンドラーを作成します。

LaunchRequestハンドラー

以下は、スキルがLaunchRequestを受信した時に呼び出されるハンドラーを設定するコードのサンプルです。特定のインテントなしでスキルが呼び出された場合、LaunchRequestイベントが発生します。

package com.amazon.ask.helloworld.handlers;

import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.LaunchRequest;
import com.amazon.ask.model.Response;
import com.amazon.ask.request.Predicates;

import java.util.Optional;

public class LaunchRequestHandler implements RequestHandler {

    @Override
    public boolean canHandle(HandlerInput input) {
        return input.matches(Predicates.requestType(LaunchRequest.class));
    }

    @Override
    public Optional<Response> handle(HandlerInput input) {
        String speechText = "ようこそ、アレクサスキルキットへ。こんにちは、と言ってみてください。";
        return input.getResponseBuilder()
                .withSpeech(speechText)
                .withSimpleCard("HelloWorld", speechText)
                .withReprompt(speechText)
                .build();
    }

}

受信したリクエストがLaunchRequestの場合、canHandleメソッドはtrueを返します。handleメソッドは、Speech、Card、Repromptなどの応答オブジェクトを使用して基本的なあいさつの応答を生成して返します。これらのオブジェクトの詳細は、こちらをご覧ください。

型付けされたリクエストハンドラーのうちいずれか1つを使用して、ビルトインインテントのハンドラーを作成することもできます。

package com.amazon.ask.helloworld.handlers;

import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.LaunchRequest;
import com.amazon.ask.model.Response;
import com.amazon.ask.request.Predicates;

import java.util.Optional;

public class LaunchRequestHandler implements com.amazon.ask.dispatcher.request.handler.impl.LaunchRequestHandler {

    @Override
    public boolean canHandle(HandlerInput input, LaunchRequest launchRequest) {
        return true;
    }

    @Override
    public Optional<Response> handle(HandlerInput input, LaunchRequest launchRequest) {
        // 応答を返します
    }

}

HelloWorldIntentハンドラー

以下は、スキルがHelloWorldIntentを受信した時に呼び出されるハンドラーを設定するコードのサンプルです。

package com.amazon.ask.helloworld.handlers;

import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.Response;
import com.amazon.ask.request.Predicates;

import java.util.Optional;

public class HelloWorldIntentHandler implements RequestHandler {

    @Override
    public boolean canHandle(HandlerInput input) {
        return input.matches(Predicates.intentName("HelloWorldIntent"));
    }

    @Override
    public Optional<Response> handle(HandlerInput input) {
        String speechText = "こんにちは";
        return input.getResponseBuilder()
                .withSpeech(speechText)
                .withSimpleCard("HelloWorld", speechText)
                .build();
    }

}

ハンドラーのcanHandleメソッドは受け取るリクエストがIntentRequestかどうかを検出し、インテント名がHelloWorldIntentの場合にtrueを返します。次に、基本的な「こんにちは」という応答が生成されて返されます。

型付けされたリクエストハンドラーを使用して作成されたHelloWorldIntentHandlerの例は、こちらを参照してください。

HelpIntentハンドラー

以下は、スキルがビルトインインテントAMAZON.HelpIntentを受け取ったときに呼び出されるハンドラーを設定するコードのサンプルです。

package com.amazon.ask.helloworld.handlers;

import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.Response;
import static com.amazon.ask.request.Predicates.intentName;

import java.util.Optional;

public class HelpIntentHandler implements RequestHandler {

    @Override
    public boolean canHandle(HandlerInput input) {
        return input.matches(intentName("AMAZON.HelpIntent"));
    }

    @Override
    public Optional<Response> handle(HandlerInput input) {
        String speechText = "こんにちは、と言ってみてください。";
        return input.getResponseBuilder()
                .withSpeech(speechText)
                .withSimpleCard("HelloWorld", speechText)
                .withReprompt(speechText)
                .build();
    }
}

先ほどのハンドラー同様、このハンドラーはIntentRequestを想定されるインテント名と照合します。基本のヘルプ手順が返されます。

CancelAndStopIntentハンドラー

このハンドラーもビルトインインテントによって呼び出されるため、HelpIntentハンドラーに非常に似ています。ただしこの場合は、1つのハンドラーを使ってAmazon.CancelIntentとAmazon.StopIntentという2つのインテントに応答することにしました。

package com.amazon.ask.helloworld.handlers;

import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.Response;
import static com.amazon.ask.request.Predicates.intentName;

import java.util.Optional;

public class CancelandStopIntentHandler implements RequestHandler {

    @Override
    public boolean canHandle(HandlerInput input) {
        return input.matches(intentName("AMAZON.StopIntent").or(intentName("AMAZON.CancelIntent")));
    }

    @Override
    public Optional<Response> handle(HandlerInput input) {
        return input.getResponseBuilder()
                .withSpeech("さようなら")
                .withSimpleCard("HelloWorld", "さようなら")
                .withShouldEndSession(true)
                .build();
    }
}

これら両方のインテントに対する応答は同じであるため、1つのハンドラーにすることで重複するコードを減らせます。

FallbackIntentハンドラー

以下は、スキルがビルトインインテントAMAZON.FallbackIntentを受信したときに呼び出されるハンドラーを設定するコードのサンプルです。このインテントが使用できるのは、現在英語(米国)でのみです。

package com.amazon.ask.helloworld.handlers;

import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.Response;

import java.util.Optional;

import static com.amazon.ask.request.Predicates.intentName;

public class FallbackIntentHandler implements RequestHandler {

    @Override
    public boolean canHandle(HandlerInput input) {
        return input.matches(intentName("AMAZON.FallbackIntent"));
    }

    @Override
    public Optional<Response> handle(HandlerInput input) {
        String speechText = "すみません、それは分かりません。ヘルプと言ってみてください。";
        return input.getResponseBuilder()
                .withSpeech(speechText)
                .withSimpleCard("HelloWorld", speechText)
                .withReprompt(speechText)
                .build();
    }
}

SessionEndedRequestハンドラー

SessionEndedRequestを受け取った後は、応答を返すことはできませんが、クリーンアップロジックを追加するにはこのハンドラーは最適な場所です。

package com.amazon.ask.helloworld.handlers;

import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.Response;
import com.amazon.ask.model.SessionEndedRequest;
import static com.amazon.ask.request.Predicates.requestType;

import java.util.Optional;

public class SessionEndedRequestHandler implements RequestHandler {

    @Override
    public boolean canHandle(HandlerInput input) {
        return input.matches(requestType(SessionEndedRequest.class));
    }

    @Override
    public Optional<Response> handle(HandlerInput input) {
        // クリーンアップロジックをここに追加します
        return input.getResponseBuilder().build();
    }
}

SkillStreamHandlerを実装する

streamハンドラーは、AWS Lambda関数のエントリポイントとなります。エンドユーザーがAlexaに対して行う、スキルを呼び出すすべてのリクエストは、このクラスを通過して、コンフィギュレーションが行われているSkillインスタンスに渡され、リクエストに適したハンドラーに転送されます。例として、HelloWorldIntentHandlerHelpIntentHandlerLaunchRequestHandlerなどがあります。リクエスト処理プロセスの一部として、リクエストと応答のインターセプターや例外ハンドラーも、必要な場合にはスキルのコンフィギュレーションに応じて呼び出すことができます。

SkillStreamHandlerは、SDKが提供するAWS LambdaのRequestStreamHandlerのサブクラスです。これは、Alexaリクエストのシリアライズとデシリアライズを行うためのボイラープレートロジック(お決まりのロジック)を処理します。つまり、スキルのストリームハンドラークラスは、SkillStreamHandlerを拡張して、ハンドラーやその他のコンフィギュレーションを使用してコンフィギュレーションが行われているスキルインスタンスを渡すだけで済みます。ストリームハンドラークラスをエントリーポイントとして使用するようにAWS Lambdaのコンフィギュレーションを行うと、すべてのリクエストはこのスキルインスタンスを介して適切なハンドラーにルーティングされます。

次のHelloWorldStreamHandlerは、作成したリクエストハンドラーを使用してコンフィギュレーションが行われたSDKのSkillインスタンスを作成します。

package com.amazon.ask.helloworld;

import com.amazon.ask.Skill;
import com.amazon.ask.Skills;
import com.amazon.ask.SkillStreamHandler;

import com.amazon.ask.helloworld.handlers.CancelandStopIntentHandler;
import com.amazon.ask.helloworld.handlers.HelloWorldIntentHandler;
import com.amazon.ask.helloworld.handlers.HelpIntentHandler;
import com.amazon.ask.helloworld.handlers.SessionEndedRequestHandler;
import com.amazon.ask.helloworld.handlers.LaunchRequestHandler;

public class HelloWorldStreamHandler extends SkillStreamHandler {

    private static Skill getSkill() {
        return Skills.standard()
                .addRequestHandlers(
                        new CancelandStopIntentHandler(),
                        new HelloWorldIntentHandler(),
                        new HelpIntentHandler(),
                        new LaunchRequestHandler(),
                        new SessionEndedRequestHandler())
                .build();
    }

    public HelloWorldStreamHandler() {
        super(getSkill());
    }

}

getSkillメソッドは、Skills.standardビルダーを使用してSDKインスタンスを作成します。リクエストハンドラーのインスタンスを作成し、addRequestHandlersビルダーメソッドでスキルに登録します。HelloWorldStreamHandlerコンストラクターは、作成されたSkillインスタンスをスーパークラスSkillStreamHandlerのコンストラクターに渡します。

streamハンドラークラスの完全修飾クラス名は、パッケージとクラス名で構成され、AWS Lambda関数を設定する時は必須です。この例では、完全修飾クラス名はcom.amazon.ask.helloworld.HelloWorldStreamHandlerです。

スキルをビルドする

スキルコードが完成したら、スキルプロジェクトをビルドできます。スキルをAWS Lambdaにアップロードするには、スキルと必要な依存関係を含むJARファイルを作成する必要があります。これを行うには、ターミナルを開き、pom.xmlを含むMavenプロジェクトの上位レベルのディレクトリに移動して、次のコマンドを実行します。

mvn org.apache.maven.plugins:maven-assembly-plugin:2.6:assembly -DdescriptorId=jar-with-dependencies package

このコマンドで、<my_project_name>.<my_project_version>-jar-with-dependencies.jarファイルがtargetディレクトリに作成されます。

スキルをAWS Lambdaにアップロードする

  1. AWSのアカウントをまだお持ちでない場合は、アマゾンウェブサービスにアクセスしてアカウントを作成します。
  2. AWSマネジメントコンソールにログインし、AWS Lambdaに移動します。
  3. コンソールの右上隅にある地域のドロップダウンリストをクリックし、Alexaスキルでサポートされる地域を1つ選択します。 アジアパシフィック(東京)、EU(アイルランド)、米国東部(バージニア北部)、米国西部(オレゴン)のいずれかを選択します。
  4. まだLambda関数がない場合は、今すぐ始めるをクリックします。または、関数の作成をクリックします。
  5. 一から作成オプションが選択されていることを確認します。
  6. 関数の名前を入力します。
  7. 関数のロールを選択します。ロールは、関数がアクセスできるAWSリソースを定義するものです。
    • 既存のロールを使用するには、既存のロールを選択でロールを選択します。
    • 新しいロールを作成するには、後述の関数の新しいロールを定義するを参照してください。
  8. ランタイムに使用する言語(この例ではJava 8)を選択します。
  9. 「関数の作成」をクリックします。
  10. こちらの手順に従い、関数のAlexa Skills Kitトリガーを設定します。Alexa Skills Kitトリガーを追加していることを確認してください。
  11. 前の手順の関数コードで作成したJARファイルをアップロードします。
  12. streamハンドラークラスの完全修飾クラス名を使用してハンドラー情報を入力します。
  13. 最後に、AWS Lambda関数のARNをコピーします。このARNはAmazon開発者コンソールでスキルを設定する際に必要となります。これは右上隅で確認できます。

スキルのコンフィギュレーションとテストを行う

スキルコードをAWS Lambdaにアップロードしたら、Alexaのスキルのコンフィギュレーションを行うことができます。最初に、Alexa Skills Kit開発者コンソールに移動します。右上の「スキルの作成ボタン」をクリックします。スキル名として「HelloWorld」を入力します。次のページで、カスタムを選択してからスキルを作成をクリックします。

これで、スキルの対話モデルを定義できます。左側の呼び出し名タブで、スキルの呼び出し名をごあいさつになるよう定義します。

次に、インテントをスキルに追加します。対話モデルのインテントセクションにある追加ボタンをクリックします。カスタムインテントを作成を選択した状態で、インテント名として「HelloWorldIntent」を入力し、インテントを作成します。ここで、ユーザーがこのインテントを呼び出すのに使用できるサンプル発話をいくつか追加します。この例では、以下のサンプル発話を追加しましたが、これ以外でもかまいません。

こんにちはと言って
ハローワールドと言って
こんにちは
ハイと言って
ハイワールドと言って
ハイ
ごきげんいかが

AMAZON.CancelIntent、AMAZON.HelpIntent、AMAZON.StopIntentはAlexaのビルトインインテントで、サンプル発話は自動的に継承されるため追加する必要はありません。

開発者コンソールでは、ナビゲーションバーでJSONエディターを選択してスキルモデル全体をJSON形式で編集することもできます。この例では、以下のJSONスキーマを使用できます。

{
  "languageModel": {
    "intents": [
      {
        "name": "AMAZON.CancelIntent",
        "samples": []
      },
      {
        "name": "AMAZON.HelpIntent",
        "samples": []
      },
      {
        "name": "AMAZON.StopIntent",
        "samples": []
      },
      {
        "name": "HelloWorldIntent",
        "samples": [
          "こんにちはと言って",
          "ハローワールドと言って",
          "こんにちは",
          "ハイと言って",
          "ハイワールドと言って",
          "ハイ",
          "ごきげんいかが"
        ],
        "slots": []
      }
    ],
    "invocationName": "ごあいさつ"
  }
}

対話モデルの編集が完了したら、モデルを保存してビルドするのを忘れないでください。

スキルのコンフィギュレーションのセクションに進みましょう。エンドポイントでAWS LambdaのARNを選択し、先ほど作成した関数のARNを貼り付けます。残りの設定は、デフォルト値のままで構いません。エンドポイントを保存をクリックし、次のセクションに進みます。

最後にスキルをテストできます。 開発者コンソールのテストタブで、スキルに対し、テキストや音声でリクエストをシミュレーションできます。呼び出し名と、先ほど設定したサンプル発話のうち1つを使います。たとえば、「アレクサ、ごあいさつを開いてこんにちはと言って」と言うと、スキルは「こんにちは」と答えるはずです。Echoウェブページに移動し、スキルにリストされているスキルを確認できます。ここでは、Alexa搭載デバイスからのテスト用にアカウントでスキルを有効にできます。

この時点で、インテントスキーマや、スキルの実装に対応するリクエストハンドラーを試してみてください。一通りのテストが完了したら、スキルの認定を申請して世界中のAlexaユーザーに公開するプロセスに進むことができます。