Exécuter des scripts côté serveur personnalisés avant et après les requêtes


Vous pouvez exécuter vos propres scripts personnalisés côté serveur avant et après chaque requête que votre application envoie à Gemini API via Firebase AI Logic, sans modifier votre code client. Vous implémentez ces scripts en tant que fonctions de style de rappel déployées sur Cloud Functions for Firebase.

Cette fonctionnalité vous permet, entre autres, de modérer les requêtes, de limiter l'utilisation de jetons, de consigner les générations pour les analyses ou de masquer le contenu des réponses.

Deux types d'événements sont disponibles :

  • beforeGenerateContent : s'exécute avant qu'une requête n'atteigne le Gemini API. La fonction peut inspecter ou modifier la requête, ou la bloquer entièrement en générant une erreur.

  • afterGenerateContent : s'exécute après l'envoi de la réponse depuis Gemini API et avant son renvoi à l'application cliente. La fonction peut inspecter ou modifier la réponse, la bloquer entièrement ou simplement l'observer (pour la journalisation ou l'audit, par exemple).

Une fois vos scripts déployés en tant que fonctions sur Cloud Functions for Firebase, ils sont enregistrés en tant que déclencheurs Firebase AI Logic. Cela signifie qu'ils s'exécuteront pour chaque requête generateContent de votre projet vers Gemini API via Firebase AI Logic (y compris les requêtes effectuées avec des modèles de requête serveur).

Ces fonctions ne sont pas déclenchées par les requêtes envoyées à Gemini API qui ne passent pas par Firebase AI Logic.

Prérequis

Étape 1 : Configurez votre projet pour Cloud Functions for Firebase

Si vous n'avez jamais utilisé Cloud Functions for Firebase dans votre projet Firebase, effectuez la configuration suivante.

  1. Assurez-vous que votre projet Firebase est associé au forfait Blaze avec paiement à l'usage (obligatoire pour utiliser Cloud Functions for Firebase).

  2. Installez les interfaces de ligne de commande (CLI) : gcloud CLI et Firebase CLI.

  3. Attribuez au compte de service Compute par défaut le rôle Compte de service Cloud Build (roles/cloudbuild.builds.builder) dont il a besoin pour compiler votre fonction. Exécutez la commande gcloud CLI suivante :

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
      --role="roles/cloudbuild.builds.builder"
    
  4. Initialisez Cloud Functions for Firebase dans votre projet Firebase :

    1. Exécutez la commande Firebase CLI suivante :

      firebase init functions
      
    2. Lorsque vous y êtes invité, sélectionnez TypeScript.

    3. Assurez-vous que firebase-functions dans votre functions/package.json est de version 6.3.0 ou ultérieure. Pour vérifier votre version :

      npm --prefix functions list firebase-functions
      

Étape 2 : Écrivez vos fonctions

 Écrire une fonction de pré-requête (beforeGenerateContent)  Écrire une fonction de post-requête (afterGenerateContent)

Écrire une fonction de pré-requête (beforeGenerateContent)

Avec le type d'événement beforeGenerateContent, la fonction est déclenchée lorsque le proxy Firebase AI Logic reçoit une requête generateContent. La fonction s'exécute sur la requête avant qu'elle ne soit envoyée à Gemini API. La fonction peut modifier la requête ou la bloquer complètement.

Avant d'écrire votre fonction, assurez-vous de lire les informations suivantes :

Exemple

Voici un exemple de fonction avant-requête qui effectue les opérations suivantes :

  • Indique que la fonction ne doit s'exécuter que lorsque la requête concerne un fournisseur Gemini API spécifique.

  • Inspecte l'invite pour détecter les thèmes bloqués et rejette la requête en générant une erreur.

  • Limite le nombre maximal de jetons de sortie pour les modèles de génération de texte.

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,
      ),
    },
  };
});

Points clés à prendre en compte pour les fonctions de pré-requête

  • Spécifiez le fournisseur Gemini API : event.data.request peut être pour Gemini Developer API ou Agent Platform Gemini API (formerly Vertex AI). Les objets de requête de ces différentes API ont des formes différentes. Pour utiliser l'objet de requête de manière sécurisée, vous devez vérifier event.data.api (par exemple, en le comparant à geminiV1Beta ou vertexV1Beta1, respectivement).

  • L'exception bloque la requête : si vous générez une HttpsError, la requête sera rejetée.

  • Renvoyez l'intégralité de la requête : si votre fonction modifie la requête, vous devez renvoyer l'objet de requête complet et modifié. Si vous ne renvoyez rien (ou undefined), la requête reste inchangée.

  • Testez la latence : selon ce que fait votre fonction, elle peut ajouter de la latence et avoir un impact sur l'expérience utilisateur.

Écrire une fonction post-requête (afterGenerateContent)

Avec le type d'événement afterGenerateContent, la fonction est déclenchée lorsque le proxy Firebase AI Logic reçoit une réponse à une requête generateContent. La fonction s'exécute sur la réponse avant qu'elle ne soit renvoyée à l'application cliente. Elle peut enregistrer l'utilisation, modifier la réponse ou la bloquer complètement.

Avant d'écrire votre fonction, assurez-vous de lire les informations suivantes :

Exemple

Voici un exemple de fonction post-request qui enregistre l'utilisation du jeton et la raison de la fin :

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.
});

Points clés à prendre en compte pour les fonctions post-requête

  • Spécifiez le fournisseur Gemini API : event.data.response peut être pour Gemini Developer API ou Agent Platform Gemini API (formerly Vertex AI). Pour caster et utiliser l'objet de requête de manière sécurisée, vous devez vérifier event.data.api (par exemple, en le comparant à geminiV1Beta ou vertexV1Beta1, respectivement).

  • Testez la latence : selon ce que fait votre fonction, elle peut ajouter de la latence et avoir un impact sur l'expérience utilisateur.

Étape 3 : Déployez vos fonctions

Le déploiement de vos fonctions sur Firebase accorde à l'agent de service Firebase AI Logic l'autorisation d'appeler ces fonctions et enregistre chaque fonction en tant que Firebase AI Logic déclencheur.

  1. Déployez vos fonctions à l'aide de la CLI Firebase :

    firebase deploy --only functions
    
  2. Après le déploiement, vérifiez que vos fonctions ont été déployées sur Firebase :

    firebase functions:list
    
  3. Si vous devez itérer sur votre fonction :

    Mettez à jour la fonction dans le répertoire de votre projet, puis exécutez à nouveau firebase deploy --only functions.

Arrêter l'exécution d'une fonction

Pour empêcher l'exécution de l'une de ces fonctions, elle doit être supprimée de nos serveurset désinscrite en tant que déclencheur Firebase AI Logic. Pour ce faire, utilisez la CLI Firebase avec l'une des options suivantes :

  • Option 1 : Supprimer la fonction de manière implicite

    1. Supprimez la fonction du codebase du répertoire de votre projet.

    2. Exécutez la commande Firebase CLI suivante :

      firebase deploy --only functions
      
  • Option 2 : Supprimer explicitement la fonction

    1. Supprimez la fonction du codebase du répertoire de votre projet.

    2. Exécutez la commande Firebase CLI suivante :

      firebase functions:delete FUNCTION_NAME
      



Documentation de référence sur les données d'événement

beforeGenerateContent et afterGenerateContent reçoivent un objet AIBlockingEvent contenant le contexte et les métadonnées de la requête.

Métadonnées de la requête de premier niveau (AIBlockingEvent)

L'objet AIBlockingEvent de premier niveau fournit des informations sur l'appelant et l'environnement de déclenchement :

  • event.authType : état de l'authentification de l'appelant : "app_user", "unauthenticated" ou "unknown".
  • event.authId : UID Firebase Authentication de l'appelant, s'il est connecté.
  • event.authClaims : revendications d'authentification personnalisées de l'appelant, le cas échéant.
  • event.appId : ID de l'application Firebase à l'origine de la requête.
  • event.androidPackageName / event.iosBundleId : nom du package ou ID du bundle de l'application appelante (applicable respectivement aux plates-formes Android ou Apple).
  • event.data : charge utile de l'événement, qui diffère entre les fonctions de pré-requête et de post-requête :

Données d'événement de pré-requête (beforeGenerateContent)

Dans une fonction beforeGenerateContent, event.data est renseigné avec un objet BeforeGenerateContentData :

  • event.data.api : fournisseur Gemini API : geminiV1Beta (Gemini Developer API) ou vertexV1Beta1 (Agent Platform Gemini API (formerly Vertex AI)).
  • event.data.model : chemin d'accès complet à la ressource de modèle (par exemple, projects/{PROJECT_ID}/locations/global/publishers/google/models/gemini-3.8-flash).
  • event.data.template : métadonnées sur le modèle de prompt du serveur utilisé (PromptTemplateInfo), le cas échéant.
  • event.data.request : charge utile de la requête sortante. Le type d'objet et les propriétés dépendent du fournisseur Gemini API :

Données d'événement post-demande (afterGenerateContent)

Dans une fonction afterGenerateContent, event.data est renseigné avec un objet AfterGenerateContentData. Cet objet étend BeforeGenerateContentData (en fournissant api, model, template et request) et ajoute la réponse du modèle :



Limites et comportements

Lorsque vous implémentez ces fonctions, gardez à l'esprit les comportements et les limites suivants :

  • Requêtes generateContent uniquement : ces fonctions ne peuvent être déclenchées que par des requêtes generateContent envoyées à Gemini API via Firebase AI Logic.

    Les éléments suivants ne déclencheront pas ces fonctions, qui seront contournées silencieusement pour cette requête :

    • Les requêtes adressées à generateContentStream ne déclenchent pas ces fonctions.

    • Les requêtes envoyées à Gemini Live API ne déclenchent pas ces fonctions.

  • Aucune modification du code côté client : à part vous assurer d'utiliser des requêtes generateContent lorsque vous souhaitez exécuter ces fonctions, aucune modification n'est requise dans votre codebase côté client.

    Ces fonctions sont déployées sur nos serveurs et enregistrées en tant que déclencheurs Firebase AI Logic afin que le proxy Firebase AI Logic puisse intercepter les requêtes et les réponses côté serveur.

  • Champ d'application au niveau du projet : vous pouvez déployer au maximum une fonction beforeGenerateContent et une fonction afterGenerateContent par projet Firebase.

  • Emplacements par défaut : ces fonctions seront déployées sur us-central1 par défaut (en savoir plus sur les emplacements des fonctions). Toutefois, la fonction sera enregistrée en tant que déclencheur Firebase AI Logic dans la région global, quel que soit l'endroit où vous déployez votre fonction.