Uruchamianie niestandardowych skryptów po stronie serwera przed żądaniami i po nich


Możesz uruchamiać własne niestandardowe skrypty po stronie serwera przed i po każdym żądaniu wysyłanym przez aplikację do Gemini API za pomocą Firebase AI Logicbez zmiany kodu klienta. Te skrypty implementujesz jako funkcje w stylu wywołania zwrotnego wdrażane w usłudze Cloud Functions for Firebase.

Dzięki tej funkcji możesz na przykład moderować prompty, ograniczać wykorzystanie tokenów, rejestrować generowane treści na potrzeby analizy lub redagować treść odpowiedzi.

Dostępne są 2 typy zdarzeń:

  • beforeGenerateContent: działa, zanim żądanie dotrze do Gemini API. Funkcja może sprawdzać lub modyfikować żądanie albo całkowicie je blokować, zgłaszając błąd.

  • afterGenerateContent: uruchamia się po wysłaniu odpowiedzi z Gemini API i przed zwróceniem jej do aplikacji klienta. Funkcja może sprawdzać lub modyfikować odpowiedź, całkowicie ją blokować lub tylko obserwować (np. w celu rejestrowania lub audytu).

Gdy skrypty zostaną wdrożone jako funkcje w Cloud Functions for Firebase, zostaną zarejestrowane jako Firebase AI Logic wyzwalacze, co oznacza, że będą uruchamiane w przypadku każdego żądania generateContent w projekcie wysyłanego do Gemini API za pomocą Firebase AI Logic (w tym żądań wysyłanych za pomocą szablonów promptów serwera).

Te funkcje nie są aktywowane przez żądania wysyłane do interfejsu Gemini API, które nie są wysyłane przez interfejs Firebase AI Logic.

Wymagania wstępne

Krok 1. Skonfiguruj projekt pod kątem Cloud Functions for Firebase

Jeśli w projekcie w Firebase nigdy nie używasz Cloud Functions for Firebase, wykonaj te czynności konfiguracji.

  1. Upewnij się, że Twój projekt w Firebase jest objęty abonamentem Blaze z płatnością według wykorzystania (wymagany do korzystania z Cloud Functions for Firebase).

  2. Zainstaluj interfejsy wiersza poleceń:gcloud CLI i Firebase.

  3. Przypisz domyślnemu kontu usługi Compute rolę Konto usługi Cloud Build (roles/cloudbuild.builds.builder), która jest potrzebna do utworzenia funkcji. Uruchom to polecenie gcloud CLI:

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

    1. Uruchom to polecenie Firebase w interfejsie wiersza poleceń:

      firebase init functions
      
    2. Gdy pojawi się odpowiedni komunikat, wybierz TypeScript.

    3. Upewnij się, że firebase-functionsfunctions/package.json ma wersję 6.3.0 lub nowszą. Aby sprawdzić wersję:

      npm --prefix functions list firebase-functions
      

Krok 2. Napisz funkcje

 Napisz funkcję przed wysłaniem żądania (beforeGenerateContent)  Napisz funkcję po wysłaniu żądania (afterGenerateContent)

Napisz funkcję przed żądaniem (beforeGenerateContent)

W przypadku typu zdarzenia beforeGenerateContent funkcja jest wywoływana, gdy serwer proxy Firebase AI Logic otrzyma żądanie generateContent. Funkcja jest wykonywana w odniesieniu do żądania przed wysłaniem go do Gemini API. Funkcja może zmodyfikować żądanie lub całkowicie je zablokować.

Zanim napiszesz funkcję, zapoznaj się z tymi informacjami:

Przykład

Oto przykładowafunkcjaprzed wysłaniem żądania, która wykonuje te czynności:

  • Określa, że funkcja powinna być uruchamiana tylko wtedy, gdy żądanie dotyczy konkretnego dostawcy Gemini API.

  • Sprawdza, czy prompt zawiera zablokowane tematy, i odrzuca żądanie, zgłaszając błąd.

  • Ogranicza maksymalną liczbę tokenów wyjściowych w przypadku modeli generujących tekst.

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

Najważniejsze kwestie dotyczące funkcji wstępnych żądań

  • Określ dostawcę Gemini API: wartość event.data.request może dotyczyć Gemini Developer API lub Agent Platform Gemini API (formerly Vertex AI). Obiekty żądań dla tych interfejsów API mają różne kształty. Aby bezpiecznie pracować z obiektem żądania, musisz sprawdzić event.data.api (np. porównać z geminiV1Beta lub vertexV1Beta1).

  • Zgłoszenie blokuje prośbę: jeśli zgłosisz HttpsError, prośba zostanie odrzucona.

  • Zwróć całe żądanie: jeśli funkcja modyfikuje żądanie, musisz zwrócić cały zmodyfikowany obiekt żądania. Jeśli nie zwrócisz niczego (lub undefined), prośba pozostanie bez zmian.

  • Sprawdź opóźnienie: w zależności od tego, co robi funkcja, może ona powodować opóźnienia i wpływać na wygodę użytkowników.

Napisz funkcję po żądaniu (afterGenerateContent)

W przypadku typu zdarzenia afterGenerateContent funkcja jest wywoływana, gdy serwer proxy Firebase AI Logic otrzymuje odpowiedź na żądanie generateContent. Funkcja jest uruchamiana w odpowiedzi zanim zostanie ona zwrócona do aplikacji klienta. Funkcja może rejestrować wykorzystanie, modyfikować odpowiedź lub całkowicie ją blokować.

Zanim napiszesz funkcję, zapoznaj się z tymi informacjami:

Przykład

Oto przykład funkcji post-request, która rejestruje wykorzystanie tokenów i przyczynę zakończenia:

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

Najważniejsze kwestie dotyczące funkcji po wysłaniu żądania

  • Określ dostawcę Gemini API: wartość event.data.response może dotyczyć Gemini Developer API lub Agent Platform Gemini API (formerly Vertex AI). Aby bezpiecznie rzutować i pracować z obiektem żądania, musisz sprawdzić event.data.api (np. porównać z geminiV1Beta lub vertexV1Beta1).

  • Sprawdź opóźnienie: w zależności od tego, co robi funkcja, może ona powodować opóźnienia i wpływać na wygodę użytkowników.

Krok 3. Wdróż funkcje

Wdrożenie funkcji w Firebase przyznaje agentowi usługi Firebase AI Logic uprawnienia do wywoływania tych funkcji i rejestruje każdą funkcję jako Firebase AI Logicaktywator.

  1. Wdróż funkcje za pomocą interfejsu wiersza poleceń Firebase:

    firebase deploy --only functions
    
  2. Po wdrożeniu sprawdź, czy funkcje zostały wdrożone w Firebase:

    firebase functions:list
    
  3. Jeśli musisz wprowadzić zmiany w funkcji:

    Zaktualizuj funkcję w katalogu projektu, a następnie ponownie uruchom polecenie firebase deploy --only functions.

Zatrzymywanie działania funkcji

Aby zatrzymać działanie jednej z tych funkcji, musisz ją usunąć z naszych serwerówi wyrejestrować jako Firebase AI Logic aktywator. Możesz to zrobić za pomocą interfejsu wiersza poleceń Firebase, korzystając z jednej z tych opcji:

  • Opcja 1. Usuń funkcję w sposób dorozumiany

    1. Usuń funkcję z bazy kodu w katalogu projektu.

    2. Uruchom to polecenie Firebase w interfejsie wiersza poleceń:

      firebase deploy --only functions
      
  • Opcja 2. Jawne usunięcie funkcji

    1. Usuń funkcję z bazy kodu w katalogu projektu.

    2. Uruchom to polecenie Firebase w interfejsie wiersza poleceń:

      firebase functions:delete FUNCTION_NAME
      



Informacje o danych zdarzeń

Zarówno beforeGenerateContent, jak i afterGenerateContent otrzymują obiekt AIBlockingEvent zawierający kontekst i metadane żądania.

Metadane żądania najwyższego poziomu (AIBlockingEvent)

Obiekt najwyższego poziomu AIBlockingEvent zawiera informacje o wywołującym i środowisku wywołującym:

  • event.authType: stan uwierzytelniania wywołującego: "app_user", "unauthenticated" lub "unknown".
  • event.authId: identyfikator UID w usłudze Uwierzytelnianie Firebase osoby wywołującej, jeśli jest zalogowana.
  • event.authClaims: niestandardowe roszczenia autoryzacyjne rozmówcy (jeśli występują).
  • event.appId: identyfikator aplikacji Firebase, która wysłała żądanie.
  • event.androidPackageName / event.iosBundleId: nazwa pakietu lub identyfikator pakietu aplikacji wywołującej (dotyczy odpowiednio platform Android i Apple).
  • event.data: ładunek zdarzenia, który różni się w przypadku funkcji przed żądaniem i po żądaniu:

Dane zdarzenia przed wysłaniem prośby (beforeGenerateContent)

W funkcji beforeGenerateContent pole event.data jest wypełniane obiektem BeforeGenerateContentData:

  • event.data.api: aprowizator Gemini API: geminiV1Beta (Gemini Developer API) lub vertexV1Beta1 (Agent Platform Gemini API (formerly Vertex AI)).
  • event.data.model: pełna ścieżka zasobu modelu (np. projects/{PROJECT_ID}/locations/global/publishers/google/models/gemini-3.8-flash).
  • event.data.template: metadane dotyczące użytego szablonu prompta serwera (PromptTemplateInfo), jeśli ma to zastosowanie.
  • event.data.request: ładunek żądania wychodzącego. Typ obiektu i jego właściwości zależą od dostawcy Gemini API:

Dane zdarzenia po wysłaniu prośby (afterGenerateContent)

W funkcji afterGenerateContent parametr event.data jest wypełniany obiektem AfterGenerateContentData. Ten obiekt rozszerza BeforeGenerateContentData (zapewniając api, model, templaterequest) i dodaje odpowiedź modelu:



Ograniczenia i zachowania

Podczas implementowania tych funkcji pamiętaj o tych sposobach działania i ograniczeniach:

  • Tylko żądania generateContent: te funkcje mogą być wywoływane tylko przez żądania generateContent wysyłane do usługi Gemini API za pomocą Firebase AI Logic.

    Poniższe działania nie spowodują uruchomienia tych funkcji, a funkcje zostaną cicho pominięte w przypadku danej prośby:

    • Żądania wysyłane do generateContentStream nie spowodują aktywacji tych funkcji.

    • Żądania wysyłane do Gemini Live API nie będą aktywować tych funkcji.

  • Brak zmian w kodzie po stronie klienta: poza upewnieniem się, że w przypadku tych funkcji używasz żądań generateContent, nie musisz wprowadzać żadnych zmian w bazie kodu po stronie klienta.

    Te funkcje są wdrażane na naszych serwerach i rejestrowane jako Firebase AI Logicwyzwalacze, dzięki czemu Firebase AI Logicserwer proxy może przechwytywać żądania i odpowiedzi po stronie serwera.

  • Zakres na poziomie projektu: w każdym projekcie w Firebase możesz wdrożyć co najwyżej 1 funkcję beforeGenerateContent i 1 funkcję afterGenerateContent.

  • Domyślne lokalizacje: te funkcje zostaną domyślnie wdrożone w usłudze us-central1 (dowiedz się więcej o lokalizacjach funkcji). Funkcja zostanie jednak zarejestrowana jako Firebase AI Logicwyzwalaczglobal regionie niezależnie od tego, gdzie ją wdrożysz.