[AWS]Bedrockでクエリ生成を賢く行う

TIPS
TIPS

このモデルの核心は、BedrockのLLMにSQL文そのものを書かせるのではなく、ユーザー(営業担当者)の自然言語の指示から「検索条件となるキーワード(パラメータ)」を抜き出させ、構造化されたデータ(主にJSON形式)として出力させることに特化させるアーキテクチャです。

一言でいうと、LLMを「SQLライター」ではなく、「超優秀な日本語(自然言語)解析エンジン」として利用します。

実際のSQL文は、アプリケーション側にあらかじめ用意しておいた安全な「SQLテンプレート」に、抽出したパラメータを埋め込むことで完成させます。

なぜこのモデルが優れているのか?

  • セキュリティ: 実行されるSQLの構造は固定されているため、SQLインジェクションの脆弱性を原理的に排除できます。
  • 信頼性: LLMの「ハルシネーション(嘘をつくこと)」によって、間違ったテーブル名やカラム名を含むSQLが生成されるリスクがありません。
  • パフォーマンス: アプリケーション側で用意するSQLは、インデックスの使用などを考慮して十分にチューニングされたものであるため、常に最高のパフォーマンスが保証されます。
[AWS]Bedrockでクエリ生成を賢く行う
[AWS]BedrockでAgents未使用時のSQL修正・管理方法
Agents for Amazon Bedrock不使用時のSQL修正・管理方法を解説。アプリ側でSQLを完全管理する堅牢なパターンと、LLMを生成アシスタントとするパターンの2種を比較し、セキュリティや信頼性の観点から最適な設計手法を提示します。

詳細な処理フローと具体例

それでは、具体的なシナリオに沿って、各ステップを詳しく見ていきましょう。

シナリオ: 不動産会社の営業担当者が、顧客の要望に合う物件を検索するため、社内システムに「世田谷区で3LDK以上、予算8000万円までのマンションを探して」と入力した。

ステップ1:ユーザー(営業担当者)からの自然言語の指示

ユーザーがアプリケーションのインターフェースに、以下のような自然言語で指示を入力します。

世田谷区で3LDK以上、予算8000万円までのマンションを探して

ステップ2:アプリケーションによるプロンプトの設計とBedrock APIの呼び出し

アプリケーションは、このユーザーの指示を元に、Bedrockの基盤モデル(例: Claude 3 Sonnet)に投げるためのプロンプトを組み立てます。これがこのモデルの心臓部です。

プロンプトの例:

XML

<prompt>
あなたは、ユーザーの自然言語の指示から、不動産物件の検索に必要なパラメータを抽出する優秀なアシスタントです。
以下の指示に従って、指定されたJSON形式で出力してください。

# 指示
- ユーザーの入力から、「所在地(location)」、「物件種別(property_type)」、「間取り(floor_plan)」、「上限価格(max_price)」を抽出してください。
- 間取りは「3LDK」や「4DK」のような形式で、価格は数値のみ(万円単位)で抽出してください。
- 該当する情報が見つからない場合は、そのキーの値をnullにしてください。
- 出力はJSON形式のみとし、他の文章は一切含めないでください。

# 出力フォーマット
{
  \"location\": \"抽出した所在地\",
  \"property_type\": \"抽出した物件種別\",
  \"floor_plan\": \"抽出した間取り\",
  \"max_price\": \"抽出した上限価格(数値)\"
}

# ユーザーの入力
世田谷区で3LDK以上、予算8000万円までのマンションを探して

</prompt>

アプリケーションはこのプロンプトをBedrock APIに送信します。

ステップ3:Bedrock LLMによるパラメータ抽出

プロンプトを受け取ったBedrockのLLMは、指示に従ってユーザーの入力内容を解析し、パラメータを抽出したJSONを生成して返します。

LLMからのJSON出力:

JSON

{
  \"location\": \"世田谷区\",
  \"property_type\": \"マンション\",
  \"floor_plan\": \"3LDK\",
  \"max_price\": 8000
}

ステップ4:アプリケーションによるSQLの構築と実行

アプリケーションは、LLMから返ってきたJSONを受け取ります。

SQLテンプレートの選択

SQLテンプレートの選択: 受け取ったJSONのキーが存在することを確認し、それに対応するSQLテンプレートを選択します。

SQLテンプレート(事前定義済み)

SELECT
    property_name,
    address,
    price,
    floor_plan
FROM properties
WHERE status = \'販売中\'
  AND address LIKE %s
  AND property_type = %s
  AND floor_plan_code >= %s -- 間取りはコード化されていると仮定
  AND price <= %s
ORDER BY price DESC
LIMIT 50;

%s の部分は、後から値を安全に埋め込むためのプレースホルダです。

パラメータの安全なバインディング

パラメータの安全なバインディング: psycopg2(PythonのPostgreSQLドライバ)などのライブラリが持つ機能を使って、抽出した値をプレースホルダに安全に埋め込み(バインドし)ます。これによりSQLインジェクションが防がれます。

(Pythonコードのイメージ)

import psycopg2

# LLMから受け取ったJSON
params_json = {
  \"location\": \"世田谷区\",
  \"property_type\": \"マンション\",
  \"floor_plan\": \"3LDK\",
  \"max_price\": 8000
}

# SQLテンプレート
sql_template = \"\"\"
    SELECT property_name, address, price, floor_plan
    FROM properties
    WHERE status = \'販売中\'
      AND address LIKE %s
      AND property_type = %s
      AND floor_plan_code >= %s
      AND price <= %s
    ORDER BY price DESC
    LIMIT 50;
\"\"\"

# 抽出した値をタプルとしてまとめる
# \'3LDK\'を内部コード\'30\'に変換するような処理もここで行う
floor_plan_code = 30 # 例: 3LDK -> 30
location_param = f\"%{params_json[\'location\']}%\"
values_to_bind = (
    location_param,
    params_json[\'property_type\'],
    floor_plan_code,
    params_json[\'max_price\']
)

# データベースに接続してクエリを実行
conn = psycopg2.connect(...)
cur = conn.cursor()

# ライブラリの機能で安全にパラメータをバインドして実行
cur.execute(sql_template, values_to_bind)

results = cur.fetchall()
# ...

    ステップ5:ユーザーへの結果提示

    データベースから返ってきた結果(物件リスト)を、アプリケーションが整形して営業担当者の画面に見やすく表示します。

    この「パラメータ抽出モデル」は、LLMの自然言語理解能力と、データベースの堅牢性・安全性を両立させる、非常に洗練された実践的なアーキテクチャです。

    [AWS]Bedrockでクエリ生成を賢く行う
    [AWS]レスポンス速度に差が出る理由!BedrockRAGとAgentの決定的な違い
    Amazon BedrockのKnowledge Base(RAG)とAgentのレスポンス速度の違いを徹底比較。RAGが高速な理由と、Agentが遅い一方でタスク完了が早い理由をアーキテクチャから解説し、ユースケースに応じた最適な選定基準を提示します。
    Q よくある質問 (FAQ)
    Q. なぜLLMに直接SQLを生成させず、パラメータ抽出にとどめるのですか?
    A.
    LLMのハルシネーションによる誤ったSQL生成(存在しないテーブル・カラムの指定など)を防ぎ、SQLインジェクションのリスクを排除して、事前にチューニングされた安全で高速なSQLを実行するためです。
    Q. 抽出したパラメータをSQLテンプレートに埋め込む際のセキュリティ対策は?
    A.
    アプリケーション側でpsycopg2などのデータベースドライバが提供するプレースホルダ機能(パラメータの安全なバインディング)を使用することで、SQLインジェクションを原理的に防止します。

    コメント

    タイトルとURLをコピーしました