将服务器端 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 步:初始化您的项目并安装 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 控制台,从导航菜单中展开 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. 请确保您已将 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,然后点击 Security(安全)标签页。

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

后续步骤