הפעלת תהליכים של Genkit מהאפליקציה

ל-Cloud Functions for Firebase יש method onCallGenkit שמאפשרת ליצור פונקציה שניתן להפעיל עם פעולת Genkit (תהליך). אפשר להפעיל את הפונקציות האלה באמצעות genkit/beta/client או Cloud Functions for Firebase Client SDK, שמוסיף באופן אוטומטי את פרטי האימות.

לפני שמתחילים

  • אתם צריכים להכיר את הקונספט של תהליכי Genkit ולדעת איך לכתוב אותם. ההוראות בדף הזה מניחות שכבר הגדרתם כמה תהליכים שאתם רוצים לפרוס.
  • אם השתמשת בעבר ב-Cloud Functions for Firebase, זה יכול לעזור, אבל זה לא חובה.

הגדרת פרויקט ב-Firebase

  1. יוצרים פרויקט חדש ב-Firebase באמצעות מסוף Firebase או בוחרים פרויקט קיים.

  2. משדרגים את הפרויקט לתוכנית התמחור Blaze בתשלום לפי שימוש, שנדרשת לפריסת Cloud Functions בסביבת הייצור.

  3. מתקינים את Firebase CLI.

  4. מתחברים ל-CLI של Firebase:

    firebase login
    firebase login --reauth # alternative, if necessary
    firebase login --no-localhost # if running in a remote shell
  5. יוצרים ספריית פרויקט חדשה:

    export PROJECT_ROOT=~/tmp/genkit-firebase-project1
    mkdir -p $PROJECT_ROOT
  6. מאתחלים פרויקט Firebase בספרייה:

    cd $PROJECT_ROOT
    firebase init functions

בהמשך הדף נניח שבחרתם לכתוב את הפונקציות ב-JavaScript.

הוספת onCallGenkit לתהליך

אחרי שמגדירים פרויקט ב-Firebase ומפעילים בו את Cloud Functions, אפשר להעתיק או לכתוב הגדרות של תהליכים בספרייה functions של הפרויקט. הנה דוגמה לתהליך שממחיש את זה:

const ai = genkit({
  plugins: [googleAI()],
  model: gemini15Flash,
});

const jokeTeller = ai.defineFlow({
  name: "jokeTeller",
  inputSchema: z.string().nullable(),
  outputSchema: z.string(),
  streamSchema: z.string(),
}, async (jokeType = "knock-knock", {sendChunk}) => {
  const prompt = `Tell me a ${jokeType} joke.`;

  // Call the `generateStream()` method to
  // receive the `stream` async iterable.
  const {stream, response: aiResponse} = ai.generateStream(prompt);

  // Send new words of the generative AI response
  // to the client as they are generated.
  for await (const chunk of stream) {
    sendChunk(chunk.text);
  }

  // Return the full generative AI response
  // to clients that may not support streaming.
  return (await aiResponse).text;
},
);

כדי לפרוס תהליך כזה, צריך לעטוף אותו ב-onCallGenkit, שזמין ב-firebase-functions/https. לשיטת העזר הזו יש את כל התכונות של פונקציות שניתן להפעיל, והיא תומכת באופן אוטומטי גם בתגובות סטרימינג וגם בתגובות JSON.

const {onCallGenkit} = require("firebase-functions/https");
exports.tellJoke = onCallGenkit({
  // Bind the Gemini API key secret parameter to the function.
  secrets: [apiKey],
},
// Pass in the genkit flow.
jokeTeller,
);

הפיכת פרטי הכניסה ל-API לזמינים לתהליכים שנפרסו

אחרי הפריסה, התהליכים צריכים דרך לאימות מול כל שירות מרוחק שהם מסתמכים עליו. ברוב התהליכים, צריך לפחות פרטי כניסה כדי לגשת לשירות Model API שבו משתמשים.

בדוגמה הזו, מבצעים אחת מהפעולות הבאות, בהתאם לספק המודל שבחרתם:

‫Gemini‏ (Google AI)

  1. יוצרים מפתח API ל-Gemini Developer API באמצעות Google AI Studio.

  2. שומרים את מפתח ה-API ב-Google Cloud Secret Manager:

    firebase functions:secrets:set GOOGLE_GENAI_API_KEY

    השלב הזה חשוב כדי למנוע דליפה מקרית של מפתח ה-API, שמעניק גישה לשירות שייתכן שהוא מוגבל.

    למידע נוסף על ניהול סודות, ראו אחסון וגישה למידע רגיש של הגדרות אישיות.

  3. עורכים את src/index.js ומוסיפים את הפרטים הבאים אחרי הייבוא הקיים:

    const {defineSecret} = require("firebase-functions/params");
    // Store the Gemini API key in Cloud Secret Manager.
    const apiKey = defineSecret("GOOGLE_GENAI_API_KEY");

    לאחר מכן, בהגדרה של הפונקציה שניתן להפעיל, מצהירים שהפונקציה צריכה גישה לערך הסודי הזה:

    // Bind the Gemini API key secret parameter to the function.
    secrets: [apiKey],

עכשיו, כשפורסים את הפונקציה הזו, מפתח ה-API נשמר ב-Google Cloud Secret Manager וזמין מהסביבה של Cloud Functions.

‫Gemini‏ (Vertex AI)

  1. במסוף Google Cloud, מפעילים את Vertex AI API בפרויקט ב-Firebase.

  2. בדף IAM, מוודאים שלחשבון ברירת המחדל של שירות Compute הוקצה התפקיד משתמש ב-Vertex AI.

הסוד היחיד שצריך להגדיר במדריך הזה הוא לספק המודל, אבל באופן כללי, צריך לעשות משהו דומה לכל שירות שבו משתמשים בתהליך העבודה.

(אופציונלי) הוספת אכיפה של Firebase App Check

‫Firebase App Check משתמש באימות מקורי כדי לוודא שהאפליקציה שלכם היא היחידה שקוראת ל-API שלנו. ה-method‏ onCallGenkit תומכת באכיפה של App Check באופן הצהרתי.

export const generatePoem = onCallGenkit({
  enforceAppCheck: true,
  // Optional. Makes App Check tokens only usable once. This adds extra security
  // at the expense of slowing down your app to generate a token for every API
  // call
  consumeAppCheckToken: true,
}, generatePoemFlow);

הגדרת CORS (שיתוף משאבים בין מקורות)

כדי לקבוע לאילו מקורות תהיה גישה לפונקציה, משתמשים באפשרות cors.

כברירת מחדל, לפונקציות שניתנות לקריאה יש הגדרות CORS שמאפשרות בקשות מכל המקורות. כדי לאפשר רק חלק מהבקשות ממקורות שונים, צריך להעביר רשימה של דומיינים ספציפיים או ביטויים רגולריים שרוצים לאפשר. לדוגמה:

export const tellJoke = onCallGenkit({
  cors: 'mydomain.com',
}, jokeTeller);

דוגמה פתורה

אחרי שתבצעו את כל השינויים שמתוארים במדריך הזה, התהליך שניתן לפריסה ייראה בערך כמו בדוגמה הבאה:

const {onCallGenkit} = require("firebase-functions/https");
const {defineSecret} = require("firebase-functions/params");

// Dependencies for Genkit.
const {gemini15Flash, googleAI} = require("@genkit-ai/googleai");
const {genkit, z} = require("genkit");

// Store the Gemini API key in Cloud Secret Manager.
const apiKey = defineSecret("GOOGLE_GENAI_API_KEY");

const ai = genkit({
  plugins: [googleAI()],
  model: gemini15Flash,
});

const jokeTeller = ai.defineFlow({
  name: "jokeTeller",
  inputSchema: z.string().nullable(),
  outputSchema: z.string(),
  streamSchema: z.string(),
}, async (jokeType = "knock-knock", {sendChunk}) => {
  const prompt = `Tell me a ${jokeType} joke.`;

  // Call the `generateStream()` method to
  // receive the `stream` async iterable.
  const {stream, response: aiResponse} = ai.generateStream(prompt);

  // Send new words of the generative AI response
  // to the client as they are generated.
  for await (const chunk of stream) {
    sendChunk(chunk.text);
  }

  // Return the full generative AI response
  // to clients that may not support streaming.
  return (await aiResponse).text;
},
);

exports.tellJoke = onCallGenkit({
  // Bind the Gemini API key secret parameter to the function.
  secrets: [apiKey],
},
// Pass in the genkit flow.
jokeTeller,
);

פריסת תהליכים ב-Firebase

אחרי שמגדירים תהליכים באמצעות onCallGenkit, אפשר לפרוס אותם כמו שפורסים פונקציות אחרות:

cd $PROJECT_ROOT
firebase deploy --only functions