利用 Gemini Code Assist 加速您的开发工作流程

1. 简介

e5b98fd4e417c877.png

在此 Codelab 中,您将了解 Gemini Code Assist 如何在软件开发生命周期 (SDLC) 的关键阶段(例如设计、构建和测试以及部署)为您提供支持。我们将设计和开发整个应用,并将其部署在 Google Cloud 上。

我们将在技术活动中构建一个 API 和应用,以搜索各个会话。每个会话都将包含标题、摘要、时长、类别以及一位或多位演讲者。

实践内容

  • 从头开始设计、构建、测试和部署基于 OpenAPI 规范的 Web 应用

学习内容

  • 如何使用 Gemini Code Assist 生成 OpenAPI 规范
  • 如何使用 Gemini Code Assist 代码生成功能来开发适用于 OpenAPI 规范的 Python Flask 应用
  • 如何使用 Gemini Code Assist 为 Python Flask 应用生成 Web 前端
  • 如何使用 Gemini Code Assist 获取有关如何将应用部署到 Google Cloud Run 的帮助
  • 在构建和测试应用时,使用 Gemini Code Assist 功能,例如代码说明、测试用例生成

所需条件

  • Chrome 网络浏览器
  • Gmail 账号
  • 启用了结算功能的 Cloud 项目
  • 已为您的云项目启用 Gemini Code Assist

本实验的适用对象为各种水平的开发者,包括新手。虽然示例应用使用的是 Python 语言,但您无需熟悉 Python 编程就能理解代码内容。我们的重点是让开发者熟悉 Gemini Code Assist 的各项功能。

2. 设置 Gemini Code Assist

本部分涵盖了开始此实验所需执行的所有操作。

在 Cloud Shell IDE 中启用 Gemini Code Assist

在此 Codelab 的其余部分,我们将使用 Cloud Shell IDE,这是一个基于 Code OSS 的全托管式开发环境。我们需要在 Cloud Shell IDE 中启用和配置 Code Assist,相关步骤如下所示:

  1. 访问 ide.cloud.google.com。IDE 可能需要一段时间才能显示,请耐心等待并接受任何设置默认选项。如果您看到有关设置 IDE 的一些说明,请继续完成这些说明,并使用默认设置。
  2. 如图所示,点击底部状态栏中的 Cloud Code - 登录按钮。按照说明对插件进行授权。如果您在状态栏中看到 Cloud Code - no project,请选择该选项,然后从项目列表中选择您打算使用的 Google Cloud 项目。

6f5ce865fc7a3ef5.png

  1. 如图所示,点击右下角的代码辅助按钮,然后最后一次选择正确的 Google Cloud 项目。如果系统要求您启用 云 AI Companion API,请按照要求操作,然后继续。
  2. 选择 Google Cloud 项目后,请确保您能够在状态栏的 Cloud Code 状态消息中看到该项目,并且在状态栏右侧看到已启用 Code Assist,如下所示:

709e6c8248ac7d88.png

Gemini Code Assist 已准备就绪,可以开始使用了!

3. 设置 Firestore

Cloud Firestore 是一种全托管式无服务器文档数据库,我们将使用它作为应用数据的后端。Cloud Firestore 中的数据以文档集合的形式进行结构化。

我们需要在默认 Firestore 数据库中创建一个名为 sessions 的集合。此集合将包含我们随后将在应用中使用的示例数据(文档)。

通过主菜单从 Cloud Shell IDE 中打开终端,如下所示:

f1535e14c9beeec6.png

我们需要创建一个名为 sessions 的集合。这将包含示例会话文档的列表。每个文档都将具有以下属性:

  1. title:字符串
  2. 类别:字符串数组
  3. speakers:字符串数组
  4. duration:字符串
  5. summary:字符串

让我们通过以下方式使用示例数据填充此集合:将包含示例数据的文件复制到您自己项目中的存储分区,然后通过 gcloud firestore import 命令导入该集合。

Firestore 数据库初始化

在 Cloud 控制台中,访问 Firestore 页面

如果您之前未在项目中初始化 Firestore 数据库,请创建 default 数据库。在创建数据库期间,请使用以下值:

  • Firestore 模式:Native
  • 位置:选择“位置类型”作为 Region,然后选择适合您应用的区域。记下此位置,因为您需要在下一步中将其用作存储分区位置。
  • 创建数据库。

504cabdb99a222a5.png

现在,我们将按照以下步骤创建 sessions 集合:

  1. 使用以下 gsutil 命令在项目中创建存储分区。将以下命令中的 <PROJECT_ID> 变量替换为您的 Google Cloud 项目 ID。将 <BUCKET_LOCATION> 替换为与默认 Firestore 数据库的地理区域对应的区域名称(如上一步中所述),可以是 US-WEST1、EUROPE-WEST1、ASIA-EAST1:
gsutil mb -l <BUCKET-LOCATION> gs://<PROJECT_ID>-my-bucket
  1. 现在,存储分区已创建完毕,我们需要将准备好的数据库导出内容复制到此存储分区中,然后才能将其导入到 Firebase 数据库中。使用以下命令:
gsutil cp -r gs://sessions-master-database-bucket/2024-03-26T09:28:15_95256  gs://<PROJECT_ID>-my-bucket

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

  1. 使用以下 gcloud 命令:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2024-03-26T09:28:15_95256

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

d3e294d46ba29cd5.png

这样就完成了 Firestore 集合的创建,我们将在应用中使用该集合。

4. 创建应用模板

我们将创建一个示例应用(一个 Python Flask 应用),用于在此 Codelab 的其余部分中使用。此应用将搜索技术会议上提供的所有会话。

请按照以下步骤操作:

  1. 点击下方状态栏中的 Google Cloud 项目名称

f151759c156c124e.png

  1. 系统会显示一个选项列表。点击下方列表中的新应用

91ea9836f38b7f74.png

  1. 选择 Cloud Run application(这将成为我们应用的运行时)。
  2. 选择 Python (Flask): Cloud Run 应用模板。
  3. 为应用命名,然后将其保存到首选位置。
  4. 系统会显示一条通知,确认已创建应用,并打开一个新窗口,其中加载了您的应用,如下所示。系统会打开一个 README.md 文件。您可以暂时关闭该视图。

aaa3725b17ce27cf.png

5. 与 Gemini Code Assist 互动

在本实验中,我们将使用 Cloud Shell IDE 中提供的 Gemini Code Assist Chat,它是 VS Code 中 Cloud Code 扩展程序的一部分。点击左侧导航栏中的“代码辅助”按钮即可打开它。在左侧导航工具栏中找到 Code Assist 图标 a489f98a34898727.png,然后点击该图标。

系统随即会在 Cloud Shell IDE 中打开 Code Assist 聊天窗格,您可以与 Code Assist 聊天。

14ad103efaa0ddaa.png

请注意顶部的回收站图标 - 您可以通过此图标重置 Code Assist 聊天记录的上下文。另请注意,此聊天互动与您在 IDE 中处理的文件相关。

6. API 设计

我们的第一步是在设计阶段借助 Gemini Code Assist 的帮助。在此步骤中,我们将为要搜索的实体(活动中的技术讲座)生成 OpenAPI 规范。

输入以下提示:

Generate an Open API spec that will allow me to retrieve all sessions, sessions by category, session by id. Each session has the following attributes: id, title, list of speakers, list of categories, summary and duration.

这应该会生成一个 OpenAPI 规范,用于通过各种查询参数在会话中进行搜索。规范示例如下所示:

openapi: 3.0.0
info:
 title: Sessions API
 description: This API allows you to retrieve all sessions, sessions by category, and session by id.
 version: 1.0.0
servers:
 - url: https://sessions.example.com
paths:
 /sessions:
   get:
     summary: Get all sessions
     operationId: getSessions
     responses:
       '200':
         description: OK
         content:
           application/json:
             schema:
               type: array
               items:
                 $ref: '#/components/schemas/Session'
 /sessions/{id}:
   get:
     summary: Get session by id
     operationId: getSessionById
     parameters:
       - name: id
         in: path
         required: true
         description: The id of the session
         schema:
           type: string
     responses:
       '200':
         description: OK
         content:
           application/json:
             schema:
               $ref: '#/components/schemas/Session'
 /sessions/categories/{category}:
   get:
     summary: Get sessions by category
     operationId: getSessionsByCategory
     parameters:
       - name: category
         in: path
         required: true
         description: The category of the sessions
         schema:
           type: string
     responses:
       '200':
         description: OK
         content:
           application/json:
             schema:
               type: array
               items:
                 $ref: '#/components/schemas/Session'
components:
 schemas:
   Session:
     type: object
     properties:
       id:
         type: string
         description: The id of the session
       title:
         type: string
         description: The title of the session
       speakers:
         type: array
         items:
           type: string
         description: The list of speakers for the session
       categories:
         type: array
         items:
           type: string
         description: The list of categories for the session
       summary:
         type: string
         description: The summary of the session
       duration:
         type: string
         description: The duration of the session

您会注意到,该规范具有以下特征:

  • 会话类型定义的架构。
  • 定义了多个 API 路径:
  • /sessions
  • /sessions/{id}
  • /sessions/categories/{category}

在顶级文件夹中创建一个名为 sessionsapi.yaml 的文件,然后使用“插入到当前文件”选项(+ 按钮)将内容从 Code Assist 对话窗口复制到该文件中,并使该文件在 Cloud Shell IDE 中保持打开状态。

此时,您可以注意到 Gemini Code Assist 的一个有趣的功能:引用。当生成的代码直接引用其他来源(例如现有开源代码)的长篇内容时,系统会向开发者显示此信息。它提供源代码和许可,以便开发者决定如何使用。

假设我们对生成的内容没有异议,现在可以使用此规范文档为其生成 Python Flask 应用。

7. 生成应用

现在,我们将让 Code Assist 生成应用。在打开 sessionsapi.yaml 文件的情况下,输入以下提示。

Generate a Python Application using the Flask framework, based on the sessionsapi.yaml file. This application uses a local in memory list of sessions. Do not use any Flask extensions.

这应该会为您提供一个 Python Flask 应用框架,该框架基于 OpenAPI 规范文件中指定的功能和路径。

提供的 Python Flask 应用代码应类似于以下代码:

from flask import Flask, jsonify, request

app = Flask(__name__)

sessions = [
    {
        "id": "1",
        "title": "Session 1",
        "speakers": ["Speaker 1", "Speaker 2"],
        "categories": ["Category 1", "Category 2"],
        "summary": "This is a summary of session 1.",
        "duration": "1 hour",
    },
    {
        "id": "2",
        "title": "Session 2",
        "speakers": ["Speaker 3", "Speaker 4"],
        "categories": ["Category 3", "Category 4"],
        "summary": "This is a summary of session 2.",
        "duration": "1 hour 30 minutes",
    },
]

@app.route('/sessions', methods=['GET'])
def get_sessions():
    return jsonify(sessions)

@app.route('/sessions/<id>', methods=['GET'])
def get_session_by_id(id):
    session = next((session for session in sessions if session['id'] == id), None)
    if session is None:
        return jsonify({}), 404
    return jsonify(session)

@app.route('/sessions/categories/<category>', methods=['GET'])
def get_sessions_by_category(category):
    sessions_by_category = [session for session in sessions if category in session['categories']]
    return jsonify(sessions_by_category)

if __name__ == '__main__':
    app.run()

存在在上一步中生成的 app.py 文件。只需将其内容替换为 Code Assist 生成的代码,然后保存该文件即可。

我们希望更改 app.run() 行,以使用端口 8080、主机地址 0.0.0.0,并在本地执行期间以调试模式运行。以下是一种实现方式。首先,我们来突出显示/选择以下行:

app.run()

然后在 Code Assist 对话界面中,输入提示:Explain this.

这应该会显示相应行的详细说明,如下所示:

58ec896a32a4fb68.png

现在,使用以下提示:

update the code to run the application on port 8080, host address 0.0.0.0, and in debug mode

生成的建议代码应如下所示:

app.run(host='0.0.0.0', port=8080, debug=True)

请务必使用此代码段更新 app.py 文件。

在本地运行应用

现在,让我们在本地运行应用,以验证应用需求是否符合我们最初设定的目标。

第一步是创建一个虚拟 Python 环境,其中包含 requirements.txt 中的 Python 软件包依赖项,以便安装到虚拟环境中。为此,请前往 Cloud Shell IDE 中的 Command Palette (Ctrl+Shift+P),然后输入 Create Python environment。按照接下来的几个步骤选择虚拟环境 (venv)Python 3.x 解释器requirements.txt 文件。

创建环境后,启动新的终端窗口 (Ctrl+Shift+`) 并运行以下命令:

python app.py

下面展示了一个执行示例:

(.venv) romin@cloudshell: $ python app.py 
 * Serving Flask app 'app'
 * Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:8080
 * Running on http://10.88.0.3:8080
Press CTRL+C to quit
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 132-247-368

您现在可以通过以下网址预览 API。我们假设您的开发服务器在 8080 端口上运行。如果不是,请将其更改为相应的端口号。

  • https://<host-name>:8080/sessions
  • https://<host-name>:8080/sessions/{id}
  • https://<host-name>:8080/sessions/categories/{category}

请按照以下步骤操作,确保您能够使用这些网址检索 app.py 文件中包含的 JSON 数据:

打开新的终端窗口,然后尝试运行以下任一命令:

curl -X GET http://127.0.0.1:8080/sessions
curl -X GET http://127.0.0.1:8080/sessions/<ID>
curl -X GET http://127.0.0.1:8080/sessions/categories/<CATEGORY_NAME> 

8. 代码重构

我们可能希望将 app.py 中包含的硬编码 JSON 示例数据分离/提取到另一个模块中,以便在代码和数据之间保持清晰的分离。我们开始吧!

保持 app.py 文件处于打开状态,然后输入以下提示:

Can I improve this code and separate out the sessions data from this app.py file?

这应该会为您提供一些有关如何实现此目标的建议。我们收到的建议示例如下所示,您应该会收到类似的建议:

9b9c56cb527dac4c.png

接下来,我们按照 Code Assist 的建议,将数据分离到 sessions.py 文件中。

创建名为 sessions.py 的新文件

其内容为 JSON 列表,根据我们生成的数据,如下所示:

sessions = [
   {
       "id": "1",
       "title": "Session 1",
       "speakers": ["Speaker 1", "Speaker 2"],
       "categories": ["Category 1", "Category 2"],
       "summary": "This is a summary of session 1.",
       "duration": "1 hour",
   },
   {
       "id": "2",
       "title": "Session 2",
       "speakers": ["Speaker 3", "Speaker 4"],
       "categories": ["Category 3", "Category 4"],
       "summary": "This is a summary of session 2.",
       "duration": "1 hour 30 minutes",
   },
]

app.py 文件现在已大大简化,如下所示:

from flask import Flask, jsonify, request
from sessions import sessions

app = Flask(__name__)

@app.route('/sessions', methods=['GET'])
def get_sessions():
   return jsonify(sessions.sessions)

@app.route('/sessions/<id>', methods=['GET'])
def get_session_by_id(id):
   session = next((session for session in sessions.sessions if session['id'] == id), None)
   if session is None:
       return jsonify({}), 404
   return jsonify(session)

@app.route('/sessions/categories/<category>', methods=['GET'])
def get_sessions_by_category(category):
   sessions_by_category = [session for session in sessions.sessions if category in session['categories']]
   return jsonify(sessions_by_category)

if __name__ == '__main__':
   app.run(host='0.0.0.0', port=8080, debug=True)

确保您仍然能够在本地运行应用,并使用这些重构的更改来测试 API。Python 开发服务器可能仍在运行,因此您只需回忆上一步中的 curl 命令即可。

9. 与 Firestore 集合集成

下一步是舍弃我们用于会话的本地内存中 JSON 列表,并将应用连接到我们在本 Codelab 开始时创建的 Firestore 数据库中的会话集合。

保持 sessions.py 文件处于打开状态,然后输入以下提示:

Can you further refactor the sessions.py code to read from a Firestore database that has a collection named sessions. The collection has the same attributes as the session object that we have defined. Use the Python module google-cloud-firestore. 

我们收到了以下建议,即从 Firestore 集合中读取所有会话:

import google.cloud.firestore

# Create a Firestore client
db = google.cloud.firestore.Client()

# Get the sessions collection
sessions_collection = db.collection("sessions")

# Create a list of sessions
sessions = []

# Iterate over the documents and add them to the list
for doc in sessions_collection.stream():
   session = doc.to_dict()
   session["id"] = doc.id
   sessions.append(session)

接下来,将代码纳入 sessions.py 中。

如果您在本地运行 Flask 开发服务器,您的应用可能会关闭,并显示找不到 Python 模块的错误消息。

您可以向 Code Assist 询问需要向 requirements.txt 文件添加哪个 Python 模块,如下所示:

Which Python package needs to be installed to make the firestore code work?

这会为您提供 Python 模块的名称(例如 google-cloud-firestore)。将该名称添加到 requirements.txt 文件中。

您需要使用新添加的模块 (google-cloud-firestore) 重新创建 Python 环境。为此,请在现有终端窗口中运行以下命令:

pip install -r requirements.txt

再次运行应用(使用 python app.py 重新启动),然后访问 /sessions 网址。您现在应该会获得我们添加到 sessions 集合中的示例文档。

975d05e6518f1a6a.png

您可以随意查询其他 URI,以检索特定会话或给定类别的所有会话,如前面的步骤中所述。

10. 代码说明

现在,您可以利用 Gemini Code Assist 的 "Explain this" 功能来深入了解代码。您可以随意进入任何文件,也可以选择特定的代码段,然后使用以下提示询问 Code Assist:Explain this

作为练习,请访问 sessions.py 文件,突出显示特定于 Firestore 的代码,并获取有关该代码的说明。您还可以尝试在项目中的其他文件(而不仅仅是 Python 代码)中使用此功能。

11. 生成 Web 应用

现在,我们已生成 API 并将其与实时 Firestore 集合集成,接下来让我们为应用生成基于 Web 的前端。我们的 Web 前端目前会尽可能减少其功能,即能够搜索属于特定类别的会话。请注意,我们有一个相应的 API 路径,即 /sessions/categories/{category},因此我们的 Web 应用应调用该路径并检索结果。

让我们直接进入正题。向 Code Assist 提供以下提示:

Generate a web application that allows me to search for sessions by category and uses the Flask application that we created. Please use basic HTML, CSS and JS. Embed all the Javascript and CSS code into a single HTML file only.

这会生成包含嵌入式 JavaScript 和 CSS 的 Web 应用 HTML。它还会要求您向 app.py 文件添加新路由,以便任何访问根网址或基础网址的用户都能看到首页。如果未提及该信息,请询问相关事宜或使用以下代码段:

@app.route('/')
def index():
   return render_template('index.html')

您可以将此文件另存为 index.html,但可能会有疑问,即此文件应保存在哪个文件夹中?我们可以向 Code Assist 提出后续问题。

Given that I am using the flask framework, where should I put the index.html file?

它应该会明确告知您,它使用的是 render_template 框架,因此 index.html 文件需要放置在 templates 文件夹中。由于我们在此 Codelab 开始时已基于 Flask 模板生成了一个应用,因此您会发现此文件夹可用。因此,系统会生成一个现有的 index.html 文件,您只需将其内容替换为此处生成的新内容即可。Code Assist 还会建议在 app.py 文件中导入 render_template

继续操作,将 Web 应用代码保存到 index.html 文件中,并记得将该文件放入 templates 文件夹中。

在本地运行应用

现在,让我们在本地运行应用,以验证应用需求是否符合我们最初设定的目标。

确保本地 Flask 服务器仍在运行,并且未显示任何错误。如果出现错误,请解决这些错误,然后启动服务器。

启动并运行后,访问应用的首页网址。它应显示所提供的 index.html 文件,如下所示:

8ca586acc4536879.png

提供数据中的一个类别作为输入内容(例如 AI),然后点击 Search 按钮。这应该会显示标记为 AI 类别的会话。

165faded790a6c.png

一项可选练习是显示每个会话的其他元数据,例如时长、类别、发言者和摘要。

12. 测试用例生成

我们已生成会话 API,现在可以使用 Gemini Code Assist 为不同的 API 路径生成单元测试用例。

保持 app.py 文件处于打开状态,然后输入以下提示:

Generate unit test cases for app routes. Use unittest module.

我们收到了以下响应:

import unittest
from app import app

class FlaskAppTestCase(unittest.TestCase):

    def test_index(self):
        tester = app.test_client()
        response = tester.get('/')
        self.assertEqual(response.status_code, 200)

    def test_get_sessions(self):
        tester = app.test_client()
        response = tester.get('/sessions')
        self.assertEqual(response.status_code, 200)

    def test_get_session_by_id(self):
        tester = app.test_client()
        response = tester.get('/sessions/1')
        self.assertEqual(response.status_code, 200)

    def test_get_sessions_by_category(self):
        tester = app.test_client()
        response = tester.get('/sessions/categories/category1')
        self.assertEqual(response.status_code, 200)

if __name__ == '__main__':
    unittest.main()

使用上述代码创建一个名为 tests.py 的文件。

关于测试用例生成的注意事项

您可能会看到与上述不同的代码列表,这可能会导致在运行测试用例时出现一些问题。例如,我们发现,在某些运行中,以下关键代码段被遗漏:

from app import app

上述代码用于导入现有 Flask 应用,我们将针对该应用调用测试用例。

if __name__ == '__main__':

`unittest.main()`

运行测试用例需要上述代码。

我们建议您查看每个测试用例,检查生成的代码中的 assertEqual 和其他条件,以确保代码能够正常运行。由于数据位于 Firestore 集合中,因此可能无法访问该数据,并且可能会使用一些虚拟数据,从而导致测试失败。因此,请相应地修改测试用例,或注释掉您可能暂时不需要的某些测试用例。

为了演示,我们使用以下命令运行了测试用例(请务必运行本地开发服务器,因为系统会调用本地 API Endpoints):

python tests.py

我们获得了以下总结结果:

Ran 4 tests in 0.274s

FAILED (failures=2)

确实如此,因为在第 3 次测试中,会话 ID 不正确,并且没有名为 category1 的类别

因此,请相应地调整测试用例并进行测试。

13. 测试驱动开发

现在,让我们按照测试驱动开发 (TDD) 方法在会话 API 中添加新的搜索方法。TDD 方法是指先编写测试用例,由于缺少实现而导致测试用例失败,然后使用 Gemini Code Assist 生成缺少的实现,以便测试通过。

前往 tests.py 文件(假设您已修复 tests.py 文件,使其包含所有通过的测试)。向 Code Assist 提出以下提示:

Generate a new test case to search for sessions by speaker

这为我们提供了以下测试用例实现,我们已将其正确插入到 tests.py 文件中。

  def test_get_sessions_by_speaker(self):
        tester = app.test_client()
        response = tester.get('/sessions/speakers/speaker1')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json, [sessions.sessions[0], sessions.sessions[1]])

如果您运行测试,应该会看到以下错误:

$ python tests.py 
.F.
======================================================================
FAIL: test_get_sessions_by_speaker (__main__.FlaskAppTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/romin/hello-world-5/tests.py", line 21, in test_get_sessions_by_speaker
    self.assertEqual(response.status_code, 200)
AssertionError: 404 != 200

----------------------------------------------------------------------
Ran 3 tests in 0.010s

FAILED (failures=1)

这是因为测试用例已调用以下路径 (/sessions/speakers/),但 app.py 中没有相应实现。

我们让 Code Assist 为我们提供实现。前往 app.py 文件,并向 Code Assist 提供以下提示:

Add a new route to search for sessions by a specific speaker

我们获得了 Code Assist 建议的以下实现,并将其添加到了 app.py 文件中:

@app.route('/sessions/speakers/<speaker>', methods=['GET'])
def get_sessions_by_speaker(speaker):
    sessions_by_speaker = [session for session in sessions.sessions if speaker in session['speakers']]
    return jsonify(sessions_by_speaker)

重新访问 tests.py 文件,并修改了我们的测试用例如下,以便快速检查:

   def test_get_sessions_by_speaker(self):
       tester = app.test_client()
       response = tester.get('/sessions/speakers/Romin Irani')
       self.assertEqual(response.status_code, 200)
       self.assertEqual(len(response.json), 1)

测试运行正常。我们留给您一个练习,让您查看生成的测试用例,根据您可能在 Firestore 中拥有的数据稍微调整一下,并在 Python 单元测试用例中添加适当的 assert* 方法。

14. 部署到 Google Cloud Run

现在,我们对开发质量感到满意,最后一步是将此应用部署到 Google Cloud Run。不过,为了保险起见,我们不妨问问 Code Assist 是否遗漏了什么。打开 app.py 后,提交以下提示:

Is there something here I should change before I deploy to production?

幸好您提出了这个问题,因为我们实际上忘记将调试标志设置为关闭了:

2f87ed3a811fb218.png

如上所示,关闭调试,然后向 Gemini Code Assist 寻求帮助,以获取可用于直接从源代码将应用部署到 Cloud Run(无需先构建容器)的 gcloud 命令。

输入以下提示:

I would like to deploy the application to Cloud Run directly from source. What is the gcloud command to do that?

尝试使用上述提示的几种变体。我们还尝试了以下提示:

I would like to deploy this application to Cloud Run. I don't want to build a container image locally but deploy directly from source to Cloud Run. What is the gcloud command for that?

理想情况下,您应该会获得以下 gcloud 命令:

gcloud run deploy sessions --source .

您还可能会获得:

gcloud run deploy <service-name> --source . \
—-platform managed \
—-allow-unauthenticated

从应用的根文件夹执行上述命令。当系统要求提供 region 时,请选择 us-central1;当系统要求允许 unauthenticated invocations 时,请选择 Y。系统可能还会要求您启用 Artifact Registry、Cloud Build 和 Cloud Run 等 Google Cloud API,并授予创建 Artifact Registry 制品库的权限,请继续操作并授予相应权限。

部署过程大约需要 2 分钟才能完成,请耐心等待。

成功部署后,您将看到 Cloud Run 服务网址。访问该公共网址,您应该会看到已成功部署并运行的同一 Web 应用。

c5322d0fd3e0f616.png

恭喜,做得好!

15. (可选)使用 Cloud Logging

我们可以在应用中引入日志记录功能,以便将应用日志集中在某个 Google Cloud 服务 (Cloud Logging) 中。然后,我们还可以使用可观测性 Gemini 功能来了解日志条目。

为此,我们首先必须使用 Google Cloud 提供的现有 Python Cloud Logging 库,并使用该库记录信息、警告或错误消息(具体取决于日志 / 严重程度)。

我们先尝试向 Code Assist 提出这个问题。尝试使用以下提示:

How do I use the google-cloud-logging package in Python?

您应该会收到一条提供相关信息的响应,如下所示:

2472e1ccaf8a217d.png

我们来为按类别搜索会话的函数添加日志语句。

首先,将 google-cloud-logging Python 软件包添加到 requirements.txt 文件中。

接下来是一段代码,展示了我们如何集成代码来实现日志记录:

...
from google.cloud import logging
...
app = Flask(__name__)

# Create a logger
logger = logging.Client().logger('my-log')

@app.route('/sessions/categories/<category>', methods=['GET'])
def get_sessions_by_category(category):
   logger.log_text(f"Fetching sessions with category {category}")
   sessions_by_category = [session for session in sessions.sessions if category in session['categories']]
   logger.log_text(f'Found {len(sessions_by_category)} sessions with category {category}')
   return jsonify(sessions_by_category)

# # Other App Routes

使用与上一部分相同的命令将服务再次部署到 Cloud Run,并在部署完成后,对 /sessions/categories/<category> 端点执行几次调用。

前往 Cloud Console → Logs Explorer

59e297577570695.png

...并且您应该能够过滤到这些日志记录语句,如下所示:

914f1fb6cac30a89.png

您可以点击任意日志语句将其展开,然后点击 Explain this log entry,系统会使用 Gemini 说明该日志条目。请注意,如果您尚未启用 Gemini for Google Cloud,系统会要求您启用 Cloud AI Companion API。请按照说明进行操作。

以下是示例回答:

7fc9783910fa92cc.png

16. 恭喜

恭喜!您已成功从头开始构建了一个应用,并在 SDLC 的多个方面(包括设计、构建、测试和部署)使用了 Gemini Code Assist。

后续操作

查看下列 Codelab…

参考文档