将服务器端 Remote Config 与 Cloud Functions 和 Vertex AI 搭配使用

本指南介绍如何将第 2 代 Cloud Functions 函数服务器端 Remote Config 搭配使用来对 Vertex AI Gemini API 进行服务器端调用。

在本教程中,您需要将 Remote Config 添加到一个聊天机器人式函数,该函数将使用 Gemini 模型回答用户提出的问题。Remote Config 将负责管理 Gemini API 输入(包括您将附加到传入用户查询前面的提示),而您则可以从 Firebase 控制台按需更新这些输入。您还需要使用 Firebase Local Emulator Suite 测试并调试该函数,然后,在验证该函数有效之后,在 Google Cloud 上部署并测试该函数。

前提条件

本指南假定您熟悉如何使用 JavaScript 开发应用。

设置 Firebase 项目

如果您还没有 Firebase 项目,请执行以下操作

  1. 登录 Firebase 控制台

  2. 点击创建项目,然后使用以下任一方法:

    • 方法 1:在“创建项目”工作流的第一步中输入新项目名称,创建一个新的 Firebase 项目(该操作会自动创建相应的底层 Google Cloud 项目)。
    • 方法 2:在“创建项目”工作流的第一步中从下拉菜单中选择一个现有 Google Cloud 项目的名称,将 Firebase 添加到该现成的 Google Cloud 项目。
  3. 如果系统提示您是否要设置 Google Analytics,您无需进行此项设置即可使用本解决方案。

  4. 继续按照屏幕上的说明操作,创建您的项目。

如果您已有 Firebase 项目

继续配置开发环境

配置开发环境

您需要使用 Node.js 环境来编写函数,并且需要使用 Firebase CLI 将函数部署到 Cloud Functions 运行时。

  1. 安装 Node.jsnpm

    建议您使用 Node Version Manager 来安装 Node.js 和 npm

  2. 使用您偏好的方法安装 Firebase CLI。例如,若要使用 npm 安装 CLI,请运行以下命令:

    npm install -g firebase-tools@latest
    

    此命令会安装全局可用的 firebase 命令。如果此命令失败,您可能需要更改 npm 权限

    如需更新到最新版本的 firebase-tools,请重新运行这一命令。

  3. 安装 firebase-functionsfirebase-admin,并使用 --save 将它们保存到 package.json

    npm install firebase-functions@latest firebase-admin@latest --save
    

现在,您可以开始实现此解决方案了。

实现

请按照以下步骤创建、测试和部署第 2 代 Cloud Functions 函数,并将其与 Remote Config 和 Vertex AI 搭配使用:

  1. 在 Google Cloud 控制台中启用 Vertex AI 推荐的 API
  2. 初始化您的项目并安装 Node 依赖项
  3. 为您的 Admin SDK 服务账号配置 IAM 权限并保存您的密钥
  4. 创建函数
  5. 创建服务器专用的 Remote Config 模板
  6. 在 Firebase Local Emulator Suite 中部署并测试函数
  7. 将函数部署到 Google Cloud

第 1 步:在 Google Cloud 控制台中启用 Vertex AI 推荐的 API

  1. 打开 Google Cloud 控制台,当系统提示您选择项目时,选择所需的项目。
  2. 在控制台顶部的搜索字段中,输入 Vertex AI,然后等待 Vertex AI 作为结果出现。
  3. 选择 Vertex AI。随即会显示 Vertex AI 信息中心。
  4. 点击启用所有推荐的 API

    API 的启用过程可能需要一些时间才能完成。请将该页面保持打开并让其处于活跃状态,直到完成启用过程。

  5. 如果您尚未启用结算功能,系统会提示您添加或关联一个 Cloud Billing 账号。启用结算账号后,返回 Vertex AI 信息中心,并确认所有推荐的 API 均已启用。

第 2 步:初始化您的项目并安装 Node 依赖项

  1. 在您的计算机上打开一个终端并导航到计划要在其中创建函数的目录。
  2. 登录 Firebase:

    firebase login
    
  3. 运行以下命令以初始化 Cloud Functions for Firebase:

    firebase init functions
    
  4. 选择使用现有项目并指定您的项目 ID。

  5. 当系统提示您选择要使用的语言时,选择 JavaScript,然后按 Enter 键。

  6. 对于所有其他选项,选择默认值即可。

    系统会在当前目录中创建一个 functions 目录。在其中,您会找到一个 index.js 文件(用于构建函数)、一个 node_modules 目录(包含函数的依赖项)和一个 package.json 文件(包含软件包依赖项)。

  7. 运行以下命令添加 Admin SDK 和 Vertex AI 软件包,使用 --save 确保将它们保存到 package.json 文件中:

    cd functions
    npm install firebase-admin@latest @google-cloud/vertexai --save
    

现在,您的 functions/package.json 文件应如下所示,其中指定了最新版本的软件包:

  {
    "name": "functions",
    "description": "Cloud Functions for Firebase",
    "scripts": {
      "serve": "firebase emulators:start --only functions",
      "shell": "firebase functions:shell",
      "start": "npm run shell",
      "deploy": "firebase deploy --only functions",
      "logs": "firebase functions:log"
    },
    "engines": {
      "node": "20"
    },
    "main": "index.js",
    "dependencies": {
      "@google-cloud/vertexai": "^1.1.0",
      "firebase-admin": "^12.1.0",
      "firebase-functions": "^5.0.0"
    },
    "devDependencies": {
      "firebase-functions-test": "^3.1.0"
    },
    "private": true
  }

请注意,如果您在使用 ESLint,则会看到一个包含它的节。此外,请确保节点引擎版本与您安装的 Node.js 版本以及您最终在 Google Cloud 上运行的版本相匹配。例如,如果您的 package.json 中的 engines 节是配置为 Node 18 版,而您在使用的是 Node.js 20,请将该文件更新为使用 20 版:

  "engines": {
    "node": "20"
  },

第 3 步:为您的 Admin SDK 服务账号配置 IAM 权限并保存您的密钥

在本解决方案中,您需要使用 Firebase Admin SDK 服务账号来运行函数。

  1. 在 Google Cloud 控制台中,打开“IAM 和管理”页面,然后找到 Admin SDK 服务账号(名为 firebase-adminsdk)。
  2. 选择该账号,然后点击修改主账号。随即会显示“修改权限”页面。
  3. 点击添加其他角色,然后选择 Remote Config Viewer
  4. 点击添加其他角色,然后选择 AI Platform Developer
  5. 点击添加其他角色,然后选择 Vertex AI User
  6. 点击添加其他角色,然后选择 Cloud Run Invoker
  7. 点击保存

接下来,导出 Admin SDK 服务账号的凭据并将它们保存在您的 GOOGLE_APPLICATION_CREDENTIALS 环境变量中。

  1. 在 Google Cloud 控制台中,打开“凭据”页面
  2. 点击 Admin SDK 服务账号以打开“详细信息”页面。
  3. 点击密钥
  4. 依次点击添加密钥 > 创建新密钥
  5. 确保选择 JSON 作为密钥类型,然后点击创建
  6. 将密钥下载到计算机上安全的位置。
  7. 在终端中,将密钥导出为环境变量:

    export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account-key.json"
    

第 4 步:创建函数

在此步骤中,您将构建一个函数,用于处理用户输入并返回依托 AI 技术生成的回答。您将组合多个代码段来构建一个综合性的函数,该函数需要初始化 Admin SDK 和 Vertex AI Gemini API、使用 Remote Config 配置默认参数、获取最新的 Remote Config 参数、处理用户输入,并将回答流式传输回用户端。

  1. 在您的代码库中,通过文本编辑器或 IDE 打开 functions/index.js
  2. 删除现有内容,然后将以下代码粘贴到文件中,以添加 Admin SDK、Remote Config 和 Vertex AI SDK 并初始化应用:

    const { onRequest } = require("firebase-functions/v2/https");
    const logger = require("firebase-functions/logger");
    
    const { initializeApp } = require("firebase-admin/app");
    const { VertexAI } = require('@google-cloud/vertexai');
    const { getRemoteConfig } = require("firebase-admin/remote-config");
    
    // Set and check environment variables.
    const project = process.env.GCLOUD_PROJECT;
    
    // Initialize Firebase.
    const app = initializeApp();
    
  3. 为您的函数配置默认值,以便函数在无法连接到 Remote Config 服务器时可以使用这些默认值。本解决方案需要配置 textModelgenerationConfigsafetySettingstextPromptlocation 作为 Remote Config 参数,这些也是您将在本指南中进一步配置的 Remote Config 参数。如需详细了解这些参数,请参阅 Vertex AI Node.js 客户端

    另外,您还可以配置一个参数来控制是否要使用 Vertex AI Gemini API(在本示例中,是通过一个名为 vertex_enabled 的参数来实现该控制)。此设置在测试函数时非常有用。在下面的代码段中,这个值被设为 false,这意味着,在您测试基本函数部署时将不会使用 Vertex AI。但如果将其设为 true,则会调用 Vertex AI Gemini API。

    // Define default (fallback) parameter values for Remote Config.
    const defaultConfig = {
    
      // Default values for Vertex AI.
      model_name: "gemini-1.5-flash-preview-0514",
      generation_config: [{
        "stopSequences": [], "temperature": 0.7,
        "maxOutputTokens": 64, "topP": 0.1, "topK": 20
      }],
      prompt: "I'm a developer who wants to learn about Firebase and you are a \
        helpful assistant who knows everything there is to know about Firebase!",
      safety_settings: [{
        "category":
          "HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT",
        "threshold": "HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE"
      }],
      location: 'us-central1',
    
      // Disable Vertex AI Gemini API access for testing.
      vertex_enabled: false
    };
    
  4. 创建函数并设置服务器端 Remote Config

    // Export the function.
    exports.generateWithVertex = onRequest(async (request, response) => {
    
      try {
    
        // Set up Remote Config.
        const rc = getRemoteConfig(app);
    
        // Get the Remote Config template and assign default values.
        const template = await rc.getServerTemplate({
          defaultConfig: defaultConfig
        });
    
        // Add the template evaluation to a constant.
        const config = template.evaluate();
    
        // Obtain values from Remote Config.
        const textModel = config.getString("model_name") ||
            defaultConfig.model_name;
        const textPrompt = config.getString("prompt") || defaultConfig.prompt;
        const generationConfig = config.getString("generation_config") ||
            defaultConfig.generation_config;
        const safetySettings = config.getString("safety_settings") ||
            defaultConfig.safety_settings;
        const location = config.getString("location") ||
            defaultConfig.location;
        const vertexEnabled = config.getBoolean("is_vertex_enabled") ||
            defaultConfig.vertex_enabled;
    
  5. 设置 Vertex AI 并添加对话和回答逻辑:

      // Allow user input.
      const userInput = request.query.prompt || '';
    
      // Instantiate Vertex AI.
        const vertex_ai = new VertexAI({ project: project, location: location });
        const generativeModel = vertex_ai.getGenerativeModel({
          model: textModel,
          safety_settings: safetySettings,
          generation_config: generationConfig,
        });
    
        // Combine prompt from Remote Config with optional user input.
        const chatInput = textPrompt + " " + userInput;
    
        if (!chatInput) {
          return res.status(400).send('Missing text prompt');
        }
        // If vertexEnabled isn't true, do not send queries to Vertex AI.
        if (vertexEnabled !== true) {
          response.status(200).send({
            message: "Vertex AI call skipped. Vertex is not enabled."
          });
          return;
        }
    
        logger.log("\nRunning with model ", textModel, ", prompt: ", textPrompt,
          ", generationConfig: ", generationConfig, ", safetySettings: ",
          safetySettings, " in ", location, "\n");
    
        const result = await generativeModel.generateContentStream(chatInput); 
        response.writeHead(200, { 'Content-Type': 'text/plain' });
    
        for await (const item of result.stream) {
          const chunk = item.candidates[0].content.parts[0].text;
          logger.log("Received chunk:", chunk);
          response.write(chunk);
        }
    
        response.end();
    
      } catch (error) {
        logger.error(error);
        response.status(500).send('Internal server error');
      }
    });
    
  6. 保存并关闭文件。

第 5 步:创建服务器专用的 Remote Config 模板

接下来,创建一个服务器端 Remote Config 模板,并配置要在函数中使用的参数和值。如需创建服务器专用的 Remote Config 模板,请执行以下操作:

  1. 打开 Firebase 控制台,然后从导航菜单中展开运行并选择 Remote Config
  2. 从 Remote Config 页面顶部的客户端/服务器选择器中,选择服务器

    • 如果您是首次使用 Remote Config 或服务器模板,请点击创建配置。随即会出现创建您的首个服务器端参数窗格。
    • 如果您不是首次使用 Remote Config 服务器模板,请点击添加参数
  3. 定义以下 Remote Config 参数:

    参数名称 说明 类型 默认值
    model_name 模型名称
    有关在代码中使用的模型名称的最新列表,请参阅模型版本和生命周期可用模型名称
    字符串 gemini-1.5-pro-preview-0514
    prompt 要附加到用户查询前面的提示。 字符串 I'm a developer who wants to learn about Firebase and you are a helpful assistant who knows everything there is to know about Firebase!
    generation_config 要发送到模型的参数 JSON [{"stopSequences": ["I hope this helps"],"temperature": 0.7,"maxOutputTokens": 512, "topP": 0.1,"topK": 20}]
    safety_settings Vertex AI 的安全设置 JSON [{"category": "HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "HarmBlockThreshold.BLOCK_LOW_AND_ABOVE"}]
    location 要运行 Vertex AI 服务和模型的位置 字符串 us-central1
    is_vertex_enabled 可选参数,用于控制是否将查询发送到 Vertex AI。 布尔值 true
  4. 添加完参数后,请仔细检查参数及其数据类型是否正确无误,然后点击发布更改

第 6 步:在 Firebase Local Emulator Suite 中部署并测试函数

现在,您便可以使用 Firebase Local Emulator Suite 在本地部署并测试您的函数。

  1. 确保您已将 GOOGLE_APPLICATION_CREDENTIALS 设置为环境变量,如第 3 步:为您的 Admin SDK 服务账号配置 IAM 权限并保存您的密钥中所述。然后,从 functions 目录的父级目录中,将函数部署到 Firebase 模拟器:

    firebase emulators:start --project PROJECT_ID --only functions
    
  2. 打开模拟器的日志页面。该日志应会显示您的函数已加载。

  3. 通过运行以下命令访问您的函数,其中,PROJECT_ID 是您的项目 ID,LOCATION 是您部署函数的区域(例如 us-central1):

    curl http://localhost:5001/PROJECT_ID/LOCATION/generateWithVertex
    
  4. 等待响应,然后返回到 Firebase 模拟器日志页面或控制台,检查是否有任何错误或警告。

  5. 尝试发送一些用户输入,请注意,由于您的 Remote Config 服务器模板中配置了 is_vertex_enabled,因此会通过 Vertex AI Gemini API 使用 Gemini,而这可能会产生一定费用:

    curl http://localhost:5001/PROJECT_ID/LOCATION/generateWithVertex?prompt=Tell%20me%20everything%20you%20know%20about%20cats
    
  6. 在 Firebase 控制台中对您的 Remote Config 服务器模板做出一些更改,然后再次使用您的函数,看看有哪些变化。

第 7 步:将函数部署到 Google Cloud

测试并验证函数后,您就可以将实际的函数部署到 Google Cloud 并对其执行测试。

部署函数

使用 Firebase CLI 部署您的函数:

firebase deploy --only functions

禁止对函数进行未经身份验证的访问

当函数是使用 Firebase 进行部署时,如果您的组织政策没有另外做出限制,默认是允许对函数进行未经身份验证的调用。在测试期间以及在您使用 App Check 确保数据安全之前,建议您禁止未经身份验证的访问。

如要禁止对函数进行未经身份验证的访问,请执行以下操作:

  1. 在 Google Cloud 控制台中,打开 Cloud Run

  2. 点击 generateWithVertex,然后点击安全标签页。

  3. 启用要求进行身份验证,然后点击保存

将您的用户账号配置为使用 Admin SDK 服务账号凭据

由于 Admin SDK 服务账号拥有运行函数并与 Remote Config 和 Vertex AI Gemini API 交互所需的所有必要角色和权限,因此您需要使用它来运行您的函数。为此,您必须能够通过自己的用户账号为该服务账号创建令牌。

以下步骤介绍了如何将您的用户账号以及您创建的函数配置为使用 Admin SDK 服务账号权限来运行。

  1. 在 Google Cloud 控制台中,启用 IAM Service Account Credentials API
  2. 为您的用户账号授予 Service Account Token Creator 角色:从 Google Cloud 控制台中,依次打开 IAM 和管理 > IAM,选择您的用户账号,然后依次点击修改主账号 > 添加其他角色
  3. 选择 Service Account Token Creator,然后点击保存

    如需详细了解服务账号模拟,请参阅 Google Cloud 文档中的服务账号模拟部分。

  4. 打开 Google Cloud 控制台中的 Cloud Functions 页面,然后点击函数列表中的 generateWithVertex 函数。

  5. 依次选择触发器 > 修改,然后展开运行时、构建、连接和安全设置

  6. 运行时标签页中,将运行时服务账号更改为 Admin SDK 账号

  7. 点击下一步,然后点击部署

设置 gcloud CLI

如要通过命令行安全地运行和测试您的函数,您需要向 Cloud Functions 服务进行身份验证并获取有效的身份验证令牌。

如要能够生成令牌,您需要安装并配置 gcloud CLI:

  1. 如果您尚未在自己的计算机上安装 gcloud CLI,请按照安装 gcloud CLI 中的说明安装 gcloud CLI。

  2. 获取您的 Google Cloud 账号的访问凭据:

    gcloud auth login
    
  3. 在 gcloud 中设置您的项目 ID:

    gcloud config set project PROJECT_ID
    

测试函数

现在,您便可以在 Google Cloud 中测试您的函数。如需测试函数,请运行以下命令:

curl -X POST https://LOCATION-PROJECT_ID.cloudfunctions.net/generateWithVertex \
  -H "Authorization: bearer $(gcloud auth print-identity-token)" \
  -H "Content-Type: application/json"

使用用户提供的数据再次运行该命令:

curl -X POST https://LOCATION-PROJECT_ID.cloudfunctions.net/generateWithVertex?prompt=Tell%20me%20everything%20you%20know%20about%20dogs \
 -H "Authorization: bearer $(gcloud auth print-identity-token)" \
 -H "Content-Type: application/json"

现在,您可以对您的 Remote Config 服务器模板做出一些更改并发布这些更改,以测试不同的配置选项。

后续步骤