Firebase plugin

The Firebase plugin provides integrations with Firebase services, allowing you to build intelligent and scalable AI applications. Key features include:

  • Firestore Vector Store: Use Firestore for indexing and retrieval with vector embeddings.
  • Cloud Functions: Deploy flows as HTTPS-triggered functions.
  • Firebase Authentication: Implement authorization policies.
  • Telemetry: Export telemetry to Google Cloud’s operations suite and see specialized views in the Firebase console

Installation

Install the Firebase plugin with npm:

npm install @genkit-ai/firebase

Prerequisites

Firebase Project Setup

  1. All Firebase products require a Firebase project. You can create a new project or enable Firebase in an existing Google Cloud project using the Firebase console.
  2. If deploying flows with Cloud Functions, upgrade your Firebase project to the Blaze plan.
  3. If you want to run code locally that exports telemetry, you need the Google Cloud CLI tool installed.

Firebase Admin SDK Initialization

You must initialize the Firebase Admin SDK in your application. This is not handled automatically by the plugin.

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

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

The plugin requires you to specify your Firebase project ID. You can specify your Firebase project ID in either of the following ways:

  • Set projectId in the initializeApp() configuration object as shown in the snippet above.

  • Set the GCLOUD_PROJECT environment variable. If you're running your flow from a Google Cloud environment (Cloud Functions, Cloud Run, and so on), GCLOUD_PROJECT is automatically set to the project ID of the environment.

    If you set GCLOUD_PROJECT, you can omit the configuration parameter in initializeApp().

Credentials

To provide Firebase credentials, you also need to set up Google Cloud Application Default Credentials. To specify your credentials:

  • If you're running your flow from a Google Cloud environment (Cloud Functions, Cloud Run, and so on), this is set automatically.

  • For other environments:

    1. Generate service account credentials for your Firebase project and download the JSON key file. You can do so on the Service account page of the Firebase console.
    2. Set the environment variable GOOGLE_APPLICATION_CREDENTIALS to the file path of the JSON file that contains your service account key, or you can set the environment variable GCLOUD_SERVICE_ACCOUNT_CREDS to the content of the JSON file.

Features and usage

Telemetry

The plugin has a direct dependency on the Google Cloud plugin and thus has provisions to enable telemetry export to Google's Cloud operations suite. To enable telemetry export call enableFirebaseTelemetry():

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

enableFirebaseTelemetry();

Refer to the Google Cloud plugin documentation for all configuration options and the necessary APIs that need to be enabled on the project.

You can use Cloud Firestore as a vector store for RAG indexing and retrieval.

This section contains information specific to the firebase plugin and Cloud Firestore's vector search feature. See the Retrieval-augmented generation page for a more detailed discussion on implementing RAG using Genkit.

Using GCLOUD_SERVICE_ACCOUNT_CREDS and Firestore

If you are using service account credentials by passing credentials directly via GCLOUD_SERVICE_ACCOUNT_CREDS and are also using Firestore as a vector store, you will need to pass credentials directly to the Firestore instance during initialization or the singleton may be initialized with application default credentials depending on plugin initialization order.

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

Define a Firestore retriever

Use defineFirestoreRetriever() to create a retriever for Firestore vector-based queries.

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

Retrieve documents

To retrieve documents using the defined retriever, pass the retriever instance and query options to 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
  },
});

Available Retrieval Options

The following options can be passed to the options field in ai.retrieve:

  • limit: (number)
    Specify the maximum number of documents to retrieve. Default is 10.

  • where: (Record<string, any>)
    Add additional filters based on Firestore fields. Example:

    where: { category: 'news', status: 'published' }
    
  • collection: (string)
    Override the default collection specified in the retriever configuration. This is useful for querying subcollections or dynamically switching between collections.

Populate Firestore with Embeddings

To populate your Firestore collection, use an embedding generator along with the Admin SDK. For example, the menu ingestion script from the Retrieval-augmented generation page could be adapted for Firestore in the following way:

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 depends on indexes to provide fast and efficient querying on collections. (Note that "index" here refers to database indexes, and not Genkit's indexer and retriever abstractions.)

The prior example requires the embedding field to be indexed to work. To create the index:

  • Run the gcloud command described in the Create a single-field vector index section of the Firestore docs.

    The command looks like the following:

    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
    

    However, the correct indexing configuration depends on the queries you will make and the embedding model you're using.

  • Alternatively, call ai.retrieve() and Firestore will throw an error with the correct command to create the index.

Learn more

Deploy flows as Cloud Functions

The plugin provides the onFlow() constructor, which creates a flow backed by a Cloud Functions for Firebase HTTPS-triggered function. These functions conform to Firebase's callable function interface and you can use the Cloud Functions client SDKs to call them.

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

Deploy your flow using the Firebase CLI:

firebase deploy --only functions

The onFlow() function has some options not present in defineFlow():

  • httpsOptions: an HttpsOptions object used to configure your Cloud Function:

    export const exampleFlow = onFlow(
      ai,
      {
        name: "exampleFlow",
        httpsOptions: {
          cors: true,
        },
        // ...
      },
      async (prompt) => {
        // ...
      }
    );
    
  • enforceAppCheck: when true, reject requests with missing or invalid App Check tokens.

  • consumeAppCheckToken: when true, invalidate the App Check token after verifying it.

    See Replay protection.

Firebase Authentication

This plugin provides a helper function to create authorization policies around Firebase Auth:

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

To define an auth policy, provide firebaseAuth() with a callback function that takes a DecodedIdToken as its only parameter. In this function, examine the user token and throw an error if the user fails to meet any of the criteria you want to require.

See Authorization and integrity for a more thorough discussion of this topic.