【AWSハンズオン】「Amazon Kendraで簡単に検索システムを作ろう！」をやってみた

# はじめに

今回は2023年に公開されたAmazon Kendraの入門編ハンズオンに取り組んでみたので、そちらの情報を共有したいと思います。

ハンズオンは以下リンクから申し込みできます。
[申し込みリンク](https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-Amazon-Kendra-2023-reg-event.html "https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-Amazon-Kendra-2023-reg-event.html")

ご参考までに、当ハンズオンが公開された記事のリンクも載せておきます。

[Amazon Kendra 入門ハンズオンを公開しました！– AWS Hands-on for Beginners Update | Amazon Web Services ブログ](https://aws.amazon.com/jp/blogs/news/aws-hands-on-for-beginners-22/ "https://aws.amazon.com/jp/blogs/news/aws-hands-on-for-beginners-22/")

なお本記事ではハンズオンの内容やKendraの仕様について細かめに記載しているため、多少長い記事となっています。全て読んでいただけると嬉しいですが、お時間が少ない場合には目次からご興味のある内容まで飛んでいただければと思います。

# 前提条件

今回実施者はPowerUserAccessとIAMFullAccessを持ったIAMユーザーで作業を行いました。ハンズオンの一部でIAMロールを新たに作成する必要があるため、基本的なAWSサービスに対する操作ができる権限＋IAMロールを作成する権限を持ったIAMユーザーの準備が必要です。

# Amazon Kendraとは

そもそもAmazon Kendraとはどういったサービスなのかについて最初に触れておきたいと思います。

[Amazon Kendra](https://docs.aws.amazon.com/ja_jp/kendra/latest/dg/what-is-kendra.html "https://docs.aws.amazon.com/ja_jp/kendra/latest/dg/what-is-kendra.html")とは「機械学習を活用したインテリジェントなエンタープライズ検索で回答を迅速に見つける」ことができるサービスです。つまり、機械学習を用いて社内のドキュメント等の検索システムを構築することができるようになるということです。

基本的な概念として、Amazon Kendraでは「**インデックス**」と呼ばれる索引を作成し、どこに何のデータがあるのかを管理しています。また検索をかけるデータソースに対してアクセス制御を行う事も可能で、「○○部門の人しかアクセスできないデータソース」等の設定も行えるようです。（今回のハンズオンではそこまで対応していないので、実際の設定方法等は未記載です。）

実運用としては下記画像のように基盤モデルと呼ばれるLLM（Large Language Model）と組み合わせて、「生成AIとして質問をしたら、社内ドキュメント類から最適解を検索して流暢な日本語で回答してくれる」ようなシステムを構築することも検討できます。

![kendra 0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804767/7106ac7a-5f54-5746-7ce3-78d1cb92597a.png)
(LLMと連携したKendraの生成AIシステム簡易構成図例)

# ハンズオン概要

今回のハンズオンではまず下記図のような小規模検索システムを構築しました。

![kendra 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804767/cbd4cb85-0da3-6b1d-550c-ac8299f6330e.png)
(Kendraハンズオンで構築するシステム簡易構成図)

作業の大きな流れとしては以下のようになります。

1. インデックスの作成
2. データソースの追加
3. 追加されたデータソースから情報をSync
4. 検索
5. 応用編）Webアプリケーションのデプロイ

また、今回のハンズオンは2種類のデータソースを設定する流れとなっており、

　① S3バケットをデータソースとする例
　② Webページをデータソースとする例

の2種類を使用した構築ハンズオンです。インデックスは同じものを使いながら、検索をかけるデータソースとしてS3やWebページを追加するという流れです。

初心者向けのハンズオンとしては、まずKendraにデータソースからSyncした情報を基にAWS Management Console上のKendra検索画面にて検索結果を表示するというシンプルな形となっています。

![kendra 1.1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804767/0edd187a-e800-2eb9-8f71-0713b083eae0.png)
(AWS Management Console上でのAmazon Kendra検索画面)

その後、応用編としてWebアプリケーションを構築し、アプリケーションから検索をかけるというハンズオンを行います。

進め方としては基本的にハンズオン公式のWebサイト上に貼り付けられているYoutube動画の説明通りに進めていきます。

# ハンズオンの内容
### 1. インデックスの追加

Kendraで検索をかけるための索引を準備するため、Management Consoleでインデックスを作成します。この際に新しくIAMロールを作成した（Create a new roleを選択することで自動生成される）のですが、内容を確認したみたところ主にCloudWatch Logsへの書き込みを行う権限を付与しているようでした。以下が実際のJSONです。
```json:Index作成時に自動作成されるIAMロールにアタッチされたポリシー例
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:PutMetricData"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "cloudwatch:namespace": "AWS/Kendra"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogGroups"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup"
            ],
            "Resource": [
                "arn:aws:logs:us-east-1:<アカウントID>:log-group:/aws/kendra/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogStreams",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:us-east-1:<アカウントID>:log-group:/aws/kendra/*:log-stream:*"
            ]
        }
    ]
}
```

その他にも以下のような設定ができるようでした。

- インデックスの中身を暗号化するための暗号化キー指定
    - デフォルトでもKendraのデフォルトキーを使って暗号化されるため、事前に用意が無くてもインデックス作成は可能
- アクセスコントロールリストの作成、及びIAM Identity Centerの利用
    - OpenID等のトークンを利用したアクセス制御を行う場合にはアクセスコントロールリストを設定する
    - 既にIAM Identity CenterでSSO管理をしている場合には利用可能
- エディションの選択（Developer Edition or Enterprise Edition）
    - Developer Edition：**検証目的**で利用（本番環境には不向き）
    - Enterprise Edition：本番ワークロードで利用（Developer Editionと比べて接続できるデータソースの数が多く、可用性も高い）

今回のハンズオンでは検証目的のため暗号化や認証の追加設定はせず、Developer Editionにて実施しました。

::: note warn
筆者が本ハンズオンを行った際インデックスの作成は数分で完了しましたが、解説動画にて説明されている通り、インデックスの作成には最大30分程度かかることもあるようです。索引としてインデックスを作成して、そのインデックスに対してデータソースを登録・Syncしていく流れなので、この段階では索引から検索をかけるデータの器を作っているイメージだと考えています。
:::

詳しくは[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/kendra/latest/dg/hiw-index.html#index-searching "https://docs.aws.amazon.com/ja_jp/kendra/latest/dg/hiw-index.html#index-searching")に記載されているインデックスの説明をご覧ください。

### 2. データソースの追加

続いてインデックスにデータソースから内容を取り込む作業を行います。今回のハンズオンではPDF化されたAWS公式ドキュメントの一部をS3に格納しインデックスに取り込むパターンと、Webページの内容をインデックスへ取り込むパターンの合計2パターンを実施しました。

インデックスに取り込むデータソースの選択画面では、ハンズオンで利用するデータソース以外にも様々なサービスへのコネクターが用意されていました。

![kendra 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804767/3893ada3-2e09-0058-7ecf-1c1609b25922.png)
（例：RDSやS3等の各種AWSサービス、Box、Dropbox、Google Drive、OneDrive、Slack、etc.）

参考リンク：[Kendraがサポートしているデータソース](https://docs.aws.amazon.com/ja_jp/kendra/latest/dg/hiw-data-source.html "https://docs.aws.amazon.com/ja_jp/kendra/latest/dg/hiw-data-source.html")


このデータソース選択画面にて**取り込みたいデータ元を選択し、詳細を設定して実際にデータをSyncする**準備を行います。データソースとして取り込む対象ドキュメントの言語指定やIAMロールの指定、VPCの設定（VPCを介したデータソースへのアクセスが必要な場合に使用）等を行うことができます。

このステップでのIAMロールは**インデックス作成時に新規作成したIAMロールとは別物**となります。S3をデータソースとするパターンでの実際のJSONを見てみると、S3に対するGetやListアクションに加え、**Kendraに対するBatchPutDocumentやBatchDeleteDocumentアクションを許可**しているようです。
```json:データソース作成時に作成されるIAMロールにアタッチされたポリシー例
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::<S3バケット名>/*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::<S3バケット名>"
            ],
            "Effect": "Allow"
        },
        {
            "Effect": "Allow",
            "Action": [
                "kendra:BatchPutDocument",
                "kendra:BatchDeleteDocument"
            ],
            "Resource": "arn:aws:kendra:us-east-1:<アカウントID>:index/<インデックスUniqueID>"
        }
    ]
}
```
Webページをデータソースとする場合のIAMロールでは、S3やKendraに対する許可に加えてSecretsManagerやKMS、EC2等の権限も付与されていました。

また基本的な設定に加え、以下の設定ができるようです。

**S3がデータソースの場合：**
![kendra 2.1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804767/b15ce3a0-49a2-5381-32a5-26e188bcdb92.png)
(データソースをS3にする際の設定画面例)

- データソースの詳細設定
    - 実際にデータソースとして取り込むS3バケットを指定する
- Metadataファイルの指定
    - データソースに付加情報を与え、特定の情報からのみ検索をかけるといった追加設定を行う（議事録からのみ検索させる等）
- Access Control Listの指定
    - ユーザーやグループに対してアクセス制御を行う設定を追加する（運用者のみがアクセスできるデータソース、管理者のみがアクセスできるデータソース等）
- Sync方法の指定
    - 全量Syncを行うか、前回Syncとの差分のみSyncを行うか等を設定する
- Syncスケジュールの設定
    - Kendraがデータソースからデータを取り込む頻度についてスケジュール化して設定する（On-demand、Hourly、Daily、Weekly、Monthly、Custom等）

**Webページがデータソースの場合：**
- ソースURLの指定
    - データソースとなるWebページのURLを追加する（複数設定も可能なため、ドメイン毎に検索対象を絞ったり複数ドメインから検索を行うことも可能）
- 認証設定
    - Webページにアクセスするために認証が必要な場合は設定を行う
- Webプロキシ設定
    - プロキシを指定する必要がある場合は、ホスト名やポート番号等を指定する
- Syncスコープの指定
    - Webクローリングの対象をドメインのみ、サブドメインまで、リンクしているドメインも含めて全て、等で指定する
- その他Syncスコープの詳細設定
    - 上記スコープの指定に加えて更に詳細な設定を行う
- Sync方法の指定
    - 全量Syncを行うか、前回Syncとの差分のみSyncを行うか等を設定する
- Syncスケジュールの設定
    - Kendraがデータソースからデータを取り込む頻度についてスケジュール化して設定する（On-demand、Hourly、Daily、Weekly、Monthly、Custom等）

初期設定画面上で利用する目的や用途によって細かな設定を行うことができるようになっていました。今回のハンズオンではシンプルにS3やWebページをデータソースとして、On-demandでSyncを行う形で設定を行いました。

### 3. データのSync

前述の通り本ハンズオンではOn-demandでデータをSyncする設定を行ったため、データソースとしてS3バケットやWebページの追加が完了したら実際にSyncしていきます。
![kendra 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804767/66162d64-e543-5513-7c9f-9a0270382e30.png)
(Syncを行った実際の画面例)

インデックスに対してデータのSyncを行うことで、毎回データソース元に検索をかけるのではなく、Kendraがデータソースのドキュメントを整理した索引（＝インデックス）を活用して迅速に検索を行えるようにしている形だと理解しています。

今回S3がデータソースの場合（量がそこまで多くないPDFファイル5つのみのSync）は数分で完了しましたが、Webページがデータソースの場合（2つのURLをSync）は15分～20分程度かかりました。場合によっては少量のデータSyncでも数十分から数時間かかることもあるようです。**実際に検索システムとして構築する際には膨大なデータソースから検索をかけることが予想されるため、その際Syncにどれだけ時間がかかるのか少し懸念が残ります。**

### 4. 検索

インデックスへデータソースからのデータSyncが完了したら、実際にManagement Console上のKendra検索ページから検索をかけることができます。基本的なUIとしては普段使うGoogle等の検索エンジンと大差ないですが、1つ注意点があります。

**前述の通りデータソースを指定する際に標準言語も指定をするのですが、検索画面でも正しい言語を指定する必要があります。**今回データソースとして指定したS3バケット内のドキュメントやWebページは日本語のため、検索画面の言語設定も日本語になっていないと検索結果が表示されません。

成功例：
![kendra 4.1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804767/d31fda04-77ab-d256-a3a0-561fd8ae32d5.png)
(Kendra検索画面 -成功例-)

失敗例：
![kendra 4.2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804767/ba3dd76f-bbed-e975-65df-3f188cbbf13c.png)
(Kendra検索画面 -失敗例-)

筆者がKendraの検索画面を操作した際には言語設定がデフォルトでEnglishとなっていたため、初回の検索が失敗しました。

### 5. Webアプリの構築

本ハンズオンの応用編として、Webアプリケーションの構築をCloudFormationを使用して行いました。作成したKendraのインデックスに加えてAWS AmplifyやCognitoと連携してWebアプリケーションをデプロイし検索をかけてみるといった目的となっており、基本的な構成は以下の通りです。

![kendra 5.1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804767/4355bcf6-556f-182c-d065-49e6245f5b4e.png)
(Webアプリケーション簡易構成図)

日本語での検索を行うためにCodeCommit上のコードを一部編集する必要がありますが、基本的にはCloudFormationで全て自動デプロイされます。デプロイが完了したら、実際にブラウザ経由で検索をかけてみます。

![kendra 5.2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804767/af439488-27fc-014b-68a3-d82ae582ee33.png)
(Webアプリケーション検索例)

結果としてManagement Console上のKendra検索画面で検索をかけた際と同じ結果が返ってきました。本ハンズオンで構築したWebアプリケーションを利用して、Management ConsoleにログインすることなくKendraのインデックスから検索をかけられていることが分かります。また、質問に対する回答の情報源についてもリンク先へ飛ぶことで確認できるため、情報の信ぴょう性について自身で確認することもできます。

# まとめ

本ハンズオンでは以下項目について実際に操作し体験できました。
- Amazon Kendraのインデックス作成
- データソースの追加とインデックスへのSync
- Management Console上で検索を実施
- Webアプリケーションをデプロイし、ブラウザ経由で検索を実施

筆者のAmazon Kendraに対する個人的な感想としては、インデックスにSyncさせるデータソースの設定方法がすごくシンプルで、かつアクセス制御や認証等の必要な機能を兼ね備えている便利なサービスという印象を受けました。AWSのみならず他のクラウドサービスプロバイダーや生成AIサービスベンダーも近しいサービスを提供していると思いますが、「AWSでのワークロードを実行していてその中のデータソースを効率的に生成AIと絡めて活用したい」といった場合には最適の実装方法かと思います。

また冒頭に記載したLLMとの連携を含めた生成AIのシステムをAWS上に構築することで、企業内でクローズドに利用できるセキュアなエンタープライズ検索システムを実装することもできると思います。

本ハンズオンはAmazon Kendraの基本的な挙動や操作について学ぶのみにとどまっていますが、今後更にKendraを活用できるよう検証していき、追加でハンズオン等出てきましたら触ってみようと思います。

以上、長い記事となりましたがお読みいただきありがとうございました。