RedshiftのゼロETL統合を使って、BedrockナレッジベースでDynamoDBを自然言語検索する

# 概要
RedshiftのゼロETL統合を使って、BedrockナレッジベースでDynamoDBを自然言語検索します。

# 説明
https://aws.amazon.com/jp/about-aws/whats-new/2024/12/amazon-bedrock-knowledge-bases-structured-data-retrieval/

https://aws.amazon.com/jp/about-aws/whats-new/2023/11/amazon-dynamodb-zero-etl-integration-redshift/

BedrockナレッジベースでRedshiftがデータソースに選べるようになり、自然言語でDBに対してクエリが行える様になりました。一方、RedshiftではゼロETL統合という機能でAWSの様々なDBと同期することができます。つまり、実質的にAWSの様々なDBをナレッジベースのデータソースにできるようになったと言うことではないでしょうか。
ナレッジベースのデータソースにしたRedshiftでDynamoDBとゼロETL統合を行い、チャット上から確かめます。

# 準備
### Redshift

Redshiftを作成していきます

![スクリーンショット 2025-02-20 9.02.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/5cb0f5fd-ec72-48da-9439-b3f412a4e874.png)

初回セットアップがあるので、デフォルト設定のまま保存をしてください。
ダッシュボードが表示されたら、右上の「ワークグループを作成」をクリックします。

![スクリーンショット 2025-02-20 9.49.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/59b46208-f827-404f-9ffd-acf676b15e4e.png)

以下のような設定で作成します。ほかはデフォルトのものでよいです。

ステップ1:
ワークグループの名前：test-zero-etl-dynamo

ステップ2:
名前空間：test-zero-etl-dynamo
許可：「IAMロールを作成 > IAMロールをデフォルトとして作成する」をクリック
1分ほどでワークグループの作成が完了します。

### dynamoDBテーブル

dynamoDBテーブルを作成していきます

![スクリーンショット 2025-02-20 10.08.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/7fa500e9-e315-4fa9-9ff0-a82589939dd7.png)

テーブル名: products
パーティションキー: product_id（文字列）
で作成してください

### Zero-ETL統合の作成

準備ができたのでdynamoDBとRedshiftのZero-ETL統合の作成をします
サイドバーから「ゼロETL統合」を選択し、「Create DynamoDB integration」を選択します。

![スクリーンショット 2025-02-20 10.14.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/733eeb96-24a8-4a1c-a2b2-ef4ee2bbdc0b.png)

以下のような設定で作成します。ほかはデフォルトのものでよいです。

ステップ1:
Integration name：test-zero-etl-dynamo-integration

ステップ2:
先ほど作成したdynamoDBテーブルを選択してください。画像のようなエラーがでるので「fix it for me」チェックを入れてください。
Zero-ETL統合を設定するには、選択したdynamoDBテーブルに適切なリソースポリシーとPITR設定が有効になっている必要があります。「fix it for me」オプションを選択すると、自動的に設定してくれます。

![スクリーンショット 2025-02-20 10.19.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/c9da2eab-d18e-400c-85c3-a69a6e390863.png)

ステップ3:
先ほど作成したRedshiftのワークグループを選択してください。画像のようなエラーがでるので「fix it for me」チェックを入れてください。こちらも必要な設定を自動的に設定してくれます。

![スクリーンショット 2025-02-20 10.25.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/48aca369-d4aa-449c-add2-725bc29e4003.png)

ステップ4:
変更なし

ステップ5:
内容を確認して、「Create DynamoDB integration」を選択すると、Zero-ETL統合の作成が開始します。ステータスが「アクティブ」になれば問題ないです。
次は作成したZero-ETL統合を選択し、Redshiftのデータベースを作成します。
「統合からデータベースを作成」を選択してください。

![スクリーンショット 2025-02-20 10.33.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/62c4346c-b1c1-4a69-bac7-97e5952a8074.png)

データベース名：dynamodb_zero_etl
で作成します。

![スクリーンショット 2025-02-20 10.36.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/5a5eda6f-0435-4ec3-a9d9-97241847a63f.png)

ここまでで、dynamoDBと同期するための設定が終了しました。
では実際にdynamoDBにデータを挿入し、同期の様子をみてみましょう。
コンソールからデータをJSONで挿入します

![スクリーンショット 2025-02-20 10.45.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/828195c8-eaf0-4506-aaf7-3cb2da7346ec.png)

挿入データ
```

{
    "product_id": {"S": "1"},
    "product_name": {"S": "もも肉の焼き鳥"},
    "sales": {"N": "800000"},
    "popular_region": {"S": "大阪府"}
},

```

![スクリーンショット 2025-02-20 10.56.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/2271b9cc-a4aa-4329-94ef-fddd21d22242.png)

dynamoDBへのデータ挿入と同時にRedshift側では自動同期が動いています。
実際にRedshift内のデータを確認してみましょう
「ゼロETL統合」から作成した統合を選択し、「データをクエリ」を選択

![スクリーンショット 2025-02-20 10.59.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/bd4a8e5a-3cf8-4037-a9b7-3782aa009bc7.png)

左側のワークグループ一覧から、今回作成した「test-zero-etl-dynamo」を選択し、「Federated user」で接続してください

![スクリーンショット 2025-02-20 11.04.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/4306678a-4bdf-4a3d-ba5f-d5645ef6098c.png)

dynamoDBの「products」テーブルが「test-zero-etl-dynamo」ワークグループの「dynamodb_zero_etl」データベースのテーブルとして存在していることがわかると思います。また、先程挿入したデータがクエリできています。

![スクリーンショット 2025-02-20 11.09.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/2b91fce0-af80-4aaf-bee7-686e57d88760.png)

これでRedshiftのゼロETL統合を用いてdynamoDBテーブルと同期する作業は完了です。

### ナレッジベースの作成

最後にナレッジベースを作成します。コンソールから「Create knowledge base with structured data store」を選択してください

![スクリーンショット 2025-02-20 11.16.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/e30212c7-e51d-46c9-97c6-60e62699c574.png)

以下のような設定で作成します。ほかはデフォルトのものでよいです。

ステップ1:
ナレッジベース名：dynamo-products
IAM 許可：新しいサービスロールを作成して使用
サービスロール名：AmazonBedrockExecutionRoleForKnowledgeBase_dynamo-products

ステップ2:
ワークグループとDBを選択する箇所があるので今回作成したものを選択してください。ほかはデフォルトで良いです。

![スクリーンショット 2025-02-20 11.21.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/4bce59a4-209b-4b92-98bb-74fe6a41416b.png)

ステップ3:
内容を確認して作成してください。

![スクリーンショット 2025-02-20 11.24.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/07760b25-c52a-4e3a-9ed8-9e18942226c2.png)

これでdynamoDBとゼロETL統合されたRedshiftをナレッジベースのデータソースにすることができました。

# 実行
### ナレッジベースの同期
ナレッジベースの同期を行い、コンソールから実際にチャットをしてみます。
その前に、ナレッジベースがRedshiftを操作できるように権限を付与します。

```
-- ナレッジベース用のDBユーザーを作成
CREATE USER "IAMR:AmazonBedrockExecutionRoleForKnowledgeBase_dynamo-products"
  WITH PASSWORD DISABLE;

-- ナレッジベースにスキーマ使用権限を付与
GRANT USAGE ON SCHEMA public 
  TO "IAMR:AmazonBedrockExecutionRoleForKnowledgeBase_dynamo-products";

-- ナレッジベースにsurveyテーブルへのSELECT権限を付与
GRANT SELECT ON products
  TO "IAMR:AmazonBedrockExecutionRoleForKnowledgeBase_dynamo-products";
```

上記SQLをRedshiftのエディタで実行してください

![スクリーンショット 2025-02-20 11.40.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/f1d91250-e638-4f89-9624-720f995dbf00.png)

ナレッジベースの「Query engine」から「dynamo_zero_etl」を選択して「同期」を開始してください。

![スクリーンショット 2025-02-20 11.42.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/8cc0a440-189b-4dec-aa75-4a898347a525.png)

ナレッジベースで使用するモデルを選択し、チャットを開始しましょう。
アクセス権がない場合は適当なモデルを申請してください。

![スクリーンショット 2025-02-20 11.44.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/f4dfbded-6e28-4b97-a052-315c91aba1f0.png)

# 結果

薄々予感はしていましたが、dynamoDBからの取り込みはパーティションキーとソートキー以外の属性に関してはまとめてvalueに入っているので価格や、名前では検索ができないですね…

![スクリーンショット 2025-02-20 12.07.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3830224/c5f5553a-b8bc-44de-83b5-72e78d75b61d.png)

今回は、パーティションキーだけ設定していたのでidでのみの検索が可能でした

一応、下記クエリを行うことができればpopular_regionが大阪府であるデータを抽出することができます。

```
SELECT *
FROM "dynamodb_zero_etl"."public"."products"
WHERE value.popular_region."S" = '大阪府'
```

なので、「人気地区が大阪府の商品の名前と値段を教えてください」といった入力で上のクエリが自動生成されるくらいの域になればすごいですね。




# まとめ
RedshiftのゼロETL統合を使って、BedrockナレッジベースでDynamoDBを自然言語検索する