powered by TechFeed
表示モード
ハウツー

ベクトルDBもAPIキー管理も不要 — BigQueryのSQLだけでRAGパイプラインを十数行で実装する方法

7月19日、Brice Fotzoが「SQL Is All You Need: RAG without a Vector Database in a Dozen Lines of BigQuery」と題した記事を公開した。ベクトルDBもオーケストレーターも不要で、BigQueryのSQL関数だけでRAGパイプラインを構築する方法を解説している。

7月19日、Brice Fotzoが「SQL Is All You Need: RAG without a Vector Database in a Dozen Lines of BigQuery」と題した記事を公開した。ベクトルDBもオーケストレーターも不要で、BigQueryのSQL関数だけでRAGパイプラインを構築する方法を解説している。


「RAGスタックの90%は不要」

LangChain、Pinecone、embedding API、複数のコンテナ——一般的なRAG(Retrieval-Augmented Generation)チュートリアルが前提とするアーキテクチャには、少なくとも5つのシステムと3つのAPIキーが登場する。しかもデータはウェアハウスの外に出る。BigQueryで丁寧に設定した行レベルセキュリティも、監査ログも、外部ベクトルストアにchunkを書き出した瞬間に意味をなさなくなる。

Brice Fotzoはこの前提を正面から否定し、BigQueryのAI関数だけで完結するRAGパイプラインを「十数行のSQL」で実現する方法を示している。

使用するデータは bigquery-public-data.bbc_news.fulltext。誰でも今すぐ手元で動かせる。


BigQueryに何が変わったか

BigQuery AI.* 関数群がGAに達し、RAGに必要な3つの操作がSQLの演算子として使えるようになった。各関数の公式ドキュメントは BigQuery AIリファレンス を参照されたい。

  • **AI.GENERATE_EMBEDDING**:テーブルから埋め込みをバッチ生成
  • **VECTOR_SEARCH**:セマンティック検索のネイティブ関数(IVFやTreeAHインデックスに対応。TreeAHはGoogleのScaNNアルゴリズムベース)
  • **AI.GENERATE**:行単位の生成関数。output_schema で型付き出力を指定でき、SELECTWHEREJOIN 条件の中にも書ける

認証はコード中のAPIキーではなく、BigQueryの「接続(Connection)」という管理サービスアカウントで一元管理される。デフォルト接続を使えば、初回実行時にBigQueryが自動でプロビジョニングしてくれる。

なお、「Geminiに縛られるのでは」という懸念はよくある誤解で、Anthropic Claude、Meta Llama、Mistral AI、そしてHugging Faceのオープンソースモデルも利用できる。


Path 2:自動更新コーパス(Preview)

先にこちらを紹介する。Path 1(バッチ版)の本番運用上の根本的な問題は「データは静止しない」ことだ。新着記事が来るたびに差分検出・再埋め込み・リトライを自前で実装する必要がある。

これを解決するのが autonomous embedding generation(自律的埋め込み生成)だ。埋め込みをテーブルの生成列(Generated Column) として宣言すると、データの挿入・更新に連動してBigQueryがバックグラウンドで自動的にベクトルを生成・更新する。

CREATE TABLE `rag_demo_us.news_live` (
  title STRING,
  body  STRING,
  body_embedding STRUCT<result ARRAY<FLOAT64>, status STRING>
    GENERATED ALWAYS AS (
      AI.EMBED(
        body,
        connection_id => 'us.my_connection',
        endpoint      => 'gemini-embedding-001')
    ) STORED OPTIONS (asynchronous = TRUE)
);

asynchronous = TRUE により、INSERTは埋め込み生成の完了を待たずに返る。バックグラウンドジョブはジョブ履歴で gc_ プレフィックスで確認できる。

検索も AI.SEARCH 関数でシンプルになる。クエリを手動で埋め込む必要すらない。

SELECT base.title, base.body, distance
FROM AI.SEARCH(
  TABLE `rag_demo_us.news_live`, 'body',
  'major browser security stories',
  top_k => 5
);

ただし この機能は現在Preview段階(プレGA条項が適用され、変更の可能性あり)。また、1テーブルあたり自動生成埋め込み列は1つのみ、頻繁なDMLよりバッチ挿入が推奨、テーブルのコピー・クローン・スナップショットは設定を引き継がない、といった制約も把握しておく必要がある。


Path 1:バッチ版パイプライン(GA)

モデルとコーパスの準備

まず埋め込みモデルを登録する(コンテナもエンドポイント管理も不要)。

CREATE OR REPLACE MODEL `rag_demo_us.emb_model`
  REMOTE WITH CONNECTION DEFAULT
  OPTIONS (ENDPOINT = 'gemini-embedding-001');

次に、BBCニュースのtech記事を一括で埋め込む。

CREATE OR REPLACE TABLE `rag_demo_us.news_emb` AS
SELECT *
FROM AI.GENERATE_EMBEDDING(
  MODEL `rag_demo_us.emb_model`,
  (
    SELECT title, body AS content
    FROM `bigquery-public-data.bbc_news.fulltext`
    WHERE category = 'tech'
  ),
  STRUCT('RETRIEVAL_DOCUMENT' AS task_type)
);

ここで2点注意がある。入力クエリは**content という列名を持つ必要がある**(エイリアスで対応)。また、task_type の使い分けが重要で、コーパス側は RETRIEVAL_DOCUMENT、ユーザーの質問側は RETRIEVAL_QUERY を指定する非対称埋め込みが検索精度を上げる。

落とし穴:サイレントな部分失敗。 バッチ全体は成功しても、個々の行がクォータ上限などで失敗していることがある。status 列が空でない行を必ず確認すること(成功行は status = '')。

検索と生成を1クエリで

SELECT
  AI.GENERATE(
    (
      'Answer using only this context:\n',
      STRING_AGG(base.content, '\n---\n'),
      '\nQuestion: what were the major browser security stories?'
    ),
    endpoint      => 'gemini-2.5-flash',
    output_schema => 'answer STRING, confidence FLOAT64, sources ARRAY<STRING>'
  ).*
FROM VECTOR_SEARCH(
  TABLE `rag_demo_us.news_emb`, 'embedding',
  (
    SELECT embedding
    FROM AI.GENERATE_EMBEDDING(
      MODEL `rag_demo_us.emb_model`,
      (SELECT 'major browser security stories' AS content),
      STRUCT('RETRIEVAL_QUERY' AS task_type)
    )
  ),
  top_k => 5
);

output_schema が肝で、返ってくるのはJSONの文字列ではなく型付きの列answerconfidencesources)だ。パースコードは不要になる。


「無料でついてくる」ものの価値

記事が強調するのは機能よりもこちらかもしれない。

  • VECTOR_SEARCH に行レベル・列レベルセキュリティが適用される。 ユーザーが見られない行はRAGのコンテキストとしても取得されない。これを外部ベクトルDBとの同期で正しく実装するのがいかに困難かは、経験者なら分かるはずだ。
  • 認証はIAMのみ。 パイプラインコードにAPIキーを埋め込まない。
  • 監査ログとコスト管理が既存のBigQueryの仕組みに乗る。

このアプローチが向かないケース

記事はメリットだけでなく、Pythonが依然として正しい選択肢であるケースも率直に挙げている。具体的には、サブ秒のレイテンシが求められるリアルタイム検索BigQueryの外に存在するデータソース(アプリDBやファイルストレージなど)を直接扱う場合LangGraphやLlamaIndexといったエージェントフレームワークの高度なオーケストレーション機能を必要とする場合などが該当する。データがすでにBigQueryに集約されており、セキュリティ・ガバナンス要件が厳しいバッチ系ユースケースで最も威力を発揮するアーキテクチャだ。ツールを正当化するために限界を隠さない点は、技術記事として誠実だ。

詳細はSQL Is All You Need: RAG without a Vector Database in a Dozen Lines of BigQueryを参照していただきたい。