Amazon Bedrock Knowledge Bases 構造化データを使って自然言語でデータ分析を行う

AWS

2025.9.1

Topics

概要

Amazon Bedrock Knowledge Bases が Amazon Redshift に格納されたデータを対象として、RAG ができる機能が発表されました。
Amazon Bedrock Knowledge Bases が構造化データ取得のサポートを開始 – AWS

この機能を使うことで、自然言語から自動で SQL クエリを生成・実行し、その結果を返すことができるようになります。
本記事では、この新機能を実際に試した記録となります。

Redshift Serverless を作成する

まず、データの格納先となる Redshift Serverless を立ち上げ、分析に用いるサンプルデータを投入します。
今回は、生成 AI を使用してテーブル定義とサンプルデータを生成しました。

テーブル定義
このテーブルは、シンプルな売上データ(sales_data)を格納する構造です。

CREATE TABLE sales_data (
    sale_date DATE,
    product_id VARCHAR(10),
    product_name VARCHAR(100),
    category VARCHAR(20),
    quantity INTEGER,
    unit_price INTEGER,
    sales_amount INTEGER,
    customer_id VARCHAR(10),
    sales_person VARCHAR(20),
    store VARCHAR(20)
);

サンプルデータ(200 件作成)

このサンプルデータは、小売業の販売データセットです。
2024 年 1 月から 2 月の 約 200 件の取引データには、商品情報、売上金額、店舗・販売員データが含まれています。

INSERT INTO sales_data VALUES
('2024-01-01','P001','ノートパソコン','電子機器',1,89800,89800,'C001','田中','東京店'),
('2024-01-01','P002','マウス','電子機器',2,2980,5960,'C002','佐藤','東京店'),
('2024-01-01','P003','コーヒー豆','食品',3,1200,3600,'C003','田中','大阪店'),
('2024-01-01','P004','Tシャツ','衣料品',1,2500,2500,'C004','鈴木','名古屋店'),
('2024-01-01','P005','化粧水','美容',2,3800,7600,'C005','山田','東京店'),
('2024-01-02','P006','スニーカー','衣料品',1,8900,8900,'C006','佐藤','大阪店'),
('2024-01-02','P007','本','書籍',4,1500,6000,'C007','田中','東京店'),
-- (以下略)

データ件数

SQLクエリの件数検索結果

テーブルデータを一部抜粋

SQLクエリの全件検索結果

Bedrock Knowledge Bases 構造化データストアを作成する

Bedrock コンソールから新しい Knowledge Bases を作成し、構造化データストアとして Redshift を指定します。

BedrockのKnowledge Bases作成画面

ウィザードに従い、IAM ロールの作成や Redshift Serverless のエンドポイントを指定して設定を進めます。

Knowledge Basesの詳細設定画面

IAM ロールを作成します。

IAMサービスロールの作成画面

先ほど作成した Redshift Serverless を選択します。

クエリエンジンの接続情報設定

データベースリストはデフォルトで作成した dev を使用します。

データソースのストレージ設定

後ほど設定するため、作成時は何も入力せずに進めます。

クエリ設定のオプション画面

データストアへのアクセスを Knowledge Bases サービスロールに付与する

Knowledge Bases からデータストアに対してアクセスするためには、データベースユーザーが必要になります。
先ほど作成した、IAM ロールに紐づくデータベースユーザーを作成しても良いですが、データソースの同期を行うとユーザーが自動的に作成されるためそちらを試してみます。

構造化データストアを使用してナレッジベースを作成するためのクエリエンジンとアクセス許可を設定する – Amazon Bedrock

データストアの同期を実行します。

クエリエンジンの同期が進行中

ただし、初回の同期は権限不足により失敗します。

クエリエンジンの同期が失敗

次に、データベースユーザーが正常に作成されたかを以下のクエリで確認します。

SELECT * FROM SVV_USER_INFO;

すると、サービスロールと同じデータベースユーザーが存在していることが確認できました。

Redshiftのユーザー情報一覧

ただしこのままでは、データベースに対する権限が不足しているため、このユーザーに対して権限を与えます。

GRANT SELECT ON ${schemaName}.${tableName} TO "IAMR:${serviceRole}";

実行結果

Bedrockロールへの権限付与

そして、改めてデータソースの同期を取ります。

クエリエンジンの同期が完了

これで事前準備は完了です。

Knowledge Bases に対して問い合わせしてみる

コンソールの Knowledge Bases からテストが実行できます。
今回はこちらで動作を試します。

Knowledge Basesの概要画面

モデルは Claude を選択します。

Knowledge Basesのテスト画面

このテスト環境では、「取得と応答生成」の設定を以下の通り変更することが可能です。
今回は、どういったクエリで結果が返ってきたかを確認するため「取得と応答生成」で動作を試します。

  • 取得のみ: データソース
    • データソースの情報を照会して取得します。
  • 取得と応答生成: データソースとモデル
    • 指定された基盤モデルを使用して、データソースをクエリし、取得した結果に基づいて応答を生成します。
  • SQL クエリの生成
    • データソースから情報を取得するための SQL クエリを生成します

動作テスト

まず、以下の内容を問い合わせてみます。

東京店の1月の売上を教えて下さい。

結果が取得できませんでした。
詳細を開くと、実行された SQL を確認することができます。

Knowledge Basesのテスト結果

実行されたクエリを確認すると、条件式の店舗名が英語表記になっています。
さらに、日付が今年の日付になっています。

SELECT SUM(sales_amount) AS total_sales FROM public.sales_data WHERE store = 'Tokyo' AND sale_date BETWEEN '2025-01-01' AND '2025-01-31';

実際は、以下のようなクエリを期待しています。

  • 店舗名は日本語名の「東京店」で検索
  • 日付は 2024 年 1 月 1 日 ~ 2024 年 1 月 31 日まで

想定のクエリ

SELECT SUM(sales_amount) AS total_sales FROM public.sales_data WHERE store = '東京店' AND sale_date BETWEEN '2024-01-01' AND '2024-01-31';

プロンプトを工夫する

プロンプトで改善できるのかを試してみました。

「東京店」を強調するために、ダブルクォーテーションでくくってみても動作変わらずでした。

Knowledge Basesのテスト結果(失敗)

また、日本語表記であることを明示しても結果は同じでした。

英語で返ってきたテスト結果

なお、日本語の条件式を入れない内容なら正しく結果は返ってきました。

メタデータを元にした回答結果

実際に作成されたクエリを Redshift に対して実行した結果は以下の通りです。

sales_dataテーブルの全件検索

説明とキュレートクエリによる回答精度向上

構造化データストアには、クエリの精度を高める設定がいくつかあります。
今回は以下の 2 つを使って、先ほどのクエリの精度をあげてみます。

  • 説明
    • テーブルまたは列の構造に関する追加のコンテキストと情報を提供することで、SQL クエリの生成を向上させることが可能
  • キュレートクエリ
    • 事前定義された質問と回答の例のセット
    • 質問は自然言語クエリ(NLQ)として記述され、回答は対応する SQL クエリ
    • 生成 SQL 出力の ​​ 精度と関連性を向上させるための参照ポイントとして機能

構造化データストアに接続してナレッジベースを作成する – Amazon Bedrock

テーブルと列の説明を追加する

まず、日付列と店舗列に対して情報を入力します。
こうすることにより、実際のデータに基づいた回答を作成してもらうようにします。

列名
sale_date

説明
商品が販売された日付 データ範囲: 2024年1月1日から2024年2月11日まで
列名
store

説明
商品が販売された店舗名 東京店,大阪店,名古屋店,福岡店

テーブルと列に説明を追加

入力が完了しました。

追加されたテーブル・列の説明

では、この状態で先ほどと同じ問い合わせを行います。

「東京店」の問題は解消されましたが、「日付」の問題は残りました。

Knowledge Basesのテスト結果(失敗2)

ただし、日付を直接指定すると正常に動作しました。

売上を正しく取得できた結果

詳細

失敗と成功のテスト結果比較

回答されたクエリを実際に Redshift に対して実行して結果を確認します。
自然言語で問い合わせて返ってきた内容と同じことが確認できました。

RedshiftでのSQL直接実行

キュレートクエリを追加

続いては、キュレートクエリを試します。
これまで問い合わせてきた質問と、期待するクエリをセットで設定します。

質問
1月の"東京店"の売上を教えて下さい。

同等の SQL クエリ
SELECT
    "store",
    SUM("sales_amount") AS "total_sales_amount"
FROM
    public.sales_data
WHERE
    "store" = '東京店'
    AND "sale_date" BETWEEN '2024-01-01'
    AND '2024-01-31'
GROUP BY
    "store";

キュレートクエリの追加画面

今回は、「東京店」の売上の結果に加え、「福岡店」でも同様に問い合わせができるか、動作を確認します。

福岡店の売上を取得できた結果

結果は正しく取得できているようです。

Redshiftでの福岡店売上

まとめ

列名やテーブル構造はメタデータとして認識されますが、実際のデータ内容(日本語の店舗名など)までは事前に把握されていないため、日本語での条件指定に課題があることが分かりました。

日本語でもある程度利用はできそうですが、説明やキュレートクエリ、プロンプトの工夫が必要だと思われます。

参考資料

構造化データストアに接続してナレッジベースを構築する – Amazon Bedrock

テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!

Cold-Airflow

2021年新卒入社。インフラエンジニアです。RDBが三度の飯より好きです。 主にデータベースやAWSのサーバレスについて書く予定です。あと寒いのは苦手です。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら