Abläufe mit Cloud Functions für Firebase bereitstellen

Cloud Functions for Firebase bietet die Methode onCallGenkit, mit der Sie schnell eine aufrufbare Funktion mit einer Genkit-Aktion (z.B. einem Flow) erstellen können. Diese Funktionen können mit genkit/beta/client oder dem Functions Client SDK aufgerufen werden, das automatisch Authentifizierungsinformationen hinzufügt.

Hinweis

  • Sie sollten mit dem Genkit-Konzept von Abläufen und deren Erstellung vertraut sein. In der Anleitung auf dieser Seite wird davon ausgegangen, dass Sie bereits einige Workflows definiert haben, die Sie bereitstellen möchten.
  • Es ist hilfreich, aber nicht zwingend erforderlich, wenn Sie Cloud Functions für Firebase bereits verwendet haben.

1. Firebase-Projekt einrichten

Wenn Sie noch kein Firebase-Projekt mit eingerichteten TypeScript-Cloud Functions haben, gehen Sie so vor:

  1. Erstellen Sie ein neues Firebase-Projekt in der Firebase Console oder wählen Sie ein vorhandenes Projekt aus.

  2. Führen Sie ein Upgrade des Projekts auf den Blaze-Tarif durch, der für die Bereitstellung von Cloud Functions erforderlich ist.

  3. Installieren Sie die Firebase CLI.

  4. Melden Sie sich mit der Firebase CLI an:

    firebase login
    firebase login --reauth # alternative, if necessary
    firebase login --no-localhost # if running in a remote shell
  5. Erstellen Sie ein neues Projektverzeichnis:

    export PROJECT_ROOT=~/tmp/genkit-firebase-project1
    mkdir -p $PROJECT_ROOT
  6. Initialisieren Sie ein Firebase-Projekt im Verzeichnis:

    cd $PROJECT_ROOT
    firebase init genkit

    Im weiteren Verlauf dieser Seite wird davon ausgegangen, dass Sie sich entschieden haben, Ihre Funktionen in TypeScript zu schreiben. Sie können Ihre Genkit-Abläufe aber auch bereitstellen, wenn Sie JavaScript verwenden.

2. Flow in onCallGenkit einbetten

Nachdem Sie ein Firebase-Projekt mit Cloud Functions eingerichtet haben, können Sie Ablaufdefinitionen in das functions/src-Verzeichnis des Projekts kopieren oder schreiben und sie in index.ts exportieren.

Damit Ihre Workflows bereitgestellt werden können, müssen Sie sie in onCallGenkit einschließen. Diese Methode bietet alle Funktionen der normalen onCall. Es unterstützt automatisch sowohl Streaming- als auch JSON-Antworten.

Angenommen, Sie haben den folgenden Ablauf:

const generatePoemFlow = ai.defineFlow(
  {
    name: "generatePoem",
    inputSchema: z.string(),
    outputSchema: z.string(),
  },
  async (subject: string) => {
    const { text } = await ai.generate(`Compose a poem about ${subject}.`);
    return text;
  }
);

Mit onCallGenkit können Sie diesen Ablauf als aufrufbare Funktion freigeben:

import { onCallGenkit } from 'firebase-functions/https';

export generatePoem = onCallGenkit(generatePoemFlow);

Autorisierungsrichtlinie definieren

Alle bereitgestellten Workflows, unabhängig davon, ob sie in Firebase bereitgestellt werden, sollten eine Autorisierungsrichtlinie haben. Andernfalls kann jeder Ihre potenziell teuren Workflows für generative AI aufrufen. Verwenden Sie den Parameter authPolicy von onCallGenkit, um eine Autorisierungsrichtlinie zu definieren:

export const generatePoem = onCallGenkit({
  authPolicy: (auth) => auth?.token?.email_verified,
}, generatePoemFlow);

In diesem Beispiel wird eine manuelle Funktion als Authentifizierungsrichtlinie verwendet. Außerdem werden mit der https-Bibliothek die signedIn()- und hasClaim()-Hilfsfunktionen exportiert. Hier ist derselbe Code mit einem dieser Helfer:

import { hasClaim } from 'firebase-functions/https';

export const generatePoem = onCallGenkit({
  authPolicy: hasClaim('email_verified'),
}, generatePoemFlow);

API-Anmeldedaten für bereitgestellte Abläufe verfügbar machen

Nach der Bereitstellung müssen sich Ihre Workflows bei allen Remote-Diensten authentifizieren können, auf die sie angewiesen sind. Für die meisten Abläufe sind mindestens Anmeldedaten für den Zugriff auf den verwendeten Modell-API-Dienst erforderlich.

Führen Sie in diesem Beispiel je nach ausgewähltem Modellanbieter einen der folgenden Schritte aus:

Gemini (Google AI)

  1. Prüfen Sie, ob Google AI in Ihrer Region verfügbar ist.

  2. Erstellen Sie einen API-Schlüssel für die Gemini API mit Google AI Studio.

  3. So speichern Sie Ihren API-Schlüssel in Cloud Secret Manager:

    firebase functions:secrets:set GOOGLE_GENAI_API_KEY

    Dieser Schritt ist wichtig, um zu verhindern, dass Ihr API-Schlüssel versehentlich weitergegeben wird, wodurch Zugriff auf einen potenziell befristeten Dienst gewährt wird.

    Weitere Informationen zum Verwalten von Secrets finden Sie unter Sensible Konfigurationsinformationen speichern und abrufen.

  4. Bearbeiten Sie src/index.ts und fügen Sie nach den vorhandenen Importen Folgendes hinzu:

    import {defineSecret} from "firebase-functions/params";
    const googleAIapiKey = defineSecret("GOOGLE_GENAI_API_KEY");
    

    Geben Sie dann in der Ablaufdefinition an, dass die Cloud-Funktion Zugriff auf diesen geheimen Wert benötigt:

    export const generatePoem = onCallGenkit({
      secrets: [googleAIapiKey]
    }, generatePoemFlow);
    

Wenn Sie diese Funktion jetzt bereitstellen, wird Ihr API-Schlüssel in Cloud Secret Manager gespeichert und ist über die Cloud Functions-Umgebung verfügbar.

Gemini (Vertex AI)

  1. Aktivieren Sie in der Cloud Console die Vertex AI API für Ihr Firebase-Projekt.

  2. Achten Sie darauf, dass dem Standarddienstkonto für Compute auf der Seite IAM die Rolle Vertex AI-Nutzer zugewiesen ist.

Für diese Anleitung müssen Sie nur ein Secret für den Modellanbieter einrichten. Im Allgemeinen müssen Sie jedoch für jeden Dienst, den Ihr Flow verwendet, etwas Ähnliches tun.

App Check-Erzwigung hinzufügen

Firebase App Check verwendet einen integrierten Attestierungsmechanismus, um zu prüfen, ob Ihre API nur von Ihrer Anwendung aufgerufen wird. onCallGenkit unterstützt die App-Überprüfung deklarativ.

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-Richtlinie festlegen

Bei aufrufbaren Funktionen kann standardmäßig jede Domain Ihre Funktion aufrufen. Wenn Sie die Domains anpassen möchten, für die dies möglich ist, verwenden Sie die Option cors. Bei einer ordnungsgemäßen Authentifizierung (insbesondere App-Überprüfung) ist CORS oft nicht erforderlich.

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

Vollständiges Beispiel

Nachdem Sie alle oben beschriebenen Änderungen vorgenommen haben, sollte Ihr implementierbarer Ablauf in etwa so aussehen:

import { genkit } from 'genkit';
import { onCallGenkit, hasClaim } from 'firebase-functions/https';
import { defineSecret } from 'firebase-functions/params';

const apiKey = defineSecret("GOOGLE_GENAI_API_KEY");

const generatePoemFlow = ai.defineFlow({
  name: "generatePoem",
  inputSchema: z.string(),
  outputSchema: z.string(),
}, async (subject: string) => {
  const { text } = await ai.generate(`Compose a poem about ${subject}.`);
  return text;
});

export const generateFlow = onCallGenkit({
  secrets: [apiKey],
  authPolicy: hasClaim("email_verified"),
  enforceAppCheck: true,
}, generatePoemFlow);

3. Abläufe in Firebase bereitstellen

Nachdem Sie Workflows mit onCallGenkit definiert haben, können Sie sie wie andere Cloud Functions bereitstellen:

cd $PROJECT_ROOT
firebase deploy --only functions

Sie haben den Ablauf jetzt als Cloud-Funktion bereitgestellt. Sie können jedoch aufgrund der Autorisierungsrichtlinie des Ablaufs nicht mit curl oder ähnlichen Diensten auf Ihren bereitgestellten Endpunkt zugreifen. Im nächsten Abschnitt wird beschrieben, wie Sie sicher auf den Ablauf zugreifen.

Optional: Bereitstellen Ablauf testen

Um Ihren Ablaufendpunkt zu testen, können Sie die folgende minimale Beispiel-Web-App bereitstellen:

  1. Fügen Sie in der Firebase Console im Bereich Projekteinstellungen eine neue Webanwendung hinzu und wählen Sie die Option zum Einrichten von Hosting aus.

  2. Aktivieren Sie in der Firebase Console im Abschnitt Authentifizierung den Anbieter Google, der in diesem Beispiel verwendet wird.

  3. Richten Sie in Ihrem Projektverzeichnis Firebase Hosting ein, wo Sie die Beispiel-App bereitstellen:

    cd $PROJECT_ROOT
    firebase init hosting

    Akzeptieren Sie die Standardeinstellungen für alle Prompts.

  4. Ersetzen Sie public/index.html durch Folgendes:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Genkit demo</title>
      </head>
      <body>
        <div id="signin" hidden>
          <button id="signinBtn">Sign in with Google</button>
        </div>
        <div id="callGenkit" hidden>
          Subject: <input type="text" id="subject" />
          <button id="generatePoem">Compose a poem on this subject</button>
          <p id="generatedPoem"></p>
        </div>
        <script type="module">
          import { initializeApp } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-app.js";
          import {
            getAuth,
            onAuthStateChanged,
            GoogleAuthProvider,
            signInWithPopup,
          } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-auth.js";
          import {
            getFunctions,
            httpsCallable,
          } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-functions.js";
    
          const firebaseConfig = await fetch("/__/firebase/init.json");
          initializeApp(await firebaseConfig.json());
    
          async function generatePoem() {
            const poemFlow = httpsCallable(getFunctions(), "generatePoem");
            const subject = document.querySelector("#subject").value;
            const response = await poemFlow(subject);
            document.querySelector("#generatedPoem").innerText = response.data;
          }
    
          function signIn() {
            signInWithPopup(getAuth(), new GoogleAuthProvider());
          }
    
          document.querySelector("#signinBtn").addEventListener("click", signIn);
          document
            .querySelector("#generatePoem")
            .addEventListener("click", generatePoem);
    
          const signinEl = document.querySelector("#signin");
          const genkitEl = document.querySelector("#callGenkit");
    
          onAuthStateChanged(getAuth(), (user) => {
            if (!user) {
              signinEl.hidden = false;
              genkitEl.hidden = true;
            } else {
              signinEl.hidden = true;
              genkitEl.hidden = false;
            }
          });
        </script>
      </body>
    </html>
    
  5. Webanwendung und Cloud Functions-Funktion bereitstellen:

    cd $PROJECT_ROOT
    firebase deploy

Öffnen Sie die Webanwendung, indem Sie die URL aufrufen, die mit dem Befehl deploy ausgegeben wurde. Sie müssen sich in der App mit einem Google-Konto anmelden, um Endpunktanfragen starten zu können.

Optional: Abläufe in der Entwickler-UI ausführen

Sie können mit onCallGenkit definierte Abläufe in der Entwickler-Benutzeroberfläche genau so ausführen wie mit defineFlow definierte Abläufe. Sie müssen also nicht zwischen Bereitstellung und Entwicklung wechseln.

cd $PROJECT_ROOT/functions
npx genkit start -- npx tsx --watch src/index.ts

oder

cd $PROJECT_ROOT/functions
npm run genkit:start

Sie können jetzt die URL aufrufen, die mit dem Befehl genkit start ausgegeben wurde.

Optional: Entwicklung mit der Firebase Local Emulator Suite

Firebase bietet eine Suite von Emulatoren für die lokale Entwicklung, die Sie mit Genkit verwenden können.

Wenn Sie die Genkit-Entwickleroberfläche mit der Firebase Emulator Suite verwenden möchten, starten Sie die Firebase-Emulatoren so:

npx genkit start -- firebase emulators:start --inspect-functions

Mit diesem Befehl wird Ihr Code im Emulator und das Genkit-Framework im Entwicklungsmodus ausgeführt. Dadurch wird die Genkit-Reflexions-API gestartet und freigegeben, aber nicht die Entwickler-Benutzeroberfläche.

Wenn Sie in der Entwickler-UI Spuren von Firestore sehen möchten, rufen Sie den Tab Inspect (Prüfen) auf und wechseln Sie den Schalter Dev/Prod (Entwickler/Produktion). Wenn prod ausgewählt ist, werden Traces aus Firestore geladen.