カスタムスキルをウェブサービスとしてホスティングする
クラウド内のAlexaサービスからリクエストを受け付けて応答を返すウェブサービスを実装することにより、Alexa用のカスタムスキルを開発できます。
Alexaから送信されたリクエストを処理するには、ウェブサービスで特定の要件を満たす必要があり、またAlexa Skills Kitインターフェース規格に準拠する必要があります。詳細については、Alexa Skills Kit技術資料のカスタムスキルをウェブサービスとしてホスティングするを参照してください。
ASD SDKウェブサービスサポート
Alexa Skills Kit SDK(ASK SDK)for Pythonでは、リクエストとタイムスタンプの検証用のボイラープレートコードがask-sdk-webservice-supportパッケージで提供されます。これはスキルビルダーオブジェクトと統合されています。このパッケージでは検証コンポーネントと、スキルを呼び出すためのベースハンドラーのみが提供され、ウェブアプリケーション開発の基本フレームワークからは独立しています。
インストール
pipを使用してask-sdk-webservice-support
パッケージをインストールします。
cryptography
パッケージには、オペレーティングシステムに応じて追加条件がある場合があります。詳細については、cryptography
のドキュメントのインストール手順を参照してください。ウェブサービスジェネリックハンドラー
WebserviceSkillHandler
クラスではSkillBuilder
オブジェクトからスキルインスタンスを登録し、verify_request_and_dispatch
メソッドを提供します。このメソッドは、スキルハンドラーを呼び出す前に入力リクエストを検証します。
WebserviceSkillHandler
インスタンスのブール値パラメーターverify_signature
およびverify_timestamp
を設定し、テスト目的として、リクエストまたはタイムスタンプの検証を有効または無効にできます。また、スキルを呼び出す前に入力リクエストに適用する必要がある、追加のカスタムベリファイア(verifier)も提供されます。
verify_request_and_dispatch
メソッドによりウェブサービスからhttp_headers
とhttp_body
が取り出され、スキルの呼び出しに成功すると、文字列形式でresponse
が返されます。入力と出力をウェブサービス固有のリクエスト/応答の構造に変換する必要があります。
使い方
from ask_sdk_core.skill_builder import SkillBuilder
from ask_sdk_webservice_support.webservice_handler import WebserviceSkillHandler
skill_builder = SkillBuilder()
# リクエストハンドラー、例外ハンドラーなどを実装します。
# ハンドラーをスキルビルダーインスタンスに登録します。
webservice_handler = WebserviceSkillHandler(
skill=skill_builder.create())
# HTTPリクエストヘッダーと本文をそれぞれネイティブ形式の
# dictとstrに変換し、dispatchメソッドを呼び出します。
response = webservice_handler.verify_request_and_dispatch(
headers, body)
# 応答strをウェブサービスの形式に変換して返します。
フレームワーク固有のアダプター
Pythonには、FlaskとDjangoという2つのウェブサービスフレームワークがあり、ウェブサービスを開発するときによく活用されています。ASK SDKでは、フレームワーク別にask-sdk-webservice-support
パッケージの拡張機能が提供され、FlaskとDjangoの両方に対応しています。これにより、リクエスト/応答の変換処理が内部で行われます。さらに、既に開発しているSDKスキルを簡単に統合して、ウェブサービスで動作させることができます。
flask-ask-sdk拡張パッケージ
flask-ask-sdk
パッケージは、Flaskの拡張機能を提供します。これにより、カスタムスキルと一緒にFlask
アプリケーションを登録できます。ヘルパーメソッドも提供され、スキルの呼び出しを、URLエンドポイントとしてFlaskアプリケーションに登録できます。
flask-ask-sdk
パッケージはFlask拡張機能の構造に準拠しています。SkillAdapter
クラスのコンストラクターで、以下を取り出します。
- スキルインスタンス。
- スキルID(拡張ディレクトリにスキルインスタンスを登録する)。
- Flaskアプリケーション(オプション。アプリケーションに拡張機能を登録する)。
また、init_app
メソッドも提供され、後でFlaskアプリインスタンスに渡され、拡張機能のインスタンスを作成し設定します。
リクエストとタイムスタンプの検証はデフォルトで有効になっています。アプリコンフィギュレーションVERIFY_SIGNATURE_APP_CONFIG
とVERIFY_TIMESTAMP_APP_CONFIG
を使用して、それぞれのブール値を設定し、検証の有効/無効を設定できます。
SkillAdapterのdispatch_request
メソッドを使用して、スキルをエンドポイントURLルールとして登録できます。リクエスト/応答の変換処理、リクエストとタイムスタンプの検証、スキルの呼び出しを処理します。
インストール
pipを使用してflask-ask-sdk
パッケージをインストールできます。
cryptography
パッケージには、オペレーティングシステムに応じて追加条件がある場合があります。詳細については、cryptography
のドキュメントのインストール手順を参照してください。使い方
from flask import Flask
from ask_sdk_core.skill_builder import SkillBuilder
from flask_ask_sdk.skill_adapter import SkillAdapter
app = Flask(__name__)
skill_builder = SkillBuilder()
# インテントハンドラーをskill_builderオブジェクトに登録します。
skill_adapter = SkillAdapter(
skill=skill_builder.create(), skill_id=<SKILL_ID>, app=app)
@app.route("/"):
def invoke_skill:
return skill_adapter.dispatch_request()
ASK_SDK_SKILL_ADAPTER
キーを使用して、拡張機能のインスタンスがアプリケーション拡張機能マッピングに追加されます。同じアプリケーション内の異なるルートに複数のスキルのコンフィギュレーションが行われるので、複数の拡張機能インスタンスを介して、それぞれの拡張機能がスキルIDマッピングとして、アプリ拡張機能のASK_SDK_SKILL_ADAPTER
ディクショナリに追加されます。django-ask-sdk拡張パッケージ
django-ask-sdk
拡張パッケージにより、Djangoの拡張機能が提供され、エンドポイントとして、カスタムスキルをDjangoアプリケーションに登録できます。
拡張機能ではSkillAdapter
ビュークラスが提供されます。カスタムスキルインスタンスでビュークラスをインスタンス化し、ASK SDK Skill Builderオブジェクトでビルドし、Djangoアプリのurls.py
ファイルに登録します。これにより、対応するエンドポイントでスキルが呼び出されます。
リクエストとタイムスタンプの検証はデフォルトで有効になっています。コンストラクター引数verify_request
およびverify_timestamp
を使用して、それぞれのブール値を設定することで、各検証を有効または無効にできます。
インストール
pipを使用してdjango-ask-sdk
拡張機能をインストールできます。
cryptography
パッケージには、オペレーティングシステムに応じて追加条件がある場合があります。詳細については、cryptography
のドキュメントのインストール手順を参照してください。django-ask-sdk
パッケージは、Python3.0以降と互換性があります。使い方
SkillBuilder
インスタンスを使用してスキルを開発する場合は、example.urls.py
で以下を使用すると、example
というDjangoアプリで、エンドポイントとしてスキルを登録できます。
import skill
from django_ask_sdk.skill_adapter import SkillAdapter
view = SkillAdapter.as_view(skill=skill.sb.create())
urlpatterns = [
path("/myskill", view, name='index')
]