פלאגין של Firebase

פלאגין Firebase מספק כמה שילובים עם שירותי Firebase:

  • יוצרים ומאחזרים של אינדקסים באמצעות מאגר וקטורים של Cloud Firestore
  • אחסון נתוני מעקב באמצעות Cloud Firestore
  • פריסה של תהליכים באמצעות Cloud Functions
  • כללי מדיניות הרשאה למשתמשים באימות ב-Firebase
  • ייצוא נתוני טלמטריה לחבילת התפעול של Google Cloud

התקנה

npm i --save @genkit-ai/firebase

דרישות מוקדמות

  • כל מוצרי Firebase דורשים פרויקט Firebase. אפשר ליצור פרויקט חדש או להפעיל את Firebase בפרויקט קיים ב-Google Cloud באמצעות מסוף Firebase.
  • בנוסף, אם רוצים לפרוס תהליכים ל-Cloud Functions, צריך לשדרג את הפרויקט לתוכנית Blaze בתשלום לפי שימוש.
  • אם רוצים להריץ קוד באופן מקומי שמייצא נתוני טלמטריה, צריך להתקין את הכלי Google Cloud CLI.

תצורה

מזהה פרויקט

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

import { genkit } from 'genkit';
import { firebase } from '@genkit-ai/firebase';

const ai = genkit({
  plugins: [firebase({ projectId: "your-firebase-project" })],
});

כדי להשתמש בפלאגין, צריך לציין את מזהה הפרויקט ב-Firebase. אפשר לציין את מזהה הפרויקט ב-Firebase באחת מהדרכים הבאות:

  • מגדירים את projectId באובייקט התצורה firebase().

  • מגדירים את משתנה הסביבה GCLOUD_PROJECT. אם אתם מריצים את התהליך מסביבת Google Cloud (Cloud Functions,‏ Cloud Run וכו'), הערך של GCLOUD_PROJECT מוגדר באופן אוטומטי כמזהה הפרויקט של הסביבה.

    אם מגדירים את GCLOUD_PROJECT, אפשר להשמיט את פרמטר ההגדרה: firebase()

פרטי כניסה

כדי לספק פרטי כניסה ל-Firebase, צריך גם להגדיר את Application Default Credentials של Google Cloud. כדי לציין את פרטי הכניסה:

  • אם אתם מריצים את התהליך מסביבת Google Cloud (Cloud Functions,‏ Cloud Run וכו'), ההגדרה הזו מוגדרת באופן אוטומטי.

  • בסביבות אחרות:

    1. יוצרים פרטי כניסה לחשבון השירות של פרויקט Firebase ומורידים את קובץ המפתח בפורמט JSON. אפשר לעשות זאת בדף Service account במסוף Firebase.
    2. מגדירים את משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS לנתיב של קובץ ה-JSON שמכיל את המַפְתח של חשבון השירות, או מגדירים את משתנה הסביבה GCLOUD_SERVICE_ACCOUNT_CREDS לתוכן של קובץ ה-JSON.

טלמטריה

ל-Plugin יש תלות ישירה בPlugin של Google Cloud, ולכן יש בו הנחיות להפעלת ייצוא טלמטריה לחבילת התפעול של Google ב-Cloud. כדי להפעיל את ייצוא הטלמטריה, קוראים לפונקציה enableFirebaseTelemetry():

import { enableFirebaseTelemetry } from '@genkit-ai/firebase';

enableFirebaseTelemetry();

במסמכי העזרה של הפלאגין של Google Cloud מפורטות כל אפשרויות ההגדרה וממשקי ה-API הנדרשים שצריך להפעיל בפרויקט.

שימוש

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

מאגר וקטורים ב-Cloud Firestore

אפשר להשתמש ב-Cloud Firestore כאחסון וקטורים להוספה לאינדקס של RAG ולאחזור.

הקטע הזה מכיל מידע ספציפי על הפלאגין firebase ועל תכונת החיפוש לפי וקטור של Cloud Firestore. בדף יצירה עם שיפור לאחזור מוסבר בהרחבה איך מטמיעים את RAG באמצעות Genkit.

שימוש ב-GCLOUD_SERVICE_ACCOUNT_CREDS וב-Firestore

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

import {initializeApp} from "firebase-admin/app";
import {getFirestore} from "firebase-admin/firestore";

const app = initializeApp();
let firestore = getFirestore(app);

if (process.env.GCLOUD_SERVICE_ACCOUNT_CREDS) {
  const serviceAccountCreds = JSON.parse(process.env.GCLOUD_SERVICE_ACCOUNT_CREDS);
  const authOptions = { credentials: serviceAccountCreds };
  firestore.settings(authOptions);
}

אחזור נתונים

הפלאגין firebase מספק פונקציית נוחות להגדרת פונקציות אחזור של Firestore, ‏ defineFirestoreRetriever():

import {defineFirestoreRetriever} from "@genkit-ai/firebase";
import {retrieve} from "@genkit-ai/ai/retriever";

import {initializeApp} from "firebase-admin/app";
import {getFirestore} from "firebase-admin/firestore";

const app = initializeApp();
const firestore = getFirestore(app);

const yourRetrieverRef = defineFirestoreRetriever({
  name: "yourRetriever",
  firestore: getFirestore(app),
  collection: "yourCollection",
  contentField: "yourDataChunks",
  vectorField: "embedding",
  embedder: textEmbeddingGecko, // Import from '@genkit-ai/googleai' or '@genkit-ai/vertexai'
  distanceMeasure: "COSINE", // "EUCLIDEAN", "DOT_PRODUCT", or "COSINE" (default)
});

כדי להשתמש בו, מעבירים אותו לפונקציה ai.retrieve():

const docs = await ai.retrieve({
  retriever: yourRetrieverRef,
  query: "look for something",
  options: { limit: 5 },
});

אפשרויות האחזור הזמינות כוללות:

  • limit: ציון מספר התוצאות התואמות שיש להחזיר.
  • where: צמדים של שדה/ערך שתתבצע להם התאמה (למשל {category: 'food'}) בנוסף לחיפוש וקטור.
  • collection: שינוי אוסף ברירת המחדל לחיפוש, למשל חיפוש באוסף משנה.

הוספה לאינדקס והטמעה

כדי לאכלס את האוסף ב-Firestore, משתמשים ב-Admin SDK ובכלי להטמעה. לדוגמה, אפשר להתאים את הסקריפט להטמעת התפריט מהדף יצירה עם שיפור לאחזור ל-Firestore באופן הבא:

import { genkit } from 'genkit';
import { vertexAI, textEmbedding004 } from "@genkit-ai/vertexai";

import { applicationDefault, initializeApp } from "firebase-admin/app";
import { FieldValue, getFirestore } from "firebase-admin/firestore";

import { chunk } from "llm-chunk";
import pdf from "pdf-parse";

import { readFile } from "fs/promises";
import path from "path";

// Change these values to match your Firestore config/schema
const indexConfig = {
  collection: "menuInfo",
  contentField: "text",
  vectorField: "embedding",
  embedder: textEmbedding004,
};

const ai = genkit({
  plugins: [vertexAI({ location: "us-central1" })],
});

const app = initializeApp({ credential: applicationDefault() });
const firestore = getFirestore(app);

export async function indexMenu(filePath: string) {
  filePath = path.resolve(filePath);

  // Read the PDF.
  const pdfTxt = await extractTextFromPdf(filePath);

  // Divide the PDF text into segments.
  const chunks = await chunk(pdfTxt);

  // Add chunks to the index.
  await indexToFirestore(chunks);
}

async function indexToFirestore(data: string[]) {
  for (const text of data) {
    const embedding = await ai.embed({
      embedder: indexConfig.embedder,
      content: text,
    });
    await firestore.collection(indexConfig.collection).add({
      [indexConfig.vectorField]: FieldValue.vector(embedding),
      [indexConfig.contentField]: text,
    });
  }
}

async function extractTextFromPdf(filePath: string) {
  const pdfFile = path.resolve(filePath);
  const dataBuffer = await readFile(pdfFile);
  const data = await pdf(dataBuffer);
  return data.text;
}

Firestore מסתמך על אינדקסים כדי לספק שאילתות מהירות ויעילות על אוספי נתונים. (הערה: המונח 'אינדקס' מתייחס כאן לאינדקסים של מסדי נתונים, ולא לשירותי ה-indexer וה-retriever של Genkit).

כדי שהדוגמה הקודמת תפעל, צריך להוסיף את השדה embedding לאינדקס. כדי ליצור את המדד:

  • מריצים את הפקודה gcloud שמתוארת בקטע יצירת אינדקס וקטור של שדה יחיד במסמכי העזרה של Firestore.

    הפקודה נראית כך:

    gcloud alpha firestore indexes composite create --project=your-project-id \
      --collection-group=yourCollectionName --query-scope=COLLECTION \
      --field-config=vector-config='{"dimension":"768","flat": "{}"}',field-path=yourEmbeddingField

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

  • לחלופין, אפשר להפעיל את ai.retrieve() ותופיע ב-Firestore שגיאה עם הפקודה הנכונה ליצירת האינדקס.

מידע נוסף

Cloud Functions

הפלאגין מספק את המבנה ההתחלתי onFlow(), שיוצר תהליך שמבוסס על פונקציה של Cloud Functions for Firebase שמופעל באמצעות HTTPS. הפונקציות האלה תואמות לממשק הפונקציות הניתנות לקריאה של Firebase, וניתן להשתמש בחבילות ה-SDK של לקוחות Cloud Functions כדי לבצע קריאה אליהן.

import { onFlow, noAuth } from "@genkit-ai/firebase/functions";

export const exampleFlow = onFlow(
  ai, // Provide the Genkit instance
  {
    name: "exampleFlow",
    authPolicy: noAuth(), // WARNING: noAuth() creates an open endpoint!
  },
  async (prompt) => {
    // Flow logic goes here.

    return response;
  }
);

פורסים את התהליך באמצעות CLI של Firebase:

firebase deploy --only functions

לפונקציה onFlow() יש כמה אפשרויות שלא קיימות ב-defineFlow():

  • httpsOptions: אובייקט HttpsOptions שמשמשים להגדרת הפונקציה ב-Cloud:

    export const exampleFlow = onFlow(
      ai,
      {
        name: "exampleFlow",
        httpsOptions: {
          cors: true,
        },
        // ...
      },
      async (prompt) => {
        // ...
      }
    );
    
  • enforceAppCheck: כשהערך הוא true, המערכת דוחה בקשות עם אסימוני בדיקת האפליקציה חסרים או לא תקינים.

  • consumeAppCheckToken: כשהערך הוא true, צריך לבטל את התוקף של אסימון App Check אחרי האימות שלו.

    הגנה מפני הפעלה חוזרת

Firebase Auth

הפלאגין הזה מספק פונקציית עזר ליצירת מדיניות הרשאות סביב אימות Firebase:

import {firebaseAuth} from "@genkit-ai/firebase/auth";

export const exampleFlow = onFlow(
  ai,
  {
    name: "exampleFlow",
    authPolicy: firebaseAuth((user) => {
      if (!user.email_verified) throw new Error("Requires verification!");
    }),
  },
  async (prompt) => {
    // ...
  }
);

כדי להגדיר מדיניות אימות, צריך לספק ל-firebaseAuth() פונקציית קריאה חוזרת שמקבלת את DecodedIdToken כפרמטר היחיד שלה. בפונקציה הזו, בודקים את אסימון המשתמש ומפעילים שגיאה אם המשתמש לא עומד באחד מהקריטריונים שאתם רוצים לדרוש.

לסקירה מעמיקה יותר בנושא הזה, אפשר לעיין במאמר הרשאה ותקינות.