פלאגין של Firebase

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

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

התקנה

מתקינים את הפלאגין של Firebase באמצעות npm:

npm install @genkit-ai/firebase

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

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

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

איך מפעילים את Firebase Admin SDK

צריך לאתחל את Firebase Admin SDK באפליקציה. הפלאגין לא מטפל בזה באופן אוטומטי.

import { initializeApp } from 'firebase-admin/app';

initializeApp({
  projectId: 'your-project-id',
});

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

  • מגדירים את projectId באובייקט התצורה initializeApp(), כפי שמוצג בקטע הקוד שלמעלה.

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

    אם מגדירים את GCLOUD_PROJECT, אפשר להשמיט את פרמטר ההגדרה ב-initializeApp().

פרטי כניסה

כדי לספק פרטי כניסה ל-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 הנדרשים שצריך להפעיל בפרויקט.

אפשר להשתמש ב-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);
}

הגדרת אובייקט אחזור של Firestore

משתמשים ב-defineFirestoreRetriever() כדי ליצור אחזור לשאילתות מבוססות-וקטור של Firestore.

import { defineFirestoreRetriever } from '@genkit-ai/firebase';
import { initializeApp } from 'firebase-admin/app';
import { getFirestore } from 'firebase-admin/firestore';

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

const retriever = defineFirestoreRetriever(ai, {
  name: 'exampleRetriever',
  firestore,
  collection: 'documents',
  contentField: 'text', // Field containing document content
  vectorField: 'embedding', // Field containing vector embeddings
  embedder: yourEmbedderInstance, // Embedder to generate embeddings
  distanceMeasure: 'COSINE', // Default is 'COSINE'; other options: 'EUCLIDEAN', 'DOT_PRODUCT'
});

אחזור מסמכים

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

const docs = await ai.retrieve({
  retriever,
  query: 'search query',
  options: {
    limit: 5, // Options: Return up to 5 documents
    where: { category: 'example' }, // Optional: Filter by field-value pairs
    collection: 'alternativeCollection', // Optional: Override default collection
  },
});

אפשרויות אחזור זמינות

אפשר להעביר את האפשרויות הבאות לשדה options ב-ai.retrieve:

  • limit: (number)
    מציינים את מספר המסמכים המקסימלי לאחזור. ברירת המחדל היא 10.

  • where: (Record<string, any>)
    הוספת מסננים נוספים על סמך שדות של Firestore. דוגמה:

    where: { category: 'news', status: 'published' }
    
  • collection: (מחרוזת)
    שינוי אוטומטי של אוסף ברירת המחדל שצוין בתצורה של האחזור. אפשר להשתמש בזה כדי לשלוח שאילתות על אוספי משנה או לעבור באופן דינמי בין אוספים.

איך מאכלסים את Firestore באמצעות הטמעות

כדי לאכלס את האוסף ב-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

הפלאגין הזה מספק פונקציית עזר ליצירת מדיניות הרשאות סביב אימות 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 כפרמטר היחיד שלה. בפונקציה הזו, בודקים את אסימון המשתמש ומציגים שגיאה אם המשתמש לא עומד באחד מהקריטריונים שאתם רוצים לדרוש.

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