🐱

NL2SQL(Text to SQL)を本番運用する前に知っておくべき3つの壁と解決策

に公開

※本発表は、「#bq_sushi #24 BigQueryとAIで話してみる」の発表内容を基にしております。
https://bq-sushi.connpass.com/event/372861/

はじめに

前回の記事「ADKで作るBigQueryのNL2SQLエージェント入門 - INFORMATION_SCHEMAへアクセス🚀」では、ADKとBigQuery 1st Party Toolsを使った自然言語データ分析エージェントの構築方法を解説しました。

これで自然言語でデータ分析ができました!ラッキー!非エンジニアにとっては間違いなく朗報です。

しかし...現場で本当に使えるでしょうか?

本記事では、ADKエージェントを本番運用しようとした際に直面する3つの曖昧性の壁と、その実践的な解決策について解説します。

課題:AIは「コンテキスト」を知らない

現場で実際に使おうとすると、3つの曖昧性の壁に直面します。

課題①:スキーマ曖昧性 (Schema Ambiguity)

例:「部署ごとの平均給与はいくらか?」

問題点:

  • current_departuredeparture_2022という2つのテーブルが存在
  • どちらのテーブルのどのカラムでクエリすればいいのか不明

課題②:セマンティック曖昧性 (Semantic Ambiguity)

例:「過去30日間で最も売れた商品は?」

「最も売れた」というビジネス上の定義は複数存在:

  • 解釈A: 販売個数 (SUM(quantity)) が最多?
  • 解釈B: 販売金額 (SUM(quantity * price)) が最多?
  • 解釈C: 注文件数 (COUNT(DISTINCT order_id)) が最多?
-- 解釈によって、まったく異なるSQLになる
-- 解釈A: 販売個数
SELECT product_name, SUM(quantity) as total_qty
FROM sales GROUP BY product_name ORDER BY total_qty DESC;

-- 解釈B: 販売金額
SELECT product_name, SUM(quantity * price) as total_revenue
FROM sales GROUP BY product_name ORDER BY total_revenue DESC;

ビジネスロジック上、複数の異なる計算方法で解釈できてしまいます。

課題③:ドメイン曖昧性 (Domain Ambiguity)

例:「今月の『アクティブユーザー数』を教えて」

問題点:

  • スキーマにactive_usersというカラムは存在しない
  • 定義が不明なので、AIは判断に迷う:
    • 定義A: 今月一度でもログインした人?
    • 定義B: 今月一度でも課金した人?
    • 定義C: 今月商品をゲットした人?

ユーザーは、DBに存在しない「社内用語」を使いますが、AIはそれを理解できません。

結局何が問題なのか?

DBを操作するには、SQLの知識だけでは不十分です。以下のようなコンテキストを理解してクエリする必要があります:

  • DBに用いられている業務ドメインの知識
  • 開発者の設計意図
  • プロダクトの歴史的背景

問い:これらの高度な「コンテキスト」を、どうやって生成AIに伝えれば良いでしょうか?

解決策:AIに「文脈」を教える3つのアプローチ

解決策①:メタデータの強化(スキーマ曖昧性対策)

例:「部署ごとの平均給与はいくらか?」

# BigQueryのテーブル/カラムにメタデータを追加
current_departure:
  description: "現在の部署情報"
  use_case: "デフォルトで使用"
  columns:
    department_name: "部署名"
    employee_count: "所属人数"
  
departure_2022:
  description: "2022年時点での部署情報(履歴データ)"
  use_case: "過去データ分析用・年次比較用"

メタデータによって、適切なテーブルへのマッピングが実現します。特に指定がない場合は、現在の部署(current_departure)でクエリすることをAIが判断できます。

BigQueryでのメタデータ設定方法

-- テーブルレベルのメタデータ
ALTER TABLE `project.dataset.current_departure`
SET OPTIONS(
  description="現在の部署情報。デフォルトで使用。"
);

-- カラムレベルのメタデータ
ALTER TABLE `project.dataset.current_departure`
ALTER COLUMN department_name
SET OPTIONS(
  description="部署名(日本語正式名称)"
);

解決策②:聞き返す(セマンティック曖昧性対策)

AIが「推測」するのを防ぎ、確認を取るアプローチです。

例:「過去30日間で最も売れた商品は?」

エージェントの応答:

「確認です。『最も売れた』とは、以下のどちらで集計しますか?
1. 販売個数(何個売れたか)
2. 販売金額(いくら売上があったか)」

エージェント実装での対応

root_agent = llm.LLMAgent(
    name="data_analytics_agent",
    model="gemini-2.0-flash-exp",
    custom_instructions="""
    あなたはBigQueryデータの分析を支援するエージェントです。
    
    重要なルール:
    - 曖昧な質問(複数の解釈が可能な場合)には、必ずユーザーに確認を取る
    - 推測でSQLを実行しない
    - 選択肢を提示して、ユーザーに選ばせる
    
    曖昧な表現の例:
    - "売れた" → 販売個数?販売金額?
    - "人気の" → アクセス数?購入数?
    - "最近" → 1週間?1ヶ月?
    """,
    tools=[bigquery_tools]
)

メリット: AIが間違った答えを自信満々に返すという最悪の事態を防げる

デメリット: 毎回聞き返してくるAIは、ちょっと面倒...

解決策③:RAG(ドメイン曖昧性対策)

RAG (Retrieval-Augmented Generation) を活用し、AIに「ドメイン知識の教科書」を渡します。

RAGとは?

生成AIが回答を作成する際に、あらかじめ用意された社内文書やウェブサイトなどの信頼できる情報源から関連情報を検索し、その内容を基に回答を生成する技術です。

RAGの仕組み

コンセプト: ユーザーの質問に応じて、関連するコンテキスト(スキーマ定義、ビジネスルール、過去のSQL例)を外部の知識ベース(Vector DBなど)から動的に検索し、プロンプトに注入します。

知識ベースの例

# 社内用語集

## アクティブユーザー
定義: 対象期間内に一度でもログインしたユニークユーザー数
SQL例:
SELECT COUNT(DISTINCT user_id) as active_users
FROM login_logs
WHERE login_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)

## 売上
定義: 販売金額の合計(quantity * price)。返品・キャンセルは除外。
SQL例:
SELECT SUM(quantity * price) as revenue
FROM sales
WHERE status = 'completed'

RAGの実装イメージ

from google.adk.extensions import llm
from google.adk.tools import BigQueryToolset
# RAGツール(例:Vertex AI Search)
from your_rag_tool import DomainKnowledgeRAG

# RAGツールの初期化
rag_tool = DomainKnowledgeRAG(
    knowledge_base_path="gs://your-bucket/knowledge-base/"
)

root_agent = llm.LLMAgent(
    name="data_analytics_agent",
    model="gemini-2.0-flash-exp",
    custom_instructions="""
    あなたはBigQueryデータの分析を支援するエージェントです。
    
    ワークフロー:
    1. ユーザーの質問に社内用語が含まれている場合、
       まずRAGツールで用語の定義を検索
    2. 定義に基づいてSQLを生成
    3. BigQueryで実行
    """,
    tools=[bigquery_tools, rag_tool]
)

最適解:3つのアプローチの組み合わせ

理想的なアーキテクチャは、メタデータ + RAG + 聞き返すエージェントの組み合わせです:

アーキテクチャの設計方針

  1. メタデータ強化(基盤): スキーマ曖昧性(例:部署テーブル)を解決
  2. RAG(教科書): ドメイン曖昧性(例:アクティブユーザー定義)を解決
  3. 対話型確認: メタデータやRAGで解決できないセマンティック曖昧性(例:最も売れた商品の基準)だけをユーザーに確認し、間違いを防ぐ

回答の精度とスピードを両立

実装の優先順位

段階的に導入することで、リスクを抑えながら品質を向上できます:

Phase 1: メタデータ強化

  • コスト:低(BigQueryの標準機能)
  • 効果:中(スキーマ曖昧性を解決)
  • 工数:1-2週間

Phase 2: 対話型エージェント

  • コスト:低(プロンプト設計のみ)
  • 効果:高(誤回答を防ぐ)
  • 工数:1週間

Phase 3: RAG導入

  • コスト:中(Vector DB構築・運用)
  • 効果:高(ドメイン知識の活用)
  • 工数:2-4週間

まとめ:AIエージェントは「育てる」もの

ADKは「自然言語でデータ分析」エージェントを構築する強力なフレームワークです。

しかし、「SQLが書ける」だけでは不十分。現場の**コンテキスト(文脈)**をAIにどう伝えるかが鍵となります。

3つの曖昧性と解決策

曖昧性 問題 解決策
スキーマ曖昧性 どのテーブル・カラムを使う? メタデータ強化
セマンティック曖昧性 ビジネス定義が複数ある 聞き返す
ドメイン曖昧性 社内用語をAIが理解できない RAG

実装のポイント

  • メタデータ強化でスキーマの基盤を整備
  • RAGで業務ドメインの知識を与える
  • 対話型エージェントで曖昧な部分を確認

この3つを組み合わせることで、実用的なエージェントが実現します。

AIエージェントは「作って終わり」ではなく、組織の知識と共に**「育てていく」**ものなのです。

参考リンク


この記事が、ADKエージェントの本番運用に向けた参考になれば幸いです!
質問やフィードバックがあれば、コメント欄でお気軽にどうぞ 🙌

Discussion