AWS Step FunctionsでAmazon Connectでの会話内容を要約し、コンタクト詳細に表示する方法

AWS Step FunctionsでAmazon Connectでの会話内容を要約し、コンタクト詳細に表示する方法

Clock Icon2025.04.03

はじめに

本記事では、AWS Step Functionsを使用して、Amazon Connect Contact Lensで文字起こしした内容を日本語で要約し、コンタクト詳細画面に表示する方法を紹介します。

Contact Lensには、会話内容の文字起こしと要約機能が標準で搭載されています。
ただし、要約機能は日本語に対応していません。

https://docs.aws.amazon.com/ja_jp/connect/latest/adminguide/supported-languages.html#supported-languages-contact-lens

そこで、Contact Lensが文字起こしデータをS3に保存した際のトリガーで、Step Functions ステートマシンからAmazon Bedrockを利用して日本語の要約を生成します。

生成した要約は、コンタクト詳細画面の属性として保存することで、以下のように表示できます。

cm-hirai-screenshot 2025-03-24 10.43.07
コンタクト詳細に要約文を表示

構成は以下の通りです。

cm-hirai-screenshot 2025-03-24 10.27.58

処理の流れは以下の通りです。

  1. Contact Lens が会話を文字起こしし、S3 に保存
  2. S3 の PUT イベントが CloudTrail を通じて EventBridge にイベントを送信
  3. EventBridge が Step Functions を起動
  4. Step Functions が S3 から文字起こしデータを取得
  5. Bedrock (Claude) で会話の要約を生成
  6. Connect UpdateContactAttributes API で要約をコンタクト属性として保存
  7. コンタクト詳細画面に要約が表示される

以前、AWS Lambdaを利用した方法を執筆しましたが、今回はコード保守の負担低減のため、Step Functionsを採用しました。

https://dev.classmethod.jp/articles/amazon-connect-contact-lens-japanese-summary/

前提条件

ステートマシン用IAMポリシー作成

以下のIAMポリシーを作成します。Connectインスタンスの文字起こしが保存されているS3バケット名とConnectインスタンスARNは各自変更ください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::amazon-connect-xxxxxxxxxx/Analysis/Voice/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "bedrock:InvokeModel"
            ],
            "Resource": [
                "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-3-5-sonnet-20240620-v1:0"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "connect:UpdateContactAttributes"
            ],
            "Resource": [
                "arn:aws:connect:ap-northeast-1:111111111111:instance/3ff2093d-af96-43fd-b038-3c07cdd7609c/contact/*"
            ]
        }
    ]
}

ステートマシン作成

ステートマシンを作成します。

cm-hirai-connect-transcript-summarizer
cm-hirai-screenshot 2025-03-24 8.40.10

{
  "Comment": "Amazon Connect 会話要約ワークフロー",
  "StartAt": "GetTranscriptFromS3",
  "QueryLanguage": "JSONata",
  "States": {
    "GetTranscriptFromS3": {
      "Type": "Task",
      "Resource": "arn:aws:states:::aws-sdk:s3:getObject",
      "Arguments": {
        "Bucket": "{% $states.context.Execution.Input.detail.requestParameters.bucketName %}",
        "Key": "{% $states.context.Execution.Input.detail.requestParameters.key %}"
      },
      "Assign": {
        "transcriptData": "{% $parse($states.result.Body) %}"
      },
      "Next": "ExtractTranscriptText"
    },
    "ExtractTranscriptText": {
      "Type": "Pass",
      "Assign": {
        "transcriptText": "{% $join($transcriptData.Transcript.(Content), ' ') %}",
        "contactId": "{% $transcriptData.CustomerMetadata.ContactId %}"
      },
      "Next": "CheckTranscriptText"
    },
    "CheckTranscriptText": {
      "Type": "Choice",
      "Choices": [
        {
          "Condition": "{% $length($transcriptText) > 0 %}",
          "Next": "GenerateSummary"
        }
      ],
      "Default": "NoTranscriptFound"
    },
    "NoTranscriptFound": {
      "Type": "Fail",
      "Error": "NoTranscriptFound",
      "Cause": "No transcript text found in the file."
    },
    "GenerateSummary": {
      "Type": "Task",
      "Resource": "arn:aws:states:::bedrock:invokeModel",
      "Arguments": {
        "ModelId": "anthropic.claude-3-5-sonnet-20240620-v1:0",
        "ContentType": "application/json",
        "Accept": "application/json",
        "Body": {
          "anthropic_version": "bedrock-2023-05-31",
          "max_tokens": 1000,
          "temperature": 0.5,
          "messages": [
            {
              "role": "user",
              "content": [
                {
                  "type": "text",
                  "text": "{% '以下の通話内容を要約してください。\n\n【要約のフォーマット】\n1. 問い合わせ概要:顧客が何について問い合わせたか、簡潔に記載\n2. 詳細確認:エージェントがどのような情報を確認したか\n3. 対応内容:エージェントがどのように対応したか\n4. 結果:最終的な解決策や顧客の反応\n\n【通話内容】\n' & $transcriptText & '\n\n【出力のルール】\n- 「要約: 」で始め、一段落の自然な文章で記述する\n- 重要な情報(日付、注文番号、金額など)は具体的に含める\n- 専門用語や略語は避け、誰にでも分かりやすい表現を使用する\n- 顧客の感情の変化(不安→安心など)も可能な限り含める\n- 全体で100〜200文字程度に収める\n- 「まもなく解決予定」「対応完了」など、明確な結論で締めくくる\n\n【出力例】\n要約: 顧客が先週購入したヘッドフォン(注文番号BT-2023)の不具合について問い合わせ。エージェントは購入履歴と保証内容を確認し、製品が保証期間内であることを確認。無償交換または返金の選択肢を提案し、顧客は返金を希望。エージェントは返金手続きを開始し、5営業日以内に全額が返金される予定と案内。顧客は対応の迅速さに満足し、手続き完了。' %}"
                }
              ]
            }
          ]
        }
      },
      "Assign": {
        "summary": "{% $states.result.Body.content[type=\"text\"].text %}"
      },
      "Next": "UpdateContactAttributes"
    },
    "UpdateContactAttributes": {
      "Type": "Task",
      "Resource": "arn:aws:states:::aws-sdk:connect:updateContactAttributes",
      "Arguments": {
        "InstanceId": "arn:aws:connect:ap-northeast-1:111111111111:instance/3ff2093d-af96-43fd-b038-3c07cdd7609c",
        "InitialContactId": "{% $contactId %}",
        "Attributes": {
          "Summary": "{% $summary %}"
        }
      },
      "End": true
    }
  }
}

InstanceIdは、EventBridgeから渡されないため、指定が必要です。

各ステートごとの処理概要は以下の通りです

  1. GetTranscriptFromS3:S3から文字起こしJSONを取得
  2. ExtractTranscriptText:JSONから会話テキストとコンタクトIDを抽出
  3. CheckTranscriptText:会話テキストが存在するか確認
  4. GenerateSummary:Bedrockで会話要約を生成
  5. UpdateContactAttributes:要約をConnectIDのコンタクト属性に保存

プロンプト内容は以下の通りです。

以下の通話内容を要約してください。

【要約のフォーマット】
1. 問い合わせ概要:顧客が何について問い合わせたか、簡潔に記載
2. 詳細確認:エージェントがどのような情報を確認したか
3. 対応内容:エージェントがどのように対応したか
4. 結果:最終的な解決策や顧客の反応

【通話内容】
 & $transcriptText & 

【出力のルール】
- 「要約: 」で始め、一段落の自然な文章で記述する
- 重要な情報(日付、注文番号、金額など)は具体的に含める
- 専門用語や略語は避け、誰にでも分かりやすい表現を使用する
- 顧客の感情の変化(不安→安心など)も可能な限り含める
- 全体で100〜200文字程度に収める
- 「まもなく解決予定」「対応完了」など、明確な結論で締めくくる

【出力例】
要約: 顧客が先週購入したヘッドフォン(注文番号A-1)の不具合について問い合わせ。エージェントは購入履歴と保証内容を確認し、製品が保証期間内であることを確認。無償交換または返金の選択肢を提案し、顧客は返金を希望。エージェントは返金手続きを開始し、5営業日以内に全額が返金される予定と案内。顧客は対応の迅速さに満足し、手続き完了。

ステートマシン作成時に IAM ロールとポリシーが自動作成されますが、一部の IAM ポリシーは手動で作成する必要があります。
そのため、先ほど作成したポリシーを適用しましょう。

cm-hirai-screenshot 2025-03-24 8.54.00

EventBridge ルール作成

EventBridge ルールを作成します。
イベントパターンは以下の通りです。

文字起こしが保存されているS3バケット名は各自で変更してください。会話内容が保存されるS3バケットのS3 URIは例えば以下のとおりです。

  • s3://amazon-connect-xxxxxxxxxx/Analysis/Voice/2025/01/01/aa165854-149e-460f-94b3-facf03ae934e_analysis_2025-01-01T01_01_01Z.json
{
  "source": ["aws.s3"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventSource": ["s3.amazonaws.com"],
    "eventName": ["PutObject"],
    "requestParameters": {
      "bucketName": ["amazon-connect-xxxxxxxxxx"],
      "key": [{
        "prefix": "Analysis/Voice/"
      }, {
        "suffix": ".json"
      }]
    }
  }
}

ターゲットは先程作成したステートマシンにします。

試してみる

実際に電話での会話を行い、システムの動作を確認します。

電話での会話が終了すると、システムが自動的に会話を分析し、以下のようにコンタクト詳細画面に要約文が表示されました。
会話を2分程度した場合、S3バケットに保存されるまでに7分程度かかりました。そのため、会話終了後、要約文が表示されるまでに7分程度かかりました。

cm-hirai-screenshot 2025-03-24 10.43.07
コンタクト詳細に要約文を表示

要約: 顧客が最近注文した商品の未着について問い合わせ。エージェントは注文番号(123-456789-01234)を確認し、商品が3日前に発送済みで2025年2月14日配達予定と回答。顧客が配送遅延の表示を指摘したため、エージェントは天候の影響による1〜2日の遅延可能性を説明。顧客は状況を理解し、安心した様子。配送は進行中で、まもなく到着予定。

なお、EventBridgeからステートマシンに渡されるイベント内容は、以下の通りです。一部省略しています。

{
  "detail-type": "AWS API Call via CloudTrail",
  "source": "aws.s3",
  "account": "111111111111",
  "time": "2025-03-24T00:17:16Z",
  "region": "ap-northeast-1",
  "resources": [],
  "detail": {
    "eventTime": "2025-03-24T00:17:16Z",
    "eventSource": "s3.amazonaws.com",
    "eventName": "PutObject",
    "awsRegion": "ap-northeast-1",
    "requestParameters": {
      "bucketName": "amazon-connect-xxxxxxxxxx",
      "key": "Analysis/Voice/2025/02/13/aa165854-149e-460f-94b3-facf03ae934e_analysis_2025-02-13T02_47_18Z.json",
    },
    "readOnly": false,
    "resources": [
      {
        "type": "AWS::S3::Object",
        "ARN": "arn:aws:s3:::amazon-connect-xxxxxxxxxx/Analysis/Voice/2025/02/13/aa165854-149e-460f-94b3-facf03ae934e_analysis_2025-02-13T02_47_18Z.json"
      },
      {
        "accountId": "111111111111",
        "type": "AWS::S3::Bucket",
        "ARN": "arn:aws:s3:::amazon-connect-xxxxxxxxxx"
      }
    ],
    "eventType": "AwsApiCall"
  }
}

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.