Save 37% off PRO during our Black Friday Sale! »

Alexa Hostedおさらい&Blueprintsでスキルリリースしてみた / Alexa Hosted & Blueprints review

Alexa Hostedおさらい&Blueprintsでスキルリリースしてみた / Alexa Hosted & Blueprints review

【大阪】スマートスピーカーミーティング 2019/02/28(https://osaka-driven-dev.connpass.com/event/117481/) のLTの資料です

5caee8d2ccdb42a940545c47c6c01373?s=128

Kuniaki Shimizu

February 28, 2019
Tweet

Transcript

  1. おさらい でスキル リリースしてみた

  2. アジェンダ • 自己紹介 • おさらい • おまけ) でスキルリリースしてみた

  3. 自己紹介

  4. @kun432 通信事業者系ISPのインフラエンジニア 最近はWiFIのシステム開発・運用全般 - Twitter/Facebook/Github/はてなブログ/Alexa - ポートフォリオ: https://kun432.github.io/ I ❤

  5. Alexa: 8 (JP:7, US:1) Google: 1 Clova: 1 今しがた一つリジェクトされました、、、 個までの道のりは長い、、、

  6. JAWS DAYS 2019に行ってきました。 - コンテナ人気すごい。でもAlexa関連も良かったです。 - Alexaハンズオン最高。資料はQiitaで公開されてます。オススメ。 →「Qiita: CodeStar+Twilio PayでAlexa経由の電話決済を実装する」

     (by 岡本さん) - パブリックスペースでの導入事例を作りたい - 導入事例(商店街・ホテル)の現地レポをブログ載せてます。 - Alexa居酒屋、池袋パルコ、名古屋松坂屋、行きたい、、、
  7. おさらい

  8. これまでの スキル開発 開発者コンソール 対話モデル設計 /エンドポイント 設定/公開申請 静的コンテンツ (画像/音声/動画) 永続データ等 アカウント

    アカウント バックエンド 実装 エラー時の 解析等 権限、ロー ルの管理
  9. これまでの スキル開発 開発者コンソール 対話モデル設計 /エンドポイント 設定/公開申請 静的コンテンツ (画像/音声/動画) 永続データ等 アカウント

    アカウント バックエンド 実装 エラー時の 解析等 権限、ロー ルの管理
  10. これまでの スキル開発 AmazonとAWSの両方のアカウントが必要。 Amazon.comのアカウント持っててハマる。 AmazonとAWSで画面行ったり来たり。 AWSのサービスごとに画面行ったり来たり。 AWSいろいろ知らなくていいことがたくさん出てくる。 - Lambdaでnpmパッケージ追加するならローカル環境必要。 -

    S3で静的ファイル扱うにはバケットのCORS設定が必要。 - S3、Alexaからはパブリックアクセス前提? - CloudWatch Logs見にくい。 - DynamoDB、RDBとは違う。 初心者にはやさしくない
  11. そこで

  12. スキルの作成、編集、公開がAlexa開発者コンソール で完結、ブラウザだけあればよい フロントエンド(対話モデル) バックエンド(Lambda相当) ファイルストレージ(S3相当) セッションストレージ(DynamoDB相当) ロギング(CloudWatch Logs相当) AWSアカウント不要、AmazonアカウントだけでOK 権限管理とかない(IAM)

    シンプル!
  13. 開発者 コンソール 相当 相当 相当 Amazon.co.jp アカウント

  14. None
  15. ※カスタムスキルのみ ※ 分程度で作成される

  16. None
  17. None
  18. 必ず忘れないで実施!

  19. これだけ

  20. 超簡単

  21. さぁ、コードを 書こう!

  22. その前に・・・

  23. 特有の やり方や制限がある

  24. 今日の本題

  25. おさらい 自分向けまとめ

  26. 自分向けまとめ • スキル開発に慣れてくるといろいろやりたくなる。 ◦ 静的ファイル、セッション、 、などなど ◦ ここが最初のハードル • いろいろ調べるけど、情報が多すぎる。

    ◦ リソース使う前提のものが多い ◦ でそれできるんだっけ? • 楽したい ◦ 使う場合に特化した情報がほしい ◦ コード頻繁に書かないので、コピペで済ませたい • とはいうものの、 ◦ まあ一応 も知って起きたいよね。 ◦ 違いを把握しておけばよい 完全にLGTMなまとめです!
  27. 画像、動画、音声、等 静的ファイル使いたい

  28. 静的ファイル(これまで) S3でホストが一般的 リージョン選択可能、東京リージョンが一般的 バケットにCORS設定必要 オブジェクトにパブリックアクセス権を付与 コードからは画像、音声、動画それぞれのやり方で呼び出す const imageUrl = 'https://s3-ap-northeast-1.amazonaws.com/xxxxxx/sample.png';

    const myImage = new Alexa.ImageHelper() .addImageInstance(imageUrl) .getImage(); const url = 'https://s3-ap-northeast-1.amazonaws.com/xxxxxx/sample.mp4'; return handlerInput.responseBuilder .speak(speechText) .addVideoAppLaunchDirective(url, 'title', 'subtitle') .getResponse();
  29. 静的ファイル( ) Alexa Hosted専用のS3でホスト。スキルごとにバケットが用意される。 リージョンは米国東部(バージニア北部)のみ。 → レイテンシー注意 設定変更一切不可(アクセス権付与、バージョニング、暗号化)。 → 逆に言うと何も気にせずアップロードだけで良い

    コードからは署名付きURLで呼び出す必要があり。 → 有効時間60秒固定、変更不可。問題になるケースがあるかも? const Util = require('util.js'); ... handle(handlerInput){ const pictureUrl = Util.getS3PreSignedUrl("Media/picture.jpg"); return handlerInput.responseBuilder .speak('画像付きのハローワールドです ') .withStandardCard('card title', 'card text', pictureUrl) .getResponse(); }
  30. 静的ファイル( ) const AWS = require('aws-sdk'); const s3SigV4Client = new

    AWS.S3({ signatureVersion: 'v4' }); module.exports.getS3PreSignedUrl = function getS3PreSignedUrl(s3ObjectKey) { const bucketName = process.env.S3_PERSISTENCE_BUCKET; const s3PreSignedUrl = s3SigV4Client.getSignedUrl('getObject', { Bucket: bucketName, Key: s3ObjectKey, Expires: 60*1 // the Expires is capped for 1 minute }); console.log(`Util.s3PreSignedUrl: ${s3ObjectKey} URL ${s3PreSignedUrl}`); return s3PreSignedUrl; }
  31. 静的ファイル( ) const AWS = require('aws-sdk'); const s3SigV4Client = new

    AWS.S3({ signatureVersion: 'v4' }); module.exports.getS3PreSignedUrl = function getS3PreSignedUrl(s3ObjectKey) { const bucketName = process.env.S3_PERSISTENCE_BUCKET; const s3PreSignedUrl = s3SigV4Client.getSignedUrl('getObject', { Bucket: bucketName, Key: s3ObjectKey, Expires: 60*1 // the Expires is capped for 1 minute }); console.log(`Util.s3PreSignedUrl: ${s3ObjectKey} URL ${s3PreSignedUrl}`); return s3PreSignedUrl; } ・util.jsでaws-sdkを使っている ・よいところ   - 環境変数からS3のバケット名を とってきている - Github等でコードを公開する場合、 このほうが都合が良い - 普通にLambda使う場合でもこのほう がいいんでは?
  32. 静的ファイル( )

  33. 静的ファイル( )

  34. 静的ファイル( )

  35. 静的ファイル( )

  36. セッション使いたい

  37. セッション(これまで) 3種類 Request attributes (1回のリクエスト中) Session attributes (1回のセッション中) Persistent attributes

    (セッション跨ぎ) Persistent attributes DynamoDBが一般的(S3でもできなくはない) LambdaのIAMロールにDynamoDBアクセス権付与 DynamoDBPersistentAdapterを使う SkillBuilders内でテーブル名を指定 テーブル自動作成も可(要権限) 読み書きする
  38. セッション(これまで) const Alexa = require('ask-sdk'); ・・・ exports.handler = Alexa.SkillBuilders.standard() .addRequestHandlers(

    ・・・ .withTableName("sampleTableName") .withAutoCreateTable(true) .lambda(); const Alexa = require('ask-sdk-core'); const Adapter = require('ask-sdk-dynamodb-persistence-adapter'); exports.handler = Alexa.SkillBuilders.custom() .addRequestHandlers( ・・・ .withPersistenceAdapter( new Adapter.DynamoDbPersistenceAdapter( {tableName: 'sampleTableName', createTable: true })) .lambda(); (全部入り) を使う場合 (ミニマム) を使う場合
  39. セッション(これまで) async handle(handlerInput) { ・・・ const attr = await handlerInput.attributesManager.getPersistentAttributes();

    const info = attr.info; ・・・ } async handle(handlerInput) { ・・・ const attr = await handlerInput.attributesManager.getPersistentAttributes(); attr.info = "foo"; handlerInput.attributesManager.setPersistentAttributes(attr); await handlerInput.attributesManager.savePersistentAttributes(); ・・・ } 読み 書き
  40. セッション( ) • Persistent attributes ◦ DynamoDBは使えない、S3のみ ◦ S3-persistence-adapterを使う ▪

    パッケージ追加必須 ▪ バケット名を指定する必要がない ▪ バケット内にユーザIDごとのファイルが作成 される
  41. セッション( ) 必ず実施! npmパッケージを使いたい場合も同じです。

  42. セッション( ) const Alexa = require('ask-sdk-core'); const persistenceAdapter = require('ask-sdk-s3-persistence-adapter');

    ・・・ exports.handler = Alexa.SkillBuilders.custom() .addRequestHandlers( ・・・ .withPersistenceAdapter( new persistenceAdapter.S3PersistenceAdapter( {bucketName:process.env.S3_PERSISTENCE_BUCKET})) .lambda(); .lambda(); 読み書きは 使う場合と同じ
  43. セッション( ) const Alexa = require('ask-sdk-core'); const persistenceAdapter = require('ask-sdk-s3-persistence-adapter');

    ・・・ exports.handler = Alexa.SkillBuilders.custom() .addRequestHandlers( ・・・ .withPersistenceAdapter( new persistenceAdapter.S3PersistenceAdapter( {bucketName:process.env.S3_PERSISTENCE_BUCKET})) .lambda(); .lambda(); 読み書きは 使う場合と同じ ・util.jsを思い出してほしい ・環境変数からS3のバケット名を とってきている
  44. セッション( )

  45. セッション( )

  46. セッション( ) “amzn1.ask.account.〜”というファイルが作成される ユーザID単位であることがわかる 中身を見たい場合はチェックしてダウンロード、テキストエディタ等 で見る(ブラウザからは見れない)

  47. セッション( ) exports.handler = Alexa.SkillBuilders.custom() .addRequestHandlers( ・・・ .withPersistenceAdapter( .withPersistenceAdapter( new

    persistenceAdapter.S3PersistenceAdapter( {bucketName:process.env.S3_PERSISTENCE_BUCKET, objectKeyGenerator: deviceIdKeyGenerator})) .lambda(); function deviceIdKeyGenerator(requestEnvelope) { if (requestEnvelope && requestEnvelope.context && requestEnvelope.context.System && requestEnvelope.context.System.device && requestEnvelope.context.System.device.deviceId) { return requestEnvelope.context.System.device.deviceId; } throw 'Cannot retrieve device id from request envelope!'; } デバイスごとにセッションを保存したい場合
  48. セッション( ) exports.handler = Alexa.SkillBuilders.custom() .addRequestHandlers( ・・・ .withPersistenceAdapter( .withPersistenceAdapter( new

    persistenceAdapter.S3PersistenceAdapter( {bucketName:process.env.S3_PERSISTENCE_BUCKET, objectKeyGenerator: deviceIdKeyGenerator})) .lambda(); function deviceIdKeyGenerator(requestEnvelope) { if (requestEnvelope && requestEnvelope.context && requestEnvelope.context.System && requestEnvelope.context.System.device && requestEnvelope.context.System.device.deviceId) { return requestEnvelope.context.System.device.deviceId; } throw 'Cannot retrieve device id from request envelope!'; } デバイスごとにセッションを保存したい場合 objectKeyGeneratorにIDを生成する 関数を指定する デバイスIDの場合
  49. セッション( ) “amzn1.ask.device.〜”というファイルが作成される デバイスID単位であることがわかる

  50. セッション( ) • Persistent attributes ◦ DynamoDBは使えない、S3のみ → 結果整合性には注意かも ◦

    S3-persistence-adapterを使う ▪ パッケージ追加必須 ▪ バケット名を指定する必要がない → 環境変数も勝手に設定されるので便利 → コード内に書く必要がなくて便利 ▪ バケット内にユーザIDごとのファイルが作成 される → デバイスIDも可能、いろいろできる 再掲 DynamoDB高いので普通に Lambda 使う場合でもS3でやればいいという声 もあり
  51. デバッグしたい

  52. デバッグ( )

  53. デバッグ( ) ここはそんなに変わらない。ロググループ探さなくてよいのは楽。

  54. デバッグ( )※余談 ロググループの中を見ると、 codebuild のログが出てて、 AWSリソースがいろ いろいじられるさまが見えて面白い

  55. 無料枠について

  56. 無料枠( ) アカウントごとに適用 → スキル単位ではない → たくさんスキルを作る場合は注意! 超えた場合は1ヶ月の猶予期間内にAWSに要移行 → 事前に通知が来るらしい

    → エンドポイント変更が必要になるはず?再審査? 詳細は公式サイトを参照
  57. 無料枠( ) AWS Lambda - スキルの利用頻度 (時間&回数) リクエスト100万件/月 コンピューティング時間 320万秒/月

    AWS CodeCommit - コードのサイズと更新頻度 ストレージ 50 GB Gitリクエスト 10,000件/月 ほとんど問題ないと思うけど、音声・動画ファイルを使う場合と永続 セッションを使う場合は気をつけたほうが良いかも。 Amazon S3 - スキル内からのファイル の利用頻度 ストレージ容量 5GB GETリクエスト 20,000件/月 PUTリクエスト 2,000件/月 データ転送量 15 GB/月
  58. まとめ

  59. まとめ AWSアカウント不要、開発者コンソールで完結する のでとても楽ちん ブラウザだけあればOK、ローカル環境構築不要 ハンズオンとかで良さげ 基本的なことはAlexa Hostedでも全部できる ハンズオンとかで良さげ ハンズオンとかで良さげ 個人レベル・小規模な開発なら問題なし

    それ以外はAWSで。
  60. スキルを作って どんどん公開しよう!

  61. None
  62. None
  63. Any questions?

  64. おまけ) でスキルリリースしてみた

  65. None
  66. • 予め用意されたテンプレートから、必要な値だけを変更 して、スキルを作成する。 • テンプレートいろいろ ◦ クイズ ◦ ◦ トリビア

    ◦ フラッシュブリーフィング ◦ などなど、現在 種類以上 • 現時点( 年 月末) オンリー ◦ アカウントでしか作れない ◦ スキルしかリリースできない
  67. None
  68. • 超かんたん! ◦ テンプレベースだからバグることがない ◦ 本当の意味でスキルの中身に集中できる ◦ テンプレの種類が豊富、ありがちなものはほぼカバー ▪ よくある案内スキルとかならすぐできる

    ◦ 審査リジェクトの可能性は低い • デメリット ◦ 日本ではまだ使えない(そのうち使えるようになるはず) ◦ 多言語もできない ◦ 凝ったことはできない ◦ 統計情報へのアクセスができない • その他 ◦ テンプレを作って公開できるといいな
  69. None
  70. ※楽しかったので  超オススメ!

  71. 導入事例レポ

  72. 導入事例レポ

  73. None