将服务器端 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.js 和 npm,建议您使用 Node Version Manager

  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
    

现在,您可以继续进行此解决方案的实现

实现

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

  1. 在 Google Cloud 控制台中启用 Vertex AI 推荐 API
  2. 初始化您的项目并安装节点依赖项
  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 步:初始化您的项目并安装节点依赖项

  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. 运行以下命令,使用 --save 添加 Admin SDK 和 Vertex AI 软件包,以确保将其保存到 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,则会看到包含它的 stanza。此外,请确保节点引擎版本与已安装的 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 控制台,从导航菜单中展开 Run,然后选择 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. 确保您已按照第 3 步:为您的 Admin SDK 服务帐号配置 IAM 权限并保存密钥中所述,将 GOOGLE_APPLICATION_CREDENTIALS 设置为环境变量。然后,从 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 中的说明进行安装。

  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 服务器模板,发布这些更改,并测试不同的选项。

后续步骤