Men-deploy alur menggunakan Cloud Functions for Firebase

Genkit menyertakan plugin yang membantu Anda men-deploy flow ke Cloud Functions untuk Firebase. Setelah di-deploy, alur tersedia sebagai endpoint HTTPS dan dapat diakses sebagai fungsi callable menggunakan library klien Cloud Functions.

Sebelum memulai

  • Instal Firebase CLI.
  • Anda harus memahami konsep alur Genkit, dan cara menulisnya. Petunjuk di halaman ini mengasumsikan bahwa Anda sudah menentukan beberapa alur yang ingin di-deploy.
  • Akan lebih baik, tetapi tidak wajib, jika Anda sudah pernah menggunakan Cloud Functions untuk Firebase sebelumnya.

1. Menyiapkan project Firebase

Jika Anda belum memiliki project Firebase dengan Cloud Functions TypeScript yang disiapkan, ikuti langkah-langkah berikut:

  1. Buat project Firebase baru menggunakan Firebase console atau pilih project yang sudah ada.

  2. Upgrade project ke paket Blaze, yang diperlukan untuk men-deploy Cloud Functions.

  3. Login dengan Firebase CLI:

    firebase login
    firebase login --reauth # alternative, if necessary
    firebase login --no-localhost # if running in a remote shell
  4. Buat direktori project baru:

    export PROJECT_ROOT=~/tmp/genkit-firebase-project1
    mkdir -p $PROJECT_ROOT
  5. Lakukan inisialisasi project Firebase di direktori:

    cd $PROJECT_ROOT
    firebase init genkit

    Bagian lain halaman ini mengasumsikan bahwa Anda telah memilih untuk menulis fungsi di TypeScript, tetapi Anda juga dapat men-deploy alur Genkit jika menggunakan JavaScript.

2. Memperbarui definisi alur

Setelah menyiapkan project Firebase dengan Cloud Functions, Anda dapat menyalin atau menulis definisi alur di direktori functions/src project, dan mengekspornya di index.ts.

Agar alur dapat di-deploy, Anda harus melakukan beberapa perubahan kecil pada cara menentukan alur. Logika inti akan tetap sama, tetapi Anda akan menambahkan beberapa informasi tambahan agar dapat di-deploy dengan lancar dan lebih aman setelah di-deploy.

Misalkan Anda memiliki alur berikut:

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

Bagian berikut menjelaskan perubahan yang perlu Anda lakukan sebelum dapat men-deploynya.

Menentukan flow dengan onFlow

Daripada menentukan alur dengan Genkit.defineFlow(), gunakan fungsi onFlow() plugin Firebase. Penggunaan fungsi ini menggabungkan logika alur Anda dalam pengendali permintaan Cloud Functions, mirip dengan onCall.

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

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

Perhatikan bahwa onFlow bukan metode Genkit, melainkan fungsi yang menggunakan instance Genkit sebagai parameter pertamanya. Jika tidak, sintaksisnya mirip dengan defineFlow.

Menentukan kebijakan otorisasi

Semua alur yang di-deploy, baik di-deploy ke Firebase maupun tidak, harus memiliki kebijakan otorisasi. Tanpa kebijakan ini, alur AI generatif Anda yang berpotensi mahal dapat dipanggil oleh siapa saja. Untuk menentukan kebijakan otorisasi, gunakan parameter authPolicy dalam definisi alur:

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

Kebijakan ini menggunakan helper firebaseAuth() untuk mengizinkan akses hanya kepada pengguna terdaftar aplikasi Anda dengan alamat email terverifikasi. Di sisi klien, Anda perlu menetapkan header Authorization: Bearer ke token ID Firebase yang memenuhi kebijakan Anda. SDK klien Cloud Functions menyediakan metode fungsi callable yang mengotomatiskan hal ini; lihat bagian Mencoba alur yang di-deploy untuk mengetahui contohnya.

Menyediakan kredensial API untuk alur yang di-deploy

Setelah di-deploy, alur Anda memerlukan beberapa cara untuk melakukan autentikasi dengan layanan jarak jauh yang menjadi andalannya. Sebagian besar alur setidaknya akan memerlukan kredensial untuk mengakses layanan API model yang mereka gunakan.

Untuk contoh ini, lakukan salah satu hal berikut, bergantung pada penyedia model yang Anda pilih:

Gemini (AI Google)

  1. Pastikan AI Google tersedia di wilayah Anda.

  2. Buat kunci API untuk Gemini API menggunakan Google AI Studio.

  3. Simpan kunci API Anda di Cloud Secret Manager:

    firebase functions:secrets:set GOOGLE_GENAI_API_KEY

    Langkah ini penting untuk mencegah kebocoran kunci API secara tidak sengaja, yang memberikan akses ke layanan yang berpotensi berbayar.

    Lihat Menyimpan dan mengakses informasi konfigurasi yang sensitif untuk mengetahui informasi selengkapnya tentang cara mengelola secret.

  4. Edit src/index.ts dan tambahkan kode berikut setelah impor yang ada:

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

    Kemudian, dalam definisi alur, deklarasikan bahwa fungsi cloud memerlukan akses ke nilai secret ini:

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

Sekarang, saat Anda men-deploy fungsi ini, kunci API Anda akan disimpan di Cloud Secret Manager, dan tersedia dari lingkungan Cloud Functions.

Gemini (Vertex AI)

  1. Di konsol Cloud, Aktifkan API Vertex AI untuk project Firebase Anda.

  2. Di halaman IAM, pastikan bahwa Akun layanan komputasi default diberikan peran Vertex AI User.

Satu-satunya secret yang perlu Anda siapkan untuk tutorial ini adalah untuk penyedia model, tetapi secara umum, Anda harus melakukan hal serupa untuk setiap layanan yang digunakan oleh flow Anda.

Menetapkan kebijakan CORS

Jika Anda akan mengakses alur dari aplikasi web (yang akan Anda lakukan di bagian Coba alur yang di-deploy), di parameter httpsOptions, tetapkan kebijakan CORS:

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

Anda mungkin menginginkan kebijakan yang lebih ketat untuk aplikasi produksi, tetapi kebijakan ini sudah memadai untuk tutorial ini.

Contoh lengkap

Setelah Anda membuat semua perubahan yang dijelaskan di atas, alur yang dapat di-deploy akan terlihat seperti contoh berikut:

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. Men-deploy flow ke Firebase

Setelah menentukan alur menggunakan onFlow, Anda dapat men-deploynya seperti men-deploy Cloud Functions lainnya:

cd $PROJECT_ROOT
firebase deploy --only functions

Sekarang Anda telah men-deploy alur sebagai Cloud Function. Namun, Anda tidak akan dapat mengakses endpoint yang di-deploy dengan curl atau yang serupa, karena kebijakan otorisasi alur. Lanjutkan ke bagian berikutnya untuk mempelajari cara mengakses alur dengan aman.

Opsional: Mencoba alur yang di-deploy

Untuk mencoba endpoint alur, Anda dapat men-deploy contoh aplikasi web minimal berikut:

  1. Di bagian Setelan project di Firebase console, tambahkan aplikasi web baru, dengan memilih opsi untuk menyiapkan Hosting juga.

  2. Di bagian Authentication di Firebase console, aktifkan penyedia Google, yang akan Anda gunakan dalam contoh ini.

  3. Di direktori project, siapkan Firebase Hosting, tempat Anda akan men-deploy aplikasi contoh:

    cd $PROJECT_ROOT
    firebase init hosting

    Terima setelan default untuk semua perintah.

  4. Ganti public/index.html dengan yang berikut:

    <!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. Men-deploy aplikasi web dan Cloud Function:

    cd $PROJECT_ROOT
    firebase deploy

Buka aplikasi web dengan membuka URL yang dicetak oleh perintah deploy. Aplikasi ini memerlukan Anda untuk login dengan Akun Google, setelah itu Anda dapat memulai permintaan endpoint.

Opsional: Menjalankan alur di UI developer

Anda dapat menjalankan flow yang ditentukan menggunakan onFlow di UI developer, dengan cara yang sama seperti saat menjalankan flow yang ditentukan menggunakan defineFlow, sehingga tidak perlu beralih antara keduanya antara deployment dan pengembangan.

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

Opsional: Mengembangkan menggunakan Firebase Local Emulator Suite

Firebase menawarkan rangkaian emulator untuk pengembangan lokal, yang dapat Anda gunakan dengan Genkit.

Untuk menggunakan Genkit dengan Firebase Emulator Suite, mulai emulator Firebase seperti ini:

GENKIT_ENV=dev firebase emulators:start --inspect-functions

Tindakan ini akan menjalankan kode Anda di emulator dan menjalankan framework Genkit dalam mode pengembangan, yang meluncurkan dan mengekspos API refleksi Genkit (tetapi bukan UI Developer).

Kemudian, luncurkan UI Developer Genkit dengan opsi --attach untuk menghubungkannya ke kode Anda yang berjalan di dalam Firebase Emulator:

npx genkit start --attach http://localhost:3100 --port 4001

Untuk melihat rekaman aktivitas dari Firestore di UI Dev, Anda dapat membuka tab Inspect dan mengalihkan tombol "Dev/Prod". Jika dialihkan ke "prod", trace akan dimuat dari firestore.