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

1. 概要

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

Gemini 3.0 Flash と Cloud SQL の ML インテグレーションを統合することで、基本的なストレージからデータベース内インテリジェンスの領域に移行します。SQL 内でマルチモーダル アイテム分析とセマンティック検索を直接実行する方法について説明します。

645daa545b0e46a6.png

作成するアプリの概要

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

学習内容

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

アーキテクチャ

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

  1. Cloud SQL + ML インテグレーション: ベクトルをリアルタイムで生成して保存します。
  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 プロジェクトに対して課金が有効になっていることを確認します。プロジェクトで課金が有効になっているかどうかを確認する方法については、こちらをご覧ください
  3. 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 を確認してください。

課金 の障壁

プロジェクトを有効にしましたが、請求先アカウントを忘れていました。課金が空の場合、Cloud SQL は起動しません。

API の伝播 の遅延

[API を有効にする] をクリックしましたが、コマンドラインに Service Not Enabled と表示されます。60 秒待ちます。クラウドがニューロンを起動するまでに時間がかかります。

3. データベースの設定

このラボでは、テストデータのデータベースとして Cloud SQL for PostgreSQL を使用します。

テストデータセットが読み込まれる Cloud SQL インスタンスを作成しましょう。

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

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

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

リージョンが一致しない

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

Cloud Shell のタイムアウト

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

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

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

5a835906362f7609.png

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

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

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

9408d708b7dac90c.png

必要に応じて [実行]、[フォーマット]、[クリア] オプションを使用して、エディタ ウィンドウに Cloud SQL のコマンドを入力します。

拡張機能を有効にする

このアプリの構築には、pgvector 拡張機能と google_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;

テーブルを作成する

Cloud SQL 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;

ML の統合を有効にする

データベース内で機械学習機能を直接利用するには、ML インテグレーション フラグを有効にする必要があります。

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

INSTANCE_NAME="<<The name of your Cloud SQL Instance>>"

gcloud sql instances patch $INSTANCE_NAME --tier=db-custom-1-3840

gcloud sql instances patch $INSTANCE_NAME \
    --database-flags=cloudsql.enable_google_ml_integration=on

gcloud sql instances patch $INSTANCE_NAME --enable-google-ml-integration

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

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

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

INSTANCE_NAME="<<The name of your Cloud SQL Instance>>"
PROJECT_ID=$(gcloud config get-value project)

SA_EMAIL=$(gcloud sql instances describe $INSTANCE_NAME --format='value(serviceAccountEmailAddress)')
gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:$SA_EMAIL" \
    --role="roles/aiplatform.user"

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

Cloud SQL クエリ エディタから次の 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 => 'generic',
    model_auth_type => 'cloudsql_service_agent_iam'
);
--replace <<YOUR_PROJECT_ID>> with your project id.

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

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

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

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

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

IAM の伝播のギャップ

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

ベクトルの次元が一致しない

items テーブルは VECTOR(768) に設定されています。後で別のモデル(1536 次元モデルなど)を使用しようとすると、挿入が失敗します。text-embedding-005 を使用してください。

プロジェクト ID の入力ミス

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

Vertex AI のインテグレーションは無効です

–enable-google-ml-integration を実行します(データベース フラグとは別)。

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

余剰アイテムの写真を保存するには、GCS バケットを使用します。このデモアプリでは、スワイプカードにすぐにレンダリングされるように、画像に一般公開アクセス権を付与します。

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

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

コマンドを実行して一般公開アクセス権を付与する場合は、Cloud Shell ターミナルで次のコマンドを実行します。

BUCKET_NAME="<<your-bucket-name>>"
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_NAME \
    --member="allUsers" \
    --role="roles/storage.objectViewer"

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

リージョンのドラッグ

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

バケット名の一意性

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

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

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

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

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

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

cd neighbor-loop-cloud-sql/

これでプロジェクトが作成されます。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 分あたりのリクエスト数)があります。Neighbor Loop で「スワイプ」が速すぎると、429 Too Many Requests エラーが発生することがあります。速度を落としてください。

公開鍵のセキュリティ

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

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

リアルタイムのデータベース内エンベディング

aa783a459f1b02da.png

Cloud SQL の最も優れた機能の 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 は、Cloud SQL AI の高度なベクトル検索でこの問題を解決します。

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

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 
ORDER BY score DESC 
LIMIT 5

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

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

「スワイプしてマッチ」ループ

UI は定番のカードのデッキです。

左にスワイプ: 破棄。

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

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

右にスワイプすると、バックエンドはスワイプ テーブルにインタラクションを記録し、アイテムをマッチ済みとしてマークします。フロントエンドは、プロバイダの連絡先情報を表示するモーダルをすぐにトリガーし、受け取りの手配ができるようにします。

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

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

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

gcloud run deploy neighbor-loop-cloud-sql \
   --source . \
   --region=us-central1 \
   --allow-unauthenticated \
   --network=easy-cloudsql-vpc \
   --subnet=easy-cloudsql-subnet \
   --vpc-egress=private-ranges-only \
   --set-env-vars GEMINI_API_KEY=<<YOUR_GEMINI_API_KEY>>,DATABASE_URL=postgresql+pg8000://postgres:<<YOUR_PASSWORD>>@<<PRIVATE_IP_HOST>>:5432/postgres,GCS_BUCKET_NAME=<<YOUR_GCS_BUCKET>>

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

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

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

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

「リビジョンに失敗しました」ループ

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

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

206a26fcd93ea48.png

10. デモ

目的地をテストに使用できます。

ただし、数日間デモを行う場合は、次のものを使用できます。

11. クリーンアップ

このラボが完了したら、Cloud SQL インスタンスを削除することを忘れないでください。

12. 完了

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

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