クライアント コードを変更することなく、アプリが Firebase AI Logic 経由で Gemini API に送信する リクエストの前後で、独自のカスタム サーバーサイド スクリプトを実行できます。これらのスクリプトは、Cloud Functions for Firebase にデプロイされたコールバック スタイルの関数として実装します。
この機能を使用すると、プロンプトの管理、トークン使用量の制限、分析用の生成のロギング、レスポンス コンテンツの編集などを行うことができます。
次の 2 つのイベントタイプを使用できます。
beforeGenerateContent: リクエストが Gemini API に到達する前に実行されます。この関数は、リクエストを検査または変更したり、エラーをスローしてリクエストを完全にブロックしたりできます。afterGenerateContent: Gemini API からレスポンスが返送された後、クライアント アプリに返される前に実行されます。この関数は、レスポンスの検査や変更、レスポンスの完全なブロック、レスポンスの監視(ロギングや監査など)を行うことができます。
スクリプトが関数として Cloud Functions for Firebase にデプロイされると、Firebase AI Logic トリガーとして登録されます。つまり、プロジェクト内の generateContent リクエストが Firebase AI Logic を介して Gemini API に送信されるたびに(サーバー プロンプト テンプレートを使用して作成されたリクエストを含む)、スクリプトが実行されます。
これらの関数は、Firebase AI Logic を介さない Gemini API へのリクエストによってトリガーされません。
前提条件
Firebase AI Logic を設定する: まだ完了していない場合は、Firebase AI Logic スタートガイドに沿って、記載されている手順(Firebase プロジェクトの設定、アプリと Firebase の連携、SDK の追加、選択した Gemini API プロバイダのバックエンド サービスの初期化、
GenerativeModelインスタンスの作成)を完了します。必要な権限: Cloud Functions for Firebaseへのデプロイに必要な IAM 権限があることを確認します。
ステップ 1: Cloud Functions for Firebase 用にプロジェクトを設定する
Firebase プロジェクトで Cloud Functions for Firebase を使用したことがない場合は、次の設定を完了します。
Firebase プロジェクトが従量課金制の Blaze のお支払いプランに登録されていることを確認します(Cloud Functions for Firebase を使用するために必要です)。
コマンドライン インターフェース(CLI): gcloud CLI と Firebase CLI をインストールします。
関数をビルドするために必要な Cloud Build サービス アカウントのロール(
roles/cloudbuild.builds.builder)をデフォルトの Compute サービス アカウントに付与します。次の gcloud CLI コマンドを実行します。gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \ --role="roles/cloudbuild.builds.builder"Firebase プロジェクトで Cloud Functions for Firebase を初期化します。
次の Firebase CLI コマンドを実行します。
firebase init functionsプロンプトが表示されたら、[TypeScript] を選択します。
functions/package.jsonのfirebase-functionsが バージョン 6.3.0 以降であることを確認します。バージョンを確認する手順は次のとおりです。npm --prefix functions list firebase-functions
ステップ 2: 関数を記述する
リクエスト前関数(beforeGenerateContent)を記述する
リクエスト後関数(afterGenerateContent)を記述する
リクエスト前の関数(beforeGenerateContent)を記述する
beforeGenerateContent イベントタイプの場合、Firebase AI Logic プロキシが generateContent リクエストを受信すると、関数がトリガーされます。この関数は、
リクエストが Gemini API に送信される前にリクエストに対して実行されます。
この関数は、リクエストを変更したり、リクエストを完全にブロックしたりできます。
関数を作成する前に、次の情報を確認してください。
- 関数で使用できるイベントデータ
- リクエスト前の関数に関する重要な考慮事項
- 関数の制限事項と動作
例
次の処理を行う事前リクエスト関数の例を次に示します。
リクエストが特定の Gemini API プロバイダに対するものである場合にのみ、関数を実行するように指定します。
ブロックされたトピックについてプロンプトを検査し、エラーをスローしてリクエストを拒否します。
テキスト生成モデルの最大出力トークン数を制限します。
import { logger } from "firebase-functions";
import {
beforeGenerateContent,
HttpsError,
vertexV1Beta1,
type VertexV1Beta1GenerateContentRequest,
} from "firebase-functions/v2/ai";
const BLOCKED_TOPICS = ["weapon", "explosive", "self-harm"];
const MAX_OUTPUT_TOKENS = 4000;
export const guardPrompts = beforeGenerateContent((event) => {
// 1. Optional: If you want the function to only run for a specific Gemini API provider, specify it here.
if (event.data.api !== vertexV1Beta1) return;
const request = event.data.request as VertexV1Beta1GenerateContentRequest;
// 2. Read the prompt: contents[] -> parts[] -> text
const prompt = (request.contents ?? [])
.flatMap((c) => c.parts ?? [])
.map((p) => ("text" in p ? p.text : "") ?? "")
.join(" ")
.toLowerCase();
// 3. Throwing rejects the request. The request is never sent to the Gemini API.
const blocked = BLOCKED_TOPICS.find((t) => prompt.includes(t));
if (blocked) {
logger.warn("Blocked a prompt", { topic: blocked });
throw new HttpsError("invalid-argument", `We don't return content about ${blocked}.`);
}
logger.info("Allowing generation", {
model: event.data.model,
authType: event.authType,
authId: event.authId,
appId: event.appId,
});
// 4. The next step truncates the response, but that will break images.
if (event.data.model.includes("image")) return;
// 5. Return the WHOLE request, edited. Returning nothing leaves it untouched.
return {
...request,
generationConfig: {
...request.generationConfig,
maxOutputTokens: Math.min(
request.generationConfig?.maxOutputTokens ?? MAX_OUTPUT_TOKENS,
MAX_OUTPUT_TOKENS,
),
},
};
});
リクエスト前関数に関する重要な考慮事項
Gemini API プロバイダを指定します。
event.data.requestは Gemini Developer API または Agent Platform Gemini API (formerly Vertex AI) のいずれかにできます。これらの異なる API のリクエスト オブジェクトは形状が異なります。リクエスト オブジェクトを安全に操作するには、event.data.apiを確認する必要があります(たとえば、それぞれgeminiV1BetaまたはvertexV1Beta1と比較します)。スローするとリクエストがブロックされる:
HttpsErrorをスローすると、リクエストは拒否されます。リクエスト全体を返す: 関数がリクエストを変更する場合は、変更されたリクエスト オブジェクト全体を返す必要があります。何も返さない(または
undefinedを返す)と、リクエストは変更されません。レイテンシのテスト: 関数の処理内容によっては、レイテンシが発生し、ユーザー エクスペリエンスに影響する可能性があります。
リクエスト後の関数を作成する(afterGenerateContent)
afterGenerateContent イベントタイプの場合、Firebase AI Logic プロキシが generateContent リクエストからレスポンスを受信すると、関数がトリガーされます。この関数は、レスポンスがクライアント アプリに返される前に、レスポンスに対して実行されます。この関数は、使用状況のログ記録、レスポンスの変更、レスポンスの完全なブロックを行うことができます。
関数を作成する前に、次の情報を確認してください。
- 関数で使用できるイベントデータ
- リクエスト後の関数に関する主な考慮事項
- 関数の制限事項と動作
例
トークンの使用状況と終了理由をログに記録するリクエスト後の関数の例を次に示します。
import { logger } from "firebase-functions";
import {
afterGenerateContent,
vertexV1Beta1,
type VertexV1Beta1GenerateContentResponse,
} from "firebase-functions/v2/ai";
export const recordGenerationUsage = afterGenerateContent((event) => {
// Optional: If you want the function to only run for a specific Gemini API provider, specify it here.
if (event.data.api !== vertexV1Beta1) return;
const response = event.data.response as VertexV1Beta1GenerateContentResponse;
logger.info("Generation finished", {
model: event.data.model,
promptTokens: response.usageMetadata?.promptTokenCount,
totalTokens: response.usageMetadata?.totalTokenCount,
finishReason: response.candidates?.[0]?.finishReason,
});
// To leave the response untouched, return nothing.
// To modify the response, return a modified response object here.
});
リクエスト後の関数に関する主な考慮事項
Gemini API プロバイダを指定します。
event.data.responseは Gemini Developer API または Agent Platform Gemini API (formerly Vertex AI) のいずれかにできます。リクエスト オブジェクトを安全にキャストして操作するには、event.data.apiを確認する必要があります(たとえば、それぞれgeminiV1BetaまたはvertexV1Beta1と比較します)。レイテンシのテスト: 関数の処理内容によっては、レイテンシが発生し、ユーザー エクスペリエンスに影響する可能性があります。
ステップ 3: 関数をデプロイする
関数を Firebase にデプロイすると、Firebase AI Logic サービス エージェントにこれらの関数を呼び出す権限が付与され、各関数が Firebase AI Logic トリガーとして登録されます。
Firebase CLI を使用して次のように関数をデプロイします。
firebase deploy --only functionsデプロイ後、関数が Firebase にデプロイされていることを確認します。
firebase functions:list関数を反復処理する必要がある場合:
プロジェクト ディレクトリで関数を更新し、
firebase deploy --only functionsを再度実行します。
関数の実行を停止する
これらの関数のいずれかの実行を停止するには、サーバーから削除し、Firebase AI Logic トリガーとしての登録を解除する必要があります。これを行うには、次のいずれかのオプションを使用して Firebase CLI を使用します。
オプション 1: 関数を暗黙的に削除する
プロジェクト ディレクトリのコードベースから関数を削除します。
次の Firebase CLI コマンドを実行します。
firebase deploy --only functions
オプション 2: 関数を明示的に削除する
プロジェクト ディレクトリのコードベースから関数を削除します。
次の Firebase CLI コマンドを実行します。
firebase functions:delete FUNCTION_NAME
イベントデータのリファレンス
beforeGenerateContent と afterGenerateContent はどちらも、リクエストに関するコンテキストとメタデータを含む AIBlockingEvent オブジェクトを受け取ります。
最上位のリクエスト メタデータ(AIBlockingEvent)
最上位の AIBlockingEvent オブジェクトは、呼び出し元とトリガー環境に関する情報を提供します。
event.authType: 呼び出し元の認証状態:"app_user"、"unauthenticated"、"unknown"。event.authId: ログインしている場合は、呼び出し元の Firebase Authentication UID。event.authClaims: 呼び出し元のカスタム認証クレーム(存在する場合)。event.appId: リクエストを行った Firebase アプリ ID。event.androidPackageName/event.iosBundleId: 呼び出し元のアプリのパッケージ名またはバンドル ID(それぞれ Android プラットフォームまたは Apple プラットフォームに適用されます)。event.data: イベント ペイロード。リクエスト前関数とリクエスト後関数で異なります。beforeGenerateContentの場合、これはBeforeGenerateContentDataオブジェクトです。afterGenerateContentの場合、これはAfterGenerateContentDataオブジェクトです。
リクエスト前のイベントデータ(beforeGenerateContent)
beforeGenerateContent 関数で、event.data に BeforeGenerateContentData オブジェクトが設定されます。
event.data.api: Gemini API プロバイダ:geminiV1Beta(Gemini Developer API)またはvertexV1Beta1(Agent Platform Gemini API (formerly Vertex AI))。event.data.model: モデルリソースの完全なパス(例:projects/{PROJECT_ID}/locations/global/publishers/google/models/gemini-3.8-flash)。event.data.template: 使用されるサーバー プロンプト テンプレート(PromptTemplateInfo)に関するメタデータ(該当する場合)。event.data.request: 送信リクエストのペイロード。オブジェクトのタイプとプロパティは、Gemini API プロバイダによって異なります。- Gemini Developer API(
geminiV1Beta):GeminiV1BetaGenerateContentRequest - Agent Platform Gemini API (formerly Vertex AI)(
vertexV1Beta1):VertexV1Beta1GenerateContentRequest
- Gemini Developer API(
リクエスト後のイベントデータ(afterGenerateContent)
afterGenerateContent 関数で、event.data に AfterGenerateContentData オブジェクトが入力されます。このオブジェクトは BeforeGenerateContentData を拡張し(api、model、template、request を提供)、モデルのレスポンスを追加します。
event.data.response: モデルのレスポンス ペイロード。オブジェクトの型とプロパティは、Gemini API プロバイダによって異なります。- Gemini Developer API(
geminiV1Beta):GeminiV1BetaGenerateContentResponse - Agent Platform Gemini API (formerly Vertex AI)(
vertexV1Beta1):VertexV1Beta1GenerateContentResponse
- Gemini Developer API(
制限事項と動作
これらの関数を実装する際は、次の動作と制限事項に注意してください。
generateContentリクエストのみ: これらの関数は、Firebase AI Logic 経由で Gemini API へのgenerateContentリクエストによってのみトリガーできます。次の場合は、これらの関数はトリガーされず、そのリクエストに対して関数はサイレントにバイパスされます。
generateContentStreamへのリクエストは、これらの関数をトリガーしません。Gemini Live API へのリクエストは、これらの関数をトリガーしません。
クライアントサイドのコード変更は不要: これらの関数を実行する場合は
generateContentリクエストを使用する必要がありますが、それ以外にクライアントサイドのコードベースを変更する必要はありません。これらの関数はサーバーにデプロイされ、Firebase AI Logic トリガーとして登録されます。これにより、Firebase AI Logic プロキシがリクエストとレスポンスをサーバーサイドでインターセプトできます。
プロジェクト レベルのスコープ: Firebase プロジェクトごとにデプロイできる
beforeGenerateContent関数とafterGenerateContent関数はそれぞれ 1 つまでです。デフォルトのロケーション: これらの関数は、デフォルトで
us-central1にデプロイされます(関数のロケーションをご覧ください)。ただし、関数をどこにデプロイしても、関数はglobalリージョンに Firebase AI Logic トリガーとして登録されます。