1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Firebase GenkitでVertex AI Vector Searchの起動/停止を自動化し、開発コストを最適化する

1
Last updated at Posted at 2026-03-19

はじめに

前回は関連記事として、Firebase Genkitを活用して、Function Callingから自己学習ループまでを備えたパーソナルAIエージェントのバックエンドを構築しました。

このAIエージェントの「長期記憶」を支えるコア技術として、Vertex AI Vector Searchを利用したハイブリッド検索を採用しています。

しかし、開発フェーズや社内PoCの段階において、「Vector Searchのインデックスを24時間稼働させ続けるとランニングコストが高くついてしまう」 というインフラ運用上の課題に直面しました。

そこで今回は、Firebase GenkitのフローとCloud Schedulerを組み合わせ、「利用しない夜間や休日はインデックスをアンデプロイし、業務開始前に自動でデプロイするバッチ処理」 を実装し、コストを大幅に最適化する方法とその知見をまとめます。

対象読者

  • Firebase Genkitを使った実践的な運用・インフラ管理に関心がある方
  • Vertex AI Vector Searchを利用中で、開発・検証環境のコスト削減を図りたい方
  • Firebase Cloud Functions (v2) のスケジュール実行 (onSchedule) の実装例を知りたい方

課題:Vector Searchの待機コスト

Vertex AI Vector Searchは、数百万〜数十億スケールの高次元ベクトルをミリ秒単位で検索できる非常に強力なサービスですが、検索クエリを受け付けるためには「インデックスをエンドポイントにデプロイ」した状態にしておく必要があります。

この「デプロイされたインデックス」は、検索リクエストの有無にかかわらず、稼働している時間(ノードの時間)に対して課金が発生 します。

24時間365日フル稼働させた場合、社内検証用の小規模なノードであっても、月額で数万円単位のコストがかかってしまいます。

「平日の日中(業務時間中)しかテストを行わない」のであれば、夜間や休日はアンデプロイしておくことで、ランニングコストを半分以下に抑えることが可能です。

解決策:Genkit Flow × Cloud Schedulerによる自動化

この起動・停止のオペレーションを手動で行うのは現実的ではないため、Firebase Genkit の機能を使って自動化します。

アーキテクチャとしては非常にシンプルで、以下の2つの要素で構成されます。

  1. Genkit Flow: @google-cloud/aiplatform SDKを使用して、実際にデプロイ/アンデプロイのAPIを叩く処理
  2. Cloud Functions (onSchedule): 指定した時間(cron)に上記のFlowを呼び出すトリガー

実装

実際に稼働しているバックエンドのコードをベースに解説します。

1. デプロイ / アンデプロイを実行するGenkit Flow

まず、Vector Searchを操作するためのフローを定義します。

daily.ts
抜粋
import { z } from 'genkit';
import { ai } from '../core/bootstrap';
import { IndexEndpointServiceClient } from '@google-cloud/aiplatform';
import { PROJECT_ID, VECTOR_SEARCH_LOCATION, PUBLIC_ENDPOINT_ID, INDEX_ID, PUBLIC_DEPLOYED_ID } from '../constants/config';

/**
 * Vector Searchインデックスをデプロイするフロー
 */
export const deployVectorIndexFlow = ai.defineFlow(
  { name: 'deployVectorIndexFlow', inputSchema: z.void(), outputSchema: z.void() },
  async () => {
    console.log('[Vector Deploy] Starting Vertex AI Vector Search index deployment...');

    try {
      const client = new IndexEndpointServiceClient({
        apiEndpoint: `${VECTOR_SEARCH_LOCATION}-aiplatform.googleapis.com`,
      });

      const indexEndpoint = `projects/${PROJECT_ID}/locations/${VECTOR_SEARCH_LOCATION}/indexEndpoints/${PUBLIC_ENDPOINT_ID}`;
      const index = `projects/${PROJECT_ID}/locations/${VECTOR_SEARCH_LOCATION}/indexes/${INDEX_ID}`;

      const request = {
        indexEndpoint: indexEndpoint,
        deployedIndex: {
          id: PUBLIC_DEPLOYED_ID,
          displayName: PUBLIC_DEPLOYED_ID,
          index: index,
          dedicatedResources: {
            machineSpec: {
              machineType: 'e2-standard-2', // 用途に合わせてマシンスペックを指定
            },
            minReplicaCount: 1,
            maxReplicaCount: 1,
          },
        },
      };

      const [operation] = await client.deployIndex(request);
      console.log('[Vector Deploy] Deploy operation started. It will take 20-30 minutes to complete.');
    } catch (error: any) {
      // 既にデプロイ済みの場合はエラーを無視して処理を続行
      if (error.message && error.message.includes('is already deployed')) {
        console.log('[Vector Deploy] Index is already deployed. No action needed.');
      } else {
        console.error('[Vector Deploy] Failed to start index deployment:', error);
      }
    }
  }
);

/**
 * Vector Searchインデックスをアンデプロイするフロー
 */
export const undeployVectorIndexFlow = ai.defineFlow(
  { name: 'undeployVectorIndexFlow', inputSchema: z.void(), outputSchema: z.void() },
  async () => {
    console.log('[Vector Undeploy] Starting Vertex AI Vector Search index undeployment...');

    try {
      const client = new IndexEndpointServiceClient({
        apiEndpoint: `${VECTOR_SEARCH_LOCATION}-aiplatform.googleapis.com`,
      });

      const request = {
        indexEndpoint: `projects/${PROJECT_ID}/locations/${VECTOR_SEARCH_LOCATION}/indexEndpoints/${PUBLIC_ENDPOINT_ID}`,
        deployedIndexId: PUBLIC_DEPLOYED_ID,
      };

      const [operation] = await client.undeployIndex(request);
      console.log('[Vector Undeploy] Undeploy operation started.');

    } catch (error: any) {
      console.error('[Vector Undeploy] Failed to start index undeployment:', error);
    }
  }
);

実装のポイント:

  • GCPの IndexEndpointServiceClient を利用してAPIを呼び出しています
  • デプロイ処理(deployIndex)は 完了までに20〜30分程度かかる 非同期オペレーションですが、ここでは「処理の開始(リクエストの送信)」のみを待機して関数を終了させています
  • 何らかの理由で既にデプロイされている状態(is already deployed)でフローが実行されても、エラーでクラッシュしないようにハンドリングしています

2. Firebase Functionsでのスケジュール設定

作成したFlowを、指定した時間に自動実行させるために onSchedule を使ってエクスポートします。

index.ts
抜粋
import { onSchedule } from 'firebase-functions/v2/scheduler';
import { deployVectorIndexFlow, undeployVectorIndexFlow } from './flows';

// Vector Searchをデプロイ(平日朝9時に実行)
export const deployVectorIndex = onSchedule({ 
  region: 'asia-northeast1', 
  schedule: "every mon,tue,wed,thu,fri 09:00", 
  memory: '1GiB', 
  timeZone: 'Asia/Tokyo' 
}, async (event) => {
  await deployVectorIndexFlow.run();
});

// Vector Searchをアンデプロイ(平日夜18時に実行)
export const undeployVectorIndex = onSchedule({ 
  region: 'asia-northeast1', 
  schedule: "every mon,tue,wed,thu,fri 18:00", 
  memory: '1GiB', 
  timeZone: 'Asia/Tokyo' 
}, async (event) => {
  await undeployVectorIndexFlow.run();
});

スケジュールのポイント:

  • schedule にcron形式(every mon,tue,wed,thu,fri 09:00)で稼働させたい時間を指定します
  • 前述の通り、Vector Searchのデプロイには20〜30分程度の時間がかかります
  • そのため、業務開始時間(例:9:30)に合わせてデプロイするのではなく、十分な余裕を持って(例:9:00)にスケジュールを設定しておくのがベストプラクティスです

デプロイと運用確認

上記の設定ができたら、Firebaseにデプロイします。

firebase deploy --only functions

スクリーンショット 2026-03-19 10.49.57.png

デプロイ後、GCPの「Cloud Scheduler」のコンソールを確認すると、指定したタイムゾーン(Asia/Tokyo)でジョブが登録されていることが確認できます。
※上記のキャプチャでは、 デプロイ6:00実行 / アンデプロイ23:00実行 としています。

おわりに

今回は、Firebase GenkitとCloud Schedulerを活用し、Vertex AI Vector Searchの稼働時間をコントロールする自動化バッチの実装について紹介しました。

このような運用スクリプトも、メインのAI機能(LLMの呼び出し等)と同じ「Genkit Flow」として一元管理することで、コードの統一性が保たれ、ローカルのDeveloper UI (genkit start) から手軽にテスト実行できるという大きなメリットがあります。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?