Déployer des flux à l'aide de Cloud Functions for Firebase

Genkit inclut un plug-in qui vous aide à déployer vos flux dans Cloud Functions for Firebase. Une fois déployés, les flux sont disponibles en tant que points de terminaison HTTPS et accessibles en tant que fonctions appelables à l'aide des bibliothèques clientes Cloud Functions.

Avant de commencer

  • Installez la CLI Firebase.
  • Vous devez connaître le concept de flux de Genkit et savoir comment les écrire. Les instructions de cette page supposent que vous avez déjà défini des flux que vous souhaitez déployer.
  • Il est utile, mais pas obligatoire, d'avoir déjà utilisé Cloud Functions pour Firebase.

1. Configurer un projet Firebase

Si vous ne disposez pas encore d'un projet Firebase avec des fonctions Cloud TypeScript configurées, procédez comme suit:

  1. Créez un projet Firebase à l'aide de la console Firebase ou choisissez-en un existant.

  2. Passez le projet à la formule Blaze, qui est requise pour déployer Cloud Functions.

  3. Connectez-vous avec la CLI Firebase:

    firebase login
    firebase login --reauth # alternative, if necessary
    firebase login --no-localhost # if running in a remote shell
  4. Créez un répertoire de projet:

    export PROJECT_ROOT=~/tmp/genkit-firebase-project1
    mkdir -p $PROJECT_ROOT
  5. Initialisez un projet Firebase dans le répertoire:

    cd $PROJECT_ROOT
    firebase init genkit

    Le reste de cette page suppose que vous avez choisi d'écrire vos fonctions en TypeScript, mais vous pouvez également déployer vos flux Genkit si vous utilisez JavaScript.

2. Mettre à jour les définitions de flux

Une fois que vous avez configuré un projet Firebase avec Cloud Functions, vous pouvez copier ou écrire des définitions de flux dans le répertoire functions/src du projet, puis les exporter dans index.ts.

Pour que vos flux puissent être déployés, vous devrez apporter quelques modifications à la façon dont vous les définissez. La logique de base restera la même, mais vous ajouterez des informations supplémentaires pour les déployer facilement et les sécuriser une fois déployées.

Supposons que vous disposiez du flux suivant:

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

Les sections suivantes décrivent les modifications que vous devez apporter avant de pouvoir le déployer.

Définir des flux avec onFlow

Au lieu de définir votre flux avec Genkit.defineFlow(), utilisez la fonction onFlow() du plug-in Firebase. L'utilisation de cette fonction encapsule votre logique de flux dans un gestionnaire de requêtes Cloud Functions, semblable à onCall.

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

export const generatePoem = onFlow(
  ai,
  {
    // ...
  },
  async (subject: string) => {
    // ...
  }
);

Notez que onFlow n'est pas une méthode de Genkit, mais plutôt une fonction qui utilise une instance Genkit comme premier paramètre. Sinon, la syntaxe est semblable à defineFlow.

Définir une règle d'autorisation

Tous les flux déployés, qu'ils soient déployés sur Firebase ou non, doivent disposer d'une règle d'autorisation. Sans cela, n'importe qui pourrait appeler vos flux d'IA générative potentiellement coûteux. Pour définir une règle d'autorisation, utilisez le paramètre authPolicy dans la définition du flux:

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

export const generatePoem = onFlow(
  ai,
  {
    name: "generatePoem",
    // ...
    authPolicy: firebaseAuth((user, input) => {
      if (!user.email_verified) {
        throw new Error("Verified email required to run flow");
      }
    }),
  },
  async (subject: string) => {
    // ...
  }
);

Cette règle utilise l'assistant firebaseAuth() pour n'autoriser l'accès qu'aux utilisateurs enregistrés de votre application disposant d'adresses e-mail validées. Côté client, vous devez définir l'en-tête Authorization: Bearer sur un jeton d'ID Firebase qui respecte votre règle. Les SDK clients Cloud Functions fournissent des méthodes de fonction appelables qui automatisent ce processus. Pour en savoir plus, consultez la section Essayer le flux déployé.

Rendre les identifiants de l'API disponibles pour les flux déployés

Une fois déployés, vos flux doivent disposer d'un moyen de s'authentifier auprès des services distants sur lesquels ils s'appuient. La plupart des flux auront au minimum besoin d'identifiants pour accéder au service d'API de modèle qu'ils utilisent.

Pour cet exemple, effectuez l'une des opérations suivantes, en fonction du fournisseur de modèle que vous avez choisi:

Gemini (IA de Google)

  1. Assurez-vous que l'IA de Google est disponible dans votre région.

  2. Générez une clé API pour l'API Gemini à l'aide de Google AI Studio.

  3. Stockez votre clé API dans Cloud Secret Manager:

    firebase functions:secrets:set GOOGLE_GENAI_API_KEY

    Cette étape est importante pour éviter de divulguer accidentellement votre clé API, qui permet d'accéder à un service potentiellement limité.

    Pour en savoir plus sur la gestion des secrets, consultez la section Stocker et accéder à des informations de configuration sensibles.

  4. Modifiez src/index.ts et ajoutez les éléments suivants après les importations existantes:

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

    Ensuite, dans la définition du flux, déclarez que la fonction cloud a besoin d'accéder à cette valeur secrète:

    export const generatePoem = onFlow(
      {
        name: "generatePoem",
        // ...
        httpsOptions: {
          secrets: [googleAIapiKey],  // Add this line.
        },
      },
      async (subject) => {
        // ...
      }
    );
    

Désormais, lorsque vous déploierez cette fonction, votre clé API sera stockée dans Cloud Secret Manager et disponible depuis l'environnement Cloud Functions.

Gemini (Vertex AI)

  1. Dans la console Cloud, activez l'API Vertex AI pour votre projet Firebase.

  2. Sur la page IAM, assurez-vous que le compte de service Compute par défaut dispose du rôle Utilisateur Vertex AI.

Le seul secret que vous devez configurer pour ce tutoriel concerne le fournisseur de modèle, mais en général, vous devez effectuer une opération similaire pour chaque service utilisé par votre flux.

Définir une règle CORS

Si vous accédez à votre flux à partir d'une application Web (ce que vous ferez dans la section Essayer le flux déployé), définissez une règle CORS dans le paramètre httpsOptions:

export const generatePoem = onFlow(
  ai,
  {
    name: "generatePoem",
    // ...
    httpsOptions: {
      cors: '*',
    },
  },
  async (subject: string) => {
    // ...
  }
);

Vous voudrez probablement une stratégie plus restrictive pour les applications de production, mais cela suffit pour ce tutoriel.

Exemple complet

Une fois toutes les modifications décrites ci-dessus effectuées, votre flux déployable se présentera comme suit:

const googleAIapiKey = defineSecret("GOOGLE_GENAI_API_KEY");

export const generatePoem = onFlow(
  ai,
  {
    name: "generatePoem",
    inputSchema: z.string(),
    outputSchema: z.string(),
    authPolicy: firebaseAuth((user, input) => {
      if (!user.email_verified) {
        throw new Error("Verified email required to run flow");
      }
    }),
    httpsOptions: {
      secrets: [googleAIapiKey],
      cors: '*',
    },
  },
  async (subject: string) => {
    const { text } = await ai.generate(`Compose a poem about ${subject}.`);
    return text;
  }
);

3. Déployer des flux sur Firebase

Une fois que vous avez défini des flux à l'aide de onFlow, vous pouvez les déployer comme vous le feriez pour d'autres fonctions Cloud:

cd $PROJECT_ROOT
firebase deploy --only functions

Vous avez maintenant déployé le flux en tant que fonction Cloud. Toutefois, vous ne pourrez pas accéder à votre point de terminaison déployé avec curl ou un outil similaire, en raison de la stratégie d'autorisation du flux. Passez à la section suivante pour découvrir comment accéder de manière sécurisée au flux.

Facultatif: Essayer le flux déployé

Pour tester votre point de terminaison de flux, vous pouvez déployer l'exemple d'application Web minimal suivant:

  1. Dans la section Project settings (Paramètres du projet) de la console Firebase, ajoutez une application Web, en sélectionnant l'option permettant également de configurer l'hébergement.

  2. Dans la section Authentication (Authentification) de la console Firebase, activez le fournisseur Google, que vous utiliserez dans cet exemple.

  3. Dans le répertoire de votre projet, configurez Firebase Hosting, où vous allez déployer l'application exemple:

    cd $PROJECT_ROOT
    firebase init hosting

    Acceptez les valeurs par défaut pour toutes les requêtes.

  4. Remplacez public/index.html par ce qui suit:

    <!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. Déployez l'application Web et la fonction Cloud:

    cd $PROJECT_ROOT
    firebase deploy

Ouvrez l'application Web en accédant à l'URL imprimée par la commande deploy. L'application vous demande de vous connecter avec un compte Google, après quoi vous pouvez lancer des requêtes de point de terminaison.

Facultatif: Exécuter des flux dans l'UI du développeur

Vous pouvez exécuter des flux définis à l'aide de onFlow dans l'interface utilisateur du développeur, exactement de la même manière que vous exécutez des flux définis à l'aide de defineFlow. Il n'est donc pas nécessaire de basculer entre les deux entre le déploiement et le développement.

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

ou

cd $PROJECT_ROOT/functions
npm run genkit:start

Vous pouvez maintenant accéder à l'URL imprimée par la commande genkit start.

Facultatif: Développement à l'aide de la suite d'émulateurs locaux Firebase

Firebase propose une suite d'émulateurs pour le développement local, que vous pouvez utiliser avec Genkit.

Pour utiliser l'UI de développement Genkit avec la suite d'émulateurs Firebase, démarrez les émulateurs Firebase comme suit:

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

Votre code sera exécuté dans l'émulateur et le framework Genkit en mode développement, qui lance et expose l'API de réflexion Genkit (mais pas l'UI de développement).

Pour afficher les traces de Firestore dans l'UI de développement, accédez à l'onglet "Inspect" (Inspecter) et activez/désactivez le bouton "Dev/Prod" (Dev/Prod). Lorsque l'option "prod" est activée, des traces de Firestore sont chargées.