はじめに
Alexa道場で勉強を進め、基本的なスキルを作成する方法を学んだため、一度オリジナルスキルを作って復習&知識の定着を図ってみることにした。
結論、2時間じゃ無理だったので、続きはまた今度やる。
やってみたこと
計画を立ててみた
- 何作るべきか考える(30分)
- 自分が何欲しいか考えてみる(5分)
- 自分以外に欲しい人がいそうか考えてみる(5分)
- 似たようなモノで、市場で必要とされているものを調べてみる(10分)
- 自分が作る方向性を決める(10分)
- モックを作る
- 設計する(30分)
- 実装する(60分)
21:00 – 21:30 アイディア出しをしてみた
自分たちが欲しい物を色々と考えてみる。思いついたのは以下。
- バーチャル面接官(加藤)
→志望動機はなんですか?とか聞いてくる
→しゃべったことをテキスト化して、あとで回答が見れる
→何秒間堪えられなかったか記録
→何秒空白があったか記録(くま)/(けん)
21:30 – 21:40 似たようなモノで、市場で必要とされているものを調べてみる
- Googleで検索してみた
- Amazon.co.jp: 圧迫面接 : Alexaスキル https://www.amazon.co.jp/Ga9-%E5%9C%A7%E8%BF%AB%E9%9D%A2%E6%8E%A5/dp/B07BQHXLJF
- ベリーグッドは「Amazon Alexa」に対応する面接練習用の「面接シミュレーション」をリリース。 | 株式会社ベリーグッド https://www.verygoodinc.biz/archives/293
→今は存在しない?
- その他、スキルストアで検索してみた。結果は次の通り
スキルストアには面接系のAlexaアプリはあまりなさそうだった。
なので、「圧迫面接」じゃない方向性で面接対策スキルを作るとよさそう、という話になった。
21:37 – 22:12 方向性の話し合いをしてみる
誰に向けて作るか話し合ってみた。結果は以下。
- for ユーザ
→バイトの面接を控えている学生や、転職活動したい社会人の練習台になる - for 自分たち
→Alexaの勉強になる
→(儲からなくてもいい)
どんな質問がされるといいか調べながら話し合ってみた。結果は以下の記事にあるような方向性
- 面接対策まとめ|よくある質問の回答例、準備~面接後のやりとり・流れ|マイナビ転職 https://tenshoku.mynavi.jp/knowhow/mensetsu
→「面接でよくある質問の回答50例」の内容をAlexaに仕込んで見る
→とりあえず「自己紹介」と「志望理由」
22:12 – 22:45 設計
ユーザにどうなってもらうかを考えてみた。結果は以下。
- 想定ユーザ:けんとくんみたいなアルバイトの面接控えている、ガジェット好きな学生
- ユーザの動き:
・(そもそもAlexaで面接したい、って思わせる何か)
→Alexaで面接できるという認知をさせる?
・ユーザが面接の練習をAlexaでできないかな?と思う
・ユーザがAlexaストアで「面接」で検索する
→Alexaストアに登録する必要あり
・ユーザがスキルの説明を見て、使いたいと思う
→説明ちゃんと入れる必要あり
・ユーザがAlexaスキルをインストールする
・ユーザがAlexaでウェイクワードを発する
・Alexaが、ユーザは何をすればいいかを説明する
→「これから面接練習をします。質問に回答してください。よろしいですか?」
・ユーザが「はい」と答える
・Alexaが最初の質問をする
・ユーザが最初の質問に答える
・Alexaが次の質問をする
・ユーザが次の質問に答える
〜ループ〜
・Alexaが最後の質問をする
・ユーザが最後の質問に答える
・Alexaが、すべての質問に回答し終わったことを伝える
・Alexaが、どこかで回答内容が確認できるようにする
→例えば、テキスト化して、どこかに置いておく
・Alexaが、回答内容の確認方法をユーザに伝える
どんな実装作業が必要か考えてみた。結果は以下。
- じゃあどんな機能とかが必要か
- ウェイクワードを設定する
- スキル名、アイコン、とか・・
- インテントを作る
- 「初めて」インテント
- コードエディタで編集する
- 起動時に最初に呼ばれるリクエストハンドラを作る
- ユーザは何をすればいいかを説明「これから面接練習をします。質問に回答してください。よろしいですか?」
- 質問リクエストハンドラを作る
- 質問を順番に行う
- 回答内容を記録する
- 最後の質問が終わったら、説明をする
- どこかで回答内容が確認できるようにする
- 起動時に最初に呼ばれるリクエストハンドラを作る
- ウェイクワードを設定する
22:45 – 23:00 作り始めてみた
Developer Consoleで新しいスキルを作成
- Alexa-hosted(Node.js)
- スクラッチ
スキルの呼び出し名を設定
インテントを作成
- StartIntentというインテントを作る
リクエストハンドラなどをコードエディタで実装(途中まで)
初めに呼ばれるリクエストハンドラと、StartIntentのハンドラを実装。
こんな感じ
/* * * This sample demonstrates handling intents from an Alexa skill using the Alexa Skills Kit SDK (v2). * Please visit https://alexa.design/cookbook for additional examples on implementing slots, dialog management, * session persistence, api calls, and more. * */ const Alexa = require('ask-sdk-core'); const LaunchRequestHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest'; }, handle(handlerInput) { const speakOutput = 'これから面接練習をします。質問に回答してください。よろしいですか?'; return handlerInput.responseBuilder .speak(speakOutput) .reprompt(speakOutput) .getResponse(); } }; const StartIntentHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && Alexa.getIntentName(handlerInput.requestEnvelope) === 'StartIntent'; }, handle(handlerInput) { // 流れ // 1回目の場合(引数が空の場合): // 質問をする // 回答をテキストで、どこかに記録する // StartIntentHandlerをまた呼び出す() // 2回目の場合(引数が空でない場合): // 質問をする // 回答をテキストで、どこかに記録する // 最後の質問だったかどうかを判別する // 最後の質問だった場合 // 最後の処理をする // 最後の質問じゃなかった場合 // StartIntentHandlerをまた呼び出す(次の質問を引数に入れる) const speakOutput = 'スタート'; return handlerInput.responseBuilder .speak(speakOutput) //.reprompt('add a reprompt if you want to keep the session open for the user to respond') .getResponse(); } }; const HelloWorldIntentHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && Alexa.getIntentName(handlerInput.requestEnvelope) === 'HelloWorldIntent'; }, handle(handlerInput) { const speakOutput = 'Hello World!'; return handlerInput.responseBuilder .speak(speakOutput) //.reprompt('add a reprompt if you want to keep the session open for the user to respond') .getResponse(); } }; const HelpIntentHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.HelpIntent'; }, handle(handlerInput) { const speakOutput = 'You can say hello to me! How can I help?'; return handlerInput.responseBuilder .speak(speakOutput) .reprompt(speakOutput) .getResponse(); } }; const CancelAndStopIntentHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && (Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.CancelIntent' || Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.StopIntent'); }, handle(handlerInput) { const speakOutput = 'Goodbye!'; return handlerInput.responseBuilder .speak(speakOutput) .getResponse(); } }; /* * * FallbackIntent triggers when a customer says something that doesn’t map to any intents in your skill * It must also be defined in the language model (if the locale supports it) * This handler can be safely added but will be ingnored in locales that do not support it yet * */ const FallbackIntentHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.FallbackIntent'; }, handle(handlerInput) { const speakOutput = 'Sorry, I don\'t know about that. Please try again.'; return handlerInput.responseBuilder .speak(speakOutput) .reprompt(speakOutput) .getResponse(); } }; /* * * SessionEndedRequest notifies that a session was ended. This handler will be triggered when a currently open * session is closed for one of the following reasons: 1) The user says "exit" or "quit". 2) The user does not * respond or says something that does not match an intent defined in your voice model. 3) An error occurs * */ const SessionEndedRequestHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'SessionEndedRequest'; }, handle(handlerInput) { console.log(`~~~~ Session ended: ${JSON.stringify(handlerInput.requestEnvelope)}`); // Any cleanup logic goes here. return handlerInput.responseBuilder.getResponse(); // notice we send an empty response } }; /* * * The intent reflector is used for interaction model testing and debugging. * It will simply repeat the intent the user said. You can create custom handlers for your intents * by defining them above, then also adding them to the request handler chain below * */ const IntentReflectorHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'; }, handle(handlerInput) { const intentName = Alexa.getIntentName(handlerInput.requestEnvelope); const speakOutput = `You just triggered ${intentName}`; return handlerInput.responseBuilder .speak(speakOutput) //.reprompt('add a reprompt if you want to keep the session open for the user to respond') .getResponse(); } }; /** * Generic error handling to capture any syntax or routing errors. If you receive an error * stating the request handler chain is not found, you have not implemented a handler for * the intent being invoked or included it in the skill builder below * */ const ErrorHandler = { canHandle() { return true; }, handle(handlerInput, error) { const speakOutput = 'Sorry, I had trouble doing what you asked. Please try again.'; console.log(`~~~~ Error handled: ${JSON.stringify(error)}`); return handlerInput.responseBuilder .speak(speakOutput) .reprompt(speakOutput) .getResponse(); } }; /** * This handler acts as the entry point for your skill, routing all request and response * payloads to the handlers above. Make sure any new handlers or interceptors you've * defined are included below. The order matters - they're processed top to bottom * */ exports.handler = Alexa.SkillBuilders.custom() .addRequestHandlers( LaunchRequestHandler, StartIntentHandler, HelloWorldIntentHandler, HelpIntentHandler, CancelAndStopIntentHandler, FallbackIntentHandler, SessionEndedRequestHandler, IntentReflectorHandler) .addErrorHandlers( ErrorHandler) .withCustomUserAgent('sample/hello-world/v1.2') .lambda();
動かしてみる
テストしてみる。モックがとりあえず動いた。
最後に
方向性は決まったものの、スキルとして必要最低限の機能はまだまだ足りない。
とりあえず、次は固定の質問をして、回答内容をテキスト化して、どこかでユーザが参照できるようにする。
参考
- 面接対策まとめ|よくある質問の回答例、準備~面接後のやりとり・流れ|マイナビ転職 https://tenshoku.mynavi.jp/knowhow/mensetsu
- Alexaの買い物リストとやることリストにアクセスする | Alexa Skills Kit
- https://developer.amazon.com/ja-JP/docs/alexa/custom-skills/access-the-alexa-shopping-and-to-do-lists.html