👋

自然言語でSQLを生成する仕組みを実装してみた - 100行のSQL生成までの道のり

に公開

自然言語でSQLを生成する仕組みを実装してみた - 100行のSQL生成までの道のり

はじめに

「自然言語をinputとし、そのinputを解釈してSQLを動的に生成する」—— LangChain SQL Database Agentを初めて触った時の感動は今でも忘れられません。テーブル名を指定せずとも意図したテーブルを検索し、「似たような目的を持つレコードは?」という曖昧な質問にも、勝手に単語単位に区切ってlike検索する賢さに驚きました。

しかし、エンタープライズ環境での実装は想像以上に困難でした。特に「営業の田中さんからの問い合わせだからこのSQL」といった、ユーザーコンテキストを理解した上でのSQL生成は、技術的にも運用的にも大きな挑戦となりました。

なぜSQL生成が難しいのか

課題1: 長文SQLでの省略・文字化け問題

100行を超えるSQLを生成しようとすると、LLMの出力が途中で省略されたり、文字化けが発生したりします。これはトークン数の制限や、モデルの学習データに起因する問題で、単純にプロンプトを調整するだけでは解決できません。

課題2: テーブル情報・ドキュメントのセキュリティ制約

企業のデータベースでは、テーブル構造やカラム情報を外部に持ち出せないことが多く、LLMに十分なコンテキストを提供できません。「このテーブルの○○カラムは実は△△を意味する」といった暗黙知が共有できないのです。

課題3: カラム名が記号化されている環境

実際の環境では「col22」が「items」を意味するなど、カラム名が記号化されているケースが多々あります。AIがカラム名から意味を推測することができず、精度が著しく低下します。

課題4: ユーザーコンテキストの理解

「新宿駅のデータを取得して」と言われた時、それはJR新宿駅なのか、メトロ新宿駅なのか、それとも新宿三丁目駅なのか。ユーザーの所属部署や過去の問い合わせ履歴を考慮しなければ、適切なSQLは生成できません。

変数置換の2つの戦略

Pythonによる単純置換

日付や数値など、明確な値の置換に使用します。特に日付処理では自動変換機能を実装:

# ユーザー入力: "202401のデータ"
# 自動変換: YYYYMM形式を認識し、現在日付との差分を計算
"登録年月 = to_char(add_months(sysdate,-XXX),'YYYYMM')"

"登録年月 = to_char(add_months(sysdate,-12),'YYYYMM')"

LLMを使った柔軟な置換

「関東地方のデータ」といった曖昧な条件を、適切なWHERE句に変換します。LLMがコンテキストを理解し、「東京都、神奈川県、埼玉県...」といった具体的な条件に展開します。

実装時の工夫

リトライ機構とエラーハンドリング

SQL生成は一発で成功することは稀です。最大10回のリトライ機構を実装し、エラー内容に応じてプロンプトを自動修正します。

for retry in range(10):
    try:
        response = await generate_sql(prompt)
        if validate_sql(response):
            break
    except Exception as e:
        prompt = modify_prompt_based_on_error(prompt, e)

プログレスバー表示

複数のSQLパーツを組み合わせる過程をリアルタイムで表示。ユーザーは処理の進捗を把握でき、長時間の処理でも安心して待つことができます。

チャット機能による対話的修正

生成されたSQLに対して「GROUP BY句を追加して」といった修正要望に対応。コンテキストを保持したまま、段階的に理想のSQLに近づけていきます。

セキュリティ対策

SQLインジェクション対策として、すべての変数値を検証し、プレースホルダー方式で安全に置換。ユーザー入力は適切にエスケープ処理されます。

実際の成果と限界

このアプローチにより、100行程度のSQLなら安定して生成できるようになりました。しかし、それ以上の複雑なSQLでは依然として精度の問題が残ります。

重要なのは、顧客との期待値調整です。「どこまでなら自動生成できるか」を明確に伝え、複雑なSQLは段階的に構築していくという運用ルールを設けることで、実用的なシステムとして機能させることができました。

まとめと今後の展望

SQL生成の精度向上には、以下の取り組みが必要です:

  1. ドキュメント整備とエージェント化: テーブル情報を構造化し、必要に応じて参照できる仕組み
  2. AI自体の精度向上: より長いコンテキストを扱えるモデルの登場を待つ
  3. ユーザーリテラシーの向上: 曖昧な要求を具体化するための対話インターフェース

「営業の田中さんの問い合わせ」を適切なSQLに変換する——この一見シンプルな要求の裏には、技術的な課題と人間的なコンテキストの理解という、AI実装の本質的な難しさが潜んでいます。

しかし、だからこそ面白い。テクノロジーと人間の知識を組み合わせることで、より良いソリューションを生み出せる。そんな可能性を、SQL生成という具体的な課題を通じて実感しています。

Discussion