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

TIPS

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

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

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

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

  • セキュリティ: 実行されるSQLの構造は固定されているため、SQLインジェクションの脆弱性を原理的に排除できます。
  • 信頼性: LLMの「ハルシネーション(嘘をつくこと)」によって、間違ったテーブル名やカラム名を含むSQLが生成されるリスクがありません。
  • パフォーマンス: アプリケーション側で用意するSQLは、インデックスの使用などを考慮して十分にチューニングされたものであるため、常に最高のパフォーマンスが保証されます。

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

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

シナリオ: 不動産会社の営業担当者が、顧客の要望に合う物件を検索するため、社内システムに「世田谷区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の自然言語理解能力と、データベースの堅牢性・安全性を両立させる、非常に洗練された実践的なアーキテクチャです。

    コメント

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