BigQuery のマネージド AI 関数で非構造化データを自由に処理しよう
こんにちは。このブログはGoogle Cloud Japan Advent Calendar 2025 12日目の記事です。
BigQueryのAI.IF()、AI.SCORE()、AI.CLASSIFY()関数を紹介します。いずれもバックエンドでGeminiを呼び出し、データをセマンティックに(=ほぼ無限のレパートリーで)処理する関数です。オブジェクトテーブルと組み合わせることで画像、音声、動画といったマルチモーダルデータを処理することも勿論可能です。
これらの関数を利用することで、オリジナリティ溢れる視点でテキストデータやマルチモーダルデータをジョインしたり、検索したり、タグ付けすることが出来ます。
サンプルクエリを動かす準備
本記事のサンプルクエリを実行するための手順です。
コネクションの作成
BigQueryのWebコンソールのエクスプローラーで「接続」を開き、右上の「接続を作成」ボタンをクリックします。
- 接続タイプは
Vertex AI リモートモデル、リモート関数、BigLake、Spanner (Cloudリソース)を選択します - 接続IDは
example_connectionとします - ロケーションはUSマルチリージョンとします
サービスアカウントへの権限付与
作成した接続の詳細画面に表示される「サービスアカウントID」をコピーします。「IAMと管理」で、コピーしたサービスアカウントIDに対して以下の権限を付与します。
- Storage オブジェクト ユーザー (roles/storage.objectUser)
- Vertex AI ユーザー (roles/aiplatform.user)
APIの有効化
- 「Vertex AI API」を検索し、APIを有効化します
以上で事前準備は終了です。
AI.IF()のサンプルクエリ
セマンティックに条件を指定してデータをフィルターしたり、ジョインすることができます。
◆フィルターのサンプルクエリ
複数のmp3ファイルから、生成AIについて話している音声ファイルを抽出します。
-- データセットの作成
CREATE SCHEMA IF NOT EXISTS audio_repo;
-- mp3ファイルのオブジェクトテーブルの作成
CREATE OR REPLACE EXTERNAL TABLE audio_repo.prompt_audio
WITH CONNECTION us.example_connection
OPTIONS (
object_metadata = 'SIMPLE',
uris = ['gs://cloud-samples-data/generative-ai/audio/*.mp3']
);
-- オーディオファイルのフィルタリングと中身の確認
SELECT
uri,
AI.GENERATE(("この音声ファイルの中身を日本語で簡潔に教えて。音声ファイル: ", OBJ.GET_ACCESS_URL(ref, 'r')),
connection_id => 'us.example_connection') AS summary
FROM
`audio_repo.prompt_audio`
WHERE
AI.IF(('この音声ファイルでは、スピーカーが生成AIを話題として取り上げていますか? 音声ファイル:', OBJ.GET_ACCESS_URL(ref, 'r')),
connection_id => 'us.example_connection');
クエリの実行結果
ファイルの概要を読む限りでは、それっぽい音声ファイルが抽出されているようです。

◆ジョインのサンプルクエリ
ペット商品の画像とマスターデータをジョインします。ジョインの条件として、商品名と商品画像が同一商品のものであるかどうかをGeminiに判定させ、同一商品であると判断された組み合わせのみを結果として戻します。
-- データセットの作成
CREATE SCHEMA IF NOT EXISTS cymbal_pets;
-- マスターデータテーブルの作成
LOAD DATA OVERWRITE cymbal_pets.products
FROM
FILES(
format = 'avro',
uris = [
'gs://cloud-samples-data/bigquery/tutorials/cymbal-pets/tables/products/products_*.avro']);
-- 商品画像のオブジェクトテーブルの作成
CREATE OR REPLACE EXTERNAL TABLE cymbal_pets.product_images
WITH CONNECTION us.example_connection
OPTIONS (
object_metadata = 'SIMPLE',
uris = ['gs://cloud-samples-data/bigquery/tutorials/cymbal-pets/images/*.png']);
-- マスターデータと商品画像をジョインする
SELECT product_name, brand, signed_url
FROM
cymbal_pets.products INNER JOIN
EXTERNAL_OBJECT_TRANSFORM(TABLE `cymbal_pets.product_images`, ['SIGNED_URL']) as images
ON
AI.IF(
(
"""ペット商品の画像を渡します。
渡された画像が、以下のペット商品の画像であるか判断してください: """,
products.product_name,
images.ref
),
connection_id => 'us.example_connection')
WHERE
products.category = "Toys" AND
products.brand = "Fluffy Buns";
クエリの実行結果
Pig Tunnelにはトンネルっぽい画像、Excercise Ballにはボールっぽい画像がマッチしていますね。

AI.SCORE()のサンプルクエリ
独自の観点でデータにスコアを付けます。ORDER BY と組み合わせることで検索にも利用できます。
◆サンプルクエリ
映画レビューのデータベースからThe English Patientに対するレビューを抜き出し、最も好意的なレビュー上位10件を検索しています。
SELECT
AI.SCORE((
"""
1から100のスケールで、レビュアーがレビュー対象の映画をどのくらい好んでいるかレイティングしてください.
レビュー:
""", review),
connection_id => 'us.example_connection') AS ai_rating,
reviewer_rating AS human_rating,
review
FROM
`bigquery-public-data.imdb.reviews`
WHERE
title = 'The English Patient'
ORDER BY ai_rating DESC
LIMIT 10;
クエリの実行結果
情熱的なレビューが多い!

AI.CLASSIFY()のサンプルクエリ
入力したカテゴリのいずれかに各レコードを分類します。それぞれのカテゴリの意味をdescriptionとして記述することが可能です。
◆サンプルクエリ
映画レビューのデータベースからThe English Patientに対するレビューを抜き出し、レビュアーの映画に対する印象を3つのカテゴリに分け、分類しています。カテゴリの意味をdescriptionとして記述しています(「レビューが肯定的」等)。
SELECT
AI.CLASSIFY(
('このレビューをセンチメントで分類して: ', review),
categories =>
[('green', 'レビューが肯定的。'),
('yellow', 'レビューがニュートラル(肯定的でも否定的でもない)。'),
('red', 'レビューが否定的。')],
connection_id => 'us.example_connection') AS ai_review_rating,
reviewer_rating AS human_provided_rating,
review,
FROM
`bigquery-public-data.imdb.reviews`
WHERE
title = 'The English Patient'
クエリの実行結果
Geminiはdescriptionを理解した上でカテゴリ分けしていそうですね。

おまけ。AI.GENERATE()との違いについて
AI.GENERATE()は汎用的な関数で、様々な観点でLLMにデータを解釈させ、その結果を取得することが可能です。
今回取り上げた3つの関数は、結果の品質及び一貫性を高めるため、「プロンプトの最適化」「モデルのエンドポイント及びパラメータのチューニング」が実行される点で、AI.GENERATE()と挙動が異なります。
用途が限定されている分、考える事が少なくて済む、というトレードオフですね。ユースケースに合わせて利用する関数を選択しましょう。
Discussion