Thúc đẩy quy trình phát triển bằng Gemini Code Assist

1. Giới thiệu

e5b98fd4e417c877.png

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách Gemini Code Assist có thể hỗ trợ bạn trong các giai đoạn chính của Vòng đời phát triển phần mềm (SDLC) như thiết kế, xây dựng, kiểm thử và triển khai. Chúng tôi sẽ thiết kế và phát triển toàn bộ ứng dụng, đồng thời triển khai ứng dụng đó trên Google Cloud.

Chúng tôi sẽ xây dựng một API và ứng dụng để tìm kiếm trong nhiều phiên hoạt động của một sự kiện kỹ thuật. Mỗi phiên sẽ có một tiêu đề, phần tóm tắt, thời lượng, danh mục và một hoặc nhiều người nói.

Bạn sẽ thực hiện

  • Thiết kế, xây dựng, thử nghiệm và triển khai ứng dụng web dựa trên thông số kỹ thuật OpenAPI từ đầu

Kiến thức bạn sẽ học được

  • Cách sử dụng Gemini Code Assistant để tạo Thông số kỹ thuật OpenAPI
  • Cách sử dụng các tính năng tạo mã của Gemini Code Assist để phát triển một Ứng dụng Python Flask cho quy cách OpenAPI
  • Cách sử dụng Gemini Code Assistant để tạo giao diện người dùng web cho Ứng dụng Python Flask
  • Cách sử dụng Gemini Code Assistant để được hỗ trợ về cách triển khai ứng dụng cho Google Cloud Run
  • Sử dụng các tính năng Hỗ trợ viết mã của Gemini như Giải thích mã, Tạo trường hợp kiểm thử trong khi xây dựng và thử nghiệm ứng dụng

Bạn cần

  • Trình duyệt web Chrome
  • Tài khoản Gmail
  • Một dự án trên đám mây đã bật tính năng thanh toán
  • Tính năng Hỗ trợ mã Gemini đã được bật cho dự án của bạn trên Google Cloud

Phòng thí nghiệm này nhắm đến nhà phát triển ở mọi cấp độ, kể cả người mới bắt đầu. Mặc dù ứng dụng mẫu bằng ngôn ngữ Python, nhưng bạn không cần phải quen thuộc với lập trình Python để hiểu điều gì đang diễn ra. Trọng tâm của chúng tôi sẽ là làm quen với các chức năng của Gemini Code Assist.

2. Thiết lập tính năng Trợ lý mã Gemini

Phần này bao gồm mọi việc bạn cần làm để bắt đầu với phòng thí nghiệm này.

Bật tính năng Hỗ trợ mã Gemini trong IDE Cloud Shell

Chúng ta sẽ sử dụng Cloud Shell IDE, một môi trường phát triển dựa trên Mã OSS được quản lý hoàn toàn, cho phần còn lại của lớp học lập trình này. Chúng ta cần bật và định cấu hình tính năng Hỗ trợ mã trong IDE Cloud Shell và thực hiện các bước dưới đây:

  1. Truy cập vào ide.cloud.google.com. Có thể mất một chút thời gian để IDE xuất hiện. Vì vậy, hãy kiên nhẫn và chấp nhận mọi lựa chọn thiết lập mặc định. Trong trường hợp bạn thấy một số hướng dẫn về cách thiết lập IDE, vui lòng tiếp tục và hoàn tất các hướng dẫn đó với chế độ cài đặt mặc định.
  2. Nhấp vào nút Cloud Code – Đăng nhập trên thanh trạng thái ở dưới cùng như minh hoạ. Uỷ quyền trình bổ trợ theo hướng dẫn. Nếu bạn thấy dòng chữ "Cloud Code - no project" (Mã đám mây – không có dự án) trên thanh trạng thái, hãy chọn mục đó rồi chọn Dự án Google Cloud cụ thể trong danh sách các dự án mà bạn dự định hợp tác.

6f5ce865fc7a3ef5.png.

  1. Nhấp vào nút Code Assist ở góc dưới cùng bên phải như minh hoạ và chọn lần cuối cùng vào đúng dự án Google Cloud. Nếu bạn được yêu cầu bật Cloud AI Companion API, vui lòng bật và tiếp tục.
  2. Sau khi chọn dự án trên Google Cloud, hãy đảm bảo rằng bạn có thể thấy điều đó trong thông báo trạng thái Mã đám mây trên thanh trạng thái và bạn cũng đã bật tính năng Hỗ trợ mã ở bên phải, trên thanh trạng thái như sau:

709e6c8248ac7d88.pngS

Trợ lý mã Gemini đã sẵn sàng cho bạn sử dụng!

3. Thiết lập Firestore

Cloud Firestore là cơ sở dữ liệu tài liệu không máy chủ được quản lý hoàn toàn và chúng tôi sẽ dùng làm cơ sở dữ liệu phụ trợ cho dữ liệu ứng dụng. Dữ liệu trong Cloud Firestore được tổ chức thành các bộ sưu tập tài liệu.

Chúng ta cần tạo một tập hợp có tên sessions trong cơ sở dữ liệu mặc định của Firestore. Bộ sưu tập này sẽ lưu giữ dữ liệu mẫu (tài liệu) mà sau đó chúng tôi sẽ sử dụng trong đơn đăng ký của mình.

Mở Terminal từ bên trong IDE Cloud Shell thông qua trình đơn chính như minh hoạ dưới đây:

f1535e14c9beeec6.png

Chúng ta cần tạo một tập hợp có tên sessions. Thao tác này sẽ lưu giữ danh sách các tài liệu mẫu của phiên. Mỗi tài liệu sẽ có các thuộc tính sau:

  1. title: chuỗi
  2. category: mảng chuỗi
  3. speakers: mảng chuỗi
  4. duration: chuỗi
  5. tóm tắt: chuỗi

Hãy điền dữ liệu mẫu vào bộ sưu tập này bằng cách sao chép một tệp có chứa dữ liệu mẫu vào một bộ chứa trong dự án của riêng bạn, từ đó bạn có thể nhập bộ sưu tập thông qua lệnh gcloud firestore import.

Firestore Khởi tạo cơ sở dữ liệu

Truy cập vào trang Khôi phục dữ liệu trong bảng điều khiển Cloud.

Nếu trước đó bạn chưa khởi động cơ sở dữ liệu Firestore trong dự án, hãy tạo cơ sở dữ liệu default. Trong quá trình tạo cơ sở dữ liệu, hãy sử dụng các giá trị sau:

  • Chế độ Firestore: Native
  • Vị trí: Chọn Loại vị trí là Region rồi chọn khu vực phù hợp với ứng dụng của bạn. Ghi lại vị trí này vì bạn sẽ cần đến vị trí này trong bước tiếp theo đối với vị trí nhóm.
  • Tạo Database (Cơ sở dữ liệu).

504cabdb99a222a5.pngs

Bây giờ, chúng ta sẽ tạo tập hợp sessions bằng cách làm theo các bước dưới đây:

  1. Tạo một bộ chứa trong dự án bằng lệnh gsutil được cung cấp bên dưới. Thay thế biến <PROJECT_ID> trong lệnh bên dưới bằng mã dự án trên Google Cloud. Thay thế <BUCKET_LOCATION> bằng tên khu vực tương ứng với Khu vực địa lý của cơ sở dữ liệu Firestore mặc định của bạn (như đã lưu ý trong bước trước), tên này có thể là US-WEST1, EUROPE-WEST1, ASIA-EAST1 :
gsutil mb -l <BUCKET-LOCATION> gs://<PROJECT_ID>-my-bucket
  1. Bây giờ, khi đã tạo bộ chứa, chúng ta cần sao chép tệp xuất cơ sở dữ liệu mà chúng ta đã chuẩn bị vào bộ chứa này, trước khi có thể nhập dữ liệu đó vào cơ sở dữ liệu Firebase. Sử dụng lệnh được cung cấp dưới đây:
gsutil cp -r gs://sessions-master-database-bucket/2024-03-26T09:28:15_95256  gs://<PROJECT_ID>-my-bucket

Bây giờ, chúng ta đã có dữ liệu để nhập, chúng ta có thể chuyển sang bước cuối cùng là nhập dữ liệu vào cơ sở dữ liệu Firebase (default) mà chúng ta đã tạo.

  1. Hãy dùng lệnh gcloud dưới đây:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2024-03-26T09:28:15_95256

Quá trình nhập sẽ mất vài giây và khi đã sẵn sàng, bạn có thể xác thực cơ sở dữ liệu Firestore và tập hợp dữ liệu của mình bằng cách truy cập https://console.cloud.google.com/firestore/databases, chọn cơ sở dữ liệu default và tập hợp sessions như minh hoạ dưới đây:

d3e294d46ba29cd5.png

Đến đây, chúng ta sẽ tạo xong tập hợp Firestore mà chúng ta sẽ dùng trong ứng dụng.

4. Tạo mẫu đơn đăng ký

Chúng ta sẽ tạo một ứng dụng mẫu (ứng dụng Python Flask) mà chúng ta sẽ sử dụng trong phần còn lại của lớp học lập trình này. Ứng dụng này sẽ tìm kiếm trong các phiên được cung cấp tại hội nghị kỹ thuật.

Hãy làm theo các bước sau:

  1. Nhấp vào tên dự án trên Google Cloud trên thanh trạng thái bên dưới.

f151759c156c124e.png

  1. Một danh sách các lựa chọn sẽ xuất hiện. Nhấp vào New Application (Ứng dụng mới) trong danh sách bên dưới.

91ea9836f38b7f74.pngS

  1. Chọn Cloud Run application (ứng dụng Cloud Run) (đây sẽ là môi trường thời gian chạy cho ứng dụng của chúng ta).
  2. Chọn mẫu ứng dụng Python (Flask): Cloud Run.
  3. Đặt tên cho ứng dụng và lưu ứng dụng đó vào vị trí bạn muốn.
  4. Một thông báo xác nhận rằng ứng dụng của bạn đã được tạo, đồng thời một cửa sổ mới sẽ mở ra cùng với ứng dụng được tải như minh hoạ dưới đây. Đang mở một tệp README.md. Bây giờ, bạn có thể đóng chế độ xem đó.

aaa3725b17ce27cf.png

5. Tương tác với Trợ lý mã của Gemini

Trong phạm vi của phòng thí nghiệm này, chúng tôi sẽ sử dụng Gemini Code Assist Chat có trong Cloud Shell IDE như một phần của tiện ích Cloud Code trong VS Code. Bạn có thể hiển thị tính năng này bằng cách nhấp vào nút Hỗ trợ mã trong thanh điều hướng bên trái. Tìm biểu tượng Hỗ trợ mã a489f98a34898727.pngtrong thanh công cụ điều hướng bên trái và nhấp vào đó.

Thao tác này sẽ hiển thị ngăn trò chuyện của tính năng Hỗ trợ mã trong IDE Cloud Shell và bạn có thể trò chuyện với Code Assist.

14ad103efaa0ddaa.png.

Lưu ý biểu tượng thùng rác ở trên cùng – đây là cách bạn dùng để đặt lại ngữ cảnh cho lịch sử trò chuyện của tính năng Hỗ trợ mã. Ngoài ra, xin lưu ý rằng hoạt động tương tác này theo bối cảnh đối với(các) tệp mà bạn đang xử lý trong IDE.

6. Thiết kế API

Bước đầu tiên, chúng ta sẽ yêu cầu Trợ lý mã của Gemini hỗ trợ trong giai đoạn Thiết kế. Ở bước này, chúng ta sẽ tạo thông số kỹ thuật OpenAPI cho các thực thể (phiên kỹ thuật trong một sự kiện) mà chúng ta muốn tìm kiếm trên đó.

Đưa ra câu lệnh sau:

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.

Thao tác này sẽ tạo ra một Bản đặc tả OpenAPI để tìm kiếm trong nhiều phiên hoạt động thông qua nhiều tham số truy vấn. Thông số kỹ thuật mẫu được cung cấp dưới đây:

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

Bạn có thể nhận thấy rằng thông số kỹ thuật có những thông tin sau:

  • Giản đồ được xác định cho Loại phiên.
  • Một số đường dẫn API đã xác định:
  • /sessions
  • /sessions/{id}
  • /sessions/categories/{category}

Tạo một tệp có tên là sessionsapi.yaml ở thư mục trên cùng rồi sao chép nội dung từ cửa sổ trò chuyện Hỗ trợ mã bằng cách sử dụng "insert in current file options" (nút +) và tiếp tục mở tệp trong Cloud Shell IDE.

Tới đây, bạn có thể ghi chú một tính năng thú vị của Trợ lý mã Gemini: trích dẫn. Thông tin này sẽ được hiển thị cho nhà phát triển khi mã được tạo trực tiếp trích dẫn toàn bộ từ một nguồn khác, chẳng hạn như mã nguồn mở hiện có. Phần này cung cấp nguồn và giấy phép để nhà phát triển quyết định việc cần làm với nguồn và giấy phép đó.

Giả sử chúng tôi hài lòng với nội dung được tạo, giờ đây chúng tôi có thể sử dụng tài liệu thông số kỹ thuật này để tạo Ứng dụng Python Flask cho nội dung đó.

7. Tạo ứng dụng

Bây giờ, chúng ta sẽ yêu cầu Code Assist tạo ứng dụng. Đưa ra câu lệnh sau với tệp sessionsapi.yaml đang mở.

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.

Lộ trình này sẽ cung cấp cho bạn một bộ khung cho Ứng dụng Python Flask dựa trên chức năng và đường dẫn đã được chỉ định trong tệp thông số kỹ thuật OpenAPI.

Mã ứng dụng Python Flask được cung cấp phải tương tự như mã sau:

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()

Hiện có một tệp app.py được tạo trong bước trước đó. Chỉ cần thay thế nội dung của tệp bằng mã do tính năng Hỗ trợ mã tạo và lưu tệp.

Chúng ta muốn thay đổi dòng app.run() để sử dụng cổng 8080, địa chỉ máy chủ lưu trữ 0.0.0.0, đồng thời chạy ở chế độ Gỡ lỗi trong quá trình thực thi cục bộ.Đây là cách để thực hiện điều đó. Đầu tiên, hãy đánh dấu/chọn dòng:

app.run()

Sau đó, trong giao diện Trò chuyện hỗ trợ mã, hãy nhập lời nhắc: Explain this.

Thao tác này sẽ hiển thị nội dung giải thích chi tiết về dòng cụ thể đó, ví dụ như dưới đây:

58ec896a32a4fb68.pngS

Bây giờ, hãy sử dụng câu lệnh sau:

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

Mã đề xuất được tạo sẽ như sau: :

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

Hãy nhớ cập nhật tệp app.py bằng đoạn mã này.

Chạy ứng dụng trên máy

Hãy chạy ứng dụng cục bộ ngay bây giờ để xác thực các yêu cầu của ứng dụng theo như chúng ta đã bắt đầu.

Bước đầu tiên sẽ là tạo một môi trường Python ảo với các phần phụ thuộc của gói Python trong requirements.txt để cài đặt trong môi trường ảo. Để thực hiện, hãy chuyển đến Command Palette (Bảng lệnh) (Ctrl+Shift+P) trong Cloud Shell IDE rồi nhập Create Python môi trường. Làm theo vài bước tiếp theo để chọn tệp Môi trường ảo (venv), trình thông dịch Python 3.x và tệp requirements.txt.

Sau khi tạo môi trường, hãy mở một cửa sổ dòng lệnh mới (Ctrl+Shift+`) và nhập lệnh sau:

python app.py

Dưới đây là một ví dụ về hoạt động thực thi:

(.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

Bạn hiện có thể xem trước API tại các URL sau. Chúng tôi giả định rằng máy chủ phát triển của bạn đang chạy trên cổng 8080. Nếu không, vui lòng thay đổi thành số cổng phù hợp.

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

Hãy làm theo các bước dưới đây để đảm bảo rằng bạn có thể truy xuất bằng những URL này, tức là dữ liệu JSON có trong tệp app.py:

Mở một cửa sổ dòng lệnh mới rồi thử bất kỳ lệnh nào sau đây:

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. Tái cấu trúc mã

Thay vì để app.py chứa dữ liệu JSON mẫu được cố định giá trị trong mã, có thể chúng ta sẽ muốn tách/trích xuất dữ liệu này vào một mô-đun khác để có thể duy trì sự tách biệt rõ ràng giữa mã và dữ liệu. Hãy bắt đầu nào!

Tiếp tục mở tệp app.py và đưa ra lời nhắc sau:

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

Thao tác này sẽ cung cấp cho bạn một số đề xuất về cách thực hiện việc đó. Dưới đây là một đề xuất mẫu mà chúng tôi đã nhận được và bạn sẽ nhận được kết quả tương tự như đề xuất này:

9b9c56cb527dac4c.png.

Hãy làm theo điều đó và tách dữ liệu của chúng ta thành một tệp sessions.py do tiện ích Hỗ trợ mã đề xuất.

Tạo một tệp mới có tên sessions.py

, nội dung trong danh sách JSON, theo dữ liệu đã tạo được cung cấp dưới đây:

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",
   },
]

Tệp app.py hiện đã được đơn giản hoá rất nhiều và hiển thị bên dưới:

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)

Đảm bảo rằng bạn vẫn có thể chạy ứng dụng trên máy và thực thi API bằng những thay đổi được tái cấu trúc này. Máy chủ phát triển python có thể vẫn đang chạy nên bạn chỉ cần thu hồi các lệnh curl ở bước trước.

9. Tích hợp với Bộ sưu tập Firestore

Bước tiếp theo là rời khỏi danh sách JSON cục bộ trong bộ nhớ mà chúng ta có cho các phiên của mình và kết nối ứng dụng với tập hợp sessions trong cơ sở dữ liệu Firestore mà chúng ta đã tạo ở đầu lớp học lập trình này.

Tiếp tục mở tệp sessions.py và đưa ra lời nhắc sau:

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. 

Chúng tôi nhận được đề xuất sau đây để đọc tất cả các phiên trong tập hợp 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)

Hãy tiếp tục và tích hợp mã vào sessions.py.

Nếu máy chủ Flask Development của bạn đang chạy thì có thể ứng dụng của bạn đã đóng khi không tìm thấy mô-đun Python.

Ví dụ: bạn có thể hỏi Code Assist về việc cần thêm mô-đun Python vào tệp requirements.txt như sau:

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

Thao tác này sẽ cho bạn tên của mô-đun Python (ví dụ: google-cloud-firestore). Thêm tên đó vào tệp requirements.txt.

Bạn cần tạo lại môi trường Python bằng mô-đun mới thêm (google-cloud-firestore). Để thực hiện việc này, hãy nhập lệnh sau trong cửa sổ dòng lệnh hiện tại:

pip install -r requirements.txt

Chạy lại ứng dụng (khởi động lại bằng python app.py) rồi truy cập vào URL của /sessions. Bây giờ, bạn sẽ nhận được các tài liệu mẫu mà chúng tôi đã thêm vào bộ sưu tập sessions.

975d05e6518f1a6a.pngS

Vui lòng truy vấn các URI khác để truy xuất các phiên cụ thể hoặc tất cả các phiên cho một danh mục nhất định như được mô tả ở các bước trước.

10. Giải thích về mã

Bây giờ là thời điểm thích hợp để sử dụng tính năng "Explain this" của Trợ lý mã Gemini để hiểu rõ về mã. Vui lòng truy cập vào bất kỳ tệp nào hoặc chọn các đoạn mã cụ thể rồi yêu cầu Code Hỗ trợ bằng lời nhắc sau: Explain this.

Để làm bài tập, hãy truy cập vào tệp sessions.py và đánh dấu mã cụ thể trên Firestore, sau đó xem nội dung giải thích về đoạn mã đó. Hãy thử sử dụng tính năng này trên các tệp khác trong dự án của bạn, không chỉ trên mã python.

11. Tạo ứng dụng web

Bây giờ, chúng ta đã tạo API và tích hợp API đó với bộ sưu tập Firestore trực tiếp, hãy để chúng ta tạo giao diện người dùng dựa trên nền tảng web cho ứng dụng. Hiện tại, giao diện người dùng Web của chúng tôi sẽ giữ chức năng ở mức tối thiểu, tức là có thể tìm kiếm các phiên thuộc một danh mục cụ thể. Hãy lưu ý rằng chúng ta có đường dẫn API cho việc đó, tức là /sessions/categories/{category}, vì vậy ứng dụng web của chúng ta sẽ gọi lệnh đó và truy xuất kết quả.

Chúng ta hãy cùng tìm hiểu kỹ hơn nhé. Đưa ra lời nhắc sau cho Hỗ trợ mã:

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.

Thao tác này sẽ tạo HTML ứng dụng web có JavaScript và CSS được nhúng trong đó. Trang này cũng sẽ yêu cầu bạn thêm tuyến mới vào tệp app.py để mọi người dùng truy cập vào URL gốc hoặc URL cơ sở đều sẽ được phân phát trang chủ. Nếu trang web không đề cập đến thông tin đó, hãy hỏi về thông tin đó hoặc sử dụng đoạn trích dưới đây:

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

Bạn có thể lưu tệp này dưới dạng index.html nhưng có thể có thắc mắc về vị trí lưu tệp này (tức là thư mục nào?). Chúng ta có thể đặt một câu hỏi tiếp theo cho Hỗ trợ mã.

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

Phần tử này sẽ cung cấp cho bạn thông tin rõ ràng về việc tệp này sử dụng khung render_template, do đó, bạn cần đặt tệpindex.html bên trong thư mục templates. Bạn sẽ thấy thư mục này vì chúng ta đã tạo một Ứng dụng dựa trên mẫu Flask ở đầu lớp học lập trình này. Do đó, đã có một tệp index.html và bạn chỉ cần thay thế nội dung của tệp đó bằng nội dung mới được tạo tại đây. Tính năng Hỗ trợ mã cũng đề cập đến việc nhập render_template trong tệp app.py của bạn.

Hãy tiếp tục và lưu mã xử lý ứng dụng web vào tệp index.html, đồng thời nhớ đặt tệp đó vào thư mục templates.

Chạy ứng dụng trên máy

Hãy chạy ứng dụng cục bộ ngay bây giờ để xác thực các yêu cầu của ứng dụng theo như chúng ta đã bắt đầu.

Đảm bảo rằng máy chủ Flask cục bộ vẫn đang chạy và không hiển thị lỗi nào. Nếu xảy ra lỗi, hãy xử lý chúng và khởi động máy chủ.

Sau khi thiết lập và chạy, hãy truy cập vào URL trang chủ của ứng dụng. Bạn sẽ thấy tệp index.html được phân phát như dưới đây:

8ca586acc4536879.pngS

Cung cấp một trong các danh mục của dữ liệu làm dữ liệu đầu vào (ví dụ: AI) rồi nhấp vào nút Search. Thao tác này sẽ hiển thị các phiên được gắn thẻ bằng danh mục AI.

165fad790a6c.png.

Một bài tập không bắt buộc là trình bày siêu dữ liệu bổ sung như thời lượng, danh mục, người nói và bản tóm tắt cho từng phiên sự kiện.

12. Tạo trường hợp kiểm thử

Chúng tôi đã tạo API phiên và đã đến lúc sử dụng Gemini Code Assist ngay bây giờ để tạo các trường hợp kiểm thử đơn vị cho nhiều Đường dẫn API.

Tiếp tục mở tệp app.py và đưa ra lời nhắc sau:

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

Chúng tôi đã nhận được phản hồi như sau:

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()

Tạo một tệp có tên tests.py bằng đoạn mã ở trên.

Lưu ý về việc tạo trường hợp thử nghiệm

Bạn có thể thấy danh sách mã khác với danh sách ở trên và điều này có thể gây ra một số sự cố khi chạy các trường hợp kiểm thử. Ví dụ: chúng ta thấy trong một số lần chạy, các đoạn mã chính sau đây bị bỏ lỡ:

from app import app

Bạn phải có đoạn mã trên để nhập Ứng dụng Flask hiện có mà chúng ta sẽ gọi các trường hợp kiểm thử.

if __name__ == '__main__':

`unittest.main()`

Cần có mã ở trên để chạy các trường hợp kiểm thử.

Bạn nên xem xét từng trường hợp kiểm thử, kiểm tra assertEqual và các điều kiện khác trong mã đã tạo để đảm bảo mã sẽ hoạt động. Vì dữ liệu nằm bên ngoài trong bộ sưu tập Firestore, nên có thể dữ liệu sẽ không truy cập được vào dữ liệu đó và có thể sử dụng một số dữ liệu giả khiến quá trình kiểm thử có thể không thành công. Vì vậy, hãy sửa đổi các trường hợp kiểm thử cho phù hợp hoặc nhận xét về một số trường hợp kiểm thử mà bạn có thể chưa cần ngay.

Để minh hoạ, chúng ta đã chạy các trường hợp kiểm thử bằng lệnh sau (Hãy nhớ chạy máy chủ phát triển cục bộ vì các lệnh gọi sẽ được thực hiện đến Điểm cuối API cục bộ):

python tests.py

Chúng tôi có kết quả tóm tắt như sau:

Ran 4 tests in 0.274s

FAILED (failures=2)

Điều đó thực sự đúng vì id phiên không chính xác trong thử nghiệm thứ 3 và không có danh mục nào có tên category1

.

Vì vậy, hãy điều chỉnh các trường hợp thử nghiệm cho phù hợp và tiến hành thử nghiệm.

13. Phát triển dựa trên kiểm thử

Bây giờ, chúng ta hãy xem xét cách thêm một phương thức tìm kiếm mới trong API phiên theo phương pháp Phát triển dựa trên kiểm thử (TDD), tức là về việc viết các trường hợp kiểm thử trước, khiến phương thức này không thành công do thiếu triển khai và sử dụng Gemini Code Assist để tạo phương thức triển khai bị thiếu sao cho kiểm thử thành công.

Chuyển đến tệp test.py (giả sử bạn đã sửa tệp tests.py để tất cả các lượt kiểm thử đều đạt). Hỏi Code Hỗ trợ lời nhắc sau:

Generate a new test case to search for sessions by speaker

Việc này đã giúp chúng tôi triển khai trường hợp kiểm thử sau đây mà chúng tôi đã chèn chính xác vào tệp 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]])

Nếu chạy kiểm thử, bạn sẽ thấy lỗi sau:

$ 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)

Điều này là do trường hợp kiểm thử đã gọi đường dẫn sau (/sessions/speakers/) và không có quy trình triển khai đường dẫn đó trong app.py.

Hãy để chúng tôi yêu cầu Code Assist cung cấp cho chúng tôi bản triển khai. Chuyển đến tệp app.py và đưa ra lời nhắc sau cho Trợ lý mã:

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

Chúng ta đã nhận được cách triển khai sau do tính năng Hỗ trợ mã đề xuất và đã thêm vào tệp 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)

Xem lại tệp tests.py và chúng ta đã sửa đổi trường hợp kiểm thử như sau để kiểm tra nhanh:

   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)

Cuộc thử nghiệm diễn ra tốt đẹp. Chúng tôi sẽ coi đây là một bài tập để bạn xem xét các trường hợp kiểm thử được tạo, điều chỉnh chúng một chút tuỳ theo dữ liệu mà bạn có thể có trong Firestore và có các phương thức assert* thích hợp trong các trường hợp Kiểm thử đơn vị Python.

14. Triển khai cho Google Cloud Run

Giờ đây, khi đã hài lòng về chất lượng phát triển, bước cuối cùng là triển khai ứng dụng này lên Google Cloud Run. Nhưng có lẽ, để có biện pháp tốt, chúng ta nên yêu cầu Hỗ trợ mã xem có quên gì không. Khi app.py đang mở, hãy gửi câu lệnh sau :

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

Cảm ơn bạn đã hỏi vì chúng tôi thực sự đã quên đặt cờ gỡ lỗi thành tắt :

2f87ed3a811fb218.pngS

Như đã hướng dẫn, hãy tắt tính năng gỡ lỗi rồi tiếp tục yêu cầu Trợ lý mã của Gemini trợ giúp bằng lệnh gcloud. Lệnh này có thể dùng để triển khai ứng dụng lên Cloud Run ngay từ nguồn (mà không phải tạo vùng chứa trước).

Đưa ra câu lệnh sau:

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

Hãy thử một vài biến thể của lời nhắc ở trên. Một cách khác mà chúng tôi đã thử là:

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?

Tốt nhất là bạn sẽ nhận được lệnh gcloud sau:

gcloud run deploy sessions --source .

Bạn cũng có thể nhận được:

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

Thực thi lệnh trên từ thư mục gốc của ứng dụng. Khi được yêu cầu region, hãy chọn us-central1 và khi được yêu cầu cho phép unauthenticated invocations, hãy chọn Y. Bạn cũng có thể được yêu cầu bật Google Cloud API như Artifact Registry, Cloud Build và Cloud Run cũng như quyền tạo kho lưu trữ Artifact Registry, vui lòng tiếp tục và cấp quyền.

Quá trình triển khai sẽ mất khoảng 2 phút để hoàn tất, do đó hãy kiên nhẫn.

Sau khi triển khai thành công, bạn sẽ thấy URL dịch vụ Cloud Run. Truy cập URL công khai đó và bạn sẽ thấy cùng một ứng dụng web được triển khai và chạy thành công.

c5322d0fd3e0f616.png

Xin chúc mừng, bạn rất xuất sắc!

15. (Không bắt buộc) Sử dụng tính năng Ghi nhật ký trên đám mây

Chúng tôi có thể triển khai tính năng ghi nhật ký trong ứng dụng của mình để tập trung nhật ký ứng dụng vào một trong các dịch vụ của Google Cloud (Cloud Logging). Sau đó, chúng ta cũng có thể dùng tính năng Gemini có thể quan sát để tìm hiểu các mục nhật ký.

Để làm được việc này, trước tiên, chúng tôi sẽ phải sử dụng một thư viện Python Cloud Logging hiện có của Google Cloud và dùng thư viện đó để ghi nhật ký các thông báo thông tin, cảnh báo hoặc lỗi (tuỳ thuộc vào mức độ nghiêm trọng / mức độ nghiêm trọng của nhật ký).

Trước tiên, hãy thử yêu cầu tính năng Hỗ trợ mã. Hãy thử câu lệnh sau:

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

Bạn sẽ nhận được phản hồi cung cấp một số thông tin về vấn đề đó, như được cung cấp dưới đây:

2472e1ccaf8a217d.png.

Hãy thêm các câu lệnh ghi nhật ký vào hàm tìm kiếm phiên theo danh mục.

Trước tiên, hãy thêm gói Python google-cloud-logging vào tệp requirements.txt.

Tiếp theo là một đoạn mã cho thấy cách chúng tôi tích hợp mã đó để triển khai tính năng ghi nhật ký:

...
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

Triển khai lại dịch vụ cho Cloud Run bằng cách dùng lệnh như trong phần trước. Sau khi dịch vụ được triển khai, hãy thực thi một vài lệnh gọi đến điểm cuối /sessions/categories/<category>.

Chuyển đến Cloud Console → Logs Explorer

59e297577570695.pngS

...và bạn sẽ có thể lọc ra các câu lệnh ghi nhật ký này như được hiển thị bên dưới:

914f1fb6cac30a89.pngS

Bạn có thể nhấp vào bất kỳ câu lệnh nhật ký nào, mở rộng câu lệnh đó rồi nhấp vào Explain this log entry. Thao tác này sẽ sử dụng Gemini để giải thích mục nhập nhật ký. Xin lưu ý rằng nếu chưa bật Gemini cho Google Cloud, bạn sẽ được yêu cầu bật Cloud AI Companion API. Vui lòng tiếp tục và làm việc đó theo hướng dẫn.

Dưới đây là câu trả lời mẫu:

7fc9783910fa92cc.pngS

16. Xin chúc mừng

Xin chúc mừng! Bạn đã xây dựng thành công một ứng dụng từ đầu và sử dụng Gemini Code Assist trong nhiều khía cạnh của SDLC như thiết kế, xây dựng, kiểm thử và triển khai.

Tiếp theo là gì?

Hãy xem một số lớp học lập trình này...

Tài liệu tham khảo