Lex＋Lambdaで、簡単なチャットボットを構築してみました

# やりたいこと
・Lex（サンプルボット）＋Lambdaで、簡単なチャットボットを構築

# ①Lexボットを作る
Lex画面に遷移、「ボットを作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/06061042-589d-110d-83b1-a4f1e46911fc.png)

Lexが提供するサンプルボットを試したいので、「例から開始」を選択
Lexは三つの例があり、今回は「旅行予約」のサンプルボットを選ぶ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/88b09304-80dd-ef00-721c-bf4f3379d595.png)

ボット名入力、IAMロールを新規で作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/9018b0a4-facd-017c-5dfc-b3e68bad2a86.png)

子供を守るための設問に、「児童オンラインプライバシー保護法 (COPPA)」に「はい」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/80adff5f-c5e6-d6f0-4041-61df9779226e.png)

詳細設定せずに「次へ」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/51210677-acd9-bf8e-c29f-55678194baa3.png)

「言語」をJapaneseにし、好きな音声を一つ選ぶ（老若男女いろいろな声があるね）、「完了」を押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/c0c1422c-9590-a234-5013-cb889f1fe766.png)

すると、ボットが構築された！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/4d863c29-c1ce-6fc8-56fb-ab66b486d19c.png)

# ②ボットの確認＋カスタマイズ
作ったボットをクリックし、左メニューの「インテント」をクリックすると、「ホテル予約」と「レンタカー予約」のボットが並んでいる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/8933f0c6-3403-97d2-0622-f3d1f15e302d.png)

「ホテル予約」をクリックしてみると、まず想定した会話フローが表示され、各質問の分岐および想定回答が確認できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/c4623700-0c7e-2759-603a-55ed1761fbbe.png)

一ボットは複数の仕事を処理できるので、それを「インテント」と言う
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/607b831e-c1a3-50a0-ed44-cb34917db387.png)

「サンプル発話」は。ユーザーが入力すると予想される代表的なフレーズ。
もし「都市名」らしい言葉が出たら、Lexは自動で認識できて、Location変数に格納する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/535d29f3-d307-6dd0-ed33-a419048f030e.png)

「初期応答」は、ユーザーの最初のリクエストを確認するメッセージ。初期状態は未設定ですが、「それではお手伝いします」でカスタマイズする！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/a322e4ca-a2bc-5f77-e652-2cc9f4f3b3e4.png)

「スロット」はボットがインテントを履行するために必要な情報。
ホテルを予約するのに、必要最小限の情報を質問でユーザーから聞き出す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/b8f1afc1-4f6a-f561-92ed-aa7191e81b84.png)

初期状態は四つしかないが、「スロットを追加」をクリックし、「何名様でしょうか？」を追加した！
Lexのほうで、様々な学習済みの「スロットタイプ」があり、例えば「AMAZON.City」を選択すると、会話中から自動で都市名らしき言葉を認識できる！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/97f52074-9d21-a44b-2ece-d8baad3197a5.png)

「確認」は、スロットですべての必要な情報をユーザーから聞き出したあとの確認メッセージ。
このタイミングで、ユーザーの反応を分析する。「はい」のようなポジティブ反応や、「いいえ」のようにネガティブ反応、それぞれに応じて分岐を設定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/2290da29-772a-44a4-a8a7-03997cb7595a.png)

「フルフィルメント」は「インテント」が完了時のメッセージを設定。
初期状態は空ですが、カスタマイズ内容を入れてみた！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/a324c443-a0aa-a7c6-4ff5-e3bb8eeef4e9.png)


「応答を閉じる」は、一連のやり取りが終わったタイミングの最後の挨拶メッセージ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/1def9890-bcd2-db85-d03c-11eefbc18ad7.png)

# ③Lambdaを作成する
Lambdaを開き、「関数の作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/9d06ea3b-5e04-9484-4257-fbaecd01f9f0.png)

「一から作成」を選択し、ランタイムは「Python3.13」にし、「関数の作成」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/acbbca37-c608-0e55-11a0-6fc45f2b7bc4.png)

関数を開き、コードを編集しデプロイ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/088f6121-ec5f-d366-6deb-aba9968f6319.png)

Lambda経由でDynamoとデータの取得や挿入、ほかのAI系サービスとの連携（BedRockなどほかのナレッジによって回答）ができるが、今回はLex＋Lambdaの連携だけ試したいので、ほかのサービスをいったん割愛する

今回は、「フルフィルメント」のタイミング（「インテント」完了時）でLambdaを発火させるのを想定し、レスポンスを以下のように設定した
```
import json

def lambda_handler(event, context):

    # Lexからの入力イベントを確認
    print("Event received from Lex:", json.dumps(event))

    response = {
        "messages": [
                {
                    "contentType": "PlainText",
                    "content": "以下のホテルが取れます：東横INN浅草、東横INN上野、どちらにしますか？"
                }
            ],
        "sessionState": {
            "dialogAction": {
                "type": "Close"
            },
            "intent": {
                "name": "BookHotel",
                "state": "Fulfilled"
            }
        }
    }


    return response


```
「フルフィルメント」時ではなく、話す途中で随時Lambdaを発火し、より複雑な分岐もできるので、そのときは以下のAWS公式を参照しつつ、適切にレスポンスの書き方を変更してください！

https://docs.aws.amazon.com/ja_jp/lexv2/latest/dg/lambda-common-structures.html

https://docs.aws.amazon.com/ja_jp/lexv2/latest/dg/lambda-input-format.html

# ④Lambdaと連携する
再び「Lex」に戻り、「ボット」＞「ボット名」＞「デプロイ」＞「エイリアス」でクリックし、言語の「Japanese」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/2fce2d05-056d-e2ed-c8e8-46ba30bb72fd.png)

先ほどのLambda関数を設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/0d64342c-6794-20a2-21fc-c991cf8262bc.png)

「BookHotelインテント」の設定画面に戻り、「フルフィルメント」の「詳細オプション」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/22550d5c-67d0-b714-1cbd-fd26c0121a58.png)

「フルフィルメントに Lambda 関数を使用」にチェックを入れる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/fc4e40b0-7af4-800f-1828-894a7c28dd71.png)


ちなみに、もし会話の開始時や途中に随時Lambdaをトリガーしたい場合、画面一番下の「初期化と検証に Lambda 関数を使用」にチェックを入れる必要がある。今回は設定しない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/101a52a3-c43c-3e20-4ddd-e6607ea31318.png)

# ⑤ボットを再構築＋テスト
すべての設定が終わったら、インテント画面右上の「構築」をクリックし、ボットを再構築する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/c2f51dac-bd48-f7e6-7042-a74ff8bafc95.png)

構築に成功したら、画面右上の「テスト」をクリックし、ボットをテストできる
そして、以下のようなボットが完成した！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/24dcd547-6790-7309-f0fb-a33feb130a53.png)

フルフィルメントのLambda関数からのレスポンスの表示できている！
（今回はLambdaにハードコードした内容をそのまま返すが、Lambda経由でDynamoやほかのAI系サービスからの結果を返すのもできる！）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/3d883ccd-a510-b86f-e251-7e92386d8bb9.png)


# 参考サイト
https://qiita.com/enumura1/items/93fc3c9dfa5c1ff49340#

https://qiita.com/hayao_k/items/268c333f3f383125fd30