Vanna.aiでText-to-SQLシステムを自作する:AIに雑多なレポート依頼の80%を任せる方法

Artificial Intelligence tutorial - IT technology blog
Artificial Intelligence tutorial - IT technology blog

「ちょっとこのレポート出しといて」という悪夢

データエンジニアやバックエンド開発者であれば、コーディングに集中している最中にマーケティング部門から「ちょっとお願い」というメッセージが届く光景はお馴染みでしょう。「先週の北部の売上はいくら?」といった質問は、難しくはないものの、貴重な時間を細切れに奪っていきます。Vanna.aiを実稼働(プロダクション)環境に導入して半年、これが本当に救世主となるソリューションであることに気づきました。

このシステムは、データチームへの雑多なクエリ依頼を最大70%削減します。毎日何十ものSQLを書く代わりに、AIにデータベース構造を学習させ、セルフサービスでユーザーに応答させることができます。この記事では、PythonとVanna.aiを使用して完全なText-to-SQL systemを構築する方法を徹底解説します。

なぜ純粋なプロンプトエンジニアリングではなく、Vanna.aiを選ぶのか?

「スキーマをChatGPTにコピーしてSQLを書かせればいいのでは?」と思うかもしれません。しかし実際には、200以上のテーブルと数千の列を持つ企業データベースの全スキーマをプロンプトに投げ込むのは不可能です。すぐにトークン制限に達し、深刻なデータセキュリティのリスクにも直面します。

Vanna.aiは、特化型のRAG(Retrieval-Augmented Generation:検索拡張生成)アプローチでこの問題を解決します。実際のデータはその場に残したまま、VannaはDDL、列の説明、サンプルSQLなどのメタデータのみをベクトルとして保存します。質問があると、関連性の高い構造を検索してLLMのコンテキストとして利用します。その結果、十分に学習させた後の精度は、実用レベルで60%から92%以上に向上しました。

Vanna.aiをスムーズに運用するための3つのコアレイヤー

効果的に導入するために、Vanna의 階層化された管理手法を理解する必要があります:

  • Infrastructure: 「脳」となるLLM(GPT-4, Claude 3, Ollamaなど)と、ベクトルストア(ChromaDB, Pineconeなど)を選択する場所です。
  • Knowledge Base: DDL文、ビジネスロジックのドキュメント、検証済みの標準SQL文を格納するナレッジの宝庫です。
  • Execution: データベースに直接接続してSQLを実行し、結果をテーブルや視覚的なチャートとして返却する架け橋です。

システム構築の実践:Text-to-SQLの実装

今回はSQLiteを使用してデモを行います。これらの手順は、プロダクション環境のPostgreSQL、MySQL、SQL Serverでも同様に適用可能です。

1. 環境構築

Python 3.9以上を使用し、ライブラリの衝突を避けるために仮想環境を作成することをお勧めします。

pip install vanna

2. Vannaの設定

Vannaは非常に柔軟で、完全なローカル実行による絶対的なセキュリティ確保も可能です。この例では、言語処理にOpenAI、ナレッジのベクトル保存にChromaDBを使用します。

import vanna as vn
from vanna.openai import OpenAI_Chat
from vanna.chromadb import ChromaDB_VectorStore

class MyVanna(ChromaDB_VectorStore, OpenAI_Chat):
    def __init__(self, config=None):
        ChromaDB_VectorStore.__init__(self, config=config)
        OpenAI_Chat.__init__(self, config=config)

vn = MyVanna(config={'api_key': 'YOUR_OPENAI_API_KEY', 'model': 'gpt-4'})

3. データベースへの接続

テスト用のデータベースファイル my_business.sqlite に接続します。

vn.connect_to_sqlite('my_business.sqlite')

4. ナレッジの学習 (Training) — 成功の鍵を握るフェーズ

AIが賢くなるかどうかは、データベースの「ルール」をどれだけ理解しているかにかかっています。適当にデータを流し込むのは禁物です。精度を最適化するために、通常は3つのレイヤーに分けて学習させます:

レイヤー1:テーブル構造(DDL)の読み込み。 どのテーブルにどのような情報が含まれているかをAIに教えます。

# AIにテーブル構造を教えるためのDDLを取得して学習させる
ddl = vn.run_sql("SELECT sql FROM sqlite_master WHERE type='table';")
for table_ddl in ddl['sql']:
    vn.train(ddl=table_ddl)

レイヤー2:ビジネスドキュメント(Documentation)。 例えば status_id = 1 が「支払い済み」を意味する場合、説明がないとAIは混乱します。

vn.train(documentation="status_id列: 1は「成功」、0は「注文キャンセル」を意味します。")

レイヤー3:サンプルSQL(Golden SQL)。 実際のクエリ例を通じてAIに教える、最も効果的な方法です。

vn.train(sql="SELECT customer_name, SUM(total_amount) FROM orders GROUP BY 1 ORDER BY 2 DESC LIMIT 10;")

5. テスト実行

いよいよ、自然な日本語で質問を投げ、成果を確認する時です。

question = "今月、最も購入額が多い顧客は誰ですか?"
sql = vn.generate_sql(question)
print(f"生成されたSQL: {sql}")

# SQLを実行して結果を表示
df = vn.run_sql(sql)
print(df)

6ヶ月間の実稼働で得られた教訓

AIを実際の現場に導入するのは、ローカルでデモを動かすよりも遥かに困難です。以下に重要な注意点をまとめます:

  • 魂を込めた命名を: データベースが table_1col_a ばかりだと、AIは必ず推測を誤ります。意味の分かりにくい列には、詳細なドキュメントを記述しましょう。
  • セキュリティ優先: 決して root ユーザーを使わないでください。読み取り専用(Read-Only)ユーザーを作成し、必要なテーブルにのみアクセス権を与え、パスワードやトークンなどの機密情報からは遠ざけましょう。
  • フィードバックループ (Feedback Loop): 毎週、AIが誤答した質問をチェックしています。正しいSQLに修正し、再び vn.train() で学習させます。2〜3週間もすれば、システムは見違えるほど賢くなります。
  • 可視化の活用: VannaはPlotlyとスムーズに連携します。クエリ結果から直接チャートを描画するようにAIに指示すると、上層部からの評価も非常に高まります。

おわりに

自然言語によるデータクエリは、もはやSFの話ではありません。Vanna.aiの登場により、Text-to-SQLシステムの構築はかつてないほど現実的で身近なものになりました。

複雑な財務レポートにおいて、AIがすぐにデータエンジニアに取って代わることはありません。しかし、日々の雑多なクエリ依頼の80%を「片付ける」には十分な実力を持っています。皆さんもぜひ、単純作業から解放され、昼休みに「ちょっとこれ確認して」と言われることのない環境を手に入れてください!

Share: