تنفيذ نصوص برمجية مخصّصة من جهة الخادم قبل الطلبات وبعدها


يمكنك تشغيل نصوص برمجية مخصّصة من جهة الخادم قبل وبعد كل طلب يرسله تطبيقك إلى Gemini API عبر Firebase AI Logic، بدون تغيير رمز العميل. يمكنك تنفيذ هذه النصوص البرمجية كدوال على نمط معاودة الاتصال يتم نشرها في 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.

المتطلبات الأساسية

الخطوة 1: إعداد مشروعك لاستخدام Cloud Functions for Firebase

إذا لم يسبق لك استخدام Cloud Functions for Firebase في مشروع Firebase، يُرجى إكمال عملية الإعداد التالية.

  1. تأكَّد من أنّ مشروع Firebase الخاص بك يستخدم خطة Blaze المَرِنة للدفع حسب الاستخدام (مطلوبة لاستخدام Cloud Functions for Firebase).

  2. تثبيت واجهات سطر الأوامر (CLI): gcloud CLI و Firebase CLI

  3. امنح حساب خدمة Compute Engine التلقائي دور حساب خدمة 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. نفِّذ أمر واجهة سطر الأوامر (CLI) التالي في Firebase:

      firebase init functions
      
    2. اختَر TypeScript عندما يُطلب منك ذلك.

    3. تأكَّد من أنّ firebase-functions في functions/package.json هو الإصدار 6.3.0 أو إصدار أحدث. إليك كيفية التحقّق من الإصدار:

      npm --prefix functions list firebase-functions
      

الخطوة 2: كتابة الدوال

كتابة دالة ما قبل الطلب (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، على التوالي).

  • اختبار وقت الاستجابة: استنادًا إلى ما تفعله الدالة، قد تضيف وقت استجابة وتؤثر في تجربة المستخدم.

الخطوة 3: نشر الدوال

يؤدي نشر الدوال في Firebase إلى منح وكيل خدمة Firebase AI Logic الإذن باستدعاء هذه الدوال، وتسجيل كل دالة على أنّها مشغّل Firebase AI Logic.

  1. انشر الدوال باستخدام واجهة سطر الأوامر (CLI) في Firebase:

    firebase deploy --only functions
    
  2. بعد النشر، تأكَّد من نشر الدوال في Firebase:

    firebase functions:list
    
  3. إذا كنت بحاجة إلى تكرار الدالة:

    عدِّل الدالة في دليل مشروعك، ثم شغِّل firebase deploy --only functions مرة أخرى.

إيقاف تشغيل دالة

لإيقاف تشغيل إحدى هذه الدوال، يجب حذفها من خوادمنا و إلغاء تسجيلها كمشغّل Firebase AI Logic. يمكنك إجراء ذلك باستخدام واجهة سطر أوامر Firebase مع أي من الخيارَين التاليَين:

  • الخيار 1: حذف الدالة ضمنيًا

    1. أزِل الدالة من قاعدة الرموز البرمجية لدليل المشروع.

    2. نفِّذ أمر واجهة سطر الأوامر (CLI) التالي في Firebase:

      firebase deploy --only functions
      
  • الخيار 2: حذف الدالة بشكل صريح

    1. أزِل الدالة من قاعدة الرموز البرمجية لدليل المشروع.

    2. نفِّذ أمر واجهة سطر الأوامر (CLI) التالي في Firebase:

      firebase functions:delete FUNCTION_NAME
      



مرجع بيانات الأحداث

يتلقّى كل من beforeGenerateContent وafterGenerateContent عنصر AIBlockingEvent يحتوي على السياق والبيانات الوصفية حول الطلب.

البيانات الوصفية للطلب على المستوى الأعلى (AIBlockingEvent)

يوفّر العنصر AIBlockingEvent على المستوى الأعلى معلومات عن المتصل والبيئة التي تم تفعيلها:

  • event.authType: حالة المصادقة للمتصل: "app_user" أو "unauthenticated" أو "unknown".
  • ‫event.authId: معرّف UID الخاص بمصادقة Firebase للمتصل، في حال تسجيل الدخول.
  • ‫event.authClaims: مطالبات المصادقة المخصّصة للمتصل، إن وُجدت
  • ‫event.appId: معرّف تطبيق Firebase الذي أرسل الطلب
  • 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 بغض النظر عن مكان نشر الدالة.