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 Logic — tanpa mengubah kode klien Anda. Anda menerapkan skrip ini sebagai fungsi bergaya 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 log 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 menampilkan error.

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

Setelah skrip 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 (diperlukan 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 komputasi 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 Firebase CLI 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 akan dipicu saat proxy Firebase AI Logic menerima permintaan generateContent. Fungsi ini 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 jika 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 generatif 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 pra-permintaan

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

  • Throwing memblokir permintaan: Jika Anda menampilkan HttpsError, permintaan akan ditolak.

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

  • Uji latensi: Bergantung pada fungsi yang dijalankan, fungsi tersebut dapat menambah latensi dan memengaruhi pengalaman pengguna.

Menulis fungsi pasca-permintaan (afterGenerateContent)

Dengan jenis peristiwa afterGenerateContent, fungsi akan dipicu saat proxy Firebase AI Logic menerima respons dari permintaan generateContent. Fungsi ini 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 ditujukan untuk Gemini Developer API atau Agent Platform Gemini API (formerly Vertex AI). Untuk mentransmisikan dan menggunakan objek permintaan dengan aman, Anda harus memeriksa event.data.api (misalnya, bandingkan dengan geminiV1Beta atau vertexV1Beta1).

  • Uji latensi: Bergantung pada fungsi yang dijalankan, fungsi tersebut dapat menambah latensi dan memengaruhi pengalaman pengguna.

Langkah 3: Deploy fungsi Anda

Men-deploy fungsi ke Firebase akan memberi agen layanan Firebase AI Logic izin 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, pastikan 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 pendaftarannya sebagai pemicu Firebase AI Logic harus dibatalkan. Anda dapat melakukannya menggunakan Firebase CLI dengan salah satu opsi berikut:

  • Opsi 1: Menghapus fungsi secara implisit

    1. Hapus fungsi dari codebase direktori project Anda.

    2. Jalankan perintah Firebase CLI berikut:

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

    1. Hapus fungsi dari codebase direktori project Anda.

    2. Jalankan perintah Firebase CLI 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 penelepon: "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 panggilan (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 ada.
  • 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), serta menambahkan respons model:



Batasan dan perilaku

Saat menerapkan fungsi ini, perhatikan perilaku dan batasan berikut:

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

    Hal berikut tidak akan memicu fungsi ini dan fungsi tersebut akan diabaikan secara otomatis 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 menangkap permintaan dan respons di sisi server.

  • Cakupan level project: Anda dapat men-deploy maksimal 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 tersebut akan didaftarkan sebagai pemicu Firebase AI Logic di region global, di mana pun Anda men-deploy fungsi.