I生成 SQL に反対する理由

モデルに
SQL を書かせるな。

テキストから SQL への変換は、エージェントをデータベースに向ける最も自然な方法であり、デモは確かに印象的だ。しかし本番環境で様相は一変する。同じ質問が異なる SQL にコンパイルされ、静かな結合エラーが収益を15%動かし、モデルの出力が攻撃対象になる。別の道がある。

IIまず公平に

Text-to-SQLは評価に値する。その領域では。

適切なツールとなる場面

  • 使い捨てデータでのプロトタイプ
  • 不慣れなスキーマの探索(人間が監視する場合)
  • 誰かが妥当性を確認する一回限りの質問
  • デモ用途——実際、デモ映えは抜群だ

破綻する場面

  • 誰かが意思決定に使う数値
  • コンテキスト内に信頼できないテキストが含まれる場合
  • 接続に本番環境の認証情報を使う場合
  • 再現性や監査が求められる回答
  • 無監督で動作するエージェント

パターン自体が間違っているのではない。被害範囲が問題だ。このページで挙げるリスクはすべて、ひとつの設計判断に行き着く——モデルの出力がコードとして実行されること。

III2つの経路

同じ質問。2つのアーキテクチャ。

ひとつの質問を両方の経路で追う——左は自由形式のSQL文字列、右は型付きプラン。番号スタンプは下のハザード台帳に対応している。

質問

売上合計が最も高い地域はどこか?

経路 A

モデルがSQLを生成する

  1. モデルが文字列を即興で生成 010304

    モデルが読み込んだもの——ユーザーメッセージでも取得済み行でも——がこの文字列を形成しうる。

    実行 1SELECT region, SUM(total) FROM orders GROUP BY region;実行 2 · 同じ質問SELECT o.region, SUM(i.amount) FROM orders o LEFT JOIN order_items i ON i.order_id = o.id GROUP BY 1;
  2. 接続がそれを実行 05

    接続の全権限で。読み取り、結合——そして誰かがフラグを設定し忘れていれば、書き込みも。

回答

run 1 → east · 2130.50

run 2 → east · 2450.08+15% — 結合のファンアウト 02

2回実行、2つの数値。どちらも一見もっともらしい。どちらが——もし一方でも——正しいかを示すシグナルはない。

経路 B

モデルが型付きプランを提出する

  1. 型付きインテント

    文字列ではなく、スキーマを持つ値。コントラクトが定義した操作しか指定できない。

    { "kind": "query", "version": "1", "source": "revenue", "op": "sum", "group_by": "region" }
  2. コントラクト検証

    ハッシュで固定済み。未知の操作は推測を返さず、最近傍の候補とともに unsupported_operation を返す。

  3. ポリシー検証

    コードレベルの許可リスト。リクエストは対象範囲を狭めることはできても、広げることはできない。

  4. 決定論的実行

    float64、シングルスレッド、固定ランタイム。同じプラン、同じバイト列、同じ回答。

回答

east · 2130.50

plan_hash f87610d8afeb…

decision_path "exact_spec"

ひとつの回答。再現に必要なハッシュを携えて——来週でも、来四半期でも、どちらの言語でも。

IVハザード台帳

生成SQLが失敗する5つの経路

  1. 01

    P2SQLarXiv 2308.01990

    インジェクションが出力チャネルに移行

    入力サニタイズはモデルへの入力を検査する。P2SQL攻撃は出力に現れる——ユーザーメッセージや取得済み行に隠された命令から組み立てられた、正当な形式の悪意あるSQL。いかなる入力フィルターもそれを検知しない——攻撃そのものが出力だからだ。

  2. 02

    −15%嘘をついたダッシュボード

    誤った結合はサイレントに失敗する

    ファンアウトした結合が行を二重計上し、売上が15%ずれて表示される。例外もなく、警告もない——誤ったSQLはクラッシュせず、報告する。結果は常に数値であり、もっともらしい数値には誤りを示すシグナルが含まれない。

  3. 03

    1 → n1つの質問、nつのクエリ

    同じ質問、異なるSQL

    2回尋ねると、モデルは質問を異なる方法でコンパイルし、異なる回答を返すことがある。レビュー、キャッシュ、再実行の基準となる正規クエリは存在しない。昨日の数値は、確認のためだけであっても再現できない。

  4. 04

    91.2 → 21.3正解率 · ベンチマーク → 実企業スキーマ

    精度の崖

    整備されたベンチマークスキーマでは、最先端モデルが91.2%の確率で正しいSQLを生成した。実際の企業スキーマでは21.3%。同じ研究の中で、text-to-SQLエージェントの実行のうち約40%が完全に失敗するか、誤った結果を返した。ベンチマークは整然としている。あなたのスキーマはそうではない。

  5. 05

    本番DB 1件エージェントが削除 — Replitの事例

    書き込み経路は常に存在した

    Replitのコーディングエージェントは、触れないよう明示的に指示されていたにもかかわらず、本番データベースを削除した。教訓はこうだ。読み取り専用の指示はあくまでリクエストに過ぎない。接続が書き込みを許可している限り書き込み経路は存在し、いつか必ず不正な補完がそこに到達する。読み取り専用はプロンプトの一文ではなく、ツールの性質でなければならない。

出力をフィルタリングするな。
生成するな。

SQL文字列なし、インジェクションなし · 推測なし、ドリフトなし

V証明書

5つの次元、並べて比較

LLM-to-SQLジェネレーターではありませんエンジン README

差異の証明書

作成インターフェース生成SQL自由形式のSQL文字列型付きプラン型付き・バージョン管理されたインテント
実行インターフェース生成SQL接続が許可するすべての操作型付きプラン4,574件の読み取り専用ケイパビリティ
書き込み経路生成SQLブロックされない限り存在する型付きプラン構造上、存在しない
ガバナンス生成SQLプロンプトレベル、ベストエフォート型付きプランモデルが拡張できないコードレベルの許可リスト
再現性生成SQLなし型付きプラン全結果にリプレイハッシュを付与

右列はコントラクトに固定sha256:79f1c5a6…924be9a1

細則は揺るぎません。エンジンの唯一の抜け道である getUnsafeRuntime は、モデルに公開されるいかなるインターフェースにも存在しないため、モデルからアクセスすることはできません。そしてREADMEはその原則を明確に述べています。これはLLM-to-SQLジェネレーターではありません。

VIFAQ

本番環境からの質問

LLMが生成したSQLでDELETEやDROPをブロックするには?

SQLをフィルタリングするのではなく、生成そのものをやめることだ。拒否リストは文字列を検査するが、モデルは新たな文字列を際限なく生み出す。SQAIはそのクラス自体を排除する。モデルは4,574件の読み取り専用ケイパビリティに対して型付きプランを提出し、いかなるプランも名指しできる書き込みケイパビリティは存在しない。

P2SQLインジェクションとは何か?

Prompt-to-SQLインジェクション。モデルが読み込んだコンテンツ——ユーザーメッセージ、ドキュメント、取得した行——に潜む指示から組み立てられ、モデルの出力に現れる悪意あるSQLだ。攻撃は出力チャネルに存在するため、入力サニタイズでは検出できない。arXiv 2308.01990に記録されている。

text-to-SQLが適切な選択となる場面はあるか?

ある。プロトタイプや非本番データに対する監視付き探索では、高速かつ実用的だ。しかし、その数値が意思決定に使われる場合、コンテキストに信頼できないテキストが含まれる場合、または回答の再現性が求められる場合には、誤った選択となる。

AIエージェントにデータベースへの読み取り専用アクセスを与えるには?

読み取り専用を設定ではなく構造にすること。接続の読み取り専用フラグは、誰かが変更できる設定に過ぎない。SQAIの実行インターフェースには読み取りケイパビリティのみが存在し、書き込み経路は構造上不在だ。エンジンの脱出口でさえ、モデルに公開されるいかなるツールからも到達できない。

型付きプランと生成SQLはどう違うのか?

SQL文字列は文法が許す限り何でも記述できる。型付きプランはコントラクトが定義したことしか記述できない。すべてのプランはハッシュ固定されたコントラクトに対して検証され、許可リストポリシーに照合され、決定論的エンジンで実行される——全結果にリプレイハッシュが付与される。

別の道を選べ。

アカウント不要。キー不要。ローカルデータはローカルに留まる。