Puedes ejecutar tus propios secuencias de comandos personalizadas del servidor antes y después de cada solicitud que tu app envía a Gemini API a través de Firebase AI Logic, sin cambiar el código del cliente. Implementarás estas secuencias de comandos como funciones de estilo de devolución de llamada implementadas en Cloud Functions for Firebase.
Con esta capacidad, puedes hacer cosas como moderar instrucciones, limitar el uso de tokens, registrar las generaciones para el análisis o redactar el contenido de las respuestas.
Existen dos tipos de eventos disponibles:
beforeGenerateContent: Se ejecuta antes de que una solicitud llegue a Gemini API. La función puede inspeccionar o modificar la solicitud, o bien bloquearla por completo si arroja un error.afterGenerateContent: Se ejecuta después de que el Gemini API envía la respuesta y antes de que se muestre en la app cliente. La función puede inspeccionar o modificar la respuesta, bloquearla por completo o solo observarla (por ejemplo, para el registro o la auditoría).
Una vez que tus secuencias de comandos se implementan como funciones en Cloud Functions for Firebase, se registran como activadores de Firebase AI Logic, lo que significa que se ejecutarán para cada solicitud de generateContent en tu proyecto a Gemini API a través de Firebase AI Logic (incluidas las solicitudes realizadas con plantillas de instrucciones del servidor).
Estas funciones no se activan con solicitudes realizadas a Gemini API que no se realicen a través de Firebase AI Logic.
Requisitos previos
Configura Firebase AI Logic: Si aún no lo hiciste, completa la guía de introducción de Firebase AI Logic, en la que se describe cómo configurar tu proyecto de Firebase, conectar tu app a Firebase, agregar el SDK, inicializar el servicio de backend para el proveedor de Gemini API que elijas y crear una instancia de
GenerativeModel.Permisos necesarios: Asegúrate de tener los permisos de IAM necesarios para realizar la implementación en Cloud Functions for Firebase.
Paso 1: Configura tu proyecto para Cloud Functions for Firebase
Si nunca usaste Cloud Functions for Firebase en tu proyecto de Firebase, completa la siguiente configuración.
Asegúrate de que tu proyecto de Firebase tenga el plan de precios Blaze de pago por uso (obligatorio para usar Cloud Functions for Firebase).
Instala las interfaces de línea de comandos (CLI): gcloud CLI y CLI de Firebase
Otorga a la cuenta de servicio de Compute predeterminada el rol de cuenta de servicio de Cloud Build (
roles/cloudbuild.builds.builder) que necesita para compilar tu función. Ejecuta el siguiente comando gcloud CLI:gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \ --role="roles/cloudbuild.builds.builder"Inicializa Cloud Functions for Firebase en tu proyecto de Firebase:
Ejecuta el siguiente comando de la CLI de Firebase:
firebase init functionsCuando se te solicite, elige TypeScript.
Asegúrate de que
firebase-functionsen tufunctions/package.jsonsea de la versión 6.3.0 o posterior. Sigue estos pasos para verificar tu versión:npm --prefix functions list firebase-functions
Paso 2: Escribe tus funciones
Escribe una función previa a la solicitud (beforeGenerateContent)
Escribe una función posterior a la solicitud (afterGenerateContent)
Escribe una función previa a la solicitud (beforeGenerateContent)
Con el tipo de evento beforeGenerateContent, la función se activa cuando el proxy Firebase AI Logic recibe una solicitud generateContent. La función se ejecuta en la solicitud antes de que se envíe al Gemini API.
La función puede modificar o bloquear la solicitud por completo.
Asegúrate de revisar la siguiente información antes de escribir tu función:
- Datos de eventos que puedes usar en tu función
- Consideraciones clave para las funciones previas a la solicitud
- Limitaciones y comportamientos de las funciones
Ejemplo
A continuación, se muestra una función de pre-solicitud de ejemplo que hace lo siguiente:
Especifica que la función solo debe ejecutarse cuando la solicitud es para un proveedor de Gemini API específico.
Inspecciona la instrucción en busca de temas bloqueados y rechaza la solicitud con un error.
Limita la cantidad máxima de tokens de salida para los modelos de generación de texto.
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,
),
},
};
});
Consideraciones clave para las funciones previas a la solicitud
Especifica el proveedor Gemini API:
event.data.requestpuede ser para Gemini Developer API o Agent Platform Gemini API (formerly Vertex AI). Los objetos de solicitud de estas diferentes APIs tienen formas diferentes. Para trabajar de forma segura con el objeto de solicitud, debes verificarevent.data.api(por ejemplo, compararlo congeminiV1BetaovertexV1Beta1, respectivamente).Lanzar bloquea la solicitud: Si lanzas un
HttpsError, se rechazará la solicitud.Devuelve la solicitud completa: Si tu función modifica la solicitud, debes devolver el objeto de solicitud completo y modificado. Si no se devuelve nada (o
undefined), la solicitud no se modifica.Prueba la latencia: Según lo que haga tu función, podría agregar latencia y afectar la experiencia del usuario.
Escribe una función posterior a la solicitud (afterGenerateContent)
Con el tipo de evento afterGenerateContent, la función se activa cuando el proxy Firebase AI Logic recibe una respuesta de una solicitud generateContent. La función se ejecuta en la respuesta antes de que se muestre al cliente. La función puede registrar el uso, modificar la respuesta o bloquearla por completo.
Asegúrate de revisar la siguiente información antes de escribir tu función:
- Datos de eventos que puedes usar en tu función
- Consideraciones clave para las funciones posteriores a la solicitud
- Limitaciones y comportamientos de las funciones
Ejemplo
Esta es una función de post-request de ejemplo que registra el uso del token y el motivo de finalización:
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.
});
Consideraciones clave para las funciones posteriores a la solicitud
Especifica el proveedor Gemini API:
event.data.responsepuede ser para Gemini Developer API o Agent Platform Gemini API (formerly Vertex AI). Para convertir y trabajar de forma segura con el objeto de solicitud, debes verificarevent.data.api(por ejemplo, compararlo congeminiV1BetaovertexV1Beta1, respectivamente).Prueba la latencia: Según lo que haga tu función, podría agregar latencia y afectar la experiencia del usuario.
Paso 3: Implementa tus funciones
Implementar tus funciones en Firebase otorga permiso al agente de servicio de Firebase AI Logic para invocar estas funciones y registra cada función como un activador de Firebase AI Logic.
Implementa tus funciones con Firebase CLI:
firebase deploy --only functionsDespués de la implementación, confirma que tus funciones se hayan implementado en Firebase:
firebase functions:listSi necesitas iterar tu función, haz lo siguiente:
Actualiza la función en el directorio del proyecto y, luego, vuelve a ejecutar
firebase deploy --only functions.
Cómo detener la ejecución de una función
Para detener la ejecución de una de estas funciones, se debe borrar de nuestros servidores y anular su registro como un activador de Firebase AI Logic. Puedes hacerlo con la CLI de Firebase con cualquiera de las siguientes opciones:
Opción 1: Borra la función de forma implícita
Quita la función de la base de código del directorio del proyecto.
Ejecuta el siguiente comando de la CLI de Firebase:
firebase deploy --only functions
Opción 2: Borra la función de forma explícita
Quita la función de la base de código del directorio del proyecto.
Ejecuta el siguiente comando de la CLI de Firebase:
firebase functions:delete FUNCTION_NAME
Referencia de datos de eventos
Tanto beforeGenerateContent como afterGenerateContent reciben un objeto AIBlockingEvent que contiene contexto y metadatos sobre la solicitud.
Metadatos de la solicitud de nivel superior (AIBlockingEvent)
El objeto AIBlockingEvent de nivel superior proporciona información sobre la persona que llama y el entorno de activación:
event.authType: Estado de autenticación de la persona que llama:"app_user","unauthenticated"o"unknown".event.authId: Es el UID de Firebase Authentication del llamador, si accedió.event.authClaims: Son las reivindicaciones de autenticación personalizadas del llamador, si existen.event.appId: Es el ID de la app de Firebase que realizó la solicitud.event.androidPackageNameoevent.iosBundleId: Es el nombre del paquete o el ID del paquete de la app que realiza la llamada (aplicable para las plataformas de Android o Apple, respectivamente).event.data: Es la carga útil del evento, que difiere entre las funciones previas a la solicitud y las posteriores a la solicitud:- Para
beforeGenerateContent, este es un objetoBeforeGenerateContentData. - Para
afterGenerateContent, este es un objetoAfterGenerateContentData.
- Para
Datos del evento previo a la solicitud (beforeGenerateContent)
En una función beforeGenerateContent, event.data se propaga con un objeto BeforeGenerateContentData:
event.data.api: El proveedor de Gemini API:geminiV1Beta(Gemini Developer API) overtexV1Beta1(Agent Platform Gemini API (formerly Vertex AI)).event.data.model: Es la ruta completa del recurso del modelo (por ejemplo,projects/{PROJECT_ID}/locations/global/publishers/google/models/gemini-3.8-flash).event.data.template: Metadatos sobre la plantilla de instrucciones del servidor que se usó (PromptTemplateInfo), si corresponde.event.data.request: Es la carga útil de la solicitud saliente. El tipo de objeto y las propiedades dependen del proveedor Gemini API:- Gemini Developer API (
geminiV1Beta):GeminiV1BetaGenerateContentRequest - Agent Platform Gemini API (formerly Vertex AI) (
vertexV1Beta1):VertexV1Beta1GenerateContentRequest
- Gemini Developer API (
Datos de eventos posteriores a la solicitud (afterGenerateContent)
En una función afterGenerateContent, event.data se propaga con un objeto AfterGenerateContentData. Este objeto extiende BeforeGenerateContentData (proporcionando api, model, template y request) y agrega la respuesta del modelo:
event.data.response: Es la carga útil de la respuesta del modelo. El tipo de objeto y las propiedades dependen del proveedor de Gemini API:- Gemini Developer API (
geminiV1Beta):GeminiV1BetaGenerateContentResponse - Agent Platform Gemini API (formerly Vertex AI) (
vertexV1Beta1):VertexV1Beta1GenerateContentResponse
- Gemini Developer API (
Limitaciones y comportamientos
Cuando implementes estas funciones, ten en cuenta los siguientes comportamientos y limitaciones:
Solo solicitudes
generateContent: Estas funciones solo se pueden activar con solicitudesgenerateContenta Gemini API a través de Firebase AI Logic.Las siguientes acciones no activarán estas funciones, y las funciones se omitirán de forma silenciosa para esa solicitud:
Las solicitudes a
generateContentStreamno activarán estas funciones.Las solicitudes a Gemini Live API no activarán estas funciones.
No se requieren cambios en el código del cliente: Además de asegurarte de usar solicitudes
generateContentcuando quieras ejecutar estas funciones, no se requieren cambios en tu base de código del cliente.Estas funciones se implementan en nuestros servidores y se registran como activadores de Firebase AI Logic para que el proxy de Firebase AI Logic pueda interceptar solicitudes y respuestas del servidor.
Alcance a nivel del proyecto: Puedes implementar como máximo una función de
beforeGenerateContenty una función deafterGenerateContentpor proyecto de Firebase.Ubicaciones predeterminadas: Estas funciones se implementarán en
us-central1de forma predeterminada (obtén información sobre las ubicaciones de las funciones). Sin embargo, la función se registrará como un activador de Firebase AI Logic en la regiónglobal, independientemente de dónde implementes la función.