はじめに
Amazon Connect、Lambda、Lex、DynamoDBを使って、ヘルプデスクボットを作成してみました。
完成イメージ
Work1: コンタクトフロー作成
Step 1: LambdaとDynamoDBによるサーバーレスアプリの構築
1. DynamoDBの作成
①AWS コンソール から Amazon DynamoDB を選択し、テーブルの作成
を選択します。
②テーブルの作成ページで、テーブル名を connectDemo
、パーティションキーを phoneNumber
文字列に設定します。
③その他のオプションはデフォルトのまま、テーブルの作成
を選択します。
④connectDemo テーブルは正常に作成されました。
が表示されれば成功です。
2. 新しい IAM ロールの作成
①AWS コンソール から IAM を選択し、アクセス管理セクションのロールを選択し、ロールを作成
を選択します。
②信頼されたエンティティタイプはAWS のサービス
を、ユースケースはLambda
を選択します。
③ポリシーのフィルタ欄で AWSLambdaBasicExecutionRole
と入力して Enter キーを押し、表示されたポリシーを選択状態にします。
④フィルターをクリアし、前の手順と同様に AmazonDynamoDBFullAccess
と入力して Enter キーを押し、表示されたポリシーを選択します。次へ
を選択します。
⑤ロール名を ws-LambdaDynamoRole
と入力します。ここまでの手順で設定した内容が正しいことを確認し、ロールの作成
を選択します。
⑥ロール ws-LambdaDynamoRole が作成されました。
と表示されれば成功です。
3. Lambda 関数の作成
①AWS コンソール から、AWS Lambda を選択し、関数の作成
を選択します。
②一から作成を選択し、関数名に dbDemo
を入力します。ランタイムはNode.js 16.x を選択します。
③デフォルトの実行ロールの変更
を展開し、既存のロールを使用する
を選択します。既存のロールドロップダウンリストで、上記の IAM で作成したロールを選択し、関数の作成
を選択します。
④下記の Javascript サンプルコード をコピーし、コードセクションの Lambda コードに貼り付けます。Deploy を選択し、関数を保存します。
Javascript サンプルコード
/*
MIT No Attribution
Copyright 2021 Amazon Web Services, Inc. or its affiliates. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// Get the AWS SDK and Dynamo SDKs ready
var AWS = require("aws-sdk");
var docClient = new AWS.DynamoDB.DocumentClient();
//Sets the timezone environment variable for the Lambda function
process.env.TZ = "Asia/Tokyo";
exports.handler = (event, context, callback) => {
// set the options for the date format
var dateOptions = {
weekday: "short",
year: "numeric",
month: "short",
day: "numeric"
};
// set the variables to record the current local date and time
var currentShortDate = new Date().toLocaleDateString();
var currentLongDate = new Date().toLocaleDateString("ja-JP", dateOptions);
var currentTime = new Date().toLocaleTimeString("ja-JP");
var currentTimeStamp = new Date().toString();
//log the incoming event from Amazon Connect for troubleshooting purposes
console.log("Received event from Amazon Connect at: " + currentTimeStamp);
console.log("Amazon Connect Event Details: " + JSON.stringify(event));
//set the variables for the customer ANI and unique contact ID
var sourcePhoneNumber = event.Details.ContactData.CustomerEndpoint.Address;
var currentContactId = event.Details.ContactData.ContactId;
//set up the database query to be used to lookup customer information from DynamoDB
var paramsQuery = {
//DynamoDB Table Name. Replace with your table name
TableName: 'connectDemo',
KeyConditionExpression: "phoneNumber = :varNumber",
ExpressionAttributeValues: {
":varNumber": sourcePhoneNumber
}
};
//set up the database query to be used to update the customer information record in DynamoDB
var paramsUpdate = {
//DynamoDB Table Name. Replace with your table name
TableName: 'connectDemo',
Key: {
"phoneNumber": sourcePhoneNumber
},
ExpressionAttributeValues: {
":var1": currentTimeStamp,
":var2": currentLongDate,
":var3": currentTime,
":var4": currentContactId,
},
UpdateExpression: "SET lastCalledTimeStamp = :var1, lastCalledDate = :var2, lastCalledTime = :var3, lastCalledCallId = :var4"
};
//use the lookup query (paramsQuery) we set up to lookup the customer data based on the source phone number from DynamoDB
docClient.query(paramsQuery, function (err, dbResults) {
//check to make sure the query executed correctly, if so continue, if not error out the lambda function
if (err) {
console.log(err); // an error occurred
context.fail(buildResponseFailed);
}
//if no error occured, proceed to process the resutls that came back from DynamoDB
else {
//log the results from the DynamoDB query
console.log("DynamoDB Query Results:" + JSON.stringify(dbResults));
//check to ensure only 1 record came back for the customer phone number
if (dbResults.Items.length === 1) {
//set variables for the pertinet information from the returned database record:
var lastCalledDate = dbResults.Items[0].lastCalledDate;
var lastCalledTime = dbResults.Items[0].lastCalledTime;
var customerFirstName = dbResults.Items[0].firstName;
var customerLastName = dbResults.Items[0].lastName;
//check to see if there is a record of a previous call, and set the previous call variable accordingly
var customerFirstCall = true;
if (lastCalledDate) {
customerFirstCall = false
}
//update the customer record in the database with the new call information using the paramsUpdate query we setup above:
docClient.update(paramsUpdate, function (err, data) {
if (err) console.log("Unable to update item. Error: ", JSON.stringify(err, null, 2));
else console.log("Updated item succeeded: ", JSON.stringify(data, null, 2));
});
callback(null, buildResponseNumberFound(customerFirstName, customerLastName, lastCalledDate, lastCalledTime, customerFirstCall));
} else {
customerFirstCall = true;
docClient.update(paramsUpdate, function (err, data) {
if (err) console.log("Unable to update item. Error: ", JSON.stringify(err, null, 2));
else console.log("Updated item succeeded: ", JSON.stringify(data, null, 2));
});
callback(null, buildResponseNumberNotFound(customerFirstCall));
}
}
});
};
//This is the function that will be called on a successful callback if we find the phone number in our database
function buildResponseNumberFound(customerFirstName, customerLastName, lastCalledDate, lastCalledTime, customerFirstCall) {
var results = {
firstName: customerFirstName,
lastName: customerLastName,
lastCalledDate: lastCalledDate,
lastCalledTime: lastCalledTime,
firstCall: customerFirstCall,
phoneNumberFound: true,
lambdaResult: "Success"
};
console.log("Lambda's Response to Amazon Connect is: " + JSON.stringify(results));
return results;
}
//This is the function that will be called on a successful callback if we don't find the phone number in our database
function buildResponseNumberNotFound(customerFirstCall) {
var results = {
firstCall: customerFirstCall,
phoneNumberFound: false,
lambdaResult: "Success"
};
console.log("Lambda's Response to Amazon Connect is: " + JSON.stringify(results));
return results;
}
//This is the function that will be called on an error
function buildResponseFailed() {
var results = {
lambdaResult: "Error"
};
console.log("Lambda's Response to Amazon Connect is: " + JSON.stringify(results));
return results;
}
⑤設定セクションで一般設定に移動し、編集
を選択します。
⑥タイムアウト 0分 8秒
に変更し、保存
を選択します。
Step 2: AWS Lambda 統合
1. Amazon Connect インスタンスにAWS Lambda関数を追加する
①AWS コンソール から、Amazon Connect
を開きます。
②インスタンスエイリアス欄から、事前に作成していたインスタンス名を押下します。
③ナビゲーションペインで、問い合わせフロー
を選択し、AWS Lambda セクションまでスクロールダウンします。Lambda 関数 ドロップダウンを選択し、dbDemo
を選択します。Add Lambda Function
を選択します。
④Lambda 関数のリストに 登録した Lambda 関数が表示されることを確認します。
Step 3: Amazon Connect ルーティングの設定
1. 新しいユーザーの追加
①Amazon Connect インスタンスにログインします。ナビゲーションバーのユーザーからユーザー管理
を選択します。
②新しいユーザーの追加
を選択し、ユーザーを手動で追加が選択されていることを確認します。
③ユーザー情報に新規ユーザーの認証情報で、すべての必須フィールドを規則に従って入力します。
④ルーティングプロファイルで Basic Routing Profile
を、セキュリティプロファイルで Agent
を選択します。
⑤完了したら画面右上の保存
を選択します。
2. キューの追加
①ナビゲーションバーからルーティングを選択し、キューを選択します。
②キューを追加
を選択します。
③名前に Customer Support
と入力し、オペレーション時間は、Basic Hours
を選択します。
④保存
を選択します。
⑤前のステップを繰り返して、Password Resetのキューを追加します。※設定値は同じです。
3. ルーティングプロファイルの編集
①ナビゲーションバーからユーザーを選択し、ルーティングプロファイル
を選択
②Basic Routing Profile
を選択します。
③キューセクションで、キューを追加
を選択します。
④追加したキューのドロップダウンリストで、Customer Support
キューを選択します。
- 優先度を 1 に設定します。
- 遅延を 0 に設定します。
⑤再度キューを追加
を選択し、同じ手順で Password Reset
キューを追加します。
- 優先度を
1
に設定します。 - 遅延を
0
に設定します。
⑥画面右上の保存を選択します。
4. コンタクトフローのインポート
⓪以下の手順を行う前に、こちらをダウンロードしてください
AWS_Demo_Flow_Main_J
①ナビゲーションバーからルーティングを選択し、フロー
を選択します。
②フローの作成
を選択します。
③画面右上の保存の横にあるドロップダウンリストから、フローのインポート(ベータ)
を選択します。
④AWS_Demo_Flow_Main_J.json
ファイルを選択し、インポート
を選択します。
すると、フロー図が自動で生成されました。
⑤画面右上の
公開`を選択してコンタクトフローを保存・公開します。
Step 4: コンタクトフローのテスト
1. 電話番号をコンタクトフローに設定
①Amazon Connect のダッシュボードのナビゲーションバーから、 チャネル
> 電話番号
を選択します。
②取得済みの電話番号を選択します。ドロップダウンリストから AWS_Demo_Flow_Main_J コンタクトフロー
を選択し、保存
を選択します。
③取得済みの電話番号にテストコールを行います。
コールすると、 お客様の電話番号が弊社の記録にありませんでしたので、今後のためにデータベースに追加しました。初めてお電話いただきました。ありがとうございます。
というメッセージが再生され、切断されます。
2. DynamoDB テーブルの更新
①AWS コンソール から、Amazon DynamoDB を開きます。
②画面左側のナビゲーションメニューの テーブル
> 項目を探索
を選択し、リストから connectDemo
テーブルを選択します。テストコールで使用した電話番号を選択します。
③項目の編集画面が開きます。
-
新しい属性の追加
>文字列
を選択します。属性名firstName
を追加します。値に任意の名前を入力します。 -
新しい属性の追加
>文字列
を選択します。属性名lastName
を追加します。値に任意の姓を入力します。 -
保存して閉じる
を選択します。
④取得済みの電話番号に再度テストコールを行います。このとき、Amazon Connect はデータベースのテーブルからテストに使用した電話番号を認識し、前の手順で設定した名前と、最後に電話をかけた時間を音声で再生します。
「Shohei Otani様、お電話ありがとうございます。」と応答が来ました!
Work2: ヘルプデスク Lex ボットの作成
Step 1: Lex ボットのインポート
Lex ボットのインポート
⓪以下の手順を行う前に、こちらをダウンロードしてください
HelpDesk-Lex_v2_Bot_J.zip
①AWS コンソール から、Amazon Lexを開きます。
②ボットセクションのアクション
> インポート
を選択します。
③ボットをインポート画面でボット名に HelpDesk
と入力します。ファイルを参照を選択し、前の手順でダウンロードした HelpDesk-Lex_v2_Bot_J.zip
を選択します。
④以下の情報を設定します。:
- IAM アクセス許可:
基本的な Amazon Lex 権限を持つロールを作成します。
を選択 - 児童オンラインプライバシー保護法 (COPPA):
いいえ
を選択 - アイドルセッションタイムアウト:
5 分
を設定
⑤インポート
を選択します。
⑥インポートが成功した通知を確認し、HelpDesk
ボットを選択します。
⑦画面左側のナビゲーションメニューで 日本語 (JP)
を選択します。画面上のセクションでBuild
を選択して、インポートしたボットの構築処理を開始します。
⑧ボット (日本語 (JP)) で言語 HelpDesk が正常に構築されました
が表示されれば成功です。
Step 2: Amazon Connect インスタンスへ Amazon Lex ボットを追加
1. Amazon Connectインスタンスへ Amazon Lex ボットを追加
①AWS コンソール から、Amazon Connect へ移動します。選択したリージョンが、Amazon Lex ボットを構築したリージョンと同じであることを確認します。
②インスタンスエイリアスの欄からワークショップに使用するインスタンスの名前を選択します。
③ナビゲーションペインで、問い合わせフロー
を選択し、Amazon Lex セクションまでスクロールダウンします。
- ボットドロップダウンから
HelpDesk
を選択します。 - エイリアスは
TestBotAlias
を選択します。 -
+ Amazon Lex ボットを追加
を選択して、Amazon Connect のボットリストに追加します。
④Amazon Lex ボットセクションに、ボットが追加されたことを確認します。
2. ヘルプデスクのデモ用フローのインポート
⓪以下の手順を行う前に、こちらをダウンロードしてください
AWS_Demo_Flow_Main_HD_J
①Amazon Connect ダッシュボードに移動します。
②画面左側のナビゲーションバーから、ルーティング
> フロー
を選択します。
③画面右上のフローの作成
を選択します。
④画面右上の保存の横にあるドロップダウンリストから フローのインポート (ベータ)
を選択します。
⑤前の手順でダウンロードした AWS_Demo_Flow_HD_J.json
ファイルを選択し、インポートを選択します。
フロー図が自動で生成されました。
⑥画面右上の保存
を選択して、コンタクトフローを保存します。
3. コンタクトフローブロックの更新
①コンタクトフロー内の顧客の入力を取得するブロックを開きます。 Amazon Lex セクションまでスクロールします。
-
Lexボットを選択
を選択します。 - 名前ドロップダウンリストから、前の手順で作成した
HelpDesk
ボットを選択します。 - エイリアスドロップダウンリストで
TestBotAlias
を選択します。 -
保存
を選択します。
②3つ並んでいる作業キューの選択ブロックのうち、一番上のブロックを開きます。 Customer Support
キューを選択し、保存
を選択します。
③前の手順を繰り返し、上から2番目の作業キューの選択ブロックに Password Reset
キューを、上から3番目の作業キューの選択ブロックに BasicQueue
キューを選択します。
④画面右上の 公開 を選択し、コンタクトフローを公開します。
4. コンタクトフローに電話番号を割り当てテストする
①Amazon Connect ダッシュボードで、画面左側のナビゲーションバーから チャネル
> 電話番号
を選択します。
②取得した電話番号を選択し、 AWS_Demo_Flow_HD_J
コンタクトフローを割り当て、保存
を選択します。
③コンタクトフローの動作を確認するために、取得した電話番号にテストコールをかけます。質問に対し、以下の選択をテストします:
- "PCが起動しません" と言うと、Customer Support キューにルーティングされます。
- "パスワードを忘れました" と言うと、Password Reset キューにルーティングされます。
まとめ
"パスワードを忘れました" などと言うと、自動音声が対応してくれました。
ただしフロー作成に用いたファイルは複雑で時間がかかりそうだったので、AWS Workshop studioのファイルそのまま使いました。
このファイルをもっと編集するとおもしろそうなのですが、前回の簡易コールセンターに比べてややこしそうなので、今回はここで留めておきます。
データをDynamoDBに保存するのは流用できそうだなと思いました。