利用 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 项目
  • 已为您的 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 中启用和配置代码助理,相关步骤如下所示:

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

6f5ce865fc7a3ef5

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

709e6c8248ac7d88

Gemini Code Assist 现在可以使用了!

3. 设置 Firestore

Cloud Firestore 是一种全代管式无服务器文档数据库,我们将用作应用数据的后端。Cloud Firestore 中的数据采用文档集合文档的结构。

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

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

f1535e14c9beeec6.png

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

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

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

Firestore 数据库初始化

访问 Cloud 控制台中的 Firestore 页面

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

  • Firestore 模式:Native
  • 位置:选择 Region 作为位置类型,然后选择适合您的应用的区域。记下此位置,因为在下一步中,您会用到此位置。
  • 创建数据库。

504cabdb99a222a5

现在,我们将按照以下步骤创建 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

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

d3e294d46ba29cd5.png

至此,我们要在应用中使用的 Firestore 集合已创建完毕。

4. 创建应用模板

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

请按照以下步骤操作:

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

f151759c156c124e.png

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

91ea9836f38b7f74

  1. 选择 Cloud Run 应用(这将是我们应用的运行时)。
  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 扩展程序的一部分。您可以点击左侧导航栏中的“代码助手”按钮来打开这个标签页。在左侧导航工具栏中找到“代码助手”图标 a489f98a34898727.png,然后点击该图标。

此操作将在 Cloud Shell IDE 中打开代码助理聊天窗格,然后您可以与代码助理聊天。

14ad103efaa0ddaa

请注意顶部的垃圾箱图标,您可以通过此图标重置代码助理聊天记录的上下文。另请注意,此聊天互动与您在 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 的文件,使用“在当前文件中插入”选项(+ 按钮)将代码助理聊天窗口中的内容复制过来,并让该文件在 Cloud Shell IDE 中保持打开状态。

此时,您可以注意到 Gemini Code Assist 的一个有趣功能:citation。当生成的代码直接引用其他来源(例如现有的开放源代码)的大量代码时,开发者便会看到这些信息。它提供了来源和许可,以便开发者决定如何处理。

假设我们没问题,现在就可以使用此规范文档为其生成 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 文件。只需将文件内容替换为代码助理生成的代码并保存文件即可。

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

app.run()

然后,在代码助理聊天界面中输入提示:Explain this.

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

58ec896a32a4fb68

现在,使用以下提示:

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 中的命令面板 (Ctrl+Shift+P),然后输入创建 Python 环境。按照接下来的几个步骤,选择虚拟环境 (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

让我们按照代码助手的建议,将数据划分到 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 列表,将我们的应用连接到 Firestore 数据库中的 sessions 集合(在该 Codelab 开头部分创建)。

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 询问需要将哪个 Python 模块添加到 requirements.txt 文件中的信息,如下所示:

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

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

10. 代码说明

现在是时候使用 Gemini Code Assist 的 "Explain this" 功能来充分了解代码了。您随时可以进入任何文件或选择特定的代码段,然后向 Code Assist 发出以下提示:Explain this

作为练习,访问 sessions.py 文件,突出显示 Firestore 专用代码,并获取该代码的说明。除了 Python 代码之外,您还可以尝试对项目中的其他文件使用此功能。

11. 生成 Web 应用

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

我们就直接进入正题吧。向代码助理显示以下提示:

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 的网络应用 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 文件存在,您只需将其内容替换为此处生成的新文件即可。代码助理还会提及在 app.py 文件中导入 render_template

接下来,将 Web 应用代码保存在 index.html 文件中,并记得将该文件放在 templates 文件夹中。

在本地运行应用

现在,我们在本地运行应用,以便根据最初的方式验证应用要求。

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

启动并运行后,请访问该应用的主网址。系统应显示 index.html 文件,如下所示:

8ca586acc4536879

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

165faded790a6c

一项可选练习是展示其他元数据,例如每节课程的时长、类别、演讲者和摘要。

12. 测试用例生成

我们已经生成了 Sessions 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 端点):

python tests.py

我们得到了以下摘要结果:

Ran 4 tests in 0.274s

FAILED (failures=2)

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

.

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

13. 测试驱动型开发

现在,我们来了解一下如何按照体验驱动开发 (TDD) 方法在 Sessions API 中添加新的搜索方法,即先编写测试用例,使其因缺少实现而失败,并使用 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 文件,然后向代码助理显示以下提示:

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?

您曾问过一件好事,因为我们实际上忘了将调试标志设置为 off:

2f87ed3a811fb218

如前所述,关闭调试功能,然后就 gcloud 命令向 Gemini Code Assist 寻求帮助。该命令可用于直接从源代码将应用部署到 Cloud Run(无需先构建容器)。

给出以下提示:

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) 中。然后,我们还可以使用 Observability Gemini 功能来了解日志条目。

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

我们先试着向 Code Assist 提问。请尝试以下提示:

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

您应该得到一个响应,其中提供了一些相关信息,如下所示:

2472e1ccaf8a217d

我们将日志记录语句添加到按类别搜索会话的函数中。

首先,将 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

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

914f1fb6cac30a89

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

示例响应如下所示:

7fc9783910fa92cc

16. 恭喜

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

后续操作

查看下列 Codelab…

参考文档