اجرای دستورگان‌های سفارشی سمت سرور قبل و بعداز درخواست‌ها


می‌توانید اسکریپت‌های سفارشی سمت سرور خودتان را قبل و بعداز هر درخواستی که برنامه‌تان ازطریق Firebase AI Logic به Gemini API ارسال می‌کند اجرا کنید — بدون تغییر دادن کد مشتری. این اسکریپت‌ها را به‌عنوان توابع سبک فراخوانی برگشتی که در Cloud Functions for Firebase مستقر شده‌اند پیاده‌سازی می‌کنید.

با این قابلیت، می‌توانید کارهایی مثل تعدیل کردن پیام‌واره‌ها، محدود کردن استفاده از نشان، ثبت کردن تولیدات برای تجزیه‌وتحلیل، یا ویرایش کردن محتوای پاسخ را انجام دهید.

دو نوع رویداد دردسترس است:

  • beforeGenerateContent: قبل‌از اینکه درخواست به Gemini API برسد اجرا می‌شود. این تابع می‌تواند درخواست را بازرسی یا اصلاح کند، یا با ایجاد خطا، درخواست را به‌طور کامل مسدود کند.

  • afterGenerateContent: پس‌از ارسال پاسخ از Gemini API و قبل‌از بازگرداندن آن به برنامه کارخواه اجرا می‌شود. این تابع می‌تواند پاسخ را بازرسی یا اصلاح کند، پاسخ را کاملاً مسدود کند، یا فقط آن را مشاهده کند (مثلاً برای ثبت یا ممیزی).

وقتی دستورات شما به‌عنوان تابع در Cloud Functions for Firebase مستقر می‌شوند، به‌عنوان راه‌اندازهای Firebase AI Logic ثبت می‌شوند، یعنی برای هر درخواست generateContent در پروژه شما به Gemini API ازطریق Firebase AI Logic (ازجمله درخواست‌های ایجادشده با الگوهای پیام‌واره سرور) اجرا خواهند شد.

این توابع با درخواست‌های ارسالی به Gemini API که ازطریق Firebase AI Logic نباشد راه‌اندازی نمی‌شوند.

پیش‌نیازها

مرحله ۱: راه‌اندازی پروژه برای Cloud Functions for Firebase

اگر هرگز از Cloud Functions for Firebase در پروژه Firebase خود استفاده نکرده‌اید، راه‌اندازی زیر را تکمیل کنید.

  1. مطمئن شوید پروژه Firebase شما در طرح قیمت‌گذاری Blaze پرداخت به اندازه استفاده (برای استفاده از Cloud Functions for Firebase لازم است) باشد.

  2. میاناهای خط فرمان (CLI) را نصب کنید: gcloud CLI و Firebase CLI

  3. به حساب سرویس محاسباتی پیش‌فرض، نقش حساب سرویس Cloud Build (roles/cloudbuild.builds.builder) را که برای ساختن تابع شما نیاز دارد اعطا کنید. فرمان gcloud CLI زیر را اجرا کنید:

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
      --role="roles/cloudbuild.builds.builder"
    
  4. Cloud Functions for Firebase را در پروژه Firebase خود مقداردهی اولیه کنید:

    1. فرمان Firebase CLI زیر را اجرا کنید:

      firebase init functions
      
    2. وقتی درخواست شد، TypeScript را انتخاب کنید.

    3. مطمئن شوید firebase-functions در functions/package.json شما نسخه ۶.۳.۰ یا جدیدتر باشد. در اینجا نحوه بررسی نسخه آمده است:

      npm --prefix functions list firebase-functions
      

مرحله ۲: نوشتن توابع

نوشتن تابع پیش‌درخواست (beforeGenerateContent) نوشتن تابع پس‌درخواست (afterGenerateContent)

نوشتن تابع پیش‌درخواست (beforeGenerateContent)

با نوع رویداد beforeGenerateContent، وقتی پراکسی Firebase AI Logic درخواست generateContent را دریافت می‌کند، تابع راه‌اندازی می‌شود. تابع پیش‌از ارسال درخواست به Gemini API، درخواست را اجرا می‌کند. این تابع می‌تواند درخواست را اصلاح کند یا درخواست را به‌طور کامل مسدود کند.

پیش‌از نوشتن تابع، حتماً اطلاعات زیر را مرور کنید:

مثال

در اینجا یک نمونه تابع پیش‌درخواست آورده شده است که کارهای زیر را انجام می‌دهد:

  • مشخص می‌کند که عملکرد فقط زمانی باید اجرا شود که درخواست برای ارائه‌دهنده Gemini API خاصی باشد.

  • پیام‌واره را برای موضوعات مسدودشده بررسی می‌کند و با ایجاد خطا، درخواست را رد می‌کند.

  • حداکثر داده‌واحدهای برونداد را برای مدل‌های تولید نوشتار محدود می‌کند.

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

ملاحظات کلیدی برای توابع پیش‌درخواست

  • ارائه‌دهنده Gemini API را مشخص کنید: event.data.request می‌تواند برای Gemini Developer API یا Agent Platform Gemini API (formerly Vertex AI) باشد. اشیاء درخواست برای این میاناهای برنامه‌سازی کاربردی مختلف شکل‌های متفاوتی دارند. برای کار کردن ایمن با شیء درخواست، باید event.data.api را بررسی کنید (برای مثال، به‌ترتیب با geminiV1Beta یا vertexV1Beta1 مقایسه کنید).

  • پرتاب کردن درخواست را مسدود می‌کند: اگر HttpsError پرتاب کنید، درخواست رد خواهد شد.

  • برگرداندن کل درخواست: اگر تابع شما درخواست را اصلاح می‌کند، باید شیء درخواست کامل و اصلاح‌شده را برگردانید. اگر چیزی (یا undefined) برنگردانید، درخواست بدون تغییر باقی می‌ماند.

  • آزمایش تأخیر: بسته به اینکه تابع شما چه کاری انجام می‌دهد، ممکن است تأخیر اضافه کند و بر تجربه کاربر تأثیر بگذارد.

نوشتن تابع پس‌درخواست (afterGenerateContent)

با نوع رویداد afterGenerateContent، وقتی پراکسی Firebase AI Logic پاسخی از درخواست generateContent دریافت می‌کند، تابع راه‌اندازی می‌شود. تابع درمقابل پاسخ قبل‌از برگردانده شدن پاسخ به برنامه کارخواه اجرا می‌شود. تابع می‌تواند استفاده را ثبت کند، پاسخ را اصلاح کند، یا پاسخ را کاملاً مسدود کند.

پیش‌از نوشتن تابع، حتماً اطلاعات زیر را مرور کنید:

مثال

در اینجا نمونه‌ای از تابع درخواست پست آورده شده است که استفاده از توکن و دلیل پایان را ثبت می‌کند:

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

ملاحظات کلیدی برای توابع درخواست پست

  • ارائه‌دهنده Gemini API را مشخص کنید: event.data.response می‌تواند برای Gemini Developer API یا Agent Platform Gemini API (formerly Vertex AI) باشد. برای ارسال ایمن و کار با شیء درخواست، باید event.data.api را بررسی کنید (برای مثال، به‌ترتیب با geminiV1Beta یا vertexV1Beta1 مقایسه کنید).

  • آزمایش تأخیر: بسته به اینکه تابع شما چه کاری انجام می‌دهد، ممکن است تأخیر اضافه کند و بر تجربه کاربر تأثیر بگذارد.

مرحله ۳: استقرار توابع

استقرار توابع در Firebase به عامل سرویس Firebase AI Logic اجازه می‌دهد این توابع را فراخوانی کند و هر تابع را به‌عنوان راه‌انداز Firebase AI Logic ثبت می‌کند.

  1. توابع خود را بااستفاده از Firebase CLI مستقر کنید:

    firebase deploy --only functions
    
  2. پس‌از استقرار، تأیید کنید که توابع شما در Firebase مستقر شده‌اند:

    firebase functions:list
    
  3. اگر لازم است تابع خود را تکرار کنید:

    تابع را در فهرست راهنمای پروژه‌تان به‌روز کنید و سپس firebase deploy --only functions را دوباره اجرا کنید.

متوقف کردن اجرای تابع

برای متوقف کردن اجرای یکی از این عملکردها، باید آن را از سرورهای ما حذف کنید و به‌عنوان راه‌انداز Firebase AI Logic لغو ثبت‌نام کنید. می‌توانید این کار را بااستفاده از Firebase CLI با یکی از گزینه‌های زیر انجام دهید:

  • گزینه ۱: حذف تابع به‌طور ضمنی

    1. تابع را از پایگاه کد دایرکتوری پروژه بردارید.

    2. فرمان CLI Firebase زیر را اجرا کنید:

      firebase deploy --only functions
      
  • گزینه ۲: حذف صریح تابع

    1. تابع را از پایگاه کد دایرکتوری پروژه بردارید.

    2. فرمان Firebase CLI زیر را اجرا کنید:

      firebase functions:delete FUNCTION_NAME
      



مرجع داده‌های رویداد

هر دو beforeGenerateContent و afterGenerateContent یک شیء AIBlockingEvent دریافت می‌کنند که حاوی بافت و فراداده درباره درخواست است.

فراداده درخواست سطح بالا (AIBlockingEvent)

شیء سطح بالا AIBlockingEvent اطلاعاتی درباره تماس‌گیرنده و محیط راه‌انداز ارائه می‌دهد:

  • event.authType: وضعیت اصالت‌سنجی برای تماس‌گیرنده: "app_user"، "unauthenticated"، یا "unknown".
  • event.authId: شناسه Firebase Authentication تماس‌گیرنده، درصورت ورود به سیستم.
  • event.authClaims: ادعاهای اصالت‌سنجی سفارشی تماس‌گیرنده، درصورت وجود.
  • event.appId: شناسه Firebase App که درخواست را ایجاد کرده است.
  • event.androidPackageName / event.iosBundleId: نام بسته یا شناسه بسته ترکیبی برنامه تماس‌گیرنده (به‌ترتیب برای پلاتفرم‌های Android یا Apple قابل‌اجرا است).
  • event.data: پایه‌بار رویداد که بین توابع پیش‌درخواست و پس‌درخواست متفاوت است:

داده‌های رویداد پیش‌درخواست (beforeGenerateContent)

در تابع beforeGenerateContent، event.data با شیء BeforeGenerateContentData پر می‌شود:

  • event.data.api: ارائه‌دهنده Gemini API: geminiV1Beta (Gemini Developer API) یا vertexV1Beta1 (Agent Platform Gemini API (formerly Vertex AI)).
  • event.data.model: مسیر کامل منبع مدل (برای مثال، projects/{PROJECT_ID}/locations/global/publishers/google/models/gemini-3.8-flash).
  • event.data.template: فراداده درباره الگوی پیام‌واره سرور استفاده‌شده (PromptTemplateInfo)، درصورت وجود.
  • event.data.request: بار داده درخواست خروجی. نوع شیء و ویژگی‌ها به ارائه‌دهنده Gemini API بستگی دارد:

داده‌های رویداد درخواست پست (afterGenerateContent)

در تابع afterGenerateContent، event.data با شیء AfterGenerateContentData پر می‌شود. این شیء BeforeGenerateContentData را گسترش می‌دهد (api، model، template، و request را ارائه می‌دهد)، و پاسخ مدل را اضافه می‌کند:



محدودیت‌ها و رفتارها

هنگام پیاده‌سازی این توابع، رفتارها و محدودیت‌های زیر را به‌خاطر داشته باشید:

  • فقط درخواست‌های generateContent: این توابع فقط با درخواست‌های generateContent به Gemini API ازطریق Firebase AI Logic راه‌اندازی می‌شوند.

    موارد زیر این توابع را راه‌اندازی نمی‌کنند و توابع برای آن درخواست بدون اطلاع نادیده گرفته می‌شوند:

    • درخواست‌های ارسال‌شده به generateContentStream این توابع را راه‌اندازی نمی‌کند.

    • درخواست‌های ارسال‌شده به Gemini Live API این توابع را راه‌اندازی نمی‌کند.

  • بدون تغییر کد سمت کارخواه: به‌جز اطمینان از اینکه هنگام اجرای این توابع از درخواست‌های generateContent استفاده می‌کنید، هیچ تغییری در پایگاه کد سمت کارخواه شما لازم نیست.

    این توابع در سرورهای ما مستقر می‌شوند و به‌عنوان راه‌اندازهای Firebase AI Logic ثبت می‌شوند تا پراکسی Firebase AI Logic بتواند درخواست‌ها و پاسخ‌ها را در سمت سرور رهگیری کند.

  • گستره سطح پروژه: می‌توانید حداکثر یک تابع beforeGenerateContent و یک تابع afterGenerateContent را برای هر پروژه Firebase مستقر کنید.

  • مکان‌های پیش‌فرض: این توابع به‌طور پیش‌فرض در us-central1 پیاده‌سازی خواهند شد (با مکان‌های توابع آشنا شوید). بااین‌حال، تابع به‌عنوان Firebase AI Logic راه‌انداز در منطقه global ثبت خواهد شد، صرف‌نظر از اینکه تابع را کجا مستقر کنید.