Alexaの基本的なスキル作成2(スロット)
2021/6
■ 前回
前回はカスタムスキルをとりあえずなんとなく理解する回でした。
なんとなく、した?
まあ、そんな簡単にわかったら困らんよね。
なんとなくするまでは多分ここ読んでも、何かが深まるわけじゃないのでまだ読まなくていいです。
ということで、なんとなくわかってきた人は今回は前回疑問の残った「インテントってそんなにいっぱい作るの?まじで?」をやります。
■ インテントいっぱいつくらなくてよい
Alexa道場を見つつ勉強してるのを平易にまとめておこうって感じなので同じように次はスロットってやつやりましょう。
スロットってのを使うと、いろんな単語をまとめて処理できる感じになり、インテントをいっぱい作らなくてよくなります。(結論)
■ スロット
スロットってなんやねん?ですが、簡単に言うと単語集での認識システムですかね。
ちょっと一回使ってみましょう。
Intentの発話文の追加入力のところで「{}」で囲んで変数みたいな名前をつけます。
例として、「{place}」とでもします。
いきなり書いていいです。
すると、入力してるそばから「え?それどのスロット?新しいスロット?」みたいにダイアログが出てきますが、無視して打ち切って発話文を追加しちゃいます。
登録されるとスロット部分は色が変わって表示されてます。
で、下のほうにスクロールしていくと「インテントスロット」という項目でこのインテントで使われているスロットが並んでます。
今書いた{place}てのに対応したplaceというスロットができてると思います。
次に、そのplaceに当てはまる単語集を選びます。
amazonが事前に用意している単語集が「スロットタイプを選択」とうっすら出てるプルダウンで選べます。
AMAZON.cityあたりを選んでみましょう。
さて、これで保存してビルドして、「東京」とか叫ぶとこのIntentがスキルに飛んできます。
もやっとするでしょうけど、なんとなく想像つきますかね?
AMAZON.cityという単語集にある単語が検出されたら「{place}」のところが満たされたと判断されるということです。
発話文が「{place} に行きたいなー」とかだと「コロールに行きたいなー」「ウィーンに行きたいなー」
とかの発話文をすべて登録したのと同じになるので便利だねってことですね。
■ スロットタイプ
上ではamazonが用意したやつを使いましたが、当然自分で作った単語集を使いたくなる項目が出てきますわな。
方言とかスラング含めて挨拶を認識したいとか。
ということで、単語集を作ってみます。
単語集を作るところはアセット>スロットタイプってところです。
追加するボタンがあると思うので、それをぽちります。
「値を持つカスタムスロットタイプを作成」を選びます。
自分で作るか、amazonの奴を拡張するかっていう違いですかね。
まずは単語集の名前を付けます。
「words_greeting」あたりであいさつ単語集でも作ってみますか。
名前を付けると、単語入力画面になるので、単語入力しましょう。
「おはよう」でも入れてください。
すると、下に追加されたのが出てきます。
そこを見ると「同義語」ってのが見えます。
同義語(シノニムっていうんだってさ)
全部別々に登録してもいいんですが、おはようと同じ意味の挨拶はこっちに登録しておくとどの意味の挨拶が入力されたから、どういう返事をするみたいなスキル処理をするときに簡単になります。
同義語に「はよー」やら「おっはー」やら追加していきます。
「こんばんは」とかも、夜っぽい挨拶を同義語に入れて、「こんにちは」の昼っぽい挨拶も同様に追加していけば挨拶の単語帳(words_greeting)の出来上がりです。
ID
各単語の同義語のどれが認識されたとかまで見て処理を書くことって基本ないと思うんですよ。
そこでIDを設定しておくと、認識された言葉と一緒にIDが飛んでくるので、IDで処理分けをすることができるようになります。
設定しましょう。
ちなみに文字列ですが、飛んできた後に数値にして使うのが楽かと思うので、数値文字列を入れておくのがおすすめ。
■ スロットなにがしが多い(小休止)
ちょっと混乱してきましたかね。
・スロットタイプ = 変数の型
・スロット = 変数名
・インテントスロット = インテントで使ってるスロットというだけ
自分はこんな風にイメージしてます。
文章中に単語集のどれかが入る変数を置けるみたいな。
「東京の名物は?」が「{place} の名物は?」とすることで、都市単語帳のどれかがplaceという変数に入ってくるみたいなね。
■ 値の扱い方
Intentと認識されて飛んできたときに、スロットの単語が認識されていたらslotsという配列にデータが入ってきます。
ウェブで探すと大抵Node.jsのやつですが、Pythonだと命名規則が違ったりするし、Pythonは「.」つなぎでdictのアクセスできないせいで記述もちょこちょこ違うんですよね。
あんまりウェブに出てきませんが、ask_sdk_core.utils.request_util.pyってのに少しアクセサーが入ってるので、これ覗くとわかりやすいかもです。
(https://github.com/alexa/alexa-skills-kit-sdk-for-python/blob/master/ask-sdk-core/ask_sdk_core/utils/request_util.py)
ということで、とっとと関数化しましょう。
めんどくさいので、最初の要素の最初のIDを得るやつです。
(複数同時に認識されることがあるので、配列になってる)
from ask_sdk_core.utils import request_util
def get_slot_id(self, handler_input, name, def_value):
try:
s = request_util.get_slot(handler_input, name)
if s is not None and s.resolutions is not None:
r = s.resolutions.resolutions_per_authority[0]
if r.status.code == StatusCode.ER_SUCCESS_MATCH:
return r.values[0].value.id
except:
return def_value
return def_value
これで、IDの値をスロット名(name)から取得できます。
認識されてなかったらdef_valueが返ります。
特に指定なしの場合に決まった処理などさせれば、あまり発言しなくていいので楽です。
■つぎは
だんだんDeveloperConsoleでの作業がつらくなってきたと思います。
特にデバッグ環境がないことに。
次はそこを最低限確保します。
最低限です。
でも、雲泥の差です。