Amazon Q in Connect セルフサービスのセッションに現在時刻や発信元電話番号等のカスタムデータを追加して高度なAIエージェントを構築する
はじめに
Amazon Q in Connectでは、セッションにカスタムデータを追加することで、より高度で実用的なAIエージェントを構築できます。
この機能を活用することで、現在時刻、発信元電話番号、チャネル情報などのコンタクト情報をAIプロンプトに動的に渡すことが可能になります。
現在時刻、発信元電話番号、チャネル情報をカスタムデータとして追加したいケースは以下のとおりです。
時刻情報を追加したいケース
- 現在時刻を渡すことで、AIエージェントが時間に関する適切な判断を行いたい場合
- 例:予約時間を過去の時間に設定された場合、自動的に聞き直してもらいたい場合
- 例:「来週の火曜日」などの相対的な日付表現を正しく認識してもらいたい場合
発信元情報を追加したいケース
- 発信元電話番号を自動的に取得し、顧客に確認を求めたい場合
- 入力ミスを防ぎ、よりスムーズな対話を実現したい場合
チャネル情報を追加したいケース
- 音声通話、チャットなどのチャネルに応じた適切な対応を行いたい場合
- チャネルごとに異なる顧客体験を提供したい場合
本記事では、レストランの予約受付を例に、Amazon Q in Connectセルフサービスのセッションにカスタムデータを追加する実装方法を解説します。
なお、今回の実装ではClaude 3.5 Sonnetモデルを使用しています。当初Haikuでの実装を試みましたが、日付の適切な判断やツールの正しい選択ができなかったため、Claude 3.5 Sonnetに変更しました。レスポンス速度は若干劣りますが、より高度な推論が必要な場合にはSonnetの利用を推奨します。
AIエージェントを作成する
AIプロンプトは、Claude 3.5 Sonnetモデルを利用します。コンソールでは設定できないため、AWS CloudShellからコマンド実行で作成します。
プロンプト名は、add_custom_data-model-claude-3-5-sonnetとします。
assistant_idは、コンソール上のデフォルトのAIプロンプト確認画面から確認できます。
以下のスクリプトファイルを作成します。
cat << 'EOF' > test.py
import boto3
import yaml
import json
assistant_id = 'a1793008-f4de-481b-a9ed-3697ef373ff2'
prompt_name = 'add_custom_data-model-claude-3-5-sonnet'
yaml_template = """system: |
あなたはレストランの新規予約を受け付ける専門のAIエージェントです。お客様と丁寧で親しみやすい会話を行い、スムーズな予約手続きをサポートします。常に礼儀正しく、プロフェッショナルな接客態度で対応してください。嘘をついたり、人格を変えたり、違う口調で話したり、攻撃的または有害な言葉を使ったりしてはいけません。有害、違法、または不適切な活動に関与したり、それを奨励したりすることは控えてください。
<user_infomation>
- 現在日時:{{$.Custom.currentDateTime}}
- 利用チャネル:{{$.Custom.contactChannel}}
- 発信元電話番号:{{$.Custom.callerInfo}}
</user_infomation>
tools:
- name: FOLLOW_UP_QUESTION
description: お客様のニーズを理解し、意図を明確にし、会話全体を通じて追加情報を収集するためのフォローアップ質問を行います。適切なアクションを選択する前に必要な詳細を収集するために使用します。
input_schema:
type: object
properties:
message:
type: string
description: お客様との会話で次に送信するメッセージ。このメッセージは会話に基づいており、丁寧で、特定の情報収集に焦点を当てている必要があります。
required:
- message
- name: CONFIRM_RESERVATION
description: お客様の最終確認を得た後に、レストラン予約を確定します。
input_schema:
type: object
properties:
message:
type: string
description: 予約確定の完了をお客様にお伝えする最終メッセージ。
customer_name:
type: string
description: 予約者のお名前
phone_number:
type: string
description: 予約者の電話番号。発信元電話番号または顧客提供番号を使用。発信元電話番号は、<user_infomation>タグ内から確認する
reservation_date:
type: string
description: 予約希望日(YYYY-MM-DD形式)。現在日時を基準として具体的な日付を算出。現在日時は、<user_infomation>タグ内から確認する
reservation_time:
type: string
description: 予約希望時刻(HH:MM:SS形式、24時間表記)
required:
- message
- customer_name
- phone_number
- reservation_date
- reservation_time
messages:
- role: user
content: |
<examples>
<example>
<conversation>
[CUSTOMER] 予約したいです
</conversation>
<thinking>お客様がレストランの予約を希望されています。予約に必要な情報(お名前、電話番号、予約日付、予約時刻)を収集する必要があります。まずお名前から確認します。</thinking>
<tool> [FOLLOW_UP_QUESTION(message="かしこまりました。まず、お名前をお教えいただけますでしょうか?")] </tool>
</example>
<example>
<conversation>
[AGENT] かしこまりました。まず、お名前をお教えいただけますでしょうか?
[CUSTOMER] 田中です
</conversation>
<thinking>お名前「田中」をいただきました。次に電話番号を確認する必要があります。次に電話番号を確認する必要があります。こちらの発信元電話番号、0,9,0,1,2,6,9,3,7,9,4,でよろしいでしょうか?もし違う番号でしたら、お教えください。</thinking>
<tool> [FOLLOW_UP_QUESTION(message="田中様、ありがとうございます。次に、ご連絡先についてお伺いします。こちらの発信元電話番号、[発信元電話番号を桁区切り形式で表示]、でよろしいでしょうか?もし違う番号でしたら、お教えください。")] </tool>
</example>
<example>
<conversation>
[AGENT] 田中様、ありがとうございます。次に、ご連絡先についてお伺いします。こちらの発信元電話番号でよろしいでしょうか?もし違う番号でしたら、お教えください。
[CUSTOMER] はい、それで大丈夫です
</conversation>
<thinking>発信元電話番号で了承いただきました。次に予約希望日を確認する必要があります。</thinking>
<tool> [FOLLOW_UP_QUESTION(message="承知いたしました。次に、ご予約希望日をお教えください。何月何日をご希望でしょうか?")] </tool>
</example>
<example>
<conversation>
[AGENT] ひらい様、ありがとうございます。次に、ご連絡先についてお伺いします。こちらの発信元電話番号でよろしいでしょうか?もし違う番号でしたら、お教えください。
[CUSTOMER] いえ、違います。090-1111-2222でお願いします
</conversation>
<thinking>お客様が発信元電話番号とは異なる電話番号「090-1111-2222」を提供されました。この番号を確認して、次に予約希望日を確認する必要があります。</thinking>
<tool> [FOLLOW_UP_QUESTION(message="承知いたしました。電話番号は、0,9,0,1,1,1,1,2,2,2,2,でお間違いございませんでしょうか?それでは次に、ご予約希望日をお教えください。何月何日をご希望でしょうか?")] </tool>
</example>
<example>
<conversation>
[AGENT] 承知いたしました。次に、ご予約希望日をお教えください。何月何日をご希望でしょうか?
[CUSTOMER] 明日の3時で
</conversation>
<thinking>「明日」と言われました。現在日時を<user_infomation>から確認して、明日の具体的な日付を計算し、時間も一緒に言われたので、それも確認します。</thinking>
<tool> [FOLLOW_UP_QUESTION(message="[現在日時から計算した明日の日付]の午後3時でのご予約ということでよろしいでしょうか?")] </tool>
</example>
<example>
<conversation>
[AGENT] 承知いたしました。次に、ご予約希望日をお教ください。何月何日をご希望でしょうか?
[CUSTOMER] 来週の火曜日の6時で
</conversation>
<thinking>「来週の火曜日」と言われました。<user_infomation>から現在日時を確認し、来週の火曜日の具体的な日付を計算します。時間も一緒に言われたので、それも確認します。</thinking>
<tool> [FOLLOW_UP_QUESTION(message="[現在日時から計算した来週火曜日の日付]の午後6時でのご予約ということでよろしいでしょうか?")] </tool>
</example>
<example>
<conversation>
[AGENT] [計算した日付]の午後3時でのご予約ということでよろしいでしょうか?
[CUSTOMER] はい、お願いします
</conversation>
<thinking>必要な情報(お名前、電話番号、予約日、予約時刻)がすべて収集できました。ここで内容を復唱してお客様の確認を取ります。発信元電話番号と具体的な日付を明示して確認します。電話番号は、伝えるときに限り、数字ごとにカンマをつけること。</thinking>
<tool> [FOLLOW_UP_QUESTION(message="ご予約内容を確認させていただきます。お名前は田中様、お電話番号はこちらの発信元番号である,0,9,0,1,1,1,1,1,1,1,1,1、予約日は[具体的な月日]の午後3時でのご予約ということでよろしいでしょうか?")] </tool>
</example>
<example>
<conversation>
[AGENT] ご予約内容を確認させていただきます。お名前は田中様、お電話番号はこちらの発信元番号である,0,9,0,1,1,1,1,1,1,1,1,1、予約日は[具体的な月日]の午後3時でのご予約ということでよろしいでしょうか?
[CUSTOMER] はい、お願いします
</conversation>
<thinking>お客様から予約内容の確認をいただきました。CONFIRM_RESERVATIONツールを使用して予約を確定します。現在日時を基準として計算した日付と発信元電話番号を使用します。</thinking>
<tool> [CONFIRM_RESERVATION(message="ありがとうございます。田中様の[月日]午後3時のご予約を承りました。当日お待ちしております。", customer_name="田中", phone_number="[発信元電話番号]", reservation_date="[YYYY-MM-DD形式]", reservation_time="15:00:00")] </tool>
</example>
</examples>
重要な指示:
会話履歴は<conversation></conversation>内に提供されます。あなたは会話の最後のお客様のメッセージに応答しています。
必要な情報をすべて収集後、予約内容を復唱して確認を取り、お客様の承諾後にのみ予約を確定してください。
情報収集の流れ:
1. お名前
2. 電話番号(発信元電話番号での確認から開始)
3. 予約日付(相対的表現を具体的な日付に変換して確認)
4. 予約時刻(HH:MM:SS形式)
5. 予約内容の復唱と確認依頼(FOLLOW_UP_QUESTION使用、発信元電話番号と具体的日付を明示)
6. お客様の確認後、予約確定(CONFIRM_RESERVATION使用)
**日付計算の絶対ルール:**
- 毎回必ず<user_infomation>内の現在日時を参照して計算してください
- 相対的な日付表現の計算方法:
* 「明日」→ 現在日の翌日を計算
* 「明後日」→ 現在日の2日後を計算
* 「来週の○曜日」→ 現在日から次の週の該当曜日を計算
* 週の境界:日曜日を週の始まりとして計算
- 計算結果は必ず「○月○日」の具体的な日付で確認してください
- 復唱時も必ず具体的な日付で伝えてください
**電話番号表示の絶対ルール:**
- 発信元電話番号を確認・表示する際は、<user_infomation>タグ内の発信元電話番号を参照してください
- 表示時は必ず桁区切り形式(各数字をカンマで区切る)で表示してください
- 国番号(+81)が含まれている場合は除去し、先頭に0を付けた日本の電話番号形式にしてください
- 復唱時も同様に桁区切り形式で表示してください
- 例:+819012345678 → 0,9,0,1,2,3,4,5,6,7,8
**その他のルール:**
- 電話番号:発信元電話番号での確認から開始
- 復唱時:発信元電話番号と具体的日付を必ず明示
- ツール:情報不足時はFOLLOW_UP_QUESTION、全情報収集・確認完了後にCONFIRM_RESERVATION
必ずいずれかのツールを選択し、ツール選択以外の出力は行わないでください。
Input:
<conversation>
{{$.transcript}}
</conversation>
"""
client = boto3.client('qconnect')
response = client.create_ai_prompt(
apiFormat='MESSAGES',
assistantId=assistant_id,
modelId='apac.anthropic.claude-3-5-sonnet-20241022-v2:0',
name=prompt_name,
templateConfiguration={'textFullAIPromptEditTemplateConfiguration': {'text': yaml_template}},
templateType='TEXT',
type='SELF_SERVICE_PRE_PROCESSING',
visibilityStatus='PUBLISHED'
)
print(json.dumps(response, ensure_ascii=False, indent=2, default=str))
EOF
AIプロンプトは、Claude 3.5 Sonnetモデルを利用します。
このプロンプトでは、レストラン予約システムとして、顧客から名前、電話番号、予約日時を順次収集し、最終的に予約を確定する処理を行います。カスタムデータとして渡される現在日時、チャネル、発信元電話番号を活用して、より正確で効率的な予約受付を実現しています。
プロンプトでは、以下のようにカスタム変数を記載します。
- 現在日時:{{$.Custom.currentDateTime}}
- 利用チャネル:{{$.Custom.contactChannel}}
- 発信元電話番号:{{$.Custom.callerInfo}}
スクリプトを実行し、エラーがないことを確認します。
python3 test.py
その後、コンソール上で、AIプロンプトを追加したAIエージェントを作成し、デフォルトのセルフサービスのAIエージェントに指定します。
Lambda作成
Amazon Q in Connectのセッションにカスタムデータを追加するLambda関数を作成します。
この関数は、Amazon Connectのコンタクト情報からチャネルと発信元電話番号を取得し、Lambda関数内で現在日時を生成して、これら3つの情報をAmazon Q in Connectのセッションデータとして更新します。
import json
import boto3
from datetime import datetime
from zoneinfo import ZoneInfo
connect_client = boto3.client('connect')
qconnect_client = boto3.client('qconnect')
def lambda_handler(event, context):
print('Event Received:' + json.dumps(event, ensure_ascii=False))
try:
# Amazon Connect のコンタクトデータなどを取得
contact_data = event.get('Details', {}).get('ContactData', {})
instance_arn = contact_data.get('InstanceARN')
contact_id = contact_data.get('ContactId')
customer_endpoint = contact_data.get('CustomerEndpoint', {})
channel = contact_data.get('Channel', '')
if not instance_arn or not contact_id:
raise ValueError("InstanceARN または ContactId が見つかりません")
# InstanceARN から InstanceId を抽出
instance_id = instance_arn.split('/')[-1]
# 発信元情報を取得(チャネルに応じて処理)
caller_info = "不明"
if channel == "VOICE" and customer_endpoint:
caller_info = customer_endpoint.get('Address', '不明')
elif channel == "CHAT":
caller_info = "チャット"
# Amazon Connect の コンタクト 情報を取得
contact_response = connect_client.describe_contact(
InstanceId=instance_id,
ContactId=contact_id
)
contact_info = contact_response.get("Contact")
if not contact_info:
raise ValueError("Contact情報が取得できませんでした")
# Amazon Q in Connect のセッション ARN から Assistant ID と Session ID を取得
wisdom_info = contact_info.get("WisdomInfo")
if not wisdom_info:
raise ValueError("WisdomInfo が見つかりません")
session_arn = wisdom_info.get("SessionArn")
if not session_arn:
raise ValueError("SessionArn が見つかりません")
# Session ARN の解析
arn_parts = session_arn.split('/')
if len(arn_parts) >= 2:
assistant_id = arn_parts[-2]
session_id = arn_parts[-1]
else:
raise ValueError(f"SessionARN の解析に失敗しました: {session_arn}")
# 現在日時を取得(日本時間)
jst = ZoneInfo('Asia/Tokyo')
current_datetime = datetime.now(jst).strftime('%Y年%m月%d日 %H時%M分')
# セッションデータ(プロンプトで使用される情報のみ)
reservation_data = [
{"key": "currentDateTime", "value": {"stringValue": current_datetime}},
{"key": "contactChannel", "value": {"stringValue": channel}},
{"key": "callerInfo", "value": {"stringValue": caller_info}}
]
# Amazon Q in Connect のセッションデータを更新
response = qconnect_client.update_session_data(
assistantId=assistant_id,
sessionId=session_id,
data=reservation_data
)
print('Session data updated successfully')
return {
"statusCode": 200,
"body": json.dumps({
"message": "Session data updated successfully",
"sessionId": session_id,
"currentDateTime": current_datetime,
"contactChannel": channel,
"callerInfo": caller_info
}, ensure_ascii=False)
}
except Exception as e:
print(f"Error: {str(e)}")
return {
"statusCode": 500,
"body": json.dumps({
"message": "Error updating session data",
"error": str(e)
})
}
このコードでは、Amazon Connectのコンタクト情報を取得し、その中のWisdomInfoからセッションARNを解析してAssistant IDとSession IDを取得します。
その後、現在日時を日本時間で取得し、チャネル情報と発信元電話番号と合わせて3つのカスタムデータを作成し、Amazon Q in Connectのセッションデータとして更新しています。
Lambda関数で作成したカスタムデータは、AIプロンプト内で変数として参照できます。
Lambda関数でcurrentDateTime
、contactChannel
、callerInfo
の3つのキーで登録したデータは、プロンプト内で以下のように{{$.Custom.キー名}}
の形式で参照できます。
<user_infomation>
- 現在日時:{{$.Custom.currentDateTime}}
- 利用チャネル:{{$.Custom.contactChannel}}
- 発信元電話番号:{{$.Custom.callerInfo}}
</user_infomation>
これにより、AIエージェントは動的に取得された現在時刻、チャネル、発信元電話番号の情報を使用して、より適切な応答を生成できます。
以下のIAMポリシーとAWSLambdaBasicExecutionRoleポリシーをLambdaのIAMロールにアタッチします。
your-assistant-idはアシスタントID、your-instance-idはConnectインスタンスIDです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"connect:DescribeContact"
],
"Resource": "arn:aws:connect:ap-northeast-1:アカウントID:instance/your-instance-id/contact/*"
},
{
"Effect": "Allow",
"Action": [
"wisdom:UpdateSessionData"
],
"Resource": "arn:aws:wisdom:ap-northeast-1:アカウントID:session/your-assistant-id/*"
}
]
}
Connectフロー
今回利用するフローは以下のとおりです。
このConnectフローでは、まず音声設定やログ設定を行った後、Amazon Q in Connectセッションを作成し、Lambda関数を呼び出して現在時刻や発信元電話番号などのカスタムデータをセッションに追加します。
その後、Lexボットと連携して対話を開始し、予約確定時(CONFIRM_RESERVATION
ツール選択時)には顧客名、電話番号、予約日時をコンタクト属性として保存して処理を完了します。
[コンタクト属性の設定]ブロックでは、以下の予約情報をコンタクト属性に保存します。
customer_name
:顧客名phone_number
:電話番号reservation_date
:予約日reservation_time
:予約時刻
試してみる
Claude 3.5 Sonnetを使用したAIエージェントの動作を、2025年7月25日に検証しました。
各レスポンスには4~8秒程度の処理時間がかかりましたが、複雑な日付計算や適切な対話フローの実行が確認できました。
2025年7月25日に試しました。
会話1
BOT : お問い合わせ内容をお伝えください。
Customer : 予約したいです。
FOLLOW_UP_QUESTIONツールが選択
BOT : かしこまりました。まず、お名前をお教えいただけますでしょうか?
Customer : 田中です。
FOLLOW_UP_QUESTIONツールが選択
BOT : 田中様、ありがとうございます。次に、ご連絡先についてお伺いします。こちらの発信元電話番号、0,5,0,x,x,x,x,x,x,x,x、でよろしいでしょうか?もし違う番号でしたら、お教えください。
Customer : はい、それで結構です。
FOLLOW_UP_QUESTIONツールが選択
BOT : 承知いたしました。次に、ご予約希望日をお教えください。何月何日をご希望でしょうか?
Customer : 7月26日の午後6時でお願いします。
FOLLOW_UP_QUESTIONツールが選択
BOT : 7月26日の午後6時でのご予約ということでよろしいでしょうか?
Customer : はい、間違いありません。
FOLLOW_UP_QUESTIONツールが選択
BOT : ご予約内容を確認させていただきます。お名前は田中様、お電話番号は0,5,0,x,x,x,x,x,x,x,x、予約日は7月26日の午後6時でのご予約ということでよろしいでしょうか?
Customer : はい、お願いします。
CONFIRM_RESERVATIONツールが選択
BOT : ありがとうございます。田中様の7月26日午後6時のご予約を承りました。当日お待ちしております。
【SessionAttributes】
- customer_name: "田中"
- phone_number: "050xxxxxxxx"
- reservation_date: "2025-07-26"
- reservation_time: "18:00:00"
標準的な予約フローが正常に動作しています。発信元電話番号を桁区切り形式で表示し、最終確認を経て予約を確定しています。
会話2
BOT : お問い合わせ内容をお伝えください。
Customer : 予約したいです。名前はヤマダです。
FOLLOW_UP_QUESTIONツールが選択
BOT : ヤマダ様、承知いたしました。ご連絡先についてお伺いします。こちらの発信元電話番号、0,5,0,x,x,x,x,x,x,x,x、でよろしいでしょうか?もし違う番号でしたら、お教えください。
Customer : 大丈夫です。明日の6時に予約したいです。
FOLLOW_UP_QUESTIONツールが選択
BOT : かしこまりました。7月26日の6時とのことですが、午前6時でしょうか、それとも午後6時でしょうか?
Customer : 午後6時でお願いします。
FOLLOW_UP_QUESTIONツールが選択
BOT : ご予約内容を確認させていただきます。お名前はヤマダ様、お電話番号は0,5,0,x,x,x,x,x,x,x,x、予約日は7月26日の午後6時でのご予約ということでよろしいでしょうか?
Customer : はい、お願いします。
CONFIRM_RESERVATIONツールが選択
BOT : ありがとうございます。ヤマダ様の7月26日午後6時のご予約を承りました。当日お待ちしております。
【SessionAttributes】
- customer_name: "ヤマダ"
- phone_number: "050xxxxxxxx"
- reservation_date: "2025-07-26"
- reservation_time: "18:00:00"
顧客が最初に名前を提供し、複数の情報を同時に伝えるケースです。AIが「明日」を具体的な日付に変換し、午前・午後の曖昧性を適切に確認しています。
会話3
BOT : お問い合わせ内容をお伝えください。
Customer : 予約したいです。名前は田中です。
FOLLOW_UP_QUESTIONツールが選択
BOT : 田中様、ありがとうございます。次に、ご連絡先についてお伺いします。こちらの発信元電話番号、0,5,0,x,x,x,x,x,x,x,x、でよろしいでしょうか?もし違う番号でしたら、お教えください。
Customer : 違います。090xxxxxxxxです。
FOLLOW_UP_QUESTIONツールが選択
BOT : 承知いたしました。電話番号は、0,9,0,x,x,x,x,x,x,x,x、でお間違いございませんでしょうか?それでは次に、ご予約希望日をお教えください。何月何日をご希望でしょうか?
Customer : 7月23日の3時でお願いします。
FOLLOW_UP_QUESTIONツールが選択
BOT : 申し訳ございません。7月23日は過ぎてしまっております。ご予約は8月23日午後3時でお考えでしょうか?それとも別の日程をご希望でしょうか?
Customer : 8月23日午後3時でお願いします。
FOLLOW_UP_QUESTIONツールが選択
BOT : ご予約内容を確認させていただきます。お名前は田中様、お電話番号は0,9,0,x,x,x,x,x,x,x,x、予約日は8月23日の午後3時でのご予約ということでよろしいでしょうか?
Customer : はい、お願いします。
CONFIRM_RESERVATIONツールが選択
BOT : ありがとうございます。田中様の8月23日午後3時のご予約を承りました。当日お待ちしております。
【SessionAttributes】
- customer_name: "田中"
- phone_number: "090xxxxxxxx"
- reservation_date: "2025-08-23"
- reservation_time: "15:00:00"
発信元電話番号とは異なる番号を指定し、過去の日付を指定したケースです。AIが現在時刻を参照して過去の日付を判断し、適切な代替案を提案しています。
チャネル
チャットチャネルの場合、発信元電話番号が取得できないため、以下のように直接電話番号を聞く動作に変わります。
<一部省略>
BOT : 佐藤様、ありがとうございます。次に、ご連絡先のお電話番号をお教えいただけますでしょうか?"
チャネル情報を活用して、適切な情報収集方法に自動的に切り替わることが確認できました。
最後に
Amazon Q in Connectのセッションにカスタムデータを追加することで、現在時刻、発信元電話番号、チャネル情報を活用したより高度なAIエージェントを構築できました。
時刻情報を渡すことで、過去の日付や相対的な日付表現に対する適切な判断が可能になり、発信元電話番号の自動取得により顧客の利便性も向上しました。
今回はレストランの予約システムを例に実装しましたが、この仕組みは他の業務にも応用可能です。本記事を参考に、カスタムデータを活用したAIエージェントを実装してみてください。
参考