Amazon ConnectとLexを活用し、自動ヒアリングした内容をAmazon Bedrockで要約してメール通知してみた
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
Amazon Connect アドベントカレンダー 2024、2日目の記事です!
クラスメソッドとギークフィードさん、クラウドビルダーズさん、ネットプロテクションズさん、AWS Japanさんの有志が募ってチャレンジしている企画になります。
(アドベントカレンダーのカレンダー一覧はこちら↓)
はじめに
本記事では、Amazon ConnectとAmazon Lexを活用し、自動ヒアリングした内容をAmazon Bedrockで要約し、メール通知する方法について解説します。
この実装によるユーザー体験の流れは、以下の通りです。
| ステップ | 実行者 | アクション |
|---|---|---|
| 1 | ユーザー | 電話をかける |
| 2 | Connect | 「申し訳ございません。ただいま電話に出ることができません。メッセージを録音してよければ、はい、とお伝えください。」 |
| 3 | ユーザー | 「はい」と応答 |
| 4 | Connect(Lex) | 「ご要件、お名前、住所の3点をお伝えください。無音の状態が一定時間ある場合、録音が切れますので、ご了承ください。」 |
| 5 | ユーザー | 必要事項を伝える |
| 6 | Lambda | 録音内容をBedrockで要約し、メール通知する |
| 7 | Connect | 「以上で録音を終了します。電話を切ります。」 |
以下に構成図を示します。

概要

詳細
前提条件
- SNSトピック作成済み
- Connectインスタンスは作成済み
- LexとConnectフローの構築、およびLexの音声入力時間の上限緩和については、以下の参考記事をもとに対応済みとします。
Lex
作成済みのLexボットのスロットfreeに以下のプロンプトを修正します。
修正前
お問い合わせ内容をお伝え下さい。無音の状態が一定時間ある場合、録音が切れますので、ご了承ください。 修正後
ご要件、お名前、住所の3点をお伝え下さい。無音の状態が一定時間ある場合、録音が切れますので、ご了承ください。 
Lambda
以下の設定でLambdaを作成します。
- ランタイム: Python 3.13
- タイムアウト: 20秒
- IAMロールに付与するポリシー
- AWSLambdaBasicExecutionRole
- AmazonBedrockFullAccess
- AmazonSNSFullAccess
- メモリ:512MB
- メモリは512MBの方が実行完了時間が短かったため、512MBを選択しています。
- メモリ128MBの場合、4~6秒
- メモリ512MBの場合、3~4秒
- メモリは512MBの方が実行完了時間が短かったため、512MBを選択しています。
import json import boto3 import datetime from zoneinfo import ZoneInfo MODEL_ID = 'anthropic.claude-3-5-sonnet-20240620-v1:0' TOPIC_ARN = 'arn:aws:sns:ap-northeast-1:012345678901:xxxx' def invoke_bedrock(prompt): client = boto3.client('bedrock-runtime') response = client.converse( modelId=MODEL_ID, messages=[{ "role": "user", "content": [{ "text": prompt }] }], inferenceConfig={ "maxTokens": 1000, "temperature": 0 } ) response_text = response['output']['message']['content'][0]['text'] print('Received response_text:' + json.dumps(response_text, ensure_ascii=False)) return response_text def get_contact_time(): jst_now = datetime.datetime.now(ZoneInfo("Asia/Tokyo")) return jst_now.strftime('%Y-%m-%d %H:%M:%S') def create_message(contact_time, phone_number, formatted_text, original_text): return f"""お問い合わせ情報 ・日時: {contact_time} ・電話番号: {phone_number} ・お問い合わせ内容(整形済み文章) {formatted_text} ・お問い合わせ内容(未整形文章) {original_text}""" def lambda_handler(event, context): print('Received event:' + json.dumps(event, ensure_ascii=False)) recording = event['Details']['ContactData']['Attributes']['recording'] phone_number = event['Details']['ContactData']['SystemEndpoint']['Address'] contact_time = get_contact_time() prompt = f""" 以下の音声文字起こしテキストから、ご要件、名前、住所の3つの情報を抽出し、以下のフォーマットで整理してください: ご要件:[内容を自然な日本語で記述] お名前:[名前を記述] ご住所:[住所を記述] なお、情報が不足している場合は「情報なし」と記載してください。 余計な説明は不要です。上記フォーマットのみを返してください。 テキスト: {recording} """ formatted_text = invoke_bedrock(prompt) message = create_message(contact_time, phone_number, formatted_text, recording) sns = boto3.client('sns') sns.publish( TopicArn=TOPIC_ARN, Message=message, Subject='新規お問い合わせ通知' ) return { 'statusCode': 200, 'body': json.dumps({ 'formatted_text': formatted_text, 'message': 'Successfully processed contact flow event' }, ensure_ascii=False) } 処理の概要は以下のとおりです。
- Lambda関数がLexの文字起こしデータ(
recording)と発信元電話番号を取得します。 - 現在時刻を日本標準時(JST)で取得し、整形します。
- 文字起こしデータをもとに、生成AIモデル(Anthropic Claude)に「ご要件」「お名前」「ご住所」を抽出してもらいます。
- 整形済みテキストを取得し、SNS通知用のメッセージを作成し、メール送信します。
Connectフロー
Connectフローでは、以下の2つのブロックを追加します。

Connectフローは、Lambdaとコンタクト属性の設定を追加します。

今回は、Lambdaの呼び出しタイムアウトは1秒に設定しています。
LambdaからConnectへのReturnは不要であり、Lambdaの実行完了をまで待つ時間が数秒かかるため、省略します。

Lambdaの呼び出しがタイムアウトになってもSNSでメール通知の処理はされます。ただし。ConnectのフローログではLambdaのエラーと出力されます。フローログのエラーが気になる場合、タイムアウトを最大の8秒にしましょう。
{ "Results": "The Lambda Function Returned An Error.", "ContactId": "9cbe3e4c-9a2f-4239-a887-41f1169e8123", "Parameters": { "FunctionArn": "arn:aws:lambda:ap-northeast-1:012345678901:function:voicemail-to-email-notifier", "ResponseValidation": "ResponseType=STRING_MAP", "TimeLimit": "1000" } ~中略~ } 作成したConnectフローのjsonファイル(クリックで展開)
{ "Version": "2019-10-30", "StartAction": "17a389ed-1002-4550-9bbf-efbbe3811cf9", "Metadata": { "entryPointPosition": { "x": 36.8, "y": 65.6 }, "ActionMetadata": { "1990a178-5825-414e-bd24-2bc3dc5dc937": { "position": { "x": 357.6, "y": 61.6 }, "children": [ "d6ed2b04-80f5-4018-8262-87d58b7f0cb7" ], "overrideConsoleVoice": true, "fragments": { "SetContactData": "d6ed2b04-80f5-4018-8262-87d58b7f0cb7" }, "overrideLanguageAttribute": true }, "d6ed2b04-80f5-4018-8262-87d58b7f0cb7": { "position": { "x": 357.6, "y": 61.6 }, "dynamicParams": [] }, "17a389ed-1002-4550-9bbf-efbbe3811cf9": { "position": { "x": 140.8, "y": 60.8 } }, "465002a2-1f89-476b-8f58-e0e2671632c7": { "position": { "x": 820.8, "y": 271.2 } }, "1a41bbb2-6b65-4bf0-871b-deaf288ba7a1": { "position": { "x": 819.2, "y": 460.8 } }, "0cebb197-9920-4fcc-8410-a2f9e9fb12ff": { "position": { "x": 572, "y": 57.6 }, "parameters": { "LexV2Bot": { "AliasArn": { "displayName": "TestBotAlias", "useLexBotDropdown": true, "lexV2BotName": "cm-hirai-beyond-15seconds" } } }, "dynamicMetadata": { "x-amz-lex:audio:start-timeout-ms:*:*": false, "x-amz-lex:audio:end-timeout-ms:*:*": false, "x-amz-lex:audio:max-length-ms:*:*": false }, "useLexBotDropdown": true, "lexV2BotName": "cm-hirai-beyond-15seconds", "lexV2BotAliasName": "TestBotAlias", "conditionMetadata": [ { "id": "7582d5d9-aaed-4540-b12d-92c9fa587fed", "operator": { "name": "Equals", "value": "Equals", "shortDisplay": "=" }, "value": "recording" } ] }, "acf5bea6-926a-42f6-a9c7-2f9cf4af97ef": { "position": { "x": 819.2, "y": 60 }, "parameters": { "Attributes": { "recording": { "useDynamic": true } } }, "dynamicParams": [ "recording" ] }, "3c2cba41-f8a9-418f-b428-c573abb3c010": { "position": { "x": 1257.6, "y": 296 } }, "87155153-6569-4cbc-8796-80b66eee6955": { "position": { "x": 1035.2, "y": 60.8 } }, "3297b9ca-f7e5-4822-9697-2a06b6b322e3": { "position": { "x": 1245.6, "y": 56.8 }, "parameters": { "LambdaFunctionARN": { "displayName": "voicemail-to-email-notifier" } }, "dynamicMetadata": {} } }, "Annotations": [], "name": "cm-hirai-voicemail-to-email-notifier", "description": "", "type": "contactFlow", "status": "published", "hash": {} }, "Actions": [ { "Parameters": { "TextToSpeechEngine": "Neural", "TextToSpeechStyle": "None", "TextToSpeechVoice": "Kazuha" }, "Identifier": "1990a178-5825-414e-bd24-2bc3dc5dc937", "Type": "UpdateContactTextToSpeechVoice", "Transitions": { "NextAction": "d6ed2b04-80f5-4018-8262-87d58b7f0cb7" } }, { "Parameters": { "LanguageCode": "ja-JP" }, "Identifier": "d6ed2b04-80f5-4018-8262-87d58b7f0cb7", "Type": "UpdateContactData", "Transitions": { "NextAction": "0cebb197-9920-4fcc-8410-a2f9e9fb12ff", "Errors": [ { "NextAction": "0cebb197-9920-4fcc-8410-a2f9e9fb12ff", "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { "FlowLoggingBehavior": "Enabled" }, "Identifier": "17a389ed-1002-4550-9bbf-efbbe3811cf9", "Type": "UpdateFlowLoggingBehavior", "Transitions": { "NextAction": "1990a178-5825-414e-bd24-2bc3dc5dc937" } }, { "Parameters": { "Text": "録音されないということで承知しました。電話を切ります。" }, "Identifier": "465002a2-1f89-476b-8f58-e0e2671632c7", "Type": "MessageParticipant", "Transitions": { "NextAction": "3c2cba41-f8a9-418f-b428-c573abb3c010", "Errors": [ { "NextAction": "3c2cba41-f8a9-418f-b428-c573abb3c010", "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { "Text": "エラーとなりました。" }, "Identifier": "1a41bbb2-6b65-4bf0-871b-deaf288ba7a1", "Type": "MessageParticipant", "Transitions": { "NextAction": "3c2cba41-f8a9-418f-b428-c573abb3c010", "Errors": [ { "NextAction": "3c2cba41-f8a9-418f-b428-c573abb3c010", "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { "Text": "申し訳ございません。ただいま電話に出ることができません。メッセージを録音してよければ、はい、とお伝え下さい。", "LexSessionAttributes": { "x-amz-lex:audio:start-timeout-ms:*:*": "8000", "x-amz-lex:audio:end-timeout-ms:*:*": "4000", "x-amz-lex:audio:max-length-ms:*:*": "50000" }, "LexV2Bot": { "AliasArn": "arn:aws:lex:ap-northeast-1:012345678901:bot-alias/OMRBM5O69M/TSTALIASID" } }, "Identifier": "0cebb197-9920-4fcc-8410-a2f9e9fb12ff", "Type": "ConnectParticipantWithLexBot", "Transitions": { "NextAction": "1a41bbb2-6b65-4bf0-871b-deaf288ba7a1", "Conditions": [ { "NextAction": "acf5bea6-926a-42f6-a9c7-2f9cf4af97ef", "Condition": { "Operator": "Equals", "Operands": [ "recording" ] } } ], "Errors": [ { "NextAction": "465002a2-1f89-476b-8f58-e0e2671632c7", "ErrorType": "NoMatchingCondition" }, { "NextAction": "1a41bbb2-6b65-4bf0-871b-deaf288ba7a1", "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { "Attributes": { "recording": "$.Lex.Slots.free" }, "TargetContact": "Current" }, "Identifier": "acf5bea6-926a-42f6-a9c7-2f9cf4af97ef", "Type": "UpdateContactAttributes", "Transitions": { "NextAction": "87155153-6569-4cbc-8796-80b66eee6955", "Errors": [ { "NextAction": "87155153-6569-4cbc-8796-80b66eee6955", "ErrorType": "NoMatchingError" } ] } }, { "Parameters": {}, "Identifier": "3c2cba41-f8a9-418f-b428-c573abb3c010", "Type": "DisconnectParticipant", "Transitions": {} }, { "Parameters": { "Text": "以上で録音を終了します。電話を切ります。" }, "Identifier": "87155153-6569-4cbc-8796-80b66eee6955", "Type": "MessageParticipant", "Transitions": { "NextAction": "3297b9ca-f7e5-4822-9697-2a06b6b322e3", "Errors": [ { "NextAction": "3297b9ca-f7e5-4822-9697-2a06b6b322e3", "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { "LambdaFunctionARN": "arn:aws:lambda:ap-northeast-1:012345678901:function:voicemail-to-email-notifier", "InvocationTimeLimitSeconds": "1", "ResponseValidation": { "ResponseType": "STRING_MAP" } }, "Identifier": "3297b9ca-f7e5-4822-9697-2a06b6b322e3", "Type": "InvokeLambdaFunction", "Transitions": { "NextAction": "3c2cba41-f8a9-418f-b428-c573abb3c010", "Errors": [ { "NextAction": "3c2cba41-f8a9-418f-b428-c573abb3c010", "ErrorType": "NoMatchingError" } ] } } ] } 試してみた
いくつかのサンプル発話を用意し、それぞれのメール通知内容を確認してみます。
サンプル1
発話内容は、以下のとおりです。住所を発話しないパターンです。
もしもし、クラスメソッドと申します。 先日、購入した洗濯機の調子が悪くて連絡しました。型番はAWAの2000です。 昨日の夜から、運転すると異常な振動と大きな音がするようになりました。脱水時に特にひどくなります。 説明書を確認して、設置の水平度合いを確認したり、洗濯物の偏りがないか調整しましたが、改善されません。 おそらく保証期間内なので、修理をお願いしたいのですが、明日か明後日に来ていただくことは可能でしょうか? 私の連絡先は090-1234-5678です。午前中であれば在宅しております。 お手数ですが、ご連絡いただければ幸いです。よろしくお願いいたします。 メール本文は以下の通りでした。
お問い合わせ情報 ・日時: 2024-11-20 15:48:16 ・電話番号: +81xxxxxxxxxx ・お問い合わせ内容(整形済み文章) ご要件:先日購入した洗濯機(型番AWA2000)の調子が悪く、昨日の夜から運転時に異常な振動と大きな音がする。特に脱水時に顕著。保証期間内なので修理を依頼したい。明日か明後日の訪問を希望。 お名前:クラスメソット ご住所:情報なし ・お問い合わせ内容(未整形文章) もしもし クラス メソット と 申し ます 先日 購入 し た 洗濯 機 の 調子 が 悪く て 連絡 し まし た 型番 は a w a の 二 千 です 昨日 の 夜 から 運転 する と 異常 な 新郎 と 大きな 音 が する よう に なり まし た 脱水 時 に 特に し とく なり ます説明 書 を 確認 し て 設置 の 水平 度合い を 確認 し たり 洗濯 物 の 偏り が ない か 調整 し まし た が 改善 さ れ ませ んおそらく 保証 期間 内 な の で 修理 を お 願い し たい の です が 明日 か 明後日 日経 化学 こと は 可能 でしょう か 私 の 連絡 先 は 〇 九 〇 一 五 三 四 五 六 七 八 です お 膳 中 で あれ ば 在宅 し て おり ます お 手数 です が 連絡 いただけ ます と 幸い です よろしく お 願い いたし ます 
文字起こしされた文章は、Bedrockによって句読点やスペースが削除されており、読みやすく整形されています。
要約に連絡先(090-1234-5678)も入っているとよりよいですね。
住所がない場合は、「情報なし」と正しく記載されています。
サンプル2
発話内容は、以下のとおりです。住所の情報が2箇所に散らばっています。
東京都港区西新橋1-1-1 に住んでいる佐藤太郎と申します。 先日メールでもお問い合わせしたんですが、返事がなくて、注文した商品がまだ届かないので確認したくて電話しました。 注文番号はわかりません。 住所は先ほど言った通りなんですが、マンション名を言い忘れました。日比谷フォートタワー26階です。 実は先週の水曜日に注文したはずなんですが、確認メールも来てなくて心配で。 普段は2,3日で届くと聞いていたので、もしかしたら注文が正しく完了していないのかなと思って。 商品は確か合計で12,800円分注文したんですが、クレジットカードの引き落としも確認できていません。 メール本文は以下の通りでした。
お問い合わせ情報 ・日時: 2024-11-20 16:18:55 ・電話番号: +81xxxxxxxxxx ・お問い合わせ内容(整形済み文章) ご要件:先週水曜日に注文した商品(口切り1万800円分)がまだ届かず、確認メールも来ていないため、注文状況を確認したい。 お名前:サトウ タロウ ご住所:東京都港区西新橋1-1-1 日比谷ポートタワー 16階 ・お問い合わせ内容(未整形文章) 東京 都 港 区 西新橋 一 の 一 の 一 に 住ん で いる サトウ タロウ と 申し ます 先日 メール で も 問い合わせ し た ん です が 返事 が なく て 注文 し た 商品 が まだ 届か ない の で 確認 し たく て 電話 し まし た 注文 番号 は わかり ませ ん 住所 は 先程 言っ た とおり なんて な ん です が マンション 名 を 言い 忘れ まし た 日比谷 ポート タワー に 十 六 回 です 実 は 先週 の 水曜 日 に 注文 し た ん です が 確認 メール も 来 なく て 心配 で 普段 は 三 三 に し て 届く と 聞い て い た の で もし か し たら 注文 が 探し 完了 し て い ない の か な と 思っ て 商品 は 確か 口 切り 一 万 に し て 八百 円 分 注文 し た ん です が クレジット カード の 引き落とし も 確認 でき て い ませ ん 問い合わせ内容では住所の情報が散らばっていますが、問題なく抽出されています。
住所を文字起こしが正しくないため、整形後の(口切り1万800円分)も誤りがあります。
サンプル3
発話内容は、以下のとおりです。住所を発話しないパターンです。
商品のことでお電話したんですけど。 カタログで見た青い花瓶がすごく気に入って、在庫を確認したいです。 鈴木と申します。 その青い花瓶なんですが、サイズが3種類あると書いてあって、一番大きいサイズだと置く場所に困るかもしれないので、実際のサイズ感を教えて頂きたいです。 あと、もし可能でしたら、実物の写真とかありますでしょうか? カタログの写真だと、色味がちょっとわかりにくくて。 ネットでも探してみたんですが、詳しい情報が見つけられませんでした メール本文は以下の通りでした。
お問い合わせ情報 ・日時: 2024-11-20 16:25:24 ・電話番号: +81xxxxxxxxxx ・お問い合わせ内容(整形済み文章) ご要件:カタログで見た青い花瓶の在庫確認、サイズ感の詳細、実物の写真の有無を問い合わせたい。 お名前:スズキ ご住所:情報なし ・お問い合わせ内容(未整形文章) 商品 の こと で お 電話 し た ん です けど カタログ で 見 た 青い 過敏 書 すごく 気 に 入っ て 在庫 を 確認 し たい です スズキ と 申し ます その 青い 過敏 な ん です が サイズ が 三 種類 ある と 書い て あっ て 一番 大きい サイズ だ と 置く 場所 に も 困る か も しれ ない の で 実際 の サイズ 感 教え て いただき たい です あと もし 可能 でし たら 実物 の 写真 と か あり ます でしょう か カタログ の 写真 だ と 色 味 が ちょっと わかり にくく て ネット で も 見 た ん です が 詳しい 情報 が 見つけ られ ませ ん でし た 住所がない場合は、「情報なし」と正しく記載されています。
サンプル4
発話内容は、以下のとおりです。要件が複数あるパターンです。
田中美咲です。 北海道札幌市中央区北3条西1-1-1 札幌ブリックキューブ10階に住んでいます。 2点ほど確認したくて電話させていただきました。 先日注文した商品の配送日の変更をしたいです。できれば来週の水曜日に配送をお願いしたいのですが、大丈夫ですか? あと、新しく出た商品カタログを送っていただきたいんです。先月お願いしたんですが、まだ届いていないです。 以前使っていた商品がとても良かったので、新商品も気になっているんです。 特に美容液のシリーズが気になっていて、新しいラインナップを確認したいので、できるだけ早めに送っていただけると嬉しいです。 メール本文は以下の通りでした。
お問い合わせ情報 ・日時: 2024-11-20 16:31:49 ・電話番号: +81xxxxxxxxxx ・お問い合わせ内容(整形済み文章) ご要件:先日注文した商品の配送日を来週の水曜日に変更したい。新しく出た商品カタログを送ってほしい。特に美容液のシリーズの新しいラインナップを確認したい。 お名前:タナカ ミサキ ご住所:北海道札幌市中央区北三条西一の一の一 札幌ブリック九日十階 ・お問い合わせ内容(未整形文章) タナカ ミサ キ です 北海道 札幌 市 中央 区 北 三条 西 一 の 一 の 一 札幌 ブリック 九 日 十 階 に 住ん で い ます 三 点 ほど 確認 し たく て 電話 し て いただけ まし た 先日 注文 し た 商品 の 配送 日 の 変更 を し たい です できれ ば 来週 の 水曜 日 に 配送 お 願い し たい の です が 大丈夫 です か あと は 新しく 出 た 商品 カタログ を 送っ て いただき たい ん です 先日 お 願い し た ん です が まだ 届い て い ない です 以前 使っ て い た 商品 が とても よかっ た の で 新 商品 も 気 に なっ て いる ん です 特に 美容 液 の シリーズ は 気 に なっ て い て 新しい ラインナップ を 確認 し たい の で できる だけ 早め に 送っ て いただける と 嬉しい です 要件が複数あるパターンですが、正しく要件がまとめられています。
住所は誤った文字起こしになっていますので、整形後も誤っています。
最後に
本記事では、Amazon Connect、Amazon Lex、Amazon Bedrockを組み合わせた自動ヒアリング内容の要約とメール通知の仕組みを解説しました。
サンプルを通じて、実装の流れや精度を確認し、実用性を検証しました。
この仕組みは、留守番電話や簡易電話代行の代替などで活用できる可能性があり、顧客対応の効率化や業務の自動化に大きく貢献します。ぜひ、自社のニーズに合わせて検証・活用してみてください。







