您可以在应用通过 Firebase AI Logic 向 Gemini API 发送的每个请求之前和之后运行自己的自定义服务器端脚本,而无需更改客户端代码。您将这些脚本实现为部署到 Cloud Functions for Firebase 的回调样式函数。
借助此功能,您可以执行以下操作:审核提示、限制令牌使用量、记录生成的内容以供分析,或编辑回答内容。
有两种类型的活动:
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
向默认的 Compute Engine 服务账号授予构建函数所需的 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 请求收到响应时,函数会被触发。该函数在响应返回到客户端应用之前针对响应运行。该函数可以记录使用情况、修改响应或完全屏蔽响应。
在编写函数之前,请务必查看以下信息:
- 可在函数中使用的事件数据
- 请求后函数的主要注意事项
- 函数的限制和行为
示例
以下是一个示例后请求函数,用于记录令牌使用情况和完成原因:
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 触发器。