使用 Cloud Functions for Firebase 部署流程

Genkit 提供外掛程式,可協助您將流程部署至 Cloud Functions for Firebase。一旦部署,流程就會以 HTTPS 端點的形式提供,並可透過 Cloud Functions 用戶端程式庫做為可呼叫的函式存取。

事前準備

  • 安裝 Firebase CLI
  • 您應該熟悉 Genkit 的流程概念,以及如何編寫流程。本頁面說明假設您已定義要部署的部分流程。
  • 如已使用過 Cloud Functions for Firebase,這會很有幫助,但並非必要條件。

1. 設定 Firebase 專案

如果您還沒有 Firebase 專案,且未設定 TypeScript Cloud 函式,請按照下列步驟操作:

  1. 使用 Firebase 主控台建立新的 Firebase 專案,或選擇現有專案。

  2. 將專案升級至 Blaze 方案,這是部署 Cloud Functions 的必要條件。

  3. 使用 Firebase CLI 登入:

    firebase login
    firebase login --reauth # alternative, if necessary
    firebase login --no-localhost # if running in a remote shell
  4. 建立新的專案目錄:

    export PROJECT_ROOT=~/tmp/genkit-firebase-project1
    mkdir -p $PROJECT_ROOT
  5. 在目錄中初始化 Firebase 專案:

    cd $PROJECT_ROOT
    firebase init genkit

    本頁其餘部分假設您已選擇在 TypeScript 中編寫函式,但如果您使用 JavaScript,也可以部署 Genkit 流程。

2. 更新流程定義

設定含有 Cloud Functions 的 Firebase 專案後,您可以在專案的 functions/src 目錄中複製或撰寫流程定義,並在 index.ts 中匯出。

如要部署流程,您需要對流程的定義方式進行一些微調。核心邏輯會維持不變,但您會新增一些額外資訊,讓這些邏輯在部署後能順利部署,並提供更高的安全性。

假設您有以下流程:

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

以下各節將說明在部署前需要進行哪些變更。

使用 onFlow 定義流程

請改用 Firebase 外掛程式的 onFlow() 函式,而非使用 Genkit.defineFlow() 定義流程。使用這個函式可在 Cloud Functions 要求處理常式中包裝流程邏輯,類似於 onCall

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

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

請注意,onFlow 並非 Genkit 的方法,而是會將 Genkit 例項做為第一個參數的函式。否則,語法與 defineFlow 相似。

定義授權政策

無論是否已部署至 Firebase,所有已部署的流程都應設有授權政策;否則,任何人都能叫用可能成本高昂的生成式 AI 流程。如要定義授權政策,請在流程定義中使用 authPolicy 參數:

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

這項政策會使用 firebaseAuth() 輔助程式,只允許已註冊應用程式且電子郵件地址已驗證的使用者存取。在用戶端,您需要將 Authorization: Bearer 標頭設為符合政策的 Firebase ID 權杖。Cloud Functions 用戶端 SDK 提供可呼叫的函式方法,可自動執行這項操作。如需範例,請參閱「嘗試已部署的流程」一節。

將 API 憑證提供給已部署的資料流

部署後,流程需要透過某種方式,驗證所依賴的任何遠端服務。大多數流程至少需要憑證,才能存取所使用的模型 API 服務。

在本例中,請根據所選模型供應器執行下列任一操作:

Gemini (Google AI)

  1. 確認 Google AI 是否支援您的地區

  2. 使用 Google AI Studio 產生 Gemini API 的 API 金鑰

  3. 將 API 金鑰儲存在 Cloud Secret Manager 中:

    firebase functions:secrets:set GOOGLE_GENAI_API_KEY

    這項步驟非常重要,可避免 API 金鑰意外外洩,導致您無法存取可能會計費的服務。

    如要進一步瞭解如何管理機密資料,請參閱「儲存及存取機密設定資訊」。

  4. 編輯 src/index.ts,並在現有匯入內容後方新增以下內容:

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

    接著,在流程定義中宣告雲端函式需要存取這組密鑰值:

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

從現在開始,當您部署這個函式時,API 金鑰會儲存在 Cloud Secret Manager 中,並可從 Cloud Functions 環境取得。

Gemini (Vertex AI)

  1. 在 Cloud 控制台中,為 Firebase 專案啟用 Vertex AI API

  2. 在「IAM」頁面上,確認「預設運算服務帳戶」已獲授「Vertex AI 使用者」角色。

您只需要為本教學課程的模型供應商設定一個機密,但一般來說,您必須為流程使用的每項服務執行類似的操作。

設定 CORS 政策

如果您要透過網頁應用程式存取流程 (您將在「嘗試已部署的流程」一節中執行這項操作),請在 httpsOptions 參數中設定 CORS 政策:

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

您可能會為實際工作環境應用程式設定更嚴格的政策,但這項政策適用於本教學課程。

完整範例

完成上述所有變更後,可部署的工作流程會如下所示:

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. 將流程部署至 Firebase

使用 onFlow 定義流程後,您可以像部署其他 Cloud Functions 一樣部署流程:

cd $PROJECT_ROOT
firebase deploy --only functions

您現在已將流程部署為 Cloud 函式!但由於流程的授權政策,您無法使用 curl 或類似方式存取已部署的端點。請繼續閱讀下一節,瞭解如何安全存取流程。

選用步驟:試用已部署的流程

如要試用流程端點,您可以部署以下簡易的範例網頁應用程式:

  1. 在 Firebase 主控台的「專案設定」部分新增網頁應用程式,並選取設定託管服務的選項。

  2. 在 Firebase 控制台的「Authentication」部分中,啟用您在本例中要使用的 Google 供應商。

  3. 在專案目錄中設定 Firebase 託管服務,以便部署範例應用程式:

    cd $PROJECT_ROOT
    firebase init hosting

    接受所有提示訊息的預設值。

  4. public/index.html 替換為以下內容:

    <!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. 部署網頁應用程式和 Cloud 函式:

    cd $PROJECT_ROOT
    firebase deploy

開啟網頁應用程式,方法是造訪 deploy 指令列印的網址。應用程式會要求您使用 Google 帳戶登入,之後您才能發出端點要求。

選用:在開發人員 UI 中執行流程

您可以在開發人員 UI 中執行使用 onFlow 定義的流程,這與使用 defineFlow 定義的流程完全相同,因此在部署和開發作業之間不需要切換這兩者。

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

cd $PROJECT_ROOT/functions
npm run genkit:start

您現在可以前往 genkit start 指令顯示的網址存取內容。

選用:使用 Firebase 本機模擬器套件進行開發

Firebase 提供一系列本機開發模擬器,可搭配 Genkit 使用。

如要搭配 Firebase 模擬器套件使用 Genkit 開發人員 UI,請按照下列方式啟動 Firebase 模擬器:

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

這會在模擬器中執行程式碼,並在開發模式下執行 Genkit 架構,該模式會啟動並公開 Genkit 反射 API (但不會顯示開發人員 UI)。

如要在開發人員 UI 中查看 Firestore 的追蹤記錄,請前往「檢查」分頁,然後切換「開發人員/生產環境」切換鈕。切換至「prod」時,系統會從 Firestore 載入追蹤記錄。