🐻

ObjectRefがすごい! - BigQueryとGoogle Cloud Storageをシームレスに連携して即AI分析 🤖💥🐻

に公開

この記事はDSKアドベントカレンダー2025企画15日目の記事です。

はじめに

初のZennブログ投稿です。
これを機に、他にも投稿できたらいいな~🌸と思っています。

電算システムでデータエンジニアとして働いてます。
基本的にGoogle Cloudを触っていて、LookerとかBigQuery、Data Analyticsに関わる諸々に触れています。

アドベントカレンダーということで、今年あったことのざっくりな振り返りですね。

今年の春は Google Cloud Next ’25 Las Vegas に参加しました。
現地参加の熱量ってやっぱり心地よかったですし活力になりました。
趣味でもイベント参加とかするとみんなの生き生きとした熱量や熱気が心地いいんですよね。
昨年2024年は、Google Cloud Partner Top Engineer 2025の受賞を頂いたのですが…。
今年は以下ふたつの賞を頂きました。

後者に関してはGenerative AI Leaderなんて楽勝だろ!と応募締め切りまで1ヶ月切ってる状態で受けて、落ちて大慌てする笑い話があったりするのですが…。
計画性って大事ですね。

さて、計画性をもって。
12月になったので書き始めました。
本題に入っていきましょうか。

ObjectRefがすごい!

この記事のタイトル、再登場です。
大事な事なので2回目です。

今年のNextで発表があり、夏ごろにPre-GAがされました。
お恥ずかしながら、この列が含まれる、そもそものBigQueryのオブジェクトテーブルについて今年まであまりよく知らなかったのですが、実際に触れる機会があり、そのものすごさに驚きました。

オブジェクトテーブルのすごいとこ

  • Google Cloud Storageの非構造化データをBigQueryからSQLで見れちゃう👈すげ~
  • ObjectRef👈これは本当に大革命!!
  • 更新いらない👈最近では当然な感じがしますが、改めてすごいというか楽。ありがたい

さて、そんなオブジェクトテーブルのObjectRefを使って今回は遊んでみます。

GCSの画像をGeminiに分析させてみよう

これが本当に画期的ですごい。
ObjectRefを使うことにより、BigQuery上のみでSQLを使って『Google Cloud Storageの画像をGeminiに分析させる』が実現できてしまうのですから。
色々組み合わせてリレーさせて…そんな日々とはお別れです。
勿論画像以外も可能です。
音声とか、PDFとかいろんな非構造化データをみにいけちゃいます。すごいですね~。

では、ざっくり手順のご紹介です。
大体Google Cloudが触れる前提で書いてます。


0.必要な権限

  • BigQuery データ編集者
  • BigQuery Connection User

1. Connection(接続)の作成

BigQueryのコンソールから[接続]を押して、接続を作ります。
接続タイプは 「VertexAI リモートモデル、リモート関数、BigLake、Spanner(Cloud リソース)」を選びます。

2. サービスアカウントへ権限付与

1.で作成した接続に書かれているサービスアカウントIDに下記の権限を与えます。

  • Vertex AI ユーザー
  • Storage オブジェクト閲覧者

3.モデルの作成

使用するモデルを作成します。

CREATE OR REPLACE MODEL `PROJECT.kumakuma_set.gemini_model`
  REMOTE WITH CONNECTION `CONNECTION_ID`
  OPTIONS (
    ENDPOINT = 'gemini-2.5-pro' 
  )

4. オブジェクトテーブルの作成

下記のようなクエリを実行して作成します。

CREATE OR REPLACE EXTERNAL TABLE `kumakuma_set.kuma_gcs`
WITH CONNECTION `CONNECTION_ID`
OPTIONS (
  object_metadata = 'SIMPLE',
  uris = ['gs://kumakana/*']
);

5. GeminiをBigQueryで呼び出す

BigQueryMLを使ってGeminiも呼び出しちゃいましょう。
下記のようなクエリを実行します。

SELECT
  t1.uri,
  t2.image_description
FROM
  `kumakuma_set.kuma_gcs` AS t1
INNER JOIN
  (
    SELECT
      uri,
      image_description
    FROM
      AI.GENERATE_TABLE(
        MODEL `PROJECT.kumakuma_set.gemini_model`,
        (
          SELECT
            ('この画像に写っているものを説明してください。', ref) AS prompt,  
            [OBJ.GET_ACCESS_URL(ref, 'r')] AS images,
            uri
          FROM
            `kumakuma_set.kuma_gcs`
          where uri = 'gs://kumakana/kumaster_image.jpg'
        ),
        STRUCT(
          'image_description STRING' AS output_schema
        )
      )
  ) AS t2
  ON t1.uri = t2.uri;

まずはマスターに使う熊の画像を説明させました。


うん、その通りですね。

構造化データと結合し、画像を比べさせて分析させてみる

オブジェクトテーブルそのものに対してAIを簡単に使えるのも十分すごいのですが…。
更にすごいのが、他の構造化データと結合させて新しいテーブルにしたとしても
オブジェクトテーブルのObjectRef列を使えば、Google Cloud Storageを見に行くことができるんです。
これが本当にすごいな~って思います。

ということでマスターテーブルと比較・分析させたい画像のあるテーブルを作ります。
それぞれオブジェクトテーブルではなく、普通のBigQueryテーブルになります。

用意したデータ

  • kumaster:マスターテーブル
    • さっきGeminiに説明させた熊の画像(マスターテーブルに登録)
    • 項目はこんな感じ
  • ayashi_animals:監視カメラに映った(想定の)黒~茶色の動物たち。画像と日時と場所が入ってます。
    • 🐻くま
    • 🐻🍼こぐま
    • 🐈‍⬛くろねこ
    • 🐾くろいいぬ …etc
    • 項目はこんな感じ

実行するクエリ

以下のようなSQLで比べさせてみます。

CREATE OR REPLACE TABLE
  kumakuma_set.multimodal_kuma_table AS
SELECT
  -- 1. あやしいどうぶつたちの情報
  ayashi.timestamp,
  ayashi.location,
  ayashi.camera_id,
  ayashi.image_ref AS ayashi_image_ref,

  -- 2. マスターの情報
  master.name AS master_name,
  master.master_image_ref.uri AS master_image_uri,

  -- 3. AI.GENERATE_TABLEによる分析結果
  ai_results.is_kuma,  -- 熊と一致したか
  ai_results.reasoning,           -- なぜそう判断したか
  ai_results.estimated_animal,  -- 具体的に何に見えるか(猫、タヌキなど)
  ai_results.how_to -- どう対処すべきか
FROM
  kumakuma_set.ayashi_animals AS ayashi
-- 全ての監視画像に対して、比較するためCROSS JOIN
CROSS JOIN
  (SELECT * FROM kumakuma_set.kumaster WHERE bear_id = 'bear01') AS master
JOIN
  (
    SELECT
      *
    FROM
      AI.GENERATE_TABLE(
        MODEL `kumakuma_set.gemini_2_pro_model`, -- 使用するモデル
        (
          SELECT
            -- プロンプトテキストの定義
            ('''あなたは熊目撃情報を精査するパートナーです。
              提示された「熊(画像1)」と「監視カメラの画像(画像2)」を比較してください。
              1. is_dangerous_match: 画像2が画像1と同じ危険生物(熊)であればtrue、そうでなければfalse。
              2. reasoning: 判定の理由。形状、耳の形、毛並みなどの特徴から具体的に説明してください。
              3. identified_creature: 画像2の生物が何であるか推測してタグ付けしてください。(例:熊、猫、タヌキ、人間、不明)
              4. どのように対処すべきか。簡潔に説明してください。危険でなければユーモアあふれる回答を期待します。そして人間は猫が好きです。
            ''', [master_image_ref,image_ref]) AS prompt,
            [
              OBJ.GET_ACCESS_URL(master.master_image_ref, 'r'),
              OBJ.GET_ACCESS_URL(ayashi.image_ref, 'r')
            ] AS images,
            ayashi.uri
          FROM
            kumakuma_set.ayashi_animals AS ayashi
          CROSS JOIN
            (SELECT * FROM kumakuma_set.kumaster WHERE bear_id = 'bear01') AS master
        ),
        STRUCT(
          -- 出力スキーマ定義
          'is_kuma BOOL, reasoning STRING, estimated_animal STRING, how_to STRING' AS output_schema
        )
      )
  ) AS ai_results
  ON ayashi.uri = ai_results.uri;

vs 熊🐻



マスターにいれた熊はヒグマでしたが、この画像はGemini先生曰くツキノワグマらしいです。
頼もしい回答!

vs 子熊🐻🍼



犬とかに勘違いしないかなと思って入れてみましたが賢い!
ママ熊の猫可愛がり 恐怖

vs 黒猫🐈‍⬛



薄暗くずんぐりとした黒猫なので勘違いしないかと期待したのですが、見抜いてる!
ただ香箱座りではないですが😂

vs 黒い犬🐾



これも薄暗く子熊とかに勘違いしないかな…といれたんですが、ちゃんと見抜いてますね~。

その他、Geminiの戦い成果

おわりに

BigQueryのオブジェクトテーブルの新機能 ObjectRef を使って遊んでみました。
監視カメラの時間等を持たせているので、出没の多い時間などの可視化とかも容易に行えると思いますし、その1テーブルで危険度や対処法などがまとめられていれば、LookerやLooker Studioでその項目を簡単に活かすことができます。

構造化データ(日時や場所とか)と非構造化データ(画像や音声)を同じテーブル操作の感覚で扱えるのは、データ分析の幅を大きく広げてくれそうですね。
またBigQueryMLも当然噛ませることが出来るので、BigQuery上のSQLのみで構造化データと非構造化データをAIを用いて分析できてしまうのは本当に便利で面白いと思います。

皆さんもぜひ、お手元のデータ(あるいはペットの写真)で遊んでみてください。 それでは、良いクリスマス&お年を!

電算システム 有志

Discussion