您可以在应用通过 Firebase AI Logic 向 Gemini API 发送的每个 请求之前和之后运行自己的自定义服务器端脚本, 而无需更改客户端代码。您需要将这些脚本实现为部署到 Cloud Functions for Firebase 的回调式函数。
借助此功能,您可以执行审核提示、限制 token 使用量、记录生成内容以进行分析或隐去回答内容等操作。
有两种事件类型:
beforeGenerateContent:在请求到达 Gemini API 之前运行。该函数可以检查或修改请求,也可以通过抛出错误来完全阻止请求。afterGenerateContent:在 Gemini API 发回响应之后、响应返回到客户端应用之前运行。该函数可以检查或修改响应、完全屏蔽响应,或仅观察响应(例如用于日志记录或审核)。
将脚本作为函数部署到 Cloud Functions for Firebase 后,它们会注册为 Firebase AI Logic 触发器,这意味着它们会在项目中通过 Firebase AI Logic 向 Gemini API 发出的每个 generateContent 请求(包括使用服务器提示模板发出的请求)中运行。
这些函数不会由向 Gemini API 发出的请求(不通过 Firebase AI Logic)触发。
前提条件
设置 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 Service Account 角色 (
roles/cloudbuild.builds.builder)。运行以下 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 提供方时,函数才应运行。
检查提示中是否存在屏蔽的主题,并通过抛出错误来拒绝请求。
为文本生成模型设置输出 token 数量上限。
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 请求的响应时,系统会触发该函数。该函数在回答返回到客户端应用之前针对回答运行。该函数可以记录使用情况、修改回答或完全屏蔽回答。
在编写函数之前,请务必查看以下信息:
- 您可以在函数中使用的事件数据
- 请求后函数的行动要点
- 函数的限制和行为
示例
以下是一个请求后函数示例,用于记录 token 用量和完成原因:
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函数。默认位置:这些函数将默认部署到
us-central1(了解函数的位置)。不过,无论您在何处部署函数,该函数都会在global区域中注册为 Firebase AI Logic 触发器。