0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Amazon Lex】Lambdaをフックして国内電話番号を正しく判定するチャットボットを構築してみた!

Last updated at Posted at 2025-03-12

はじめに

Amazon Lexを使用して、ユーザーの電話番号を聞き取るチャットボットを構築する際には、組み込みスロットタイプ「AMAZON.PhoneNumber」を利用できます。
しかし、このスロットタイプは、「1234-5678」などの市外局番を除いた番号や、「123」などの短い数字列まで電話番号として解釈してしまうため、そのままでは意図しない入力を許してしまうことがあります。

本記事ではチャットボットにLambda関数をフックすることで、国内の携帯電話(070/080/090など※)や固定電話(03/06など)のみを受け付けるチャットボットを構築します。

携帯番号への060番号の追加については対応ができていません。

本記事の情報は2025年3月時点のものです。
最新情報については公式ドキュメントをご確認ください。

目次

1.動作環境
2.前提条件
3.Lambda Layerの準備
4.Lambda関数の作成
5.Lexチャットボットの作成
6.Lambda関数のフック前後での動作比較
まとめ

1. 動作環境

本記事で使用する環境は以下のとおりです。

  • AWS リージョン:東京
  • Amazon Lex:Lex V2
  • AWS Lambda:Node.js 20.x
  • google-libphonenumber (電話番号の解析ライブラリ)
  • npmを利用

2. 前提条件

本記事では以下を前提とします。

  • AWSアカウントが作成されていること
  • AWS Lambda 関数の作成権限やAmazon Lexのボット作成権限、またそれに係る権限を持つユーザーで操作を行うこと

3. Lambda Layerの準備

AWS Lambdaでgoogle-libphonenumberを使用するために、Lambda Layerを準備します。
google-libphonenumberはGoogleが提供しているlibphonenumberをNode.js向けにラップしたnpmパッケージで、以下の機能を提供しています。

  • 電話番号の解析(国コードの判定など)
  • 電話番号のフォーマット(国際形式、国内形式など)
  • 電話番号のバリデーション(正しい番号かどうかの確認)

3.1 必要なパッケージのインストール

以下のコマンドより、作成したnodejsフォルダにgoogle-libphonenumberをインストールします。

ターミナル
$ mkdir nodejs
$ cd nodejs
$ mkdir node_modules
$ cd node_modules 
npm install google-libphonenumber

  • 上記操作後、以下のようなディレクトリ構造になっていることを確認
nodejs
├── node_modules
│   └── google-libphonenumber
│       ├── LICENSE
│       ├── README.md
│       ├── dist
│       │   └── libphonenumber.js
│       └── package.json
├── package-lock.json
└── package.json

3.2 パッケージのzip化

  • 用意したnodejsフォルダをzip化します。(任意のzip名でzip化してください。)
    • 今回はtest_custom_layerとしています。

$ zip -r test_custom_layer nodejs

3.3 Lambda Layerの作成

AWS Lambdaコンソール画面の「レイヤー」より、以下の設定でLambda Layerを作成します。
image.png

  • 名前:test_custom_layer
  • .zipファイルをアップロード: パッケージのzip化で作成したzipファイルを選択
  • 互換性のあるアーキテクチャ:x86_64
  • 互換性のあるランタイム:Node.js 20.x

4. Lambda関数の作成

AWS Lambdaコンソール画面の「関数の作成」より、以下の設定でLambda関数を作成します。

image.png

  • オプション:一から作成
  • 関数名:test_lex_phone_number_validation
  • ランタイム:Node.js 20.x
  • アーキテクチャ:x86_64
  • アクセス権限 , その他の構成:デフォルト

4.1 Lambda関数 コード

作成したtest_lex_phone_number_validationindex.mjsを以下のコードで上書きします。
このコードには、Lambdaコードフック元のLexチャットボットに入力された値が、日本国内の電話番号かを判定する処理が含まれています。(詳細はコメントアウトをご参照ください)

import libphonenumber from 'google-libphonenumber';

export const handler = async (event) => {

  // google-libphonenumber のユーティリティを取得
  const phoneNumberUtil = libphonenumber.PhoneNumberUtil.getInstance();
  const phoneNumberFormat = libphonenumber.PhoneNumberFormat;

  // Amazon Lex から受け取ったイベントオブジェクトからセッション情報を取得
  const sessionState = event.sessionState || {}; // セッション情報を取得(初回呼び出し時は空オブジェクト)
  const intentInfo = sessionState.intent || {}; // インテント情報を取得
  const slots = intentInfo.slots || {}; // インテント内のスロット情報を取得

  // スロット 'PhoneNumber' の値を取得(ユーザーが入力した電話番号)
  let phoneNumber = "";
  if (slots.PhoneNumber?.value?.interpretedValue) {
    phoneNumber = slots.PhoneNumber.value.interpretedValue;
  }

  // 初期状態のバリデーションフラグとメッセージを設定
  let validationFlag = false; // バリデーション結果(成功なら true)
  let validationMessage = ""; // ユーザーへ返すメッセージ

  // 電話番号が入力されている場合のみバリデーションを実施
  if (phoneNumber) {

      // 入力された電話番号を "JP"(日本)として解析
      const parsedPhone = phoneNumberUtil.parseAndKeepRawInput(phoneNumber, 'JP');

      // 解析した電話番号から国コードを取得(例: "JP")
      const regionCode = phoneNumberUtil.getRegionCodeForNumber(parsedPhone);

      // 取得した国コードが "JP"(日本)で、かつ有効な電話番号かどうかを確認
      if (regionCode === "JP" && phoneNumberUtil.isValidNumberForRegion(parsedPhone, "JP")) {
        validationFlag = true; // バリデーション成功
        validationMessage = "電話番号が正しく入力されました";

        // スロットの値をフォーマット済みの電話番号に更新
        slots.PhoneNumber = {
          value: {
            interpretedValue: phoneNumber, // もともとの入力値を格納
            originalValue: phoneNumber // 変更なしで格納
          }
        };
      } else {
        // 日本国内の有効な電話番号でない場合の処理
        validationMessage = "日本国内の電話番号のみ入力してください。再度入力をお願いします。";
        delete slots.PhoneNumber; // 不正な値を削除(スロットクリア)
      }
  }

  // Amazon Lex へのレスポンスを作成
  const response = {
    sessionState: {
      // バリデーション結果に応じて対話アクションを決定
      dialogAction: validationFlag
        ? { type: "Close", fulfillmentState: "Fulfilled" } // 成功時は会話を終了
        : { type: "ElicitSlot", slotToElicit: "PhoneNumber" }, // 失敗時はスロットの再入力を要求
      intent: {
        name: intentInfo.name || "", // インテント名を設定
        slots: slots, // スロット情報を更新
        state: validationFlag ? "Fulfilled" : "InProgress" // 成功時は完了、失敗時は進行中
      },
    },
    // ユーザーへの応答メッセージ
    messages: [{
      contentType: "PlainText",
      content: validationMessage
    }]
  };

  return response;
};

4.2 Lambda Layerの追加

image.png
Lambda 関数の設定画面から「レイヤーの追加」をクリックし、以下の設定でLambda LayerをLambda関数に追加します。
image.png

  • レイヤーを選択:カスタムレイヤー
  • カスタムレイヤー:test_custom_layer
  • バージョン:1

5. Lexチャットボットの作成

Amazon Lex チャットボットを作成し、電話番号の取得とバリデーションを行うための設定を行います。

5.1 ボットの設定

Amazon Lexコンソール画面の「ボットを作成」より、以下の設定でチャットボットを作成します。
image.png
image.png

  • 作成方法:空のボットを作成します。
  • ボット名:test_phone_number_bot
  • IAMアクセス許可:基本的な Amazon Lex 権限を持つロールを作成します。
  • 児童オンラインプライバシー保護法 (COPPA):いいえ
  • アーキテクチャ:x86_64
  • アイドルセッションタイムアウト:5分(デフォルト)

また、言語設定は以下の通りです。
image.png

  • 言語を選択:Japanese(JP)
  • 音声による対話:Kazuha(デフォルト)
  • インテント分類信頼スコアのしきい値:0.40(デフォルト)

5.2 スロットの追加

Amazon Lex ボット構築画面の「スロット」より、「スロットを追加」をクリックし、以下の設定でスロットを追加します。
image.png
image.png

  • 名前:PhoneNumber
  • スロットタイプ:AMAZON.PhoneNumber
  • プロンプト:任意の文字列

今回は、LexボットにLambda関数をフックし処理を委任するため、スロット内のプロンプトは再生されません。

5.3 サンプル発話の追加

スロットの追加で追加したスロット名を基にサンプル発話を追加します。
スロット名を中括弧{}で囲むことで、インテントに定義したスロットをインテントのトリガーとして使用することができます。

image.png

5.4 コードフックの有効化

コードフック-オプションより、「初期化と検証に Lambda 関数を使用」 をクリックし、有効化する。
image.png

5.5 コードフック用のLamnbda関数の設定

test_phone_number_bot > エイリアス >エイリアス名(TestBotAlias) >言語をクリックします。
image.png

Lambda関数の作成で作成したLambda関数を選択して「保存」をクリックします。
image.png

以上で準備完了です!

6. Lambda関数のフック前後での動作比較

Lexコンソールのテスト画面からメッセージを入力し、送信した際の動作を比較します。

6.1 Lambda関数をフックしていないLexチャットボットの場合

image.png

  • 実行結果
    • 国内の電話番号(070/080/090 などの携帯番号や 03/06 などの固定電話)を入力
      → 入力値を受け付け、チャットボットの処理を終了する。
    • 市外局番を除いた電話番号や、不適切な入力(短い数字列など)を入力
      入力値を受け付け、チャットボットの処理を終了する。

6.2 Lambda関数をフックしている Lex チャットボットでの実行結果

image.png

  • 実行結果
    • 国内の電話番号(070/080/090 などの携帯番号や 03/06 などの固定電話)を入力
      → 入力値を受け付け、チャットボットの処理を終了する。
    • 市外局番を除いた電話番号や、不適切な入力(短い数字列など)を入力
      「日本国内の電話番号のみ入力してください」などのエラーメッセージを返し、再入力を促す。

その他の入力値での比較

入力値 Lambda フックなしの動作 Lambda フックありの動作
090-1234-5678 受け付けて処理を終了(09012345678) 受け付けて処理を終了 (09012345678)
03-1234-5678 受け付けて処理を終了(0312345678) 受け付けて処理を終了(0312345678)
12345678901234567890 受け付けて処理を終了(12345678901234567890) エラー:「日本国内の電話番号のみ入力してください」
+1 310-555-6789 受け付けて処理を終了(+13105556789) エラー:「日本国内の電話番号のみ入力してください」
+81 90-1234-5678 受け付けて処理を終了(+819012345678) 受け付けて処理を終了

まとめ

本記事ではチャットボットにLambdaをフックし、国内の携帯電話(070/080/090など)や固定電話(03/06 など)のみを受け付けるチャットボットの構築方法を紹介しました。
AMAZON.PhoneNumberのみ設定した場合と比較して、Lambdaをフックすることでより正確なバリデーションが可能になり、不適切な入力を防ぐことができます。
また、今回利用したgoogle-libphonenumberは、国コードの判定の他、国内形式・国際形式・E.164形式などの電話番号のフォーマットも行える便利なパッケージです。
そのため、コードフック用のLambda関数をカスタマイズすることで、より柔軟なチャットボットの作成が可能です。

次回の記事では、Lambdaコードフックによる、より柔軟なチャットボットの開発方法を紹介します。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?