Complemento de Firebase

El complemento de Firebase proporciona varias integraciones con los servicios de Firebase:

  • Indexadores y recuperadores que usan el almacén de vectores de Cloud Firestore
  • Haz un seguimiento del almacenamiento con Cloud Firestore
  • Implementación de flujos con Cloud Functions
  • Políticas de autorización para los usuarios de Firebase Authentication

Instalación

npm i --save @genkit-ai/firebase

Requisitos previos

  • Todos los productos de Firebase requieren un proyecto de Firebase. Puedes crear un proyecto nuevo o habilita Firebase en un proyecto existente de Google Cloud con la Firebase console.
  • Además, si quieres implementar flujos en Cloud Functions, debes actualizar tu proyecto al plan Blaze (pago por uso).

Configuración

ID del proyecto

Para usar este complemento, especifícalo cuando llames a configureGenkit():

import {configureGenkit} from "@genkit-ai/core";
import {firebase} from "@genkit-ai/firebase";

configureGenkit({
  plugins: [firebase({projectId: "your-firebase-project"})],
});

El complemento requiere que especifiques el ID de tu proyecto de Firebase. Puedes especificar el ID del proyecto de Firebase de las siguientes maneras:

  • Configura projectId en el objeto de configuración firebase().

  • Configura la variable de entorno GCLOUD_PROJECT. Si ejecutas tu flujo desde un entorno de Google Cloud (Cloud Functions, Cloud Run, etcétera), GCLOUD_PROJECT se configura de forma automática en el ID del proyecto del entorno.

    Si configuras GCLOUD_PROJECT, puedes omitir el parámetro de configuración: firebase()

Credenciales

Para proporcionar credenciales de Firebase, también debes configurar Google Cloud Credenciales predeterminadas de la aplicación. Para especificar tus credenciales, haz lo siguiente:

  • Si ejecutas tu flujo desde un entorno de Google Cloud (Cloud Functions, Cloud Run, etc.), esto se configura automáticamente.

  • Para otros entornos:

    1. Genera credenciales de cuentas de servicio para tu proyecto de Firebase y descarga el archivo de claves JSON. Puedes hacerlo en la Cuenta de servicio de Firebase console.
    2. Establece la variable de entorno GOOGLE_APPLICATION_CREDENTIALS en el archivo. del archivo JSON que contiene la clave de tu cuenta de servicio, o puedes configurar la variable de entorno GCLOUD_SERVICE_ACCOUNT_CREDS en el contenido del archivo JSON.

Telemetría

El complemento depende directamente del complemento de Google Cloud y, por lo tanto, tiene aprovisionamiento para habilitar la exportación de telemetría a Google Cloud's Cloud's operations suite. Para habilitar la exportación de telemetría, establece enableTracingAndMetrics en true y agrega una sección de telemetría a la configuración de Genkit:

import {configureGenkit} from "@genkit-ai/core";
import {firebase} from "@genkit-ai/firebase";

configureGenkit({
  plugins: [firebase()],
  enableTracingAndMetrics: true,
  telemetry: {
    instrumentation: 'firebase',
    logger: 'firebase',
  },
});

Consulta la documentación del complemento de Google Cloud para conocer todas las opciones de configuración y las APIs necesarias que se deben habilitar en el proyecto.

Uso

Este complemento ofrece varias integraciones con servicios de Firebase, que puedes en conjunto o de forma individual.

Almacén de vectores de Cloud Firestore

Puedes usar Cloud Firestore como almacén de vectores para la indexación y recuperación RAG.

Esta sección contiene información específica del complemento firebase y de Cloud Función de búsqueda de vectores de Firestore. Consulta la página de generación de recuperación aumentada para obtener información más detallada. debate sobre la implementación de RAG con Genkit.

Usa GCLOUD_SERVICE_ACCOUNT_CREDS y Firestore

Si pasas las credenciales directamente a través de GCLOUD_SERVICE_ACCOUNT_CREDS para usar credenciales de cuentas de servicio y también usas Firestore como almacén de vectores, deberás pasar las credenciales directamente a la instancia de Firestore durante la inicialización o se podría inicializar el singleton con credenciales predeterminadas de la aplicación según el orden de inicialización del complemento.

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

Recuperadores

El complemento firebase proporciona una función conveniente para definir Firestore retrievers, 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)
});

Para usarlo, pásalo a la función retrieve():

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

Las opciones de recuperación disponibles incluyen las siguientes:

  • limit: Especifica la cantidad de resultados coincidentes que se mostrarán.
  • where: Pares de campo/valor que deben coincidir (p.ej., {category: 'food'}) además de la búsqueda de vectores.
  • collection: Anula la colección predeterminada para buscar, p.ej., búsqueda de subcolecciones.

Indexación e incorporación

Para propagar la colección de Firestore, usa un generador de incorporaciones junto con el archivo SDK de Admin. Por ejemplo, la secuencia de comandos de transferencia de menú de La página de generación aumentada de recuperación se podría adaptar para Firestore de la siguiente manera:

import { configureGenkit } from "@genkit-ai/core";
import { embed } from "@genkit-ai/ai/embedder";
import { defineFlow, run } from "@genkit-ai/flow";
import { textEmbeddingGecko, vertexAI } 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 * as z from "zod";

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: textEmbeddingGecko,
};

configureGenkit({
  plugins: [vertexAI({ location: "us-central1" })],
  enableTracingAndMetrics: false,
});

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

export const indexMenu = defineFlow(
  {
    name: "indexMenu",
    inputSchema: z.string().describe("PDF file path"),
    outputSchema: z.void(),
  },
  async (filePath: string) => {
    filePath = path.resolve(filePath);

    // Read the PDF.
    const pdfTxt = await run("extract-text", () =>
      extractTextFromPdf(filePath)
    );

    // Divide the PDF text into segments.
    const chunks = await run("chunk-it", async () => chunk(pdfTxt));

    // Add chunks to the index.
    await run("index-chunks", async () => indexToFirestore(chunks));
  }
);

async function indexToFirestore(data: string[]) {
  for (const text of data) {
    const embedding = await 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 depende de índices para proporcionar consultas rápidas y eficientes en colecciones. (ten en cuenta que, en este caso, “índice” se refiere a índices de bases de datos y no (abstracciones de indexador y retriever de Genkit).

El ejemplo anterior requiere que se indexe el campo embedding para el trabajo. Para crear el índice, sigue estos pasos:

  • Ejecuta el comando gcloud que se describe en Cómo crear un índice vectorial de campo único de los documentos de Firestore.

    El comando se ve de la siguiente manera:

    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
    

    Sin embargo, la configuración de indexación correcta depende de las consultas que realices marca y el modelo de incorporación que estés usando.

  • Como alternativa, llama a retrieve(); Firestore mostrará un error con el el comando correcto para crear el índice.

Más información

Almacenamiento de seguimiento de Cloud Firestore

Puedes usar Cloud Firestore para almacenar seguimientos:

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

configureGenkit({
  plugins: [firebase()],
  traceStore: "firebase",
  enableTracingAndMetrics: true,
});

De forma predeterminada, el complemento almacena seguimientos en una colección llamada genkit-traces en la base de datos predeterminada del proyecto. Para cambiar cualquiera de las opciones, sigue estos pasos:

firebase({
  traceStore: {
    collection: "your-collection";
    databaseId: "your-db";
  }
})

Cuando uses el almacenamiento de seguimientos basado en Firestore, deberás habilitar el TTL para los documentos de seguimiento: https://firebase.google.com/docs/firestore/ttl

Cloud Functions

El complemento proporciona el constructor onFlow(), que crea un flujo respaldado por un Función activada por HTTPS de Cloud Functions para Firebase. Estas funciones cumplen con al de Firebase de función que admiten llamadas y puedes usar la SDKs de cliente de Cloud Functions llamarlos.

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

configureGenkit({
  plugins: [firebase()],
});

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

    return response;
  }
);

Implementa tu flujo con Firebase CLI:

firebase deploy --only functions

La función onFlow() tiene algunas opciones que no están presentes en defineFlow():

  • httpsOptions: Es un HttpsOptions. objeto usado para configurar tu Cloud Function:

    export const exampleFlow = onFlow(
      {
        name: "exampleFlow",
        httpsOptions: {
          cors: true,
        },
        // ...
      },
      async (prompt) => {
        // ...
      }
    );
    
  • enforceAppCheck: Cuando sea true, rechaza las solicitudes con Verificación de aplicaciones que falten o no sean válidas. tokens.

  • consumeAppCheckToken: Cuando es true, invalida el token de la Verificación de aplicaciones después de verificarlo.

    Consulta Protección contra la repetición.

Firebase Auth

Este complemento proporciona una función auxiliar para crear políticas de autorización en torno a Firebase Auth:

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

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

Para definir una política de autenticación, proporciona a firebaseAuth() una función de devolución de llamada que toma un DecodedIdToken como único parámetro. En esta función, examinarás el token de usuario y arrojará una si el usuario no cumple con los criterios requeridos.

Consulta Integridad y autorización para obtener un análisis más detallado de este tema.