Open7
PythonでAlexaスキルを開発する
Goal
Alexa公式のチュートリアルスキルをベースとして、以下のような要素を追加したAlexaスキルを開発する。
- pipenvでPython仮想環境を構築する
- Github ActionsでAWS LambdaのCI/CD環境を構築する
- Alexaのタイマー機能を利用する
スキル開発の公式チュートリアル
- ここに記載されている手順をベースにして、Alexaスキルの雛形を実装する
- 「オプション2:デコレーターを利用した実装」で実装する
pipenvでPython仮想環境を構築
pipenv
$ export PIPENV_VENV_IN_PROJECT=1
$ pipenv install --dev flake8 black isort mypy
$ pipenv install ask-sdk
-
PIPENV_VENV_IN_PROJECT=1
を設定することで、プロジェクトルートに.venv
フォルダを作成する- あとでlambda用のzipファイルを作成するときのための設定
- Pythonのバージョンは明示的に3.9に設定した方がベターかも
リンター・フォーマッター
リンター・フォーマッターの設定はこちらを参照。
AWS Lambdaのデプロイパッケージ作成
AWS公式のチュートリアルでは、lambdaデプロイ用のzipファイル作成の具体的な方法は記載されていない。
こちらの記事の内容を参考にして、手動でデプロイパッケージを作成。
zipファイルを手動でlambdaにアップロードする場合は、以下のコマンドを実行。
$ aws lambda update-function-code --function-name {YOUR FUNCTION NAME} --zip-file fileb://lambda.zip --publish
-
--publish
でlambdaのバージョニングを行う
AWS CLIの設定について
AWSのクレデンシャル情報は、こちらのページの方法に基づいて管理する。
Github ActionsでAWS Lambdaへのアップロードを自動化
このサイトの手順を参考にして実装。
ただし、「IAMロールの登録」の箇所で、「信頼されたエンティティのサンプル」を以下のように書き換える必要があった。- "vstoken.actions.githubusercontent.com:sub": "repo:{GITHUB_ORGANIZATION_NAME}/{GITHUB_REPO_NAME}:*"
+ "token.actions.githubusercontent.com:sub": "repo:{GITHUB_ORGANIZATION_NAME}/{GITHUB_REPO_NAME}:*"
-
vstoken
をtoken
に変更
zipファイルの作成も自動化
上記ページの手順に加え、zipファイルの作成部分も自動化する。以下はdeploy.ymlの一部抜粋。
- name: install pipenv, awscli
run: |
pip3 install pipenv
pip3 install awscli
- name: run pipenv sync
run: |
export PIPENV_VENV_IN_PROJECT=1
pipenv sync
- name: make lambda.zip
run: |
PROJECT_DIR=$(pwd)
SITE_PACKAGES_DIR=$(pipenv --venv)/lib/python3.9/site-packages
echo "Project Location: $PROJECT_DIR"
echo "Library Location: $SITE_PACKAGES_DIR"
cd $SITE_PACKAGES_DIR
rm -rf __pycache__
zip -r $PROJECT_DIR/lambda.zip *
cd $PROJECT_DIR/src
zip -g ../lambda.zip lambda_function.py
cd $PROJECT_DIR
- name: lambda update (DEV)
if: contains(toJSON(github.ref), 'dev')
run: |
aws lambda update-function-code --function-name lambda-alexa-curry-udon-timer --zip-file fileb://lambda.zip
- name: lambda update (STG)
if: contains(toJSON(github.ref), 'main')
run: |
aws lambda update-function-code --function-name lambda-alexa-curry-udon-timer --zip-file fileb://lambda.zip --publish
-
pipenv sync
でローカル環境と同じ環境を構築する。 - pushするブランチでlambdaへのアップロード処理を分岐する。mainブランチへのpushの場合は、
--publish
を付与してバージョン管理を行うようにしてみた。(後述)
AWS Lambdaのバージョン管理
こちらのページの方法を参考に、バージョン管理とエイリアス設定を実施する。
- 本番Alexaスキル:エンドポイントARNはエイリアス設定した修飾ARNを指定し、利用するlambdaのバージョンを固定
- 検証Alexaスキル:エンドポイントARNは非修飾ARN(
$latest
)を指定し、devブランチにプッシュした最新のlambdaを利用
https://zenn.dev/amarelo_n24/articles/158a166d832487
Alexaスキルにタイマーを追加する
実装方法はこちらを参照した。
上記のサンプルはNode.jsで実装されている。Pythonで書き換えた実装は以下の通り。
タイマーの実装サンプル
@sb.request_handler(can_handle_func=is_request_type("LaunchRequest"))
def launch_request_handler(handler_input: HandlerInput) -> Response:
request_envelope = handler_input.request_envelope
service_client_factory = handler_input.service_client_factory
permissions = request_envelope.context.system.user.permissions
if not (permissions and permissions.consent_token):
# パーミッションがない場合の処理
pass
else:
# タイマーをセットする
timer1 = {
"duration": "PT3M",
"timerLabel": "タイマー1",
"creationBehavior": {"displayExperience": {"visibility": "VISIBLE"}},
"triggeringBehavior": {
"operation": {
"type": "ANNOUNCE",
"textToAnnounce": [
{"locale": "ja-JP", "text": "タイマー終了時の発話"}
],
},
"notificationConfig": {"playAudible": True},
},
}
try:
timer_service_client = service_client_factory.get_timer_management_service()
timer_response = timer_service_client.create_timer(timer1)
except Exception as e:
logger.error("タイマー作成エラー", e)
speech_text = "スピーチテキスト"
return (
handler_input.response_builder.speak(speech_text)
.set_card(SimpleCard("カードのタイトル", speech_text))
.set_should_end_session(False)
.response
)
StandardSkillBuilder
get_timer_management_service()
を実行するために、チュートリアルに記載されているSkillBuilder
をStandardSkillBuilder
に変更する必要がある。
from ask_sdk.standard import StandardSkillBuilder
sb = StandardSkillBuilder()