1. 简介
您是否喜欢钻研书籍,却困于繁杂的海量图书选择?假设有一款 AI 赋能的应用,它不仅能推荐理想的读物,还会根据您选择的图书类型提供简明摘要,让您快速掌握书本的精髓。在此 Codelab 中,我将逐步介绍如何在 Gemini 的助力下使用 BigQuery 和 Cloud Functions 构建此类应用。
项目概览
我们的应用场景围绕以下 4 个关键组件展开:
- Book Database:这是一个庞大的互联网归档图书 BigQuery 公共数据集,将作为全面的图书目录。
- AI Summarization Engine:这是一个 Google Cloud Functions 函数,配有 Gemini-Pro 语言模型,可根据用户请求生成富有见地的图书摘要。
- BigQuery Integration:BigQuery 中的远程函数,可调用 Cloud Functions 函数,以便按需提供图书摘要和主题。
- 用户界面:托管在 Cloud Run 上的 Web 应用,可供用户查看结果。
我们将实现代码分为 3 个 Codelab:
Codelab 1:使用 Gemini 为 Gemini 应用构建 Java Cloud Functions 函数。
Codelab 2:使用 Gemini 通过 BigQuery 构建仅限 SQL 的生成式 AI 应用。
Codelab 3:使用 Gemini 创建与 BigQuery 进行交互的 Java Spring Boot Web 应用。
2. 使用 Gemini 在 Java Cloud Functions 上以无服务器方式构建生成式 AI 应用
构建内容
您将创建一个
- Java Cloud Functions 应用,可实现 Gemini 1.0 Pro 以 JSON 数组形式接受特定提示作为输入,并返回响应(标记为“replies”的 JSON 值)。
- 您将在 Gemini 的帮助下完成构建和部署步骤
3. 要求
以下是前提条件:
创建项目
- 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。
- 确保您的 Cloud 项目已启用结算功能。了解如何检查项目是否已启用结算功能。
激活 Cloud Shell
- 您将使用 Cloud Shell,这是一个在 Google Cloud 中运行的命令行环境,它预加载了 bq:
在 Cloud 控制台中,点击右上角的“激活 Cloud Shell”:
- 在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且项目已设置为您的项目 ID。在 Cloud Shell 中运行以下命令,以确认您已通过身份验证:
gcloud auth list
- 在 Cloud Shell 中运行以下命令,以确认 gcloud 命令了解您的项目
gcloud config list project
- 如果项目未设置,请使用以下命令进行设置:
gcloud config set project <YOUR_PROJECT_ID>
如需了解 gcloud 命令和用法,请参阅文档。
4. 启用 Gemini for Google Cloud 和必要的 API
启用 Gemini
- 前往 Marketplace 中的 Gemini for Google Cloud 启用该 API。您还可以使用以下命令:
gcloud services enable cloudaicompanion.googleapis.com --project PROJECT_ID
- 访问 Gemini 页面,然后点击“开始聊天”。
重要提示:请按照此 Codelab 中的第 1 步和第 2 步操作,分别开始使用 Gemini 并在 Cloud Shell IDE 中启用 Gemini。
启用其他必要的 API
我们该怎么做呢?让我们来问问 Gemini 吧。但在此之前,请记住:
LLM 具有不确定性。因此,在您尝试提出这些问题时,您收到的回答可能与我的屏幕截图中的回答有所不同。
点击右上角的“打开 Gemini”图标(位于 Google Cloud 控制台搜索栏旁边),前往 Gemini Chat 控制台。

在“在此处输入提示”部分输入以下问题:
How do I enable the cloud functions api using a gcloud command?
您应该会收到类似如下的响应:
gcloud services enable cloudfunctions.googleapis.com
复制该命令(您可以使用命令代码段顶部的复制图标),并在 Cloud Shell 终端中运行,以便启用 Cloud Functions。对 Cloud Run 执行相同的操作,因为我们需要这两个服务来构建和部署 Cloud Functions 函数:
gcloud services enable \
cloudfunctions.googleapis.com \
aiplatform.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com
5. 使用 Gemini 准备 Cloud Functions 模板
在此阶段,我假设您已在 Cloud Shell IDE 中启用 Gemini。
点击 Cloud Shell 终端右上角的“打开编辑器”图标,打开 Cloud Shell 编辑器(我通常更喜欢在单独的标签页中并行打开终端和编辑器,以便在一个标签页中编写代码,在另一个标签页中构建)。

打开编辑器后,确保编辑器控制台右下角的 Gemini 徽标处于有效状态(而非取消状态)。此外,确保左下角的 Google Cloud 项目指向您当前想要处理的有效项目。如果它们处于无效状态,请点击进行授权,选择您要指向的 Google Cloud 项目并将其激活。
两者都处于有效状态后,点击左下角的项目名称,在随即打开的名为“Cloud Code”的弹出式列表中向下滚动到“新应用”。

在该列表中,选择“Cloud Functions 应用”。从弹出的列表中选择“Java”:

在结果列表中,输入项目名称“duetai-gemini-calling”而不是“helloworld”,然后点击“确定”。

太棒了!您已在简单的 Java Cloud Functions 应用中启用 Gemini 引导功能,除了启用和激活配置之外,您并没进行太多操作,对吧?
您应该会看到以下项目结构:

现在,您就可以部署函数了。但这并非我们开始这项工作的原因。接下来,我们使用 Java SDK 在此 Cloud Functions 函数中构建 Gemini Pro API 实现。
现在,我们来构建相应功能,以便在此 Cloud Functions 中调用 Gemini Pro 模型。为此,您可以添加更多提示,并使用 Gemini 逐步开发代码,也可以自行编写逻辑。我会同时采用这两种方法。
6. 添加依赖项
在 Gemini 对话控制台(位于 Cloud Code 编辑器左侧窗格中)中,输入以下提示:
what is the maven dependency for com.google.cloud.vertexai library
我之所以专门询问 com.google.cloud.vertexai 软件包,是因为我在实现 Gemini 调用代码的源代码中使用了该软件包。
我得到了以下结果:

<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-vertexai</artifactId>
<version>0.1.0</version>
</dependency>
复制此内容并将其粘贴到 pom.xml 文件中,位于 </dependencies> 标记的前面。将版本替换为 0.1.0(如果您使用 Spring Cloud GCP BOM 为您管理 spring-cloud-gcp 版本号,则可以移除 <version> 标记)。
依赖项部分应如下所示:

请务必根据需要更新版本号,使其与上述版本号一致。如果您仔细观察,会发现我还添加了另一个依赖项:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10</version>
</dependency>
7. 修改函数入口点和类名称
- 前往“.vscode”文件夹下的“launch.json”文件。将函数名称从“function-hello-world”修改为“function-gemini-calling”。
- 将 entryPoint 值从“cloudcode.helloworld.HelloWorld”更新为“cloudcode.bookshelf.Bookshelf”。
- 现在,前往 Java 类文件“HelloWorld.java”。将软件包名称更改为 package cloudcode.bookshelf;在弹出的错误中,点击黄色灯泡,然后点击显示“将 HelloWorld.java 移至软件包 cloudcode.bookshelf”的选项。

- 将类名称更新为 Bookshelf,然后在弹出的错误中点击黄色小灯泡,并选择“将文件重命名为 Bookshelf.java”。选择该选项。
8. 创建调用 Gemini Pro 的方法
我们将在 Bookshelf.java 类中实现此功能。将您的 Bookshelf.java 替换为以下代码:
package cloudcode.bookshelf;
import java.io.BufferedWriter;
import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.cloud.vertexai.VertexAI;
import com.google.cloud.vertexai.api.GenerateContentResponse;
import com.google.cloud.vertexai.api.GenerationConfig;
import com.google.cloud.vertexai.generativeai.preview.GenerativeModel;
import com.google.cloud.vertexai.generativeai.preview.ResponseHandler;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import java.util.Map;
import java.util.LinkedHashMap;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;
public class Bookshelf implements HttpFunction {
private static final Gson gson = new Gson();
@Override
public void service(HttpRequest request, HttpResponse response) throws Exception {
BufferedWriter writer = response.getWriter();
// Get the request body as a JSON object.
JsonObject requestJson = new Gson().fromJson(request.getReader(), JsonObject.class);
JsonArray calls_array = requestJson.getAsJsonArray("calls");
JsonArray calls = (JsonArray) calls_array.get(0);
String context = calls.get(0).toString().replace("\"", "");
//Invoke Gemini model
String raw_result = callGemini(context);
raw_result = raw_result.replace("\n","");
String trimmed = raw_result.trim();
List<String> result_list = Arrays.asList(trimmed);
Map<String, List<String>> stringMap = new LinkedHashMap<>();
stringMap.put("replies", result_list);
// Serialization
String return_value = gson.toJson(stringMap);
writer.write(return_value);
}
public String callGemini(String context) throws IOException{
String res = "";
try (VertexAI vertexAi = new VertexAI("REPLACE_WITH_YOUR_PROJECT_ID", "us-central1"); ) {
GenerationConfig generationConfig =
GenerationConfig.newBuilder()
.setMaxOutputTokens(2048)
.setTemperature(0.4F)
.setTopK(32)
.setTopP(1)
.build();
GenerativeModel model = new GenerativeModel("gemini-pro", generationConfig, vertexAi);
GenerateContentResponse response = model.generateContent(context);
res = ResponseHandler.getText(response);
}catch(Exception e){
System.out.println(e);
}
return res;
}
}
此类需要采用以下 JSON 结构作为输入:
{ "calls": [["YOUR_PROMPT_HERE"]] }
系统会返回如下所示的响应:
(Json) Map<String, List<String>> {"replies": ["response"]}
在左侧窗格的 Cloud Shell 编辑器中试用 Gemini 对话选项,以解释代码。或者,您也可以选择所有代码,然后点击所选内容左上角的黄色灯泡,并选择“解释此内容”选项。

9. 部署 Cloud Functions 函数
现在,Cloud Functions 函数已准备就绪,我们来问问 Gemini 如何部署它。前往 Cloud Code 代码编辑器中的 Gemini 对话,然后输入以下内容:
How to deploy this Cloud Function with a gcloud command?
我收到了以下回答:

我现在想进一步探究。因此,我让 Gemini 提供了完整的 gcloud functions deploy 命令。响应如下所示:

我无法确定您是否会收到相同的回答,但令我惊讶的是,我发现它还补充了一些细节,如下图所示:
请求正文格式:

和
回答格式:

现在,我们运行 Gemini 给出的 gcloud 命令来部署函数。为此,我们需要打开 Cloud Shell 终端。您可以在新标签页中打开 https://console.cloud.google.com,并确保已选择正确的项目。点击控制台右上角的“激活 Cloud Shell”图标,打开 Cloud Shell 终端,然后使用以下命令确保您位于正确的项目文件夹中:
cd duetai-gemini-calling
然后运行以下命令:
gcloud functions deploy bookshelf --runtime java17 --trigger-http --entry-point cloudcode.bookshelf.Bookshelf --allow-unauthenticated
系统会询问您“是否允许对新函数 [bookshelf] 进行未经身份验证的调用?”输入“y”,然后按 Enter 键。之后,系统会询问几个问题(如果适用),然后部署您的无服务器 Cloud Functions,并提供已部署的网址:https://us-central1-*******.cloudfunctions.net/bookshelf。
现在,我们来调用已部署的 Cloud Functions 函数并对其进行测试!
注意:如果您不小心跳过了“允许未经身份验证的调用”问题或选择了“N”,那么在未授予其他 IAM 设置的情况下,您将无法访问 Cloud Functions 的结果,并且会看到“权限错误”。因此,请注意这一点。
10. 调用已部署的 Cloud Functions 函数
我们来问问 Gemini 吧。我输入了提示
How to call the deployed cloud function?
我得到了以下结果:(您可能会看到完全相同的回答,也可能不会,请随意尝试不同的提示,看看回答有何不同)。

围绕调用已部署函数的替代方法、使用 gcloud 命令进行调用等提出具体问题,对聊天机器人进行测试。我提交了以下提示:
how to call the deployed cloud function using gcloud
我收到了以下回答:
您可以对终端中的此响应(“gcloud functions call”命令)进行调整,使其适用于我们的场景(或者,尝试在提示本身中传递参数,看看您是否能够获得详细的“gcloud functions call”响应):
gcloud functions call bookshelf --region=us-central1 --gen2 --data '{"calls":[["Hello! This is my test prompt."]]}'
我的结果如下:

11. 清理
您可以点击 Cloud Functions 详情页面中的“删除”按钮,删除之前创建的 Cloud Functions。
12. 恭喜
您已成功构建、部署并测试了一个 Java Cloud Functions 函数,该函数可使用 Gemini 调用 Gemini 1.0 Pro!此应用会获取与图书推荐相关的输入提示,其中包含图书的摘要和主题。