C#によるAlexaスキル実装:スロットとセッションを活用した対話の実現:特集:はじめてのAlexaスキル開発(3/3 ページ)
「スロット」を使い、ユーザーとの対話から必要な情報を取得したり、その情報を1つのセッションで保持して使い回したりする方法を解説する。
カスタムスロットタイプ
先ほどの例では、Alexa Skills Kitで定義されている標準のスロットタイプを使用していた(AMAZON.DATE、AMAZON.City)。しかし、開発者が独自のスロットタイプを作成することも可能だ。
独自のスロットタイプを作成するには、Alexaコンソールの左側ペーンで[Slot Types]の隣にある[Add]リンクをクリックする。
そして、[Create custom slot type]ラジオボタンをオンにして、タイプ名を指定し、[Create custom slot type]ボタンをクリックする。実際に作成してみたカスタムスロットタイプを以下に示す。
seriesスロットタイプは、ウルトラシリーズの小ネタを教えてくれるスキル用に作成したもので、上の画像では「ウルトラマン」と「ウルトラセブン」だけがその型で使用できる列挙値として定義されている。[VALUE]列の値は正規化された値、[ID]列のオプションとしてその値に割り当てることが可能なID値、[SYNONYMS]列には「類義語」「同義語」「省略形」などを入力して[+]ボタンをクリックすると、それらが右側に追加されていく。ここでは「ウルトラセブン」には「Ultraseven」と「セブン」が、ウルトラマンには「Ultraman」と「初代」が同義語として登録されている。
これを使用するインテント(UltramanKonetaIntent)は次のようになっている。
ユーザーが単に「ウルトラマンの小ネタ」「セブンについて教えて」などと尋ねれば、テキトーな答えを返してくれるというのがこのスキルだ。ユーザーへの応答を組み立てるLambda関数の実装は次の通り。大枠はこれまでに見てきたコードと同様なので、細かな説明は省略する。
public class Function
{
static string[] ultramantips =
{
"日本中の子供のカレー好きを決定的なものしたのがウルトラマンだからね",
…… 省略 ……
};
static string[] ultraseventips =
{
"ウルトラマンセブンじゃなくって、ウルトラセブンだからね",
…… 省略 ……
};
static Dictionary<string, string[]> dict = new Dictionary<string, string[]>
{
{ "ultraman", ultramantips },
{ "ultraseven", ultraseventips }
};
public SkillResponse FunctionHandler(SkillRequest input,
ILambdaContext context)
{
var response = new SkillResponse
{
…… 省略 ……
};
if (input.Request.Type == "LaunchRequest")
{
…… 省略 ……
}
IntentRequest ir = input.Request as IntentRequest;
…… 省略 ……
string msg = "";
var series =
ir.Intent.Slots["series"].Resolution.Authorities[0].Values[0].Value.Id;
var tmp = ir.Intent.Slots["series"].Value;
if (series == "ultraman" || series == "ultraseven")
{
Random r = new Random();
int index = r.Next(dict[series].Length);
msg = $"{dict[series][r.Next(index)]}";
//msg = $"Slots.Value={tmp}, Authorities.Values.Value.Id={series}";
}
else
{
msg = "ウルトラマンかウルトラセブンのことしか分からないんです";
}
response.Response.OutputSpeech =
new PlainTextOutputSpeech() { Text = msg };
return response;
}
private static SkillResponse ProcRequest(SkillResponse response, string msg,
bool shouldEndSession = false)
{
…… 省略 ……
}
}
シリーズごとの小ネタを文字列配列として作成し、それらをディクショナリに格納している。キーにはseriesスロットから得られる値(ID値)を指定している。
ただし、単に「Slots["series"].Value」と記述すると、ユーザーが実際に口にした語を取得してしまう。例えば、「セブンの小ネタ」と尋ねたときには「Slots["series"].Value」の値は「ウルトラセブン」や「Ultraseven」のように正規化された値ではなく「セブン」となってしまう。ユーザーの発話次第で値が変わってしまうので、この値はキーとしては使えない。
ディクショナリのキーに一貫して使える値が欲しいので、ここでは「Slots["series"].Resolution.Authorities[0].Values[0].Value.Id」というエライ深くに潜んでいるID値(上のカスタムスロットタイプの[ID]値欄に指定した値)を得るようにしている。
Alexaシミュレーターでのテストの様子を以下に示す。上に示したコードでメッセージを組み立てている部分にあるコメント行を有効にした場合の例も掲載しているので、Slots[].Valueの値とID値がどうなっているかも確認してみよう。
今回はAlexaスキル開発を行う上で必須の要素といえるスロットの使い方、セッション内で情報を保持して使い回す方法を見た。「おもしろネタになるかもしれない」と思って作り始めたウルトラマン小ネタスキルは途中でスベリ加減なことが判明した(からざっくりとした説明だけにした)ので、次回こそ音声インタフェースを使って何か面白いことをしたいと思う。
Copyright© Digital Advantage Corp. All Rights Reserved.