使用 Firestore、Vector Search 和 Gemini 2.0(Java 版)构建上下文瑜伽姿势推荐应用!

1. 概览

在健康和健身应用领域,为用户提供丰富而引人入胜的体验至关重要。对于瑜伽应用,这意味着不仅要提供简单的姿势文字说明,还要提供全面的信息、多媒体内容和智能搜索功能。在这篇博文中,我们将探讨如何使用 Google Cloud 的 Firestore 构建强大的瑜伽姿势数据库,如何利用其 Vector Search 扩展程序进行情境匹配,以及如何集成 Gemini 2.0 Flash(实验版)的强大功能来处理多模态内容。

为什么选择 Firestore?

Firestore 是 Google Cloud 的无服务器 NoSQL 文档数据库,非常适合用于构建可扩缩的动态应用。以下是它非常适合我们的瑜伽应用的原因:

  • 可伸缩性和性能:Firestore 可自动扩缩以处理数百万用户和海量数据集,确保您的应用即使在不断增长的情况下也能保持响应速度。
  • 实时更新:内置的实时同步功能可确保所有关联的客户端上的数据保持一致,非常适合实时课程或协作练习等功能。
  • 灵活的数据模型:Firestore 基于文档的结构可让您存储各种数据类型,包括文本、图片,甚至嵌入内容,非常适合表示复杂的瑜伽姿势信息。
  • 强大的查询功能:Firestore 支持复杂的查询,包括等值查询、不等值查询,以及现在通过新扩展程序支持的向量相似度搜索
  • 离线支持:Firestore 会在本地缓存数据,让您的应用即使在用户离线时也能正常运行。

使用 Firestore Vector Search 扩展程序增强搜索功能

在处理瑜伽姿势等复杂概念时,传统的基于关键字的搜索可能会受到限制。用户可能想搜索“打开髋部”或“改善平衡”的姿势,但不知道具体姿势名称。这时,向量搜索就派上用场了。

借助与 Firestore 集成的 Vector Search,您可以:

  • 生成嵌入:使用 Vertex AI 中提供的模型或自定义模型,将文本说明(未来可能还包括图片和音频)转换为可捕捉其语义含义的数值向量表示形式(嵌入)。
  • 存储嵌入:直接将这些嵌入存储在 Firestore 文档中。
  • 执行相似度搜索:查询数据库以查找与给定查询向量在语义上相似的文档,从而实现上下文匹配。

集成 Gemini 2.0 Flash(实验版)

Gemini 2.0 Flash 是 Google 最先进的多模态 AI 模型。虽然仍处于实验阶段,但它为丰富我们的瑜伽应用提供了令人兴奋的可能性:

  • 文本生成:使用 Gemini 2.0 Flash 生成瑜伽体式的详细说明,包括益处、调整和禁忌症。
  • 图片生成(模拟):虽然直接使用 Gemini 生成图片的功能尚未公开提供,但我已使用 Google 的 Imagen 模拟了此功能,生成了直观展示姿势的图片。
  • 音频生成(模仿):同样,我们可以使用文字转语音 (TTS) 服务为每个姿势创建音频指令,引导用户完成练习。

我设想提出集成建议,以增强应用,使其能够使用模型的以下功能:

  • Multimodal Live API:借助这一新的 API,您可以创建支持工具使用的实时视觉和音频流式传输应用。
  • 速度和性能:与 Gemini 1.5 Flash 相比,Gemini 2.0 Flash 的首个令牌生成时间 (TTFT) 大幅缩短。
  • 改进了智能体体验:Gemini 2.0 改进了多模态理解、编码、复杂指令遵从和函数调用功能。这些改进相辅相成,可支持更好的智能体体验。

如需了解详情,请参阅这篇关于 Gemini 1.5 Flash 的文档页面

为了提高可信度并提供更多资源,我们可以集成 Google 搜索来为应用提供的信息建立依据。这意味着:

  • 情境搜索:当管理员用户输入姿势的详细信息时,我们可以使用姿势名称执行 Google 搜索。
  • 网址提取:我们可以从搜索结果中提取相关网址(例如文章、视频或信誉良好的瑜伽网站),并在应用内显示这些网址。

构建内容

在本实验中,您将:

  1. 创建 Firestore 集合并加载瑜伽文档
  2. 了解如何使用 Firestore 创建 CRUD 应用
  3. 使用 Gemini 2.0 Flash 生成瑜伽姿势说明
  4. 启用与 Firestore 集成的 Firebase 向量搜索功能
  5. 根据瑜伽说明生成嵌入
  6. 针对用户搜索文本执行相似度搜索

要求

  • 一个浏览器,例如 ChromeFirefox
  • 启用了结算功能的 Google Cloud 项目。

2. 准备工作

创建项目

  1. Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目
  2. 确保您的 Cloud 项目已启用结算功能。了解如何检查项目是否已启用结算功能
  3. 您将使用 Cloud Shell,这是一个在 Google Cloud 中运行的命令行环境,它预加载了 bq。点击 Google Cloud 控制台顶部的“激活 Cloud Shell”。

“激活 Cloud Shell”按钮图片

  1. 连接到 Cloud Shell 后,您可以使用以下命令检查自己是否已通过身份验证,以及项目是否已设置为您的项目 ID:
gcloud auth list
  1. 在 Cloud Shell 中运行以下命令,以确认 gcloud 命令了解您的项目。
gcloud config list project
  1. 如果项目未设置,请使用以下命令进行设置:
gcloud config set project <YOUR_PROJECT_ID>
  1. 点击此链接,按照说明启用所需的 API,直到您可以点击“启用”按钮为止。

如果遗漏了任何 API,您始终可以在实施过程中启用它。

如需了解 gcloud 命令和用法,请参阅文档

3. 数据库设置

该文档提供了有关如何设置 Firestore 实例的更完整的步骤。概括来讲,我将按以下步骤开始操作:

前往 Firestore 查看器,然后在“选择数据库服务”界面中,选择“原生模式下的 Firestore”

  1. 为 Firestore 选择一个位置(请务必选择 us-central1,并在整个 Codelab 中选择区域 / 位置时遵循此规则)
  2. 点击“创建数据库”(如果是首次创建,请将其保留为“(default)”数据库)

您在创建 Firestore 项目时,也会在 Cloud API 管理器中启用 API

  1. 重要提示:请选择安全规则的测试(而非生产)版本,以便访问数据
  2. 设置完成后,您应该会看到原生模式下的 Firestore 数据库、集合和文档视图,如下图所示:

f7136d53253c59a.png

  1. 虽然现在还不用执行此步骤,但为了记录,您可以点击“开始收集”并创建一个新集合。将集合 ID 设置为“姿势”。点击保存按钮。

a26eb470aa9bfda9.png

生产应用方面的专业提示

  1. 确定数据模型并确定哪些人应能够访问不同类型的文档后,您可以在 Firebase 界面中创建、修改和监控安全规则。您可以通过以下链接访问安全规则:https://console.firebase.google.com/u/0/project/<<your_project_id>>/firestore/rules
  2. 在从开发阶段部署 / 推出项目之前,请务必修改、监控和测试安全规则,因为这通常是导致应用运行方式不同的幕后原因 :)

在本演示中,我们将以 TEST 模式使用它。

4. Firestore REST API

  1. REST API 在以下使用情形中会很有帮助:a. 从资源受限的环境(无法运行完整客户端库)访问 Firestore。自动执行数据库管理,或检索详细的数据库元数据
  2. 虽然 Firestore 最简单的用法是使用某个原生客户端库,但在有些情况下,直接调用 REST API 会很有用。
  3. 在本博文中,您将看到 Firestore REST API 的用法和演示,而不是原生客户端库
  4. Firestore REST API 接受使用 Firebase Authentication ID 令牌或 Google Identity OAuth 2.0 令牌进行身份验证。如需详细了解身份验证和授权主题,请参阅相关文档
  5. 所有 REST API 端点都存在于基准网址 https://firestore.googleapis.com/v1/ 下面。

Spring Boot 和 Firestore API

此 Spring Boot 框架中的解决方案旨在演示一个客户端应用,该应用使用 Firestore API 来收集和修改瑜伽姿势和呼吸细节,并提供用户互动体验。

如需详细了解瑜伽姿势应用中 Firestore CRUD 解决方案部分的分步说明,您可以访问此博客链接

为了专注于当前解决方案并随时随地学习 CRUD 部分,请从 Cloud Shell 终端克隆以下代码库中专注于此博客的整个解决方案,并获取代码库的副本。

git clone https://github.com/AbiramiSukumaran/firestore-poserecommender

请注意:

  1. 克隆此代码库后,您只需对项目 ID、API 等进行一些更改。无需进行任何其他更改,即可让应用正常运行。在接下来的部分中,我们将介绍应用的各个组成部分。以下是变更列表:
  2. src/main/java/com/example/demo/GenerateImageSample.java 文件中,将“<<YOUR_PROJECT_ID>>”替换为您的项目 ID
  3. src/main/java/com/example/demo/GenerateEmbeddings.java 文件中,将“<<YOUR_PROJECT_ID>>”替换为您的项目 ID
  4. src/main/java/com/example/demo/PoseController.java 中,将所有出现的“<<YOUR_PROJECT_ID>>"”和数据库名称(在本例中为 "(default)",)替换为配置中的相应值:,
  5. src/main/java/com/example/demo/PoseController.java 中,将“[YOUR_API_KEY]”替换为 Gemini 2.0 Flash 的 API 密钥。您可以从 AI Studio 获取此密钥。
  6. 如果您想在本地进行测试,请在 Cloud Shell 终端中从项目文件夹运行以下命令:
mvn package

mvn spring-boot:run

现在,您可以点击 Cloud Shell 终端中的“网页预览”选项,查看正在运行的应用。我们尚未准备好执行测试和试用应用。

  1. 可选:如果您想在 Cloud Run 中部署应用,则必须从 Cloud Shell 编辑器中从头开始引导全新的 Java Cloud Run 应用,并将 仓库中的 src 文件和模板文件添加到新项目的相应文件夹中(因为当前 GitHub 仓库项目默认情况下未针对 Cloud Run 部署配置进行设置)。在这种情况下,应遵循以下步骤(而不是克隆现有代码库):
  2. 前往 Cloud Shell 编辑器(确保编辑器已打开,而不是终端),然后点击状态栏左侧的 Google Cloud 项目名称图标(下方屏幕截图中被遮盖的部分)

d3f0de417094237d.png

  1. 从选项列表中选择“新建应用” ->“Cloud Run 应用” ->“Java: Cloud Run”,并将其命名为“firestore-poserecommender”

d5ef8b4ca8bf3f85.png

  1. 现在,您应该会看到 Java Cloud Run 应用的完整堆栈模板,该模板已预先配置好,可随时使用
  2. 移除现有的 Controller 类,并将以下文件复制到项目结构中的相应文件夹中:

firestore-poserecommender/src/main/java/com/example/demo/

  1. FirestoreSampleApplication.java
  2. GenerateEmbeddings.java
  3. GenerateImageSample.java
  4. Pose.java
  5. PoseController.java
  6. ServletInitializer.java
             firestore-poserecommender/src/main/resources/static/
    
  7. Index.html

firestore-poserecommender/src/main/resources/templates/

  1. contextsearch.html
  2. createpose.html
  3. errmessage.html
  4. pose.html
  5. ryoq.html
  6. searchpose.html
  7. showmessage.html

firestore-poserecommender/

  1. Dockerfile
  2. 您需要在相应文件中进行更改,将项目 ID 和 API 密钥替换为各自的值。(上述第 1 步的 a、b、c 和 d)。

5. 数据注入

应用的数据位于此文件 data.json 中:https://github.com/AbiramiSukumaran/firestore-poserecommender/blob/main/data.json

如果您想从一些预定义的数据开始,可以复制 JSON 并将所有出现的“<<YOUR_PROJECT_ID>>”替换为您的值

  • 前往 Firestore Studio
  • 确保您已创建名为“poses”的集合
  • 手动添加上述 repo 文件中的文档,一次添加一个

您也可以通过运行以下步骤,从我们为您创建的预定义集中一次性导入数据:

  1. 前往 Cloud Shell 终端,确保已设置活跃的 Google Cloud 项目,并确保您已获得授权。使用以下 gsutil 命令在项目中创建存储分区。将以下命令中的 <PROJECT_ID> 变量替换为您的 Google Cloud 项目 ID:

gsutil mb -l us gs://<PROJECT_ID>-yoga-poses-bucket

  1. 现在,存储分区已创建完毕,我们需要将准备好的数据库导出内容复制到此存储分区中,然后才能将其导入到 Firebase 数据库中。使用以下命令:

gsutil cp -r gs://demo-bq-gemini-public/yoga_poses gs://<PROJECT_ID>-yoga-poses-bucket

现在,我们已经准备好要导入的数据,接下来可以进入最后一步,将数据导入到我们创建的 Firebase 数据库(默认)中。

  1. 立即前往 Firestore 控制台,然后点击左侧导航菜单中的导入/导出

选择“导入”,然后选择您刚刚创建的 Cloud Storage 路径,并导航到可以选择“yoga_poses.overall_export_metadata”文件的位置:

f5c1d16df7d5a64a.png

  1. 点击“导入”。

导入过程需要几秒钟,完成后,您可以访问 https://console.cloud.google.com/firestore/databases 来验证您的 Firestore 数据库和集合,选择 default 数据库和 poses 集合,如下所示:

  1. 另一种方法是,在部署后,您还可以通过应用使用“创建新姿势”操作手动创建记录。

6. Vector Search

启用 Firestore 向量搜索扩展程序

使用此扩展程序,通过新的向量搜索功能自动嵌入和查询 Firestore 文档!系统会将您转到 Firebase Extensions Hub。

安装 Vector Search 扩展程序时,您需要指定集合和文档字段名称。添加或更新包含此字段的文档会触发此扩展程序,从而计算文档的向量嵌入。此向量嵌入会写回同一文档,并且该文档会在向量存储中编入索引,以便进行查询。

下面我们来看看具体步骤:

安装扩展程序

点击“在 Firebase 控制台中安装”,从 Firebase Extensions Marketplace 安装“Vector Search with Firestore”扩展程序。

重要提示

首次前往此扩展程序页面时,您需要选择与 Firebase 控制台中列出的 Google Cloud 控制台中的项目相同的项目。

715426b97c732649.png

如果您的项目未列出,请继续在 Firebase 中添加该项目(从列表中选择现有的 Google Cloud 项目)。

配置扩展程序

指定集合(“姿势”)、包含要嵌入的文本的字段(“姿势”)以及其他参数(例如嵌入维度)。

如果此步骤中列出了需要启用的 API,配置页面将允许您启用这些 API,请按照相应步骤操作。

如果您在启用 API 后,页面长时间没有响应,只需刷新页面,您应该就能看到已启用的 API。

5ba59b45710c567b.png

在后续步骤中,您可以选择使用自己喜欢的 LLM 来生成嵌入。选择“Vertex AI”。

bb528a04ebb5f976.png

接下来的几项设置与您的集合以及要嵌入的字段有关:

LLM:Vertex AI

集合路径:姿势

默认查询限制:3

距离衡量指标:余弦

输入字段名称:姿势

输出字段名称:嵌入

状态字段名称:status

嵌入现有文档:是

更新现有嵌入:是

Cloud Functions 位置:us-central1

“Enable Events”(启用事件):未选中

fb8cdf1163fac7cb.png

完成所有这些设置后,点击“安装扩展程序”按钮。此过程将需要 3-5 分钟时间。

生成嵌入

当您在“姿势”集合中添加或更新文档时,扩展程序将通过 API 端点使用预训练模型或您选择的模型自动生成嵌入。在本例中,我们在扩展程序配置中选择了 Vertex AI。

索引创建

它将强制要求在应用中使用嵌入时,在嵌入字段上创建索引。

Firestore 会自动为基本查询创建索引;不过,您也可以通过运行没有索引的查询,让 Firestore 生成索引语法,然后它会在应用端的错误消息中为您提供指向所生成索引的链接。以下是创建向量索引的步骤列表:

  1. 前往 Cloud Shell 终端
  2. 运行以下命令:
gcloud firestore indexes composite create --collection-group="poses" --query-scope=COLLECTION --database="(default)" --field-config vector-config='{"dimension":"768", "flat": "{}"}',field-path="embedding"

如需了解详情,请点击此处

创建向量索引后,您就可以使用向量嵌入执行最近邻搜索了。

重要提示

从现在开始,您无需对来源进行任何更改。只需跟着操作,即可了解应用在做什么。

我们来看看新建的应用如何使用 Vector Search。存储嵌入后,您可以使用 Firestore Java SDK 的 VectorQuery 类执行向量搜索并获取最近邻结果:

CollectionReference coll = firestore.collection("poses");
    VectorQuery vectorQuery = coll.findNearest(
        "embedding",
        userSearchTextEmbedding, 
        /* limit */ 3,
        VectorQuery.DistanceMeasure.EUCLIDEAN,
        VectorQueryOptions.newBuilder().setDistanceResultField("vector_distance")
         .setDistanceThreshold(2.0)
          .build());
ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();
List<Pose> posesList = new ArrayList<Pose>();
// Get the ID of the closest document (assuming results are sorted by distance)
String closestDocumentId = vectorQuerySnapshot.getDocuments().get(0).getId();

此代码段会将用户搜索文本的嵌入与 Firestore 中文档的嵌入进行比较,并提取在上下文中最为接近的嵌入。

7. Gemini 2.0 Flash

集成 Gemini 2.0 Flash(用于生成说明)

我们来看看您新建的应用如何处理 Gemini 2.0 Flash 集成以生成说明。

现在,假设某位管理员用户 / 瑜伽教练想要在 Gemini 2.0 Flash 的帮助下输入姿势的详细信息,然后执行搜索以查看最接近的匹配项。这样一来,系统会提取匹配姿势的详细信息以及支持结果的多模态对象。

String apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=[YOUR_API_KEY]";
Map<String, Object> requestBody = new HashMap<>();
List<Map<String, Object>> contents = new ArrayList<>();
List<Map<String, Object>> tools = new ArrayList<>();
Map<String, Object> content = new HashMap<>();
List<Map<String, Object>> parts = new ArrayList<>();
Map<String, Object> part = new HashMap<>();
part.put("text", prompt);
parts.add(part);
content.put("parts", parts);
contents.add(content);
requestBody.put("contents", contents);
/**Setting up Grounding*/
Map<String, Object> googleSearchTool = new HashMap<>();
googleSearchTool.put("googleSearch", new HashMap<>());
tools.add(googleSearchTool);
requestBody.put("tools", tools);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.exchange(apiUrl, HttpMethod.POST, requestEntity, String.class);
System.out.println("Generated response: " + response);
String responseBody = response.getBody();
JSONObject jsonObject = new JSONObject(responseBody);
JSONArray candidates = jsonObject.getJSONArray("candidates");
JSONObject candidate = candidates.getJSONObject(0);
JSONObject contentResponse = candidate.getJSONObject("content");
JSONArray partsResponse = contentResponse.getJSONArray("parts");
JSONObject partResponse = partsResponse.getJSONObject(0);
String generatedText = partResponse.getString("text");
System.out.println("Generated Text: " + generatedText);

a. 模仿图片和音频生成

Gemini 2.0 Flash Experimental 能够生成多模态结果,但我尚未注册其抢先体验计划,因此我分别使用 Imagen 和 TTS API 模拟了图片和音频输出。想象一下,只需通过一次 API 调用 Gemini 2.0 Flash 即可生成所有这些内容,是不是很棒!

try (PredictionServiceClient predictionServiceClient =
          PredictionServiceClient.create(predictionServiceSettings)) {
  
        final EndpointName endpointName =
            EndpointName.ofProjectLocationPublisherModelName(
                projectId, location, "google", "imagen-3.0-generate-001");
  
        Map<String, Object> instancesMap = new HashMap<>();
        instancesMap.put("prompt", prompt);
        Value instances = mapToValue(instancesMap);
  
        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("sampleCount", 1);
        paramsMap.put("aspectRatio", "1:1");
        paramsMap.put("safetyFilterLevel", "block_few");
        paramsMap.put("personGeneration", "allow_adult");
        Value parameters = mapToValue(paramsMap);
  
        PredictResponse predictResponse =
            predictionServiceClient.predict(
                endpointName, Collections.singletonList(instances), parameters);
  
        for (Value prediction : predictResponse.getPredictionsList()) {
          Map<String, Value> fieldsMap = prediction.getStructValue().getFieldsMap();
          if (fieldsMap.containsKey("bytesBase64Encoded")) {
            bytesBase64Encoded = fieldsMap.get("bytesBase64Encoded").getStringValue();
       }
      }
      return bytesBase64Encoded;
    }
 try {
            // Create a Text-to-Speech client
            try (TextToSpeechClient textToSpeechClient = TextToSpeechClient.create()) {
                // Set the text input to be synthesized
                SynthesisInput input = SynthesisInput.newBuilder().setText(postureString).build();

                // Build the voice request, select the language code ("en-US") and the ssml
                // voice gender
                // ("neutral")
                VoiceSelectionParams voice =
                        VoiceSelectionParams.newBuilder()
                                .setLanguageCode("en-US")
                                .setSsmlGender(SsmlVoiceGender.NEUTRAL)
                                .build();

                // Select the type of audio file you want returned
                AudioConfig audioConfig =
                        AudioConfig.newBuilder().setAudioEncoding(AudioEncoding.MP3).build();

                // Perform the text-to-speech request on the text input with the selected voice
                // parameters and audio file type
                SynthesizeSpeechResponse response =
                        textToSpeechClient.synthesizeSpeech(input, voice, audioConfig);

                // Get the audio contents from the response
                ByteString audioContents = response.getAudioContent();

                // Convert to Base64 string
                String base64Audio = Base64.getEncoder().encodeToString(audioContents.toByteArray());

                // Add the Base64 encoded audio to the Pose object
               return base64Audio;
            }

        } catch (Exception e) {
            e.printStackTrace(); // Handle exceptions appropriately. For a real app, log and provide user feedback.
            return "Error in Audio Generation";
        }
}

b. 使用 Google 搜索建立依据

如果您查看第 6 步中的 Gemini 调用代码,您会注意到以下代码段,该代码段用于为 LLM 回答启用 Google 搜索接地:

 /**Setting up Grounding*/
Map<String, Object> googleSearchTool = new HashMap<>();
googleSearchTool.put("googleSearch", new HashMap<>());
tools.add(googleSearchTool);
requestBody.put("tools", tools);

这是为了确保我们:

  • 让模型基于实际搜索结果
  • 提取搜索中提及的相关网址

8. 运行应用

我们来通过一个简单的 Thymeleaf Web 界面看看新建的 Java Spring Boot 应用的所有功能:

  1. Firestore CRUD 操作(创建、读取、更新、删除)
  2. 关键字搜索
  3. 基于生成式 AI 的情境创建
  4. 内容相关搜索(向量搜索)
  5. 与搜索内容相关的多模态输出
  6. 运行您自己的查询(采用 structuredQuery 格式的查询)

示例:{"structuredQuery":{"select":{"fields":[{"fieldPath":"name"}]},"from":[{"collectionId":"fitness_poses"}]}}

到目前为止,我们讨论的所有功能都属于您刚刚从以下代码库创建的应用:https://github.com/AbiramiSukumaran/firestore-poserecommender

如需构建、运行和部署该应用,请在 Cloud Shell 终端中运行以下命令:

mvn package

mvn spring-boot:run

您应该会看到结果,并能够试用应用的功能。如需查看输出内容的演示,请观看以下视频:

使用 Firestore、Vector Search 和 Gemini 2.0 Flash 构建姿势推荐器

可选步骤

如需将其部署到 Cloud Run(假设您已使用 Dockerfile 引导启动了一个全新的应用,并根据需要复制了文件),请从项目目录内的 Cloud Shell 终端运行以下命令:

gcloud run deploy --source .

提供应用名称、区域代码(选择 us-central1 对应的代码),然后根据提示选择未通过身份验证的调用“Y”。部署成功后,您应该会在终端中收到应用端点。

9. 清理

为避免系统因本博文中使用的资源向您的 Google Cloud 账号收取费用,请按照以下步骤操作:

  1. 在 Google Cloud 控制台中,前往管理资源页面。
  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关停以删除项目。

10. 恭喜

恭喜!您已成功利用 Firestore 创建了一个强大而智能的瑜伽姿势管理应用。通过结合使用 Firestore、Vector Search 扩展程序和 Gemini 2.0 Flash 的功能(包括模拟图片和音频生成),我们创建了一款真正引人入胜且信息丰富的瑜伽应用,可用于实现 CRUD 操作、执行基于关键字的搜索、场景化向量搜索和生成多媒体内容。

此方法不仅限于瑜伽应用。随着 Gemini 等 AI 模型的不断发展,我们能够打造的沉浸式个性化用户体验只会越来越丰富。请务必及时了解 Google Cloud 和 Firebase 的最新动态和文档,以便充分发挥这些技术的潜力。

如果我要扩展此应用,我会尝试使用 Gemini 2.0 Flash 完成以下两项任务:

  1. 通过为用例创建实时视觉和音频流,使用 Multimodal Live API。
  2. 启用思考模式,让 Gemini 根据实时数据生成回答背后的想法,从而打造更逼真的体验。

欢迎尝试并发送拉取请求:>D!!!