Genkit 与 Cloud Functions for Firebase

Firebase Genkit 包含一个插件,可帮助您将流部署到 Firebase Cloud Functions以此页面为例,它会引导您完成 将默认示例流部署到 Firebase。

将流部署为 Cloud Functions 函数

  1. 安装所需的工具:

    1. 确保您使用的是 Node.js 20 或更高版本(请运行 node --version 以 检查)。

    2. 安装 Firebase CLI

  2. 使用 Firebase 控制台创建一个新的 Firebase 项目,或者选择一个现有的项目。

    将项目升级到部署 Cloud 所需的 Blaze 方案 函数。

  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. 使用文件夹中的 Genkit 初始化 Firebase 项目:

    cd $PROJECT_ROOT
    firebase init genkit
    
    • 选择您之前创建的项目。
    • 选择要使用的模型提供方。

    对于其余提示,接受默认设置即可。genkit 工具将创建 一些示例源文件,可帮助您开始开发自己的 AI 流程。 不过,在本教程的其余部分,您只需部署示例 flow 即可。

  6. 将 API 凭据提供给您的 Cloud Functions 函数。根据您选择的模型提供方,执行以下操作之一:

    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 密钥非常重要 该角色会授予对可能按流量计费的服务的访问权限。

      请参阅存储和访问敏感配置信息 如需详细了解如何管理 Secret。

    4. 修改 src/index.ts,并在现有导入代码后添加以下代码:

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

      然后,在流定义中,声明 Cloud Functions 函数需要 访问此 Secret 值的权限:

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

    现在,当您部署此函数时,您的 API 密钥将存储在 Cloud Secret Manager,可通过 Cloud Functions 函数获取 环境

    Gemini (Vertex AI)

    1. 在 Cloud 控制台中 启用 Vertex AI API 创建项目

    2. IAM 页面上,确保为默认计算服务账号授予 Vertex AI User 角色。

    在本教程中,您只需要为模型提供方设置 Secret,但一般来说,您必须为 flow 使用的每项服务执行类似的操作。

  7. 如果您要从 Web 应用(您将在 在 httpsOptions 参数中,设置 CORS 政策:

    export const menuSuggestionFlow = onFlow(
      {
        name: "menuSuggestionFlow",
        // ...
        httpsOptions: {
          cors: true,  // Add this line.
        },
      },
      async (subject) => {
        // ...
      }
    );
    

    您可能希望为正式版应用制定更严格的政策 将对本教程执行的操作

  8. 可选:在开发者界面中试用 flow:

    1. 将 API 凭据设置为可在本地使用。执行以下其中一项操作: 具体取决于您选择的模型提供商:

      Gemini (Google AI)

      GOOGLE_GENAI_API_KEY 环境变量设置为您的密钥:

      export GOOGLE_GENAI_API_KEY=<your API key>
      

      Gemini (Vertex AI)

      设置一些额外的环境变量,并使用 gcloud 工具进行设置 本地应用默认凭据:

      export GCLOUD_PROJECT=<your project ID>
      export GCLOUD_LOCATION=us-central1
      gcloud auth application-default login
      
    2. 启动界面:

      cd $PROJECT_ROOT/functions
      genkit start
      
    3. 在开发者界面 (http://localhost:4000/) 中,运行 flow:

      1. 点击 menuSuggestionFlow

      2. 输入 JSON 标签页上,为模型提供一个主题:

        "AI app developers"
        
      3. Auth JSON 标签页上,提供一个模拟的 auth 对象:

        {
          "uid": 0,
          "email_verified": true
        }
        
      4. 点击运行

  9. 如果到目前为止一切正常,您就可以部署该数据流:

    cd $PROJECT_ROOT
    firebase deploy --only functions
    

现在,您已将该流部署为 Cloud Functions 函数!但是,您将无法 使用 curl 或类似方法访问已部署的端点, 授权政策。继续阅读下一部分,了解如何安全地 访问该流程。

尝试部署的流程

您部署的每个流程都必须设置授权政策,这一点至关重要。不包含 第一,你可以调用可能很昂贵的生成式 AI 流程, 任何人。

默认示例流程的授权政策如下所示:

firebaseAuth((user) => {
  if (!user.email_verified) {
    throw new Error('Verified email required to run flow');
  }
});

此政策使用 firebaseAuth() 帮助程序仅允许已注册的内容进行访问 拥有经过验证的电子邮件地址的应用用户。在客户端,您需要 将 Authorization: Bearer 标头设置为符合以下要求的 Firebase ID 令牌: 您的政策。Cloud Functions 客户端 SDK 提供 Callable 函数 自动执行此操作的方法。

如需试用流端点,您可以部署以下极简示例 Web app:

  1. 项目设置 部分,添加新的 Web 应用,然后选择 还设置了 Hosting

  2. 身份验证 部分,启用 Google 提供方 示例。

  3. 在项目目录中设置 Firebase Hosting,您将在其中部署 示例应用:

    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="suggestMenuItem">Suggest a menu theme</button>
          <p id="menuItem"></p>
        </div>
        <script type="module">
          import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.10.0/firebase-app.js';
          import {
            getAuth,
            onAuthStateChanged,
            GoogleAuthProvider,
            signInWithPopup,
          } from 'https://www.gstatic.com/firebasejs/10.10.0/firebase-auth.js';
          import {
            getFunctions,
            httpsCallable,
          } from 'https://www.gstatic.com/firebasejs/10.10.0/firebase-functions.js';
    
          const firebaseConfig = await fetch('/__/firebase/init.json');
          initializeApp(await firebaseConfig.json());
    
          async function generateMenuItem() {
            const menuSuggestionFlow = httpsCallable(
              getFunctions(),
              'menuSuggestionFlow'
            );
            const subject = document.querySelector('#subject').value;
            const response = await menuSuggestionFlow(subject);
            document.querySelector('#menuItem').innerText = response.data;
          }
    
          function signIn() {
            signInWithPopup(getAuth(), new GoogleAuthProvider());
          }
    
          document
            .querySelector('#signinBtn')
            .addEventListener('click', signIn);
          document
            .querySelector('#suggestMenuItem')
            .addEventListener('click', generateMenuItem);
    
          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. 部署 Web 应用和 Cloud Functions 函数:

    cd $PROJECT_ROOT
    firebase deploy
    

通过访问 deploy 命令输出的网址打开 Web 应用。应用 您需要使用 Google 账号登录,然后才可以启动 端点请求

使用 Firebase Local Emulator Suite 进行开发

Firebase 提供了一套用于本地开发的模拟器,您可以将其与 Genkit 搭配使用。

如需将 Genkit 与 Firebase Emulator Suite 搭配使用,请按如下方式启动 Firebase 模拟器:

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

这将在模拟器中运行您的代码,并在开发模式下运行 Genkit 框架,这将启动和公开 Genkit 反射 API(而不是开发界面)。

然后,使用 --attach 选项启动 Genkit Dev UI,将其连接到在 Firebase 模拟器中运行的代码:

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

如需在开发界面中查看来自 Firestore 的跟踪记录,您可以前往“Inspect”(检查)标签页,然后切换“Dev/Prod”(开发/生产)。切换为“生产”时它将从 Firestore 加载轨迹。