Gemini 3 Flash と AlloyDB を使用してリアルタイムの余剰エンジンを構築する

1. 概要

この Codelab では、インテリジェンスをデータレイヤーのファーストクラスの市民として扱う、持続可能な余剰共有アプリ「Neighbor Loop」を作成します。

Gemini 3.0 Flash と AlloyDB AI を統合することで、基本的なストレージからデータベース内インテリジェンスの領域に移行できます。SQL 内で直接マルチモーダル アイテム分析とセマンティック ディスカバリを実行する方法を学び、レイテンシとアーキテクチャの肥大化という「AI 税」を排除します。

1da27e0c4d9a33e0.jpeg

作成するアプリの概要

コミュニティの余剰品を共有するための高性能な「スワイプしてマッチング」ウェブ アプリケーション。

学習内容

  • ワンクリック プロビジョニング: AI ワークロード用に設計された AlloyDB クラスタとインスタンスを設定する方法。
  • インデータベース エンベディング: INSERT ステートメント内で text-embedding-005 ベクトルを直接生成します。
  • マルチモーダル推論: Gemini 3.0 Flash を使用してアイテムを「認識」し、ウィットに富んだデートスタイルの自己紹介を自動的に生成します。
  • セマンティック検出: ai.if() 関数を使用して SQL クエリ内で論理ベースの「雰囲気チェック」を実行し、単なる計算だけでなくコンテキストに基づいて結果をフィルタリングします。

アーキテクチャ

Neighbor Loop は、従来のアプリケーション レイヤのボトルネックを回避します。データを抽出して処理する代わりに、次のものを使用します。

  1. AlloyDB AI: ベクトルをリアルタイムで生成して保存します。
  2. Google Cloud Storage: 画像を保存する
  3. Gemini 3.0 Flash: SQL を介して画像データとテキストデータに対して 1 秒未満の推論を直接実行します。
  4. Cloud Run: 軽量な単一ファイルの Flask バックエンドをホストします。

要件

  • ブラウザ(ChromeFirefox など)
  • 課金を有効にした Google Cloud プロジェクト
  • SQL と Python に関する基本的な知識。

2. 始める前に

プロジェクトを作成する

  1. Google Cloud コンソールのプロジェクト選択ページで、Google Cloud プロジェクトを選択または作成します。
  2. Cloud プロジェクトに対して課金が有効になっていることを確認します。詳しくは、プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください
  1. Google Cloud 上で動作するコマンドライン環境の Cloud Shell を使用します。Google Cloud コンソールの上部にある [Cloud Shell をアクティブにする] をクリックします。

[Cloud Shell をアクティブにする] ボタンの画像

  1. Cloud Shell に接続したら、次のコマンドを使用して、すでに認証済みであることと、プロジェクトがプロジェクト ID に設定されていることを確認します。
gcloud auth list
  1. Cloud Shell で次のコマンドを実行して、gcloud コマンドがプロジェクトを認識していることを確認します。
gcloud config list project
  1. プロジェクトが設定されていない場合は、次のコマンドを使用して設定します。
gcloud config set project <YOUR_PROJECT_ID>
  1. 必要な API を有効にする: リンクにアクセスして、API を有効にします。

または、この操作に gcloud コマンドを使用することもできます。gcloud コマンドとその使用方法については、ドキュメントをご覧ください。

注意点とトラブルシューティング

「ゴースト プロジェクト」症候群

gcloud config set project を実行したが、実際にはコンソール UI で別のプロジェクトが表示されている。左上のプルダウンでプロジェクト ID を確認してください。

請求のバリケード

プロジェクトを有効にしたが、請求先アカウントを忘れた。AlloyDB は高性能エンジンです。ガソリン タンク(課金)が空の場合、起動しません。

API 伝播の遅延

[API を有効にする] をクリックしたのに、コマンドラインに Service Not Enabled と表示される。60 秒ほど待ちます。クラウドがニューロンを起動するまでしばらくお待ちください。

割り当て Quags

新しいトライアル アカウントを使用している場合は、AlloyDB インスタンスのリージョン割り当てに達する可能性があります。us-central1 が失敗した場合は、us-east1 を試してください。

「非表示」のサービス エージェント

AlloyDB サービス エージェントに aiplatform.user ロールが自動的に付与されないことがあります。SQL クエリが後で Gemini と通信できない場合、通常はこのことが原因です。

3. データベースの設定

このラボでは、テストデータのデータベースとして AlloyDB を使用します。クラスタを使用して、データベースやログなどのすべてのリソースを保持します。各クラスタには、データへのアクセス ポイントを提供するプライマリ インスタンスがあります。テーブルには実際のデータが格納されます。

テスト データセットを読み込む AlloyDB クラスタ、インスタンス、テーブルを作成しましょう。

  1. ボタンをクリックするか、以下のリンクを Google Cloud コンソールのユーザーがログインしているブラウザにコピーします。

  1. この手順が完了すると、リポジトリがローカルの Cloud Shell エディタにクローンされ、プロジェクト フォルダから次のコマンドを実行できるようになります(プロジェクト ディレクトリにいることを確認することが重要です)。
sh run.sh
  1. UI を使用します(ターミナルのリンクをクリックするか、ターミナルの [ウェブでプレビュー] リンクをクリックします)。
  2. プロジェクト ID、クラスタ名、インスタンス名の詳細を入力して、開始します。
  3. ログがスクロールしている間にコーヒーを飲んで、裏で何が行われているかについてはこちらをご覧ください。

注意点とトラブルシューティング

「忍耐」の問題

データベース クラスタは重いインフラストラクチャです。ページを更新したり、「フリーズした」ように見える Cloud Shell セッションを強制終了したりすると、部分的にプロビジョニングされた「ゴースト」インスタンスが作成され、手動で介入しないと削除できなくなる可能性があります。

リージョンが一致しない

us-central1 で API を有効にしたが、asia-south1 でクラスタをプロビジョニングしようとすると、割り当ての問題やサービス アカウントの権限の遅延が発生する可能性があります。ラボ全体で 1 つのリージョンを使用してください。

ゾンビ クラスタ

以前にクラスタに同じ名前を使用し、削除していない場合、スクリプトでクラスタ名がすでに存在すると表示されることがあります。クラスタ名はプロジェクト内で一意にする必要があります。

Cloud Shell のタイムアウト

コーヒー ブレイクに 30 分かかると、Cloud Shell がスリープ状態になり、sh run.sh プロセスが切断されることがあります。タブをアクティブな状態に保つ

4. スキーマのプロビジョニング

AlloyDB クラスタとインスタンスが実行されたら、AlloyDB Studio の SQL エディタに移動して、AI 拡張機能を有効にしてスキーマをプロビジョニングします。

1e3ac974b18a8113.png

インスタンスの作成が完了するまで待つ必要がある場合があります。完了したら、クラスタの作成時に作成した認証情報を使用して AlloyDB にログインします。PostgreSQL の認証には次のデータを使用します。

  • ユーザー名: 「postgres
  • データベース: 「postgres
  • パスワード: 「alloydb」(作成時に設定したパスワード)

AlloyDB Studio への認証が成功すると、エディタに SQL コマンドが入力されます。最後のウィンドウの右にあるプラス記号を使用して、複数のエディタ ウィンドウを追加できます。

28cb9a8b6aa0789f.png

必要に応じて [実行]、[形式]、[クリア] オプションを使用して、エディタ ウィンドウに AlloyDB のコマンドを入力します。

拡張機能を有効にする

このアプリのビルドには、拡張機能 pgvectorgoogle_ml_integration を使用します。pgvector 拡張機能を使用すると、ベクトル エンベディングを保存して検索できます。google_ml_integration 拡張機能は、Vertex AI 予測エンドポイントにアクセスして SQL で予測を取得するために使用する関数を提供します。次の DDL を実行して、これらの拡張機能を有効にします。

CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;

テーブルを作成する

AlloyDB Studio で次の DDL ステートメントを使用してテーブルを作成できます。

-- Items Table (The "Profile" you swipe on)
CREATE TABLE items (
   item_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
   owner_id UUID,
   provider_name TEXT,
   provider_phone TEXT,
   title TEXT,
   bio TEXT,
   category TEXT,
   image_url TEXT,
   item_vector VECTOR(768),
   status TEXT DEFAULT 'available',
   created_at TIMESTAMP DEFAULT NOW()
);

-- Swipes Table (The Interaction)
CREATE TABLE swipes (
   swipe_id SERIAL PRIMARY KEY,
   swiper_id UUID,
   item_id UUID REFERENCES items(item_id),
   direction TEXT CHECK (direction IN ('left', 'right')),
   is_match BOOLEAN DEFAULT FALSE,
   created_at TIMESTAMP DEFAULT NOW()
);

item_vector 列には、テキストのベクトル値を格納できます。

権限を付与

次のステートメントを実行して、「embedding」関数に対する実行権限を付与します。

GRANT EXECUTE ON FUNCTION embedding TO postgres;

AlloyDB サービス アカウントに Vertex AI ユーザーロールを付与する

Google Cloud IAM コンソールで、AlloyDB サービス アカウント(service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com のような形式)に「Vertex AI ユーザー」ロールへのアクセス権を付与します。PROJECT_NUMBER にはプロジェクト番号が設定されます。

または、Cloud Shell ターミナルから次のコマンドを実行することもできます。

PROJECT_ID=$(gcloud config get-value project)


gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"

AlloyDB に Gemini 3 Flash モデルを登録する

AlloyDB クエリエディタから次の SQL ステートメントを実行します。

CALL google_ml.create_model(
   model_id => 'gemini-3-flash-preview',
   model_request_url => 'https://aiplatform.googleapis.com/v1/projects/<<YOUR_PROJECT_ID>>/locations/global/publishers/google/models/gemini-3-flash-preview:generateContent',
   model_qualified_name => 'gemini-3-flash-preview',
   model_provider => 'google',
   model_type => 'llm',
   model_auth_type => 'alloydb_service_agent_iam'
);
--replace <<YOUR_PROJECT_ID>> with your project id.

注意点とトラブルシューティング

「パスワード忘れ」ループ

「ワンクリック」設定を使用していて、パスワードを忘れた場合は、コンソールのインスタンスの基本情報ページに移動し、[編集] をクリックして postgres パスワードをリセットします。

「拡張機能が見つかりません」というエラー

CREATE EXTENSION が失敗するのは、インスタンスが初期プロビジョニングの「メンテナンス」状態または「更新中」状態のままになっていることが原因であることがよくあります。インスタンスの作成ステップが完了しているかどうかを確認し、必要に応じて数秒待ちます。

IAM 伝播のギャップ

gcloud IAM コマンドを実行しましたが、SQL CALL が権限エラーで失敗します。IAM の変更が Google バックボーンに反映されるまでに時間がかかることがあります。深呼吸しましょう。

ベクトル ディメンションの不一致

items テーブルは VECTOR(768) に設定されます。後で別のモデル(1, 536 次元モデルなど)を使用しようとすると、挿入が爆発します。text-embedding-005 に準拠します。

プロジェクト ID の誤字脱字

create_model 呼び出しで、角かっこ « » をそのままにしたり、プロジェクト ID を誤って入力したりすると、モデル登録は成功したように見えますが、最初の実際のクエリで失敗します。文字列を再確認してください。

5. 画像ストレージ(Google Cloud Storage)

余剰品の写真を保存するために、GCS バケットを使用します。このデモアプリでは、スワイプ カードにすぐに表示されるように、画像を一般公開します。

  1. バケットを作成する: 作成: GCP プロジェクトに新しいバケット(neighborloop-images など)を作成します。データベースとアプリケーションと同じリージョンに作成することをおすすめします。
  2. 公開アクセスを構成する: * バケットの [権限] タブに移動します。
  3. allUsers プリンシパルを追加します。
  4. Storage オブジェクト閲覧者ロール(すべてのユーザーが写真を見ることができるようにするため)と Storage オブジェクト作成者ロール(デモのアップロード用)を割り当てます。

代替(サービス アカウント): 一般公開アクセスを使用しない場合は、アプリケーションのサービス アカウントに AlloyDB への完全アクセス権と、オブジェクトを安全に管理するために必要なストレージ ロールが付与されていることを確認してください。

注意点とトラブルシューティング

リージョン ドラッグ

データベースが us-central1 にあり、バケットが europe-west1 にある場合、AI の速度が低下します。「バイブ チェック」はすばやく行われますが、UI の画像を取得するのに時間がかかります。同じリージョンに配置する

バケット名の一意性

バケット名はグローバル名前空間です。バケットに neighborloop-images という名前を付けようとすると、すでに別のユーザーがその名前を使用している可能性があります。作成に失敗した場合は、ランダムな接尾辞を追加します。

「作成者」と「閲覧者」の混同

「作成者」と「閲覧者」の混同: 「閲覧者」のみを追加した場合、ユーザーが新しいアイテムを一覧表示しようとすると、アプリはファイルを書き込む権限がないためクラッシュします。この特定のデモ設定では両方が必要です。

6. アプリケーションを作成してみましょう

このリポジトリをプロジェクトにクローンして、内容を確認しましょう。

  1. このクローンを作成するには、Cloud Shell ターミナル(ルート ディレクトリまたはこのプロジェクトを作成する場所)から次のコマンドを実行します。
git clone https://github.com/AbiramiSukumaran/neighbor-loop

これでプロジェクトが作成されます。Cloud Shell エディタで確認できます。

53a398aff6ba7d5b.png

  1. Gemini API キーを取得する方法
  2. Google AI Studio にアクセスする: aistudio.google.com にアクセスします。
  3. ログイン: Google Cloud プロジェクトで使用している同じ Google アカウントを使用します。
  4. API キーを作成する:
  5. 左側のサイドバーで [API キーを取得] をクリックします。
  6. [新しいプロジェクトで API キーを作成] ボタンをクリックします。
  7. キーをコピーする: キーが生成されたら、コピーアイコンをクリックします。
  8. 次に、.env ファイルで環境変数を設定します。
GEMINI_API_KEY=<<YOUR_GEMINI_API_KEY>>
DATABASE_URL=postgresql+pg8000://postgres:<<YOUR_PASSWORD>>@<<HOST_IP>>:<<PORT>>/postgres
GCS_BUCKET_NAME=<<YOUR_GCS_BUCKET>>

プレースホルダ <<YOUR_GEMINI_API_KEY>>, <<YOUR_PASSWORD>, <<HOST_IP>>, <<PORT>> and <<YOUR_GCS_BUCKET>>. の値を置き換えます。

注意点とトラブルシューティング

複数のアカウントの混同

複数の Google アカウント(個人用と仕事用)にログインしている場合、AI Studio でデフォルトで選択されるアカウントが間違っている可能性があります。右上にあるアバターを確認して、GCP プロジェクト アカウントと一致していることを確認します。

「無料枠」の割り当て超過

無料枠を使用している場合は、レート制限(RPM - 1 分あたりのリクエスト数)があります。近隣ループでスワイプが速すぎると、429 Too Many Requests エラーが発生することがあります。スピードを落として!

公開されたキーのセキュリティ

キーを含む .env ファイルを誤って git commit した場合。常に .gitignore.env を追加します。

「接続タイムアウト」の無効化

.env ファイルでプライベート IP アドレスを使用しているが、VPC の外部(ローカルマシンなど)から接続しようとしている。プライベート IP には、同じ Google Cloud ネットワーク内からのみアクセスできます。パブリック IP に切り替えます。

ポート 5432 の前提条件

5432 は標準の PostgreSQL ポートですが、Auth Proxy を使用している場合、AlloyDB で特定のポート構成が必要になることがあります。このラボでは、ホスト文字列の末尾に :5432 を使用していることを確認してください。

「承認済みネットワーク」Gatekeeper

パブリック IP があっても、コードを実行しているマシンの IP アドレスをホワイトリストに登録していない限り、AlloyDB は「接続を拒否」します。修正: AlloyDB インスタンスの設定で、承認済みネットワークに 0.0.0.0/0(一時的なテストのみ)または特定の IP を追加します。

SSL/TLS ハンドシェイクの失敗

AlloyDB は安全な接続を優先します。DATABASE_URL でドライバが正しく指定されていない場合(pg8000 を使用するなど)、ハンドシェイクがサイレントに失敗し、一般的な「データベースにアクセスできません」というエラーが表示されることがあります。

「プライマリ プールと読み取りプール」の切り替え

誤ってプライマリ インスタンスではなく読み取りプールの IP アドレスをコピーした場合、アプリはアイテムの検索には使用できますが、新しいアイテムを一覧表示しようとすると「読み取り専用」エラーでクラッシュします。書き込みには常にプライマリ インスタンスの IP を使用します。

7. コードを確認しましょう

モノの「出会い系プロフィール」

c2c543562cc9b353.png

ユーザーが商品の写真をアップロードする際に、長い説明文を入力する必要はありません。Gemini 3 Flash を使用して商品を「確認」し、リスティングを作成します。

バックエンドでは、ユーザーはタイトルと写真を提供するだけです。残りの処理は Gemini が行います。

prompt = """
You are a witty community manager for NeighborLoop.
Analyze this surplus item and return JSON:
{
   "bio": "First-person witty dating-style profile bio for the product, not longer than 2 lines",
   "category": "One-word category",
   "tags": ["tag1", "tag2"]
}
"""
response = genai_client.models.generate_content(
   model="gemini-3-flash-preview",
   contents=[types.Part.from_bytes(data=image_bytes, mime_type="image/jpeg"), prompt],
   config=types.GenerateContentConfig(response_mime_type="application/json")
)

21f871a1b549efcf.png

リアルタイムの In-Database エンベディング

aa783a459f1b02da.png

AlloyDB の最も優れた機能の 1 つは、SQL コンテキストを離れることなくエンベディングを生成できることです。Python でエンベディング モデルを呼び出してベクトルを DB に送り返す代わりに、embedding() 関数を使用して 1 つの INSERT ステートメントでこれらすべてを行います。

INSERT INTO items (owner_id, provider_name, provider_phone, title, bio, category, image_url, status, item_vector)
VALUES (
   :owner, :name, :phone, :title, :bio, :cat, :url, 'available',
   embedding('text-embedding-005', :title || ' ' || :bio)::vector
)

これにより、投稿されたアイテムは、投稿された瞬間にその意味で「検索可能」になります。これは、Neighbor Loop アプリの「商品を掲載する」機能をカバーする部分です。

商品リスティング機能のスクリーンショットを追加する

Gemini 3.0 による高度なベクトル検索とスマート フィルタリング

標準のキーワード検索は制限されています。「椅子の修理」を検索した場合、従来のデータベースでは、タイトルに「椅子」という単語が含まれていないと、何も返されない可能性があります。Neighbor Loop は、AlloyDB AI の高度なベクトル検索でこの問題を解決します。

pgvector 拡張機能と AlloyDB の最適化されたストレージを使用することで、非常に高速な類似性検索を実行できます。しかし、ベクトル近接性と LLM ベースのロジックを組み合わせると、真の「魔法」が起こります。

AlloyDB AI を使用すると、SQL クエリ内で Gemini などのモデルを直接呼び出すことができます。つまり、ai.if() 関数を使用して、論理ベースの「健全性チェック」を含むセマンティック検出を実行できます。

SELECT item_id, title, bio, category, image_url,
      1 - (item_vector <=> embedding('text-embedding-005', :query)::vector) as score
FROM items
WHERE status = 'available'
 AND item_vector IS NOT NULL
 AND ai.if(
       prompt => 'Does this text: "' || bio ||'" match the user request: "' ||  :query || '", at least 60%? "',
       model_id => 'gemini-3-flash-preview'
     ) 
ORDER BY score DESC
LIMIT 5

このクエリは、ロジックをデータに移行するという大きなアーキテクチャの変更を表しています。Gemini 3 Flash は、数千もの結果をアプリケーション コードに pull してフィルタリングするのではなく、データベース エンジン内で「バイブ チェック」を実行します。これにより、レイテンシが短縮され、下り(外向き)費用が削減され、結果が数学的に類似しているだけでなく、コンテキストに関連していることが保証されます。

セマンティック検索機能のスクリーンショット

「スワイプして一致」ループ

UI はクラシックなカードのデッキです。

左にスワイプ: 破棄します。

右にスワイプ: マッチしました!

スワイプして一致させる機能のスクリーンショット

右にスワイプすると、バックエンドでスワイプ テーブルにインタラクションが記録され、アイテムが一致済みとしてマークされます。フロントエンドで、プロバイダの連絡先情報を示すモーダルがすぐにトリガーされるため、集荷の手配を行うことができます。

8. Cloud Run にデプロイしましょう。

  1. プロジェクトがクローンされた Cloud Shell ターミナルから次のコマンドを実行して、Cloud Run にデプロイします。プロジェクトのルートフォルダにいることを確認してください

Cloud Shell ターミナルで次のコマンドを実行します。

gcloud beta run deploy neighbor-loop \
   --source . \
   --region=us-central1 \
   --network=<<YOUR_NETWORK_NAME>> \
   --subnet=<<YOUR_SUBNET_NAME>> \
   --allow-unauthenticated \
   --vpc-egress=all-traffic \
   --set-env-vars GEMINI_API_KEY=<<YOUR_GEMINI_API_KEY>>,DATABASE_URL=postgresql+pg8000://postgres:<<YOUR_PASSWORD>>@<<PRIVATE_IP_HOST>>:<<PORT>>/postgres,GCS_BUCKET_NAME=<<YOUR_GCS_BUCKET>>

プレースホルダ <<YOUR_GEMINI_API_KEY>>, <<YOUR_PASSWORD>, <<PRIVATE_IP_HOST>>, <<PORT>> and <<YOUR_GCS_BUCKET>> の値を置き換えます。

コマンドが完了すると、サービス URL が出力されます。コピーします。

  1. Cloud Run サービス アカウントに AlloyDB クライアント ロールを付与します。これにより、サーバーレス アプリケーションがデータベースに安全にトンネリングできるようになります。

Cloud Shell ターミナルで次のコマンドを実行します。

# 1. Get your Project ID and Project Number
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")

# 2. Grant the AlloyDB Client role
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
--role="roles/alloydb.client"

サービス URL(先ほどコピーした Cloud Run エンドポイント)を使用してアプリをテストします。古い電動工具の写真をアップロードすると、残りの処理は Gemini が行います。

注意点とトラブルシューティング

「審査に失敗しました」ループ

デプロイが完了しても URL から 500 Internal Server Error が返される場合は、ログを確認してください。これは通常、環境変数が欠落しているDATABASE_URL のタイプミスなど)か、Cloud Run サービス アカウントに GCS バケットから読み取る権限がないことが原因です。

IAM の「シャドー」ロール

ユーザーにデプロイ権限がある場合でも、実際にデータベースへの接続を確立するには、Cloud Run サービス アカウント(通常は [project-number]-compute@developer.gserviceaccount.com)に AlloyDB Client ロールが必要です。

9. 高度なトラブルシューティング

b6cdd3785d5461a9.jpeg

10. デモ

エンドポイントをテストに使用できるようになります。

ただし、数日間のデモ目的であれば、次の方法を試すことができます。

11. クリーンアップ

このラボが完了したら、必ず AlloyDB クラスタとインスタンスを削除してください。

クラスタとそのインスタンスをクリーンアップする必要があります。

12. 完了

これで、Google Cloud を使用して持続可能なコミュニティ向けの Neighbor Loop アプリを正常に構築できました。エンベディングと Gemini 3 Flash AI ロジックを AlloyDB に移行することで、アプリの速度が大幅に向上し(デプロイ設定による)、コードが非常にクリーンになります。データを保存するだけでなく、意図も保存します。

Gemini 3 Flash の速度と AlloyDB の最適化されたベクトル処理の組み合わせは、コミュニティ主導のプラットフォームにとって真に次のフロンティアです。