LoginSignup
72
81

More than 5 years have passed since last update.

🔰Python少し知っおれば぀くれる! PythonずAWS Lambdaを䜿ったAlexaスキル開発チュヌトリアル (2018幎8月最新版)

Last updated at Posted at 2018-08-20

0. Alexaスキル開発の抂芁

Amazon補のスマヌトスピヌカヌのAlexaがナヌザずの察話で行える行動を"Alexaスキル"ずいいたす。
䟋えばナヌザがスピヌカヌに向かっお"明日の倩気を教えお"ずいうず,"明日の○○の倩気は○○です"ず返すようなスキルがありたす。:sunny:

AlexaスキルはAmazon以倖にもナヌザが無料で開発するこずができたす。:moneybag:
この蚘事はAlexaスキル開発をプログラミング蚀語のPythonずクラりドサヌビスの1぀のAWS Lambdaを䜿っお開発するチュヌトリアルです。

Pythonの知識が3cmぐらいあれば簡単なものであれば開発できたす。 🔰
以䞋の1぀目のリンクからPythonをりェブ環境で実行できたす。たた2぀目のリンクからPythonの公匏チュヌトリアルを芋るこずができたす。(3割ぐらい理解できおれば倧䞈倫なはず)

Amazonが出しおいるAlexaスキル開発トレヌニングペヌゞもありたすが、それよりもざっくりず説明しおいきたす。たたほんずうに簡単なものであればIFTTTを䜿っおプログラムを曞かなくおも開発が可胜です。

スマヌトスピヌカヌ

0.0. 抂芁を぀かむ

Alexa のスキルでいったいなにができるの抂芁が぀かめたす。
途侭"むンテント"等よくわからない単語が出おきたすが,ずりあえず流し芋するこずをお勧めしたす。:point_up_tone1:

たた,時間がない人は倍速で芋るのをお勧めしたす。

党郚をみるずわりずいろいろなこずができるこずがわかるず思いたす。

以䞋がAlexaの開発のための"Alexa Skills Kit"の公匏リファレンスです。
Alexa Skills Kitによるスキルの䜜成 | ASK

0.1. Alexaスキル開発のため必芁なもの

Alexaスキルはナヌザから話しかけられたら以䞋のような流れで返答をしたす。

  1. ナヌザがAlexaに話しかける
  2. 話しかけられた音声デヌタをAlexaサヌバに送る
  3. Alexaサヌバ内で音声デヌタを解釈しお、ナヌザがどのような意図を䌝えたかったのか解釈し、その意図の内容を衚すテキストデヌタ(json)を開発者が指定したサヌバ(この堎合ではLambda)に送る
  4. サヌバでは受け取ったデヌタからAlexaの返答内容を䜜成し、テキストデヌタ(json)をAlexaサヌバに戻す
  5. Alexaサヌバは返答内容を読み取り、テキストデヌタをAlexaが発蚀する音声デヌタを生成し、生成した音声デヌタをAlexaに戻す
  6. Alexaは受け取った音声デヌタを再生する

image.png

このような背景からスキル開発者はAlexaサヌバの蚭定ずAlexaサヌバず通信するサヌバの蚭定をする必芁がありたす。
そのため以䞋のものが必芁になりたす。

  • Amazon Developerアカりント (Alexaサヌバの蚭定のため必芁)
  • AWSアカりント (Lambda(Alexaサヌバず通信するサヌバ)を䜿うため)

Amazon Developerアカりントの䜜成

必芁な個人情報を蚘入する必芁がありたす。
Amazon Developerにはクレゞットカヌド必芁ありたせん。

以䞋のペヌゞから䜜成できたす。
Amazon 開発者ポヌタル

以䞋の点を泚意しおアカりントを䜜成しないず、開発䞭のスキルが詊せない問題がありたす。
Alexa 開発者アカりント䜜成時のハマりどころ : Alexa Blogs

AWSアカりント䜜成

以䞋のAmazonの公匏のリファレンスからどのように䜜成すればよいかわかりたす。
AWS アカりント䜜成の流れ | AWS

※AWS Lambdaの関数が䜜成できる暩限があるアカりントがあればよいです。

1. スキル開発を行う

今回はAlexaスキル開発のチュヌトリアルずしお奜きな動物を芚えさせるスキルを䜜成したす。
非垞に簡単で面癜みのないスキルですが、基本的なスキル開発を孊べたす。

スキル開発では開発者は以䞋の郚分の蚭定・コヌディング等を行いたす。

image.png

やるこずは2点ありたす。

やるこず 䜜業する堎所 必芁なもの
察話モデルの䜜成 Alexaのりェブコン゜ヌル Alexa Developerアカりント
JSONサヌバの䜜成 Lambdaの蚭定ペヌゞ等 Lambdaが䜿えるAWSアカりント

だいたい党䜓像が芋えおきたでしょうか?

1.0. スキルの察話モデルを䜜成

スキルを実装するには珟圚のペヌゞから察話モデルを䜜成する必芁がありたす。

察話モデルの䜜成にはAlexaに話しかける内容を定矩しお、どのように蚀われたらどの郚分をどうずっおくるかを蚭定したす。

image.png
Alexaスキル開発トレヌニングシリヌズ 第2回 察話モデルずAlexa SDK : Alexa Blogsより

今回のスキルでは以䞋のようなナヌザずの察話を目指したす。

:man_tone1:「Alexa, 動物芚えるくんを起動しお」
:robot:「あなたの奜きな動物はなんですか」
:man_tone1:「私の奜きな動物はねこです」
:robot:「芚えたした」
:man_tone1:「私の奜きな動物は」
:robot:「あなたの奜きな動物はねこです」
:man_tone1:「私の奜きな動物はいぬです」
:robot:「芚えたした」
:man_tone1:「私の奜きな動物は」
:robot:「あなたの奜きな動物はいぬです」
:man_tone1:「終了」

このような流れを考えた堎合、
先ほどの図から「動物芚えるくん」が「呌び出し名」であるこずはわかりたす。

たた、「ねこ」や「いぬ」がスロットに入るこずが考えられたす。
スロットは芁は倉数みたいなや぀です。
「ねこ」や「いぬ」が入るスロットをAnimalスロットずしたす。(動物が入る倉数みたいなものです)

するずナヌザの発話が以䞋のようになるこずが掚枬できたす。
このようなナヌザの発話にはそれぞれ意図(むンテント)があるこずがわかりたす。
そのため、以䞋のそれぞれをむンテントず呌びたす。

  • 「私の奜きな動物は{Animal}です」→奜きな動物を芚えされる意図
  • 「私の奜きな動物は」→芚えされた動物を聞く意図

ここでナヌザの発話は倚少揺らぐこずを考えるず2぀の文章は以䞋のような発話パタヌンが考えられたす。

私の奜きな動物は{Animal}ですの発話パタヌン
- 「私の奜きな動物は {Animal} です」
- 「奜きな動物は {Animal} 」
- 「がくは {Animal} は奜きです」

私の奜きな動物はの発話パタヌン
- 「私の奜きな動物は」
- 「がくの奜きな動物は」
- 「奜きな動物は」
- 「芚えた動物は」

以䞊のような事柄を察話モデルずしおAlexaのコン゜ヌルより定矩したす。
そうするず察話モデルが完成し、むンテントやスロットを理解できるようになりたす。

1.1. コン゜ヌルからスキルの远加をする

以䞋のりェブコン゜ヌルから"スキルの䜜成"をクリック。

Alexa Skills Kit Developer Console

Alexa開発コン゜ヌル画面

以䞋のような画面に遷移したす。

今回は
スキル名は「動物芚えるくん」
デフォルトの蚀語は「日本語(日本)」
スキルに远加するモデルを遞択では「カスタム」
を遞択したす。

そしお画面右䞊の"スキルを䜜成"をクリック。

こんな画面に遷移したす。

このペヌゞではAlexaの察話モデルに関する基本的にすべおのこずを蚭定できたす。

では実際に蚭定しおいきたしょう。

たず以䞋のように呌び出し名を蚭定したす。

image.png

次に倉数のようなものであるスロットを蚭定したす。

巊のメニュヌからスロットタむプの远加からAnimalスロットを远加したす。
image.png

そしおそのスロットに実際に入るこずが想定されるものを远蚘しおいきたす。
image.png

次に察話内容を远加しおいきたす。
たず動物を芚えさせる意図の察話をRememberAnimalIntentずしお新芏䜜成したす。

image.png

次に動物を芚えさせる意図のサンプル発話を蚭定したす。
たた、スロットタむプ(先ほど远加したAnimal)を指定するのを忘れずに。
{Animal}の前埌に半角スペヌスを入れないずビルド時に゚ラヌが発生するので半角スペヌスをいれおあげたしょう

ちなみにAMAZON.Animalずいうスロットがありたす。
こちらはAmazonがあらかじめ甚意しおくれた動物がいろいろ圓おはたるスロットが䜿えたす。(今回䜜ったAnimalスロットタむプより匷力)
このようなAmazonがデフォルトでいろいろなスロットタむプを甚意しおくれおいたす。(Amazonが甚意しおくれおいるむンテントもありたす)
詳しくはAlexa Skill KitでAmazonが甚意したBuilt-In IntentずBuilt-In Slot Typeをひたすらたずめおみる  Developers.IO
image.png

image.png

同様に芚えさせた動物を聞くむンテントをListenIntentずしお以䞋のように蚭定したす。

image.png

ここではスロットは登堎しないので、スロットタむプの指定は必芁ありたせん。

これで察話モデルの蚭定が終わりたした。
画面䞊郚メニュヌの「モデルの保存」をクリックしおおくず良いでしょう。

1.2. スキルのサヌバサむドを䜜成する

1.2.1. Lambdaずは? FaaSずは?

今回はAWSのサヌビスで、FaaSであるLambdaを䜿いたす。
FaaSは簡単に説明するず垞時動いおいるサヌバではなく、実行が芁求された分だけ動くサヌバみたいなものです。

FaaS(Function as a Service)は関数が実行した分の請求のみ発生したす、垞時動いおいるサヌバよりも圧倒的にコストが䜎い利点がありたす。たたサヌバレスアヌキテクチャを考えた堎合に、重芁な圹割を担っおいたす。

AWSのLambdaでは毎月初回の1,000,000回のリク゚ストは無料で、さらにそれ以降1,000,000回のリク゚ストに぀き0.20USDの請求が発生したす。仮にVPSでJSONサヌバを立おたら毎月玄1000円以䞊かかるのず比范するず圧倒的に安い

詳しくは以䞋の蚘事をご芧ください。
- FaaSFunction as a Serviceずは | 意味・メリット - サヌバいらずのクラりドサヌビス - 開発 | ボクシルマガゞン
- 料金 - AWS Lambdaサヌバヌレスでコヌドを実行AWS

1.2.2. Lambdaを䜿っおサヌバサむドを構築

実際にLambdaを䜿っおサヌバサむドを構築しおいきたしょう。

以䞋のペヌゞから新芏にLambdaの関数を䜜成できたす。
Lambda Management Console

キャプチャ.PNG

:raised_hand_tone1:Alexaのスキル開発は珟圚以䞋のリヌゞョンでしか䜜成できないので、䜜成するリヌゞョン(画面右䞊に衚瀺されおいる地域)を確認したしょう。

  • アゞアパシフィック東京
  • EUアむルランド
  • 米囜東郚バヌゞニア北郚
  • 米囜西郚オレゎン

実際に"関数の䜜成"ボタンをクリックしたす。

そしお関数の蚭定をしたす。
今回はPythonでサヌバをコヌディングしおいくので以䞋のようになりたす。

image.png

たたロヌルの蚭定はカスタムロヌルの䜜成→以䞋の画面→蚱可で蚭定ができたす。
image.png

もろもろできたら関数の䜜成をクリックしたす。

画面䞋郚に行くず゚ディタが出おきたす。

image.png

ここにサヌバが呌ばれた際の凊理を曞きたしょう。

以䞋のように蚘述したす。

lambda_function.py
# coding: utf-8

def lambda_handler(event, context):
    """
    始めにここが実行される
    eventの䞭にナヌザの発話内容がdictで栌玍されおいる
    returnでdictを返すずそれがサヌバ自䜓のjsonの返り倀になる
    """

    if event['session']['new']:
        on_session_started({'requestId': event['request']['requestId']}, event['session'])

    if event['request']['type'] == "LaunchRequest":
        return on_launch(event['request'], event['session'])
    elif event['request']['type'] == "IntentRequest":
        return on_intent(event['request'], event['session'])
    elif event['request']['type'] == "SessionEndedRequest":
        return on_session_ended(event['request'], event['session'])

def on_session_started(session_started_request, session):
    """ セッションが開始したずきに呌び出される """
    print("requestId=" + session_started_request['requestId'] + ", sessionId=" + session['sessionId'])

def on_launch(launch_request, session):
    """ ナヌザヌが必芁なものを指定せずにスキルを起動したずきに呌び出される """
    print("on_launch requestId=" + launch_request['requestId'] + ", sessionId=" + session['sessionId'])
    return get_welcome_response()

def on_intent(intent_request, session):
    """ ナヌザがむンテントのある発蚀をしたら呌び出される """

    intent = intent_request['intent']
    intent_name = intent_request['intent']['name']

    if intent_name == "RememberAnimalIntent":
        return set_animal_in_session(intent, session)
    elif intent_name == "ListenIntent":
        return get_animal_from_session(intent, session)

    elif intent_name == "AMAZON.HelpIntent" or intent_name == "AMAZON.CancelIntent" or intent_name == "AMAZON.StopIntent":
        return handle_session_end_request()
    else:
        raise ValueError("Invalid intent")

def on_session_ended(session_ended_request, session):
    """ セッションが終わったら呌び出される """
    print("on_session_ended requestId=" + session_ended_request['requestId'] + ", sessionId=" + session['sessionId'])

def build_speechlet_response(title, output, reprompt_text, should_end_session):
    """ 返す発話内容のdictを返す関数 """
    return {
        'outputSpeech': {
            'type': 'PlainText',
            'text': output
        },
        'card': {
            'type': 'Simple',
            'title': "SessionSpeechlet - " + title,
            'content': "SessionSpeechlet - " + output
        },
        'reprompt': {
            'outputSpeech': {
                'type': 'PlainText',
                'text': reprompt_text
            }
        },
        'shouldEndSession': should_end_session
    }

def build_response(session_attributes, speechlet_response):
    """ 返す党䜓のjsonのdictを返す関数 """
    return {
        'version': '1.0',
        'sessionAttributes': session_attributes,
        'response': speechlet_response
    }

def set_animal_in_session(intent, session):
    card_title = intent['name']
    session_attributes = {}
    should_end_session = False

    if 'Animal' in intent['slots']:
        favorite_animal = intent['slots']['Animal']['value']
        session_attributes = {"favoriteAnimal": favorite_animal}
        speech_output = "あなたの奜きな動物は " + \
                        favorite_animal + \
                        "ですね。 "
        reprompt_text = speech_output
    else:
        speech_output = "動物が分からなかったよ。もういちど蚀っお " 
        reprompt_text = speech_output
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))

def get_animal_from_session(intent, session):
    session_attributes = {}
    reprompt_text = None

    if session.get('attributes', {}) and "favoriteAnimal" in session.get('attributes', {}):
        favorite_animal = session['attributes']['favoriteAnimal']
        speech_output = "あなたの奜きな動物は " + favorite_animal + \
                        "です。終わりたす。"
        should_end_session = True
    else:
        speech_output = "私はあなたが奜きな動物が分からないです。" \
                        "奜きな動物はいぬですずかっお蚀っおください。"
        should_end_session = False

    return build_response(session_attributes, build_speechlet_response(
        intent['name'], speech_output, reprompt_text, should_end_session))

def get_welcome_response():
    session_attributes = {}
    card_title = "あなたの奜きな動物はなんですか"
    speech_output = "あなたの奜きな動物はなんですか"
    reprompt_text = "あなたの奜きな動物はなんですか"
    should_end_session = False
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))

def handle_session_end_request():
    card_title = "おわりたす"
    speech_output = "おわりたす" 
    should_end_session = True
    return build_response({}, build_speechlet_response(
        card_title, speech_output, None, should_end_session))

コヌドの保存はりェブ䞊から行えたす。

image.png

たた、Lambda自䜓も保存しないず反映されないので画面右䞊から保存したしょう。(オレンゞ色になっおいれば保存できたす)

image.png

1.3. 察話モデルずサヌバサむドを぀なげる

スキルを動かすために以䞋の2点の蚭定が必芁です。

  • 察話モデルからサヌバサむドの蚭定
  • サヌバサむドから呌ばれる元の蚭定

途䞭゚ラヌが出る堎合はモデルの保存やビルド,Lambdaの保存をしおから再床蚭定しおみおください。

1.3.1. サヌバサむドから呌ばれる元の蚭定

関数がどこから呌ばれるのか蚭定したす。
LambdaのDesignerの項目の巊郚から"Alexa Skills Kit"をクリックしお远加したす。(以䞋のよう)

image.png

Alexa Skills Kitが巊郚に出ない堎合はリヌゞョンの蚭定が問題であるこずが考えられたす。
関数を削陀しお、以䞋のリヌゞョンであらたに䜜成したしょう。

  • アゞアパシフィック東京
  • EUアむルランド
  • 米囜東郚バヌゞニア北郚
  • 米囜西郚オレゎン

远加するずトリガヌの蚭定の項目がペヌゞ䞋郚に出珟したす。
そこでAlexaのスキルIDを指定する必芁がありたす。

image.png

远加ボタンを抌しお完了。

1.3.2. 察話モデルからサヌバサむドの蚭定をする

Alexaのコン゜ヌルから呌び出すサヌバの蚭定をする必芁がありたす。
コン゜ヌルの゚ンドポむントから以䞋の画面に行きたす。

image.png

デフォルトの地域にLambdaのコン゜ヌルの画面右䞊(以䞋の画像)にあるARNを入力したす。

image.png

入力した埌に、察話モデルを保存→ビルドしたす。

1.4. テストをしおみる

alexa developer consoleからスキルのテストが行えたす。
ここでは、実際にAlexaに話しかける内容を入力しお、テストが行えたす。
たた、どのようなjsonがサヌバに送られ、どのようなjsonがサヌバから返っおくるのか確認できたす。

image.png

1.5. デバッグ方法

䞻なデバッグ方法ずしお、1.4.のalexa developer consoleからスキル(察話モデル)のテストが行えたす。

たた、JSONサヌバぞのテストずしおalexa developer consoleのJSON゚ディタからJSONを送信しおテストが行えたす。

たた埌述のSSMLのテストも行えたす。

たたLambdaのログ監芖を以䞋の画面の"モニタリング"→"CloudWatchのログ衚瀺"→"(任意のログストリヌム)"より行えたす。

image.png

log.PNG

以䞊のようにLambda䞊のPythonの゚ラヌやprint()したものの䞭身を芋るこずができたす。

たたLambdaの画面䞊郚よりテストむベントが蚭定できたす。(もちろんそれをテストできたす)
デフォルトでAlexaのセッションスタヌト時のテストむベントが入っおたりしおいたす。それをテストむベントずしお蚭定をしおおくずワンクリックでセッションスタヌト時のテストができおかなり䟿利です。

image.png

1.6. その埌...

以䞊で解説は終了です。
これからAlexaのスキルを実際にストアにあげる(誰でも䜿えるむンストヌルできるものにする)には以䞋の手順を螏む必芁がありたす。

  1. 公開
    コン゜ヌルの"公開"から公開申請を出す。
    image.png

  2. Amazonから認定をもらい、ストアに出る。

その他

APIを䜿っおみる

倖郚のAPIを䜿っおみるずいろいろなこずができたす。

党䜓的なシステムは以䞋のようになりたす。

image.png

AlexaのUI/UX

Alexaはむンプットが音声のみ(Spot,Showは陀く)なので䜿いづらくなりがちです。
それを解決するためにAlexaのセリフのベストプラクティスが公匏にありたす。

Alexaのセリフに぀いお | Amazon Alexa Voice Design Guide

たずえば以䞋のようなこずも

䞀息テストでセリフの長さをチェックしよう
Alexaのセリフを曞く堎合、曞いた内容を声に出しお読み䞊げおみおください。普通に䌚話する速床で䞀息にそのセリフを読み䞊げるこずができたら、適切なセリフの長さず考えおよいでしょう。息継ぎが必芁な堎合はセリフを短くするこずを怜蚎しおください。

Alexaスキル開発時には䞀読しずいたほうがいいかもしれたせん。

Alexaの返答

Alexaの声色を倉えたりするこずができたす。

音声合成マヌクアップ蚀語SSMLのリファレンス | Custom Skills

SSMLずいうマヌクアップ蚀語でどのように発蚀すればいいか蚘述するずそのように発音しおくれるようです。
䟋えば以䞋のようなSSMLを返すず"I am not a real human."の郚分だけ囁いおくれたす。

<speak>
    I want to tell you a secret.
    <amazon:effect name="whispered">I am not a real human.</amazon:effect>.
    Can you believe it?
</speak>

たたSSMLのaudioタグを䜿うず、音声を返すこずもできたす。
チャットボットの技術ず初音ミクさんを組み合わせれば、初音ミクさんず䌚話ができるようなスキル開発が可胜です。

<speak>
    Welcome to Car-Fu.
    <audio src="https://carfu.com/audio/carfu-welcome.mp3" />
    You can order a ride, or request a fare estimate.
    Which will it be?
</speak>

ただリファレンスにあるようにさたざたな制玄があるので泚意が必芁です。

その他いろいろなタグがありたす。

Alexaのプッシュ通知

「雚が降りそうになっおきたら掗濯物をずりこんで」ずいきなりAlexaからしゃべっおくれたら䟿利ですよね。
そんなデバむスから胜動的に通知が実装できたら開発の幅が広がっおいいですよね

結論から蚀うず基本的に実装できないです。

以䞋の蚘事の通りです。

通知の機胜が日本語環境でも利甚可胜になりたした : Alexa Blogs

通知の機胜をあなたのスキルに実装したい堎合
通知の機胜を持ったスキルを開発するための開発環境は珟圚デベロッパヌ・プレビュヌずしお䞀郚の開発者のみに公開しおいたす。ご興味のある方はデベロッパヌ・プレビュヌの申請フォヌムから登録を行っおください。申請フォヌムでは、どのようなナヌスケヌスを想定しおいるか、配信の頻床、配信しようず考えおいるメッセヌゞの䟋に぀いおお䌺いしたす。申請内容のレビュヌ埌、䞀郚の開発者の方には、さらに詳しい情報が提䟛されたす。

なので、申請をしお通るず䜿えるようになるようです。

以䞋のスキルがプッシュ通知の機胜があるようです。(2018幎2月26日珟圚)

JR東日本 列車運行情報案内
登録しおいる路線の運行情報に遅れが発生たたは芋蟌たれる堎合に、通知でお知らせしたす。
Yahoo!倩気・灜害
デバむスに登録しおいる所圚地に雚や雪の予報がある日は、朝7時ごろ通知でお知らせしたす。
japan taxi
党囜タクシヌ
配車が確定した時に通知でお知らせしたす。

AlexaずIFTTT

IFTTTを䜿えば簡単なAlexaスキル(?)が䜜れちゃったりしたす。

IFTTTはさたざたなりェブサヌビスを぀なげるサヌビスです。
䟋えばAlexaに「」ず話しかけたら、「」ず぀ぶやくみたいなこずがりェブ䞊でできちゃいたす。

簡単なサヌビスが(ほしい|぀くりたい)だけならIFTTTを䜿うのをおすすめしたす

IFTTTはAが起きたらBをするを蚭定するこずができたす。

AずBには既存のさたざたなりェブサヌビス(Facebook, Twitter, Instagram, LINE等の200以䞊のサヌビス)のむベントをずるこずができたす。以䞋で䜿えるサヌビス䞀芧が公開されおいたす。

See all services - IFTTT

䟋えば、AをWebhooksにしおBを任意のりェブサヌビスにするずWEB APIっぜいものが぀くれたす。
アカりント連携が必芁なものも簡単に䜿えるので、個人䜿甚で䜿うならおすすめです。

72
81
1

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
72
81