Esegui script lato server personalizzati prima e dopo le richieste


Puoi eseguire i tuoi script lato server personalizzati prima e dopo ogni richiesta che la tua app invia a Gemini API tramite Firebase AI Logic, senza modificare il codice client. Implementi questi script come funzioni di tipo callback di cui è stato eseguito il deployment su Cloud Functions for Firebase.

Con questa funzionalità, puoi moderare i prompt, limitare l'utilizzo dei token, registrare le generazioni per l'analisi o oscurare i contenuti delle risposte.

Sono disponibili due tipi di eventi:

  • beforeGenerateContent: viene eseguito prima che una richiesta raggiunga Gemini API. La funzione può esaminare o modificare la richiesta oppure bloccarla completamente generando un errore.

  • afterGenerateContent: viene eseguita dopo l'invio della risposta da Gemini API e prima che venga restituita all'app client. La funzione può esaminare o modificare la risposta, bloccarla completamente o semplicemente osservarla (ad esempio per la registrazione o il controllo).

Una volta eseguiti il deployment degli script come funzioni in Cloud Functions for Firebase, questi vengono registrati come trigger Firebase AI Logic, il che significa che verranno eseguiti per ogni richiesta generateContent nel tuo progetto a Gemini API tramite Firebase AI Logic (incluse le richieste effettuate con i modelli di prompt del server).

Queste funzioni non vengono attivate da richieste effettuate a Gemini API che non avvengono tramite Firebase AI Logic.

Prerequisiti

Passaggio 1: configura il progetto per Cloud Functions for Firebase

Se non hai mai utilizzato Cloud Functions for Firebase nel tuo progetto Firebase, completa la seguente configurazione.

  1. Assicurati che il tuo progetto Firebase sia nel piano tariffario Blaze con pagamento a consumo (obbligatorio per utilizzare Cloud Functions for Firebase).

  2. Installa le interfacce a riga di comando (CLI): gcloud CLI e Firebase CLI

  3. Concedi al service account Compute predefinito il ruolo Cloud Build Service Account (roles/cloudbuild.builds.builder) necessario per creare la tua funzione. Esegui questo comando gcloud CLI:

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

    1. Esegui questo comando CLI Firebase:

      firebase init functions
      
    2. Quando richiesto, scegli TypeScript.

    3. Assicurati che firebase-functions nel tuo functions/package.json sia la versione 6.3.0 o successive. Ecco come controllare la versione:

      npm --prefix functions list firebase-functions
      

Passaggio 2: scrivi le funzioni

Scrivi una funzione pre-richiesta (beforeGenerateContent) Scrivi una funzione post-richiesta (afterGenerateContent)

Scrivi una funzione pre-richiesta (beforeGenerateContent)

Con il tipo di evento beforeGenerateContent, la funzione viene attivata quando il proxy Firebase AI Logic riceve una richiesta generateContent. La funzione viene eseguita sulla richiesta prima che venga inviata a Gemini API. La funzione può modificare la richiesta o bloccarla completamente.

Prima di scrivere la funzione, assicurati di esaminare le seguenti informazioni:

Esempio

Ecco una funzione di pre-richiesta di esempio che esegue le seguenti operazioni:

  • Specifica che la funzione deve essere eseguita solo quando la richiesta riguarda un fornitore Gemini API specifico.

  • Ispeziona il prompt per verificare la presenza di argomenti bloccati e rifiuta la richiesta generando un errore.

  • Limita il numero massimo di token di output per i modelli di generazione di testo.

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

Considerazioni chiave per le funzioni di pre-richiesta

  • Specifica il fornitore Gemini API: event.data.request può essere per Gemini Developer API o Agent Platform Gemini API (formerly Vertex AI). Gli oggetti richiesta per queste diverse API hanno forme diverse. Per utilizzare in sicurezza l'oggetto richiesta, devi controllare event.data.api (ad esempio, confrontalo rispettivamente con geminiV1Beta o vertexV1Beta1).

  • Lancio che blocca la richiesta: se lanci un HttpsError, la richiesta verrà rifiutata.

  • Restituisci l'intera richiesta:se la funzione modifica la richiesta, devi restituire l'oggetto richiesta completo e modificato. Se non restituisci nulla (o undefined), la richiesta rimane invariata.

  • Test per la latenza:a seconda della funzione, potrebbe aggiungere latenza e influire sull'esperienza utente.

Scrivere una funzione post-richiesta (afterGenerateContent)

Con il tipo di evento afterGenerateContent, la funzione viene attivata quando il proxy Firebase AI Logic riceve una risposta da una richiesta generateContent. La funzione viene eseguita sulla risposta prima che venga restituita all'app client. La funzione può registrare l'utilizzo, modificare la risposta o bloccarla completamente.

Prima di scrivere la funzione, assicurati di esaminare le seguenti informazioni:

Esempio

Di seguito è riportato un esempio di funzione post-richiesta che registra l'utilizzo dei token e il motivo della fine:

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

Considerazioni chiave per le funzioni post-richiesta

  • Specifica il fornitore Gemini API: event.data.response può essere per Gemini Developer API o Agent Platform Gemini API (formerly Vertex AI). Per eseguire il cast e utilizzare in modo sicuro l'oggetto richiesta, devi controllare event.data.api (ad esempio, confrontalo con geminiV1Beta o vertexV1Beta1, rispettivamente).

  • Test per la latenza:a seconda della funzione, potrebbe aggiungere latenza e influire sull'esperienza utente.

Passaggio 3: esegui il deployment delle funzioni

Il deployment delle funzioni su Firebase concede all'agente di servizio Firebase AI Logic l'autorizzazione a richiamare queste funzioni e registra ogni funzione come trigger Firebase AI Logic.

  1. Esegui il deployment delle funzioni utilizzando la CLI Firebase:

    firebase deploy --only functions
    
  2. Dopo il deployment, verifica che le funzioni siano state eseguite su Firebase:

    firebase functions:list
    
  3. Se devi eseguire l'iterazione della funzione:

    Aggiorna la funzione nella directory del progetto, quindi esegui di nuovo firebase deploy --only functions.

Interrompere l'esecuzione di una funzione

Per impedire l'esecuzione di una di queste funzioni, deve essere eliminata dai nostri server e annullata la registrazione come trigger Firebase AI Logic. Puoi farlo utilizzando Firebase CLI con una delle seguenti opzioni:

  • Opzione 1: elimina la funzione in modo implicito

    1. Rimuovi la funzione dal codebase della directory del progetto.

    2. Esegui questo comando CLI Firebase:

      firebase deploy --only functions
      
  • Opzione 2: elimina la funzione in modo esplicito

    1. Rimuovi la funzione dal codebase della directory del progetto.

    2. Esegui questo comando CLI Firebase:

      firebase functions:delete FUNCTION_NAME
      



Riferimento ai dati sugli eventi

Sia beforeGenerateContent che afterGenerateContent ricevono un oggetto AIBlockingEvent contenente il contesto e i metadati della richiesta.

Metadati della richiesta di primo livello (AIBlockingEvent)

L'oggetto di primo livello AIBlockingEvent fornisce informazioni sul chiamante e sull'ambiente di attivazione:

  • event.authType: stato di autenticazione per il chiamante: "app_user", "unauthenticated" o "unknown".
  • event.authId: l'UID Firebase Authentication del chiamante, se ha eseguito l'accesso.
  • event.authClaims: le rivendicazioni di autenticazione personalizzate del chiamante, se presenti.
  • event.appId: l'ID app Firebase che ha effettuato la richiesta.
  • event.androidPackageName / event.iosBundleId: il nome del pacchetto o l'ID bundle dell'app chiamante (applicabile rispettivamente per le piattaforme Android o Apple).
  • event.data: il payload dell'evento, che varia tra le funzioni pre-richiesta e post-richiesta:

Dati degli eventi pre-richiesta (beforeGenerateContent)

In una funzione beforeGenerateContent, event.data viene compilato con un oggetto BeforeGenerateContentData:

  • event.data.api: il provider Gemini API: geminiV1Beta (Gemini Developer API) o vertexV1Beta1 (Agent Platform Gemini API (formerly Vertex AI)).
  • event.data.model: il percorso completo della risorsa del modello (ad esempio, projects/{PROJECT_ID}/locations/global/publishers/google/models/gemini-3.8-flash).
  • event.data.template: metadati sul modello di prompt del server utilizzato (PromptTemplateInfo), se applicabile.
  • event.data.request: il payload della richiesta in uscita. Il tipo di oggetto e le proprietà dipendono dal fornitore Gemini API:

Dati sugli eventi post-richiesta (afterGenerateContent)

In una funzione afterGenerateContent, event.data viene compilato con un oggetto AfterGenerateContentData. Questo oggetto estende BeforeGenerateContentData (fornendo api, model, template e request) e aggiunge la risposta del modello:



Limitazioni e comportamenti

Quando implementi queste funzioni, tieni presente i seguenti comportamenti e limitazioni:

  • Solo richieste generateContent: queste funzioni possono essere attivate solo da richieste generateContent all'Gemini API tramite Firebase AI Logic.

    I seguenti elementi non attiveranno queste funzioni e le funzioni verranno ignorate in modo silenzioso per quella richiesta:

    • Le richieste a generateContentStream non attiveranno queste funzioni.

    • Le richieste all'Gemini Live API non attiveranno queste funzioni.

  • Nessuna modifica al codice lato client: a parte assicurarti di utilizzare richieste generateContent quando vuoi eseguire queste funzioni, non sono necessarie modifiche nel codebase lato client.

    Queste funzioni vengono implementate sui nostri server e registrate come trigger Firebase AI Logic in modo che il proxy Firebase AI Logic possa intercettare richieste e risposte lato server.

  • Ambito a livello di progetto: puoi eseguire il deployment di al massimo una funzione beforeGenerateContent e una funzione afterGenerateContent per progetto Firebase.

  • Posizioni predefinite: per impostazione predefinita, il deployment di queste funzioni verrà eseguito in us-central1 (scopri di più sulle posizioni per le funzioni). Tuttavia, la funzione verrà registrata come trigger Firebase AI Logic nella regione global indipendentemente da dove esegui il deployment della funzione.