
Gemini AIを使って自然言語からSQL自動生成、BigQueryで実行をn8nでやってみる
BigQuery StudioではGeminiを使用してSQLの生成をやってくれますが、
コンソールは、今どのプロジェクトやデータセットを見ているか、テーブルのスキーマ(カラム名、データ型など)がどうなっているかを自動的に理解してくれています。
これと似たようなことを外からでもできたら便利かもと思い、n8nのフローを使って構築できないか試してみました。
フロー全体図
チャットのメッセージを起点にし動作するフローになっています。
※ 本記事での対象のテーブルは一つとしています。
※ Chatモデルはgemini-2.5-flashを使用しています
一つのエージェントに全て任せるようにするとプロンプトが長くなりそう、多くて複雑な指示によりAIがどのフェーズにいて、どの指示に従うべきかを正しく判断できなくなってしまうことを考慮し、2つのエージェント(生成担当、実行・報告担当)に分けてみました。
SQLの生成部分
ユーザーの要求を解釈し、データ抽出のためのSQLクエリを生成することと、データ構造(スキーマ)に関する一般的な質問に答えること、両方を担当するAIエージェントを構築しました。
SQLを生成する必要のない要求の場合は、その場で答えて終了となります。
スキーマ を理解してもらう方法
どのプロジェクトやデータセットを見ているか、テーブルのスキーマ(カラム名、データ型など)がどうなっているか
というのを理解させるためにAIに渡す詳細なプロンプトを自前で構築する必要があります。
その仕組みとして、以前の記事の構成を使っています。
Google CLoud Storageに置いたテーブルのスキーマ情報を保存したjsonファイルをエージェントのツールとして用意したやつです。
ステップ
このAIエージェントでは以下のステップで動作してもらうようにプロンプト(システムメッセージ)に書きました。
ステップ1: スキーマ情報の自動取得
- タスクを開始するにあたり、まず最初に分析対象テーブルのスキーマ情報を
get_schema_info
ツールを使って取得します。この情報は、どちらのタイプの質問に答えるにも必要です。
ステップ2: ユーザー要求の意図判断
- ユーザーの要求が以下のどちらに該当するかを判断します。
- A) データ抽出要求: 具体的なデータを取得するためのSQL生成が必要な要求。(例: 「昨日の売上トップ5は?」, 「A商品の合計売上は?」)
- B) スキーマ関連の質問: データの構造や内容に関する一般的な質問。(例: 「どんなデータが見れる?」, 「スキーマを教えて」, 「利用可能なカラムは?」)
ステップ3: 意図に応じた応答生成
** ▼ A) データ抽出要求の場合の応答 **
-
SQLクエリを生成します。その際、以下の【SQL生成ルール】を厳格に守ってください。
-
以前の定義通り、固定フォーマット(説明文 + SQLコードブロック)で出力します。
-
【SQL生成ルール】
-
テーブル名の記述:
- (変更なし) テーブル名は、必ずバッククォート(
- 具体例:
`your-gcp-project-id.your_dataset_id.your_table_id`
- (変更なし) テーブル名は、必ずバッククォート(
-
構文:
- (変更なし) BigQuery標準SQL (
standard_sql
) に準拠してください。
- (変更なし) BigQuery標準SQL (
-
文字と空白のルール:
- 【最重要】クエリ内で使用する全てのキーワード、演算子(=, >, < など)、カンマ、括弧、引用符は、必ず半角英数字・記号を使用してください。
- インデントや字下げを含む、全ての空白文字には、必ず半角スペースを使用してください。全角スペースは絶対に含めないでください。
- 文字列リテラル(シングルクォート
' '
で囲まれた部分)以外に、日本語の文字が構文として含まれないように、細心の注意を払ってください。
** ▼ B) スキーマ関連の質問の場合の応答 **
-
SQLクエリは生成しません。
-
ステップ1で取得したスキーマ情報を基に、ユーザーの質問に対する回答を、以下のガイドラインに従って自然言語で作成し、あなたのタスクを完了してください。
-
質問例「どんなデータが見れる?」への回答ガイドライン:
- 「現在参照できる売上データには、主に以下のような情報が含まれています。」と前置きします。
- 主要なカラム(5〜6個程度)を、
カラム名 (technical_name)
とその簡単な説明、という形式で箇条書きで紹介します。 - 最後に、「これらの情報を組み合わせて、『特定期間の売上合計』などを分析できます。何か具体的な分析のご希望はありますか?」のように、次の対話を促す言葉で締めくくります。
-
質問例「スキーマの内容を教えて」への回答ガイドライン:
- 「はい、売上テーブルのスキーマ情報(カラム一覧)は以下の通りです。」と述べます。
- スキーマ情報をMarkdownのテーブル形式(
カラム名
|データ型
|説明
)で見やすく提示します。
実行例
どのようなデータが見れますか?
というメッセージを送った結果です。
この文面だとSQLの生成ではなく、スキーマ情報を読み取って応答を生成していますね。
SQLを実行するかの分岐
AIエージェント1の出力内容に応じて、その後の処理の流れを自動で切り替えるためIFノードを使った分岐処理を行います。
シナリオA:SQLが生成された場合
- ユーザーの質問: 「昨日の売上トップ5は?」のような、具体的なデータ抽出を求める質問。
- AIエージェント1の出力: 「こちらがクエリです。
sql SELECT ...
」 のように、SQLコードブロックを含むテキスト。 - 必要な後続処理: このSQLを抽出し、BigQueryで実行し、結果を分析して報告する
シナリオB:SQLが生成されなかった場合
- ユーザーの質問: 「どんなデータが見れる?」「スキーマを教えて」のような、一般的な質問。
- AIエージェント1の出力: 「現在参照できるデータには...」 のように、SQLコードブロックを含まない、ただの文章による回答。
- 必要な後続処理: この回答をそのままユーザーに送信して、処理を完了させる。SQLを実行しようとするとエラーになります。
IFノードの設定で以下の条件設定を行います。
- 前のAIエージェントの出力に ```sql という文字が含まれていたら
Trueなら後続のAIエージェントに接続し、Flaseの場合は返却するメッセージをセットするノードに接続します。
Falseの場合は、その回答をユーザーに直接送信して終了となりますね。
SQLの実行と結果報告部分
前のAIエージェントが生成したテキストを解釈してSQLを抽出し、ツールで実行し、そのプロセス全体をユーザーに分かりやすく報告するタスクを担っている部分です。
SQLの実行方法
n8nにBigQueryでクエリを実行できるツールが用意されているので、それをエージェントに接続します。
必要な設定としては、
- Credential
- Google Cloudに接続する資格情報を作成してセットします
- Operation
- Execute か Insertから選択できます。 今回はExecuteです。
- Project
- BigQueryのプロジェクト
- SQL Query
- 実行するSQLを入力します。
- {{ }}で囲むと、中はJavaScriptとして動作させることができます。
SQLクエリですが、ここはユーザーの要求によって変わります。
前のAIエージェントの出力でSQLコードブロックで囲むように命令しているので、それを抽出するJavascriptのコードを書きました。
{{ $json.output.match(/```sql([\s\S]*?)```/)[1].trim() }}
ステップ
このAIエージェントでは以下のステップで動作してもらうようにプロンプト(システムメッセージ)に書きました。
ステップ1: SQLクエリの抽出 (AIの能力)
- 受け取った入力テキストの中からSQLコードブロック(
```sql ... ```
)を見つけ出し、その中に含まれるSQLクエリ文字列だけを、あなた自身のテキスト解釈能力で正確に抜き出してください。 - この抜き出したSQLクエリを、ステップ3で使うために記憶しておきます。
- もしSQLコードブロックが見つからない場合は、エラーとして処理し、ユーザーにその旨を伝えてください。
ステップ2: SQLの実行 (ツール使用)
- **
execute_sql
ツールを実行します。
ステップ3: 最終報告の作成
execute_sql
ツールの実行結果と、ステップ1であなたが抜き出して記憶しておいたSQLクエリ文字列の両方の情報を使って、以下の**【最終報告フォーマット】**に従って、ユーザーへの最終的な報告を作成してください。
** 【最終報告フォーマット】 **
1. 実行されたSQLクエリ
- 「以下のSQLクエリを実行しました。」という見出しを付けます。
- ステップ1であなたが抽出したSQLクエリ文字列を、SQLコードブロック(
sql ...
)で囲んでここに記載してください。
2. サマリー(要約)
- 次に、SQL実行結果の要点を述べます。
3. データテーブル
- 結果のデータをMarkdownのテーブル形式で提示します。(11件以上は先頭10件のみ)
4. インサイトと次のアクション提案
- データから読み取れる洞察と、次の分析の提案をします。
5. 例外処理
- 結果がゼロ件の場合や、SQLエラーが発生した場合も、必ず「実行されたSQLクエリ」を提示した上で、状況を報告します。
実行例
2025/5の売り上げを日別で出して
というメッセージを送った時の結果です。
前のエージェントの結果が渡ってきて、それを元にSQLを実行できました。
報告内容も指定のフォーマットですね。
まとめ
自然言語からSQLの生成、実行をn8nのAIエージェントでやってみました。
役割を明確に分離した2つのAIエージェントを連携させるアーキテクチャにすることで、単純な要求には答えてくれたかなと思っています。
今回は一つのテーブルだけで行いましたが、実際は複数のテーブルを扱うことがほとんどなので、
今後の試行で増えた時の挙動も確認していかないといけないですね。