Menjalankan skrip sisi server kustom sebelum dan sesudah permintaan


Anda dapat menjalankan skrip sisi server kustom Anda sendiri sebelum dan setelah setiap permintaan yang dikirim aplikasi Anda ke Gemini API melalui Firebase AI Logictanpa mengubah kode klien Anda. Anda menerapkan skrip ini sebagai fungsi gaya callback yang di-deploy ke Cloud Functions for Firebase.

Dengan kemampuan ini, Anda dapat melakukan hal-hal seperti memoderasi perintah, membatasi penggunaan token, mencatat pembuatan untuk analisis, atau menyamarkan konten respons.

Dua jenis peristiwa tersedia:

  • beforeGenerateContent: Berjalan sebelum permintaan mencapai Gemini API. Fungsi ini dapat memeriksa atau mengubah permintaan, atau memblokir permintaan sepenuhnya dengan memunculkan error.

  • afterGenerateContent: Berjalan setelah respons dikirim kembali dari Gemini API dan sebelum dikembalikan ke aplikasi klien. Fungsi ini dapat memeriksa atau mengubah respons, memblokir respons sepenuhnya, atau hanya mengamatinya (seperti untuk logging atau audit).

Setelah skrip Anda di-deploy sebagai fungsi ke Cloud Functions for Firebase, skrip tersebut akan didaftarkan sebagai pemicu Firebase AI Logic, yang berarti skrip tersebut akan berjalan untuk setiap permintaan generateContent di project Anda ke Gemini API melalui Firebase AI Logic (termasuk permintaan yang dibuat dengan template perintah server).

Fungsi ini tidak dipicu oleh permintaan yang dibuat ke Gemini API yang tidak melalui Firebase AI Logic.

Prasyarat

Langkah 1: Siapkan project Anda untuk Cloud Functions for Firebase

Jika Anda belum pernah menggunakan Cloud Functions for Firebase di project Firebase, selesaikan penyiapan berikut.

  1. Pastikan project Firebase Anda menggunakan paket harga Blaze bayar sesuai penggunaan (wajib untuk menggunakan Cloud Functions for Firebase).

  2. Instal antarmuka command line (CLI): gcloud CLI dan Firebase CLI

  3. Berikan peran Akun Layanan Cloud Build (roles/cloudbuild.builds.builder) yang diperlukan akun layanan Compute Engine default untuk membangun fungsi Anda. Jalankan perintah gcloud CLI berikut:

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

    1. Jalankan perintah CLI Firebase berikut:

      firebase init functions
      
    2. Saat diminta, pilih TypeScript.

    3. Pastikan firebase-functions di functions/package.json Anda adalah versi 6.3.0 atau yang lebih baru. Berikut cara memeriksa versi Anda:

      npm --prefix functions list firebase-functions
      

Langkah 2: Tulis fungsi Anda

Menulis fungsi pra-permintaan (beforeGenerateContent) Menulis fungsi pasca-permintaan (afterGenerateContent)

Menulis fungsi pra-permintaan (beforeGenerateContent)

Dengan jenis peristiwa beforeGenerateContent, fungsi dipicu saat proxy Firebase AI Logic menerima permintaan generateContent. Fungsi berjalan terhadap permintaan sebelum permintaan dikirim ke Gemini API. Fungsi ini dapat mengubah permintaan atau memblokir permintaan sepenuhnya.

Pastikan Anda meninjau informasi berikut sebelum menulis fungsi:

Contoh

Berikut adalah contoh fungsi pra-permintaan yang melakukan hal berikut:

  • Menentukan bahwa fungsi hanya boleh berjalan saat permintaan ditujukan untuk penyedia Gemini API tertentu.

  • Memeriksa perintah untuk topik yang diblokir dan menolak permintaan dengan menampilkan error.

  • Membatasi token output maksimum untuk model pembuatan teks.

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

Pertimbangan utama untuk fungsi prapermintaan

  • Tentukan penyedia Gemini API: event.data.request dapat berupa Gemini Developer API atau Agent Platform Gemini API (formerly Vertex AI). Objek permintaan untuk berbagai API ini memiliki bentuk yang berbeda. Untuk bekerja dengan aman menggunakan objek permintaan, Anda harus memeriksa event.data.api (misalnya, membandingkan dengan geminiV1Beta atau vertexV1Beta1).

  • Melempar memblokir permintaan: Jika Anda melempar HttpsError, permintaan akan ditolak.

  • Mengembalikan seluruh permintaan: Jika fungsi Anda mengubah permintaan, Anda harus mengembalikan objek permintaan yang telah diubah dan lengkap. Tidak menampilkan apa pun (atau undefined) akan membuat permintaan tidak berubah.

  • Uji latensi: Bergantung pada fungsi yang Anda lakukan, hal ini dapat menambah latensi dan memengaruhi pengalaman pengguna.

Menulis fungsi pasca-permintaan (afterGenerateContent)

Dengan jenis peristiwa afterGenerateContent, fungsi dipicu saat proxy Firebase AI Logic menerima respons dari permintaan generateContent. Fungsi berjalan terhadap respons sebelum respons ditampilkan ke aplikasi klien. Fungsi ini dapat mencatat penggunaan, mengubah respons, atau memblokir respons sepenuhnya.

Pastikan Anda meninjau informasi berikut sebelum menulis fungsi:

Contoh

Berikut adalah contoh fungsi pasca-permintaan yang mencatat penggunaan token dan alasan penyelesaian:

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

Pertimbangan utama untuk fungsi pasca-permintaan

  • Tentukan penyedia Gemini API: event.data.response dapat berupa Gemini Developer API atau Agent Platform Gemini API (formerly Vertex AI). Untuk melakukan transmisi dan bekerja dengan objek permintaan secara aman, Anda harus memeriksa event.data.api (misalnya, bandingkan dengan geminiV1Beta atau vertexV1Beta1).

  • Uji latensi: Bergantung pada fungsi yang Anda lakukan, hal ini dapat menambah latensi dan memengaruhi pengalaman pengguna.

Langkah 3: Deploy fungsi Anda

Men-deploy fungsi ke Firebase akan memberikan izin kepada agen layanan Firebase AI Logic untuk memanggil fungsi ini, dan mendaftarkan setiap fungsi sebagai pemicu Firebase AI Logic.

  1. Deploy fungsi Anda menggunakan Firebase CLI:

    firebase deploy --only functions
    
  2. Setelah men-deploy, konfirmasi bahwa fungsi Anda telah di-deploy ke Firebase:

    firebase functions:list
    
  3. Jika Anda perlu melakukan iterasi pada fungsi:

    Perbarui fungsi di direktori project Anda, lalu jalankan firebase deploy --only functions lagi.

Menghentikan fungsi agar tidak berjalan

Untuk menghentikan salah satu fungsi ini agar tidak berjalan, fungsi tersebut harus dihapus dari server kami dan dibatalkan pendaftarannya sebagai pemicu Firebase AI Logic. Anda dapat melakukannya menggunakan Firebase CLI dengan salah satu opsi berikut:

  • Opsi 1: Hapus fungsi secara implisit

    1. Hapus fungsi dari codebase direktori project Anda.

    2. Jalankan perintah CLI Firebase berikut:

      firebase deploy --only functions
      
  • Opsi 2: Hapus fungsi secara eksplisit

    1. Hapus fungsi dari codebase direktori project Anda.

    2. Jalankan perintah CLI Firebase berikut:

      firebase functions:delete FUNCTION_NAME
      



Referensi data peristiwa

beforeGenerateContent dan afterGenerateContent menerima objek AIBlockingEvent yang berisi konteks dan metadata tentang permintaan.

Metadata permintaan tingkat teratas (AIBlockingEvent)

Objek AIBlockingEvent level teratas memberikan informasi tentang pemanggil dan lingkungan pemicu:

  • event.authType: Status autentikasi untuk pemanggil: "app_user", "unauthenticated", atau "unknown".
  • event.authId: UID Firebase Authentication pemanggil, jika login.
  • event.authClaims: Klaim autentikasi kustom pemanggil, jika ada.
  • event.appId: ID Aplikasi Firebase yang membuat permintaan.
  • event.androidPackageName / event.iosBundleId: Nama paket atau ID paket aplikasi pemanggil (masing-masing berlaku untuk platform Android atau Apple).
  • event.data: Payload peristiwa, yang berbeda antara fungsi pra-permintaan dan pasca-permintaan:

Data peristiwa pra-permintaan (beforeGenerateContent)

Dalam fungsi beforeGenerateContent, event.data diisi dengan objek BeforeGenerateContentData:

  • event.data.api: Penyedia Gemini API: geminiV1Beta (Gemini Developer API) atau vertexV1Beta1 (Agent Platform Gemini API (formerly Vertex AI)).
  • event.data.model: Jalur resource model lengkap (misalnya, projects/{PROJECT_ID}/locations/global/publishers/google/models/gemini-3.8-flash).
  • event.data.template: Metadata tentang template perintah server yang digunakan (PromptTemplateInfo), jika berlaku.
  • event.data.request: Payload permintaan keluar. Jenis dan properti objek bergantung pada penyedia Gemini API:

Data peristiwa pasca-permintaan (afterGenerateContent)

Dalam fungsi afterGenerateContent, event.data diisi dengan objek AfterGenerateContentData. Objek ini memperluas BeforeGenerateContentData (menyediakan api, model, template, dan request), dan menambahkan respons model:



Batasan dan perilaku

Saat menerapkan fungsi ini, perhatikan perilaku dan batasan berikut:

  • Hanya permintaan generateContent: Fungsi ini hanya dapat dipicu oleh permintaan generateContent ke Gemini API melalui Firebase AI Logic.

    Berikut ini tidak akan memicu fungsi ini dan fungsi akan dilewati secara diam-diam untuk permintaan tersebut:

    • Permintaan ke generateContentStream tidak akan memicu fungsi ini.

    • Permintaan ke Gemini Live API tidak akan memicu fungsi ini.

  • Tidak ada perubahan kode sisi klien: Selain memastikan bahwa Anda menggunakan permintaan generateContent saat ingin menjalankan fungsi ini, tidak ada perubahan yang diperlukan dalam codebase sisi klien Anda.

    Fungsi ini di-deploy ke server kami, dan didaftarkan sebagai pemicu Firebase AI Logic sehingga proxy Firebase AI Logic dapat mencegat permintaan dan respons di sisi server.

  • Cakupan tingkat project: Anda dapat men-deploy paling banyak satu fungsi beforeGenerateContent dan satu fungsi afterGenerateContent per project Firebase.

  • Lokasi default: Fungsi ini akan di-deploy ke us-central1 secara default (pelajari lokasi untuk fungsi). Namun, fungsi akan didaftarkan sebagai pemicu Firebase AI Logic di region global, terlepas dari tempat Anda men-deploy fungsi.