Triển khai Imagen cho Cloud Run

1. Thông tin về lớp học lập trình này

Lần cập nhật gần đây nhất: 11/10/2024

Tác giả: Laurie White

Tạo hình ảnh

Thành thật mà nói, việc tạo hình ảnh bằng Mô hình ngôn ngữ lớn (LLM) có thể rất thú vị. Tất nhiên, có rất nhiều ứng dụng kinh doanh để tạo hình ảnh từ câu lệnh, từ quảng cáo tuỳ chỉnh đến bản trình bày hấp dẫn. (Trang web Google Cloud có nhiều trường hợp sử dụng cụ thể của các công ty sử dụng Tác nhân sáng tạo.) Tuy nhiên, việc xem kết quả khi bạn yêu cầu hình ảnh "chó màu xanh lục đang vui vẻ trên cánh đồng" có thể khá thú vị.

Cho dù bạn quan tâm đến việc tạo hình ảnh vì lý do chuyên nghiệp hay giải trí (hoặc cả hai!), thì vẫn có một số thách thức giữa việc sử dụng chương trình tạo hình ảnh và triển khai chương trình đó cho một ứng dụng web. Phòng thí nghiệm này sẽ giúp bạn vượt qua những thách thức đó.

Sản phẩm bạn sẽ tạo ra

Trong lớp học lập trình này, bạn sẽ xây dựng một ứng dụng sẽ nhận một câu lệnh văn bản và trả về một trang web có hình ảnh được tạo bằng câu lệnh đó.

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

Trong lớp học lập trình này, bạn sẽ tìm hiểu:

  • Cách sử dụng Google Imagen để tạo hình ảnh từ câu lệnh văn bản trong môi trường sổ tay
  • Khó khăn khi di chuyển mã Imagen từ sổ tay sang ứng dụng web
  • Cách triển khai một ứng dụng Cloud Run sử dụng Imagen để tạo hình ảnh
  • Cách đưa hình ảnh từ Imagen vào HTML

Lớp học lập trình này tập trung vào Imagen và hoạt động triển khai. Các khái niệm và khối mã không liên quan được tinh chỉnh và cung cấp cho bạn, chỉ cần sao chép và dán.

Bạn cần có

Bạn có thể xem mã hoàn chỉnh cho lớp học lập trình này tại https://github.com/Annie29/imagen-deployment .

2. Bật API

Chọn một dự án để sử dụng cho lớp học lập trình này. Bạn nên tạo một dự án mới để dễ dàng xoá tất cả công việc khi hoàn tất.

Trước khi có thể bắt đầu sử dụng Imagen, bạn cần bật một số API.

  1. Truy cập vào Google Cloud Console.
  2. Chuyển đến Trang tổng quan Vertex AI.
  3. Chọn "Bật tất cả API được đề xuất"

a8f336f7380a9eab.png

3. Khám phá Google Imagen (không bắt buộc)

Nếu đã quen thuộc với Imagen, bạn có thể bỏ qua phần này.

Trước khi tìm cách tạo một ứng dụng web sử dụng Imagen, bạn nên tìm hiểu xem Imagen có thể làm được gì. May mắn thay, có một số sổ ghi chạy mã Imagen đơn giản, vì vậy, hãy bắt đầu với một trong số đó.

  1. Truy cập vào sổ tay tại https://github.com/GoogleCloudPlatform/generative-ai/blob/main/vision/getting-started/image_generation.ipynb .
  2. Chọn Mở trong Colab để mở sổ tay trong máy chủ sổ tay của Google.
  3. Chọn "Tệp -> Lưu bản sao trong Drive" hoặc nhấp vào "Sao chép vào Drive" ở đầu trang để tạo bản sao của riêng bạn cho sổ tay này.
  4. Đóng bản sao gốc (chỉ để tránh làm việc trong bản sao không chính xác!).
  5. Bạn cần kết nối với một môi trường thời gian chạy bằng cách nhấp vào nút Kết nối ở trên cùng bên phải. 2afdc8fa660a89bd.png
  6. Bắt đầu xử lý từng ô trong sổ tay.
  7. Để chạy một ô, bạn có thể nhấp vào biểu tượng [] hoặc mũi tên ở bên trái ô hoặc sử dụng tuỳ chọn Run Selection (Chạy lựa chọn) trong trình đơn Runtime (Thời gian chạy) (hoặc phím tắt của tuỳ chọn này): dfec032ef6c31296.png
  8. Khi khởi động lại môi trường thời gian chạy hiện tại, bạn sẽ nhận được thông báo hệ thống đã gặp sự cố. Đừng lo lắng! Đây là điều bình thường.
  9. Bạn cần xác thực môi trường sổ tay.
  10. Bạn có thể nhập mã dự án (không phải tên) và vị trí (us-central1 hoạt động nếu bạn chưa đặt vị trí) vào các hộp ở bên phải mã và để Colab chèn các thông tin đó vào mã cho bạn.
  11. Khi đến phần "Tạo hình ảnh", bạn sẽ có cơ hội xem những gì Imagen có thể làm. Hãy thay đổi câu lệnh và chạy lại ô để xem nhiều hình ảnh mà bạn có thể nhận được.
  12. Đến đây, bạn đã hiểu rõ cách Imagen có thể tạo hình ảnh từ sổ tay. Bạn có thể hoàn tất sổ tay này để xem thêm về các tham số hình ảnh ngay bây giờ hoặc vào thời điểm thuận tiện.

4. Bắt đầu tạo một ứng dụng web để hiển thị hình ảnh

Chúng ta sẽ sử dụng Python thông qua khung Flask trên Cloud Run để xây dựng ứng dụng.

Các ứng dụng Python Flask được thiết lập trong một thư mục như sau:

app-folder
    templates
        template.html
        (etc.)
        anothertemplate.html
    main.py
    requirements.txt

Mẫu là các tệp chứa HTML, thường có phần giữ chỗ được đặt tên mà chương trình sẽ chèn văn bản đã tạo. main.py là chính ứng dụng máy chủ web và requirements.txt là danh sách tất cả thư viện không chuẩn mà main.py sử dụng.

Ứng dụng sẽ có hai trang – trang đầu tiên để nhận lời nhắc và trang thứ hai để hiển thị hình ảnh và cho phép người dùng nhập một lời nhắc khác.

Trước tiên, hãy tạo khung dự án.

Tạo cấu trúc tệp

Lớp học lập trình này giả định dự án của bạn nằm trong thư mục imageapp. Nếu bạn sử dụng tên khác, hãy nhớ cập nhật các lệnh cho phù hợp.

Truy cập vào Cloud Shell bằng cách chọn biểu tượng lời nhắc ở phía trên cùng bên phải màn hình.

28135f700c5b12b0.png

Bạn có thể có thêm không gian để làm việc nếu di chuyển shell sang một thẻ mới bằng cách sử dụng mũi tên ở đầu cửa sổ shell:

310422ac131813e1.png

Trong thư mục gốc của bạn trong Cloud Shell, hãy tạo thư mục imageapp, chuyển sang thư mục đó rồi tạo thư mục templates. Bạn có thể thực hiện việc này từ dòng lệnh hoặc trình chỉnh sửa Cloud Shell.

Tạo mẫu

Ứng dụng sẽ có hai trang – trang đầu tiên (chúng ta sẽ gọi là home.html) để nhận lời nhắc và trang thứ hai (chúng ta sẽ gọi là display.html) để hiển thị hình ảnh và cho phép người dùng nhập một lời nhắc khác.

Sử dụng trình chỉnh sửa Cloud Shell hoặc trình chỉnh sửa Linux mà bạn chọn, hãy tạo hai mẫu. Trong thư mục imageapp/templates, hãy tạo trang ban đầu mà người dùng sẽ thấy, home.html. Phương thức này sử dụng biến prompt để trả về nội dung mô tả mà người dùng nhập.

templates/home.html

<!DOCTYPE html>
<html>
   <head>
       <title>Let's draw a picture</title>
   </head>
   <body>
       <h1>Let's draw a picture</h1>
       <form  action="/" method="post" >
           <input type="text" id="prompt" name="prompt">
           <input type="submit" value="Send">
       </form>
   </body>
</html>

Sau đó, hãy tạo display.html để hiển thị hình ảnh. Lưu ý rằng vị trí của hình ảnh sẽ nằm trong image_url.

templates/display.html

<!DOCTYPE html>
<html>
   <head>
       <title>Let's draw a picture</title>
   </head>
   <body>
       <h1>Let's draw a picture</h1>

       <div>
           <form  action="/" method="post" >
               <input type="text" id="prompt" name="prompt">
               <input type="submit" value="Send">
           </form>

           <p></p>
       </div>

       <div id="picture">
           <img id="pict" name="pict" alt="The created image" src="{{image_uri}}" style="width:100%;">
       </div>

   </body>
</html>

5. Bắt đầu mã

Bạn cần tạo tệp requirements.txt để đảm bảo tất cả thư viện mà chương trình của bạn cần đều có sẵn. Hiện tại, bạn chỉ cần đưa flask vào tệp requirements.txt.

Tệp main.py chứa mã sẽ phân phát các yêu cầu web. Chúng ta chỉ phải xử lý hai yêu cầu: yêu cầu GET cho trang chủ và yêu cầu POST gửi biểu mẫu mô tả hình ảnh mà chúng ta muốn tạo.

Sử dụng trình chỉnh sửa Cloud Shell hoặc trình chỉnh sửa Linux mà bạn chọn, hãy tạo tệp main.py trong thư mục imageapp. Chúng ta sẽ bắt đầu với khung dưới đây:

main.py

import flask

app = flask.Flask(__name__)

@app.route("/", methods=["GET"])
def home_page():
    return flask.render_template("home.html")

@app.route("/", methods=["POST"])
def display_image():
    # Code to get the prompt (called prompt) from the submitted form
    # Code to generate the image
    # Code to create a URL for the image (called image_url)

    return flask.render_template("display.html", prompt=prompt, image_url=image_url)

# Initialize the web server app when the code locally (Cloud Run handles it in that environment)
if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=8080)

Thực tế, đó gần như là toàn bộ ứng dụng. Có ba nhận xét trong display_image cần được triển khai bằng mã Python.

Hãy bắt đầu điền vào những phần còn thiếu đó. Flask giúp truy xuất lời nhắc dễ dàng. Thêm một dòng sau chú thích như minh hoạ dưới đây:

# Code to get the prompt (called prompt) from the submitted form
prompt = flask.request.form["prompt"]

Nếu muốn kiểm thử ứng dụng ngay, bạn có thể thêm một dòng trước câu lệnh return trong display_image để cung cấp giá trị cho image_url (một URL hợp lệ trỏ đến hình ảnh).

Ví dụ: image_url="<your url here>"

Bạn có thể chạy chương trình cục bộ từ Cloud Shell (bằng lệnh python main.py) và xem trước chương trình bằng tính năng Xem trước trên cổng 8080 ở trên cùng bên phải màn hình.

a80b4abd28cb7eed.png

Với chương trình hiện tại, bạn sẽ luôn thấy hình ảnh trong URL mà bạn đã cung cấp. Hãy tiếp tục và xem cách lấy giá trị đó từ ứng dụng. Hãy nhớ xoá dòng cung cấp giá trị tĩnh cho image_url.

6. Tạo hình ảnh

Google Cloud có một API Python cho AI tạo sinh trên Vertex AI. Để sử dụng, chúng ta phải thêm một dòng nhập cùng với các dòng nhập khác ở gần đầu chương trình:

from vertexai.vision_models import ImageGenerationModel

và đưa vertexai vào tệp requirements.txt.

Tài liệu về ImageGenerationModel cho biết cách sử dụng mô hình này. Chúng ta sẽ tạo một mô hình rồi tạo hình ảnh từ mô hình đó dựa trên một câu lệnh. Thêm mã vào main.py cho bước thứ hai, tạo hình ảnh và lưu hình ảnh đó vào response:

# Code to generate the image
model = ImageGenerationModel.from_pretrained("imagegeneration@006")
response = model.generate_images(prompt=prompt)[0]

Bạn có thể tạo tối đa 4 hình ảnh cùng một lúc, tuỳ thuộc vào các tham số được gửi đến generate_images, vì vậy, giá trị được trả về sẽ là danh sách GeneratedImage, ngay cả khi chỉ có một hình ảnh được trả về, như trong trường hợp này.

Bây giờ, chúng ta cần hiển thị hình ảnh trên trang WWW. GeneratedImage có một phương thức để show hình ảnh, nhưng phương thức này chỉ hoạt động trong môi trường sổ tay. Tuy nhiên, có một phương thức để lưu hình ảnh. Chúng ta sẽ lưu hình ảnh và gửi URL của hình ảnh đã lưu khi hiển thị mẫu.

Việc này hơi khó và có nhiều cách để thực hiện. Hãy cùng xem xét từng bước một trong những phương pháp đơn giản hơn. (Có hình ảnh minh hoạ các bước bên dưới nếu bạn là người học thiên về hình ảnh.)

Trước tiên, chúng ta cần lưu hình ảnh. Nhưng bạn sẽ đặt tên cho danh sách đó là gì? Có thể xảy ra vấn đề khi sử dụng tên tĩnh vì nhiều người có thể sử dụng chương trình cùng một lúc. Mặc dù chúng ta có thể tạo tên hình ảnh riêng cho từng người dùng (bằng một giá trị như UUID), nhưng cách đơn giản hơn là sử dụng thư viện tempfile của Python. Thư viện này sẽ tạo một tệp tạm thời có tên duy nhất. Mã bên dưới sẽ tạo một tệp tạm thời, lấy tên của tệp đó và ghi phản hồi của bước tạo hình ảnh vào tệp tạm thời. Chúng ta sẽ chưa nhập URL vào mã vì trước tiên, chúng ta cần lấy một URL.

with tempfile.NamedTemporaryFile("wb") as f:
    filename = f.name
    response.save(filename, include_generation_parameters=False)
    # process the saved file here, before it goes away

Có một số cách để xử lý tệp đã lưu, nhưng một trong những cách đơn giản và an toàn nhất là sử dụng URL dữ liệu.

URL dữ liệu cho phép gửi dữ liệu thực tế trong URL, chứ không chỉ đường dẫn đến dữ liệu đó. Cú pháp cho URL dữ liệu là:

data:[image/png][;base64],<data>

Để lấy mã hoá base64 của hình ảnh, chúng ta cần mở tệp do tempfile lưu và đọc tệp đó vào một biến. Có, đây sẽ là một chuỗi lớn, nhưng điều đó sẽ không gây ra vấn đề với các trình duyệt và máy chủ hiện đại. Sau đó, chúng ta sẽ sử dụng thư viện base64 để mã hoá chuỗi đó thành một chuỗi mà chúng ta có thể gửi trong URL dữ liệu.

Mã cuối cùng của chúng ta để thực hiện bước thứ ba (tạo URL) sẽ là:

# Code to create a URL for the image (called image_url)
with tempfile.NamedTemporaryFile("wb") as f:
    filename = f.name
    response.save(filename, include_generation_parameters=False)
    # process the saved file here, before it goes away
    with open(filename, "rb") as image_file:
        binary_image = image_file.read()
        base64_image = base64.b64encode(binary_image).decode("utf-8")
        image_url = f"data:image/png;base64,{base64_image}"

Bạn có thể xem tất cả các bước này trong hình ảnh bên dưới:

268876579dc02376.png

Bạn cần nhập tempfile và base64 ở đầu chương trình.

import tempfile
import base64

Hãy thử chạy chương trình của bạn từ Cloud Shell bằng cách đảm bảo bạn đang ở trong thư mục có main.py và chạy lệnh:

python main.py

Sau đó, bạn có thể xem trước ứng dụng bằng cách sử dụng tính năng Xem trước trên cổng 8080 ở trên cùng bên phải màn hình.

a80b4abd28cb7eed.png

7. Lỗi thường gặp

Tại một thời điểm nào đó, bạn có thể nhận thấy rằng khi chạy chương trình (trong khi kiểm thử hoặc sau khi triển khai chương trình), bạn sẽ nhận được thông báo như sau:

2366c3bba6273517.png

Rất có thể điều này là do một câu lệnh vi phạm Các phương pháp sử dụng AI có trách nhiệm của Google . Một câu lệnh đơn giản như "mèo con chơi với quả bóng đầy màu sắc" cũng có thể gây ra vấn đề này. (Nhưng đừng lo, bạn có thể tìm được hình ảnh "mèo con chơi với đồ chơi nhiều màu sắc".)

Để xử lý lỗi này, chúng ta sẽ thêm mã để phát hiện ngoại lệ được đưa ra khi cố gắng tạo hình ảnh. Nếu có, chúng ta sẽ kết xuất lại mẫu home.html kèm theo một thông báo.

Trước tiên, hãy thêm một div trong mẫu home.html sau biểu mẫu đầu tiên sẽ hiển thị nếu có lỗi:

<!DOCTYPE html>
<html>
   <head>
       <title>Let's draw a picture</title>
   </head>
   <body>
       <h1>Let's draw a picture</h1>
       <form  action="/" method="post" >
           <input type="text" id="prompt" name="prompt">
           <input type="submit" value="Send">
       </form>
       {% if mistake %}
       <div id="warning">
       The prompt contains sensitive words that violate
       <a href=\"https://ai.google/responsibility/responsible-ai-practices\">
           Google's Responsible AI practices</a>.
       Try rephrasing the prompt."</div>

       {% endif %}

   </body>
</html>

Sau đó, hãy thêm mã trong main.py để phát hiện ngoại lệ có thể xảy ra khi gọi mã generate_images trong display_image. Nếu có ngoại lệ, mã sẽ hiển thị mẫu home.html kèm theo một thông báo.

# Code to generate the image
   model = ImageGenerationModel.from_pretrained("imagegeneration@006")
   try:
       response = model.generate_images(prompt=prompt)[0]   
   except:
       #  This is probably due to a questionable prompt
       return flask.render_template("home.html", warning=True)

Đây không phải là tính năng AI có trách nhiệm duy nhất của Imagen. Có một số tính năng bảo vệ việc tạo người và trẻ em cũng như các bộ lọc chung trên hình ảnh. Bạn có thể xem thêm về các tính năng này tại đây.

8. Triển khai ứng dụng lên web

Bạn có thể triển khai ứng dụng lên web bằng lệnh trong thư mục imageapp trong Cloud Shell. Hãy nhớ sử dụng mã dự án thực tế của bạn trong lệnh.

gcloud run deploy imageapp \
  --source . \
  --region us-central1 \
  --allow-unauthenticated \
  --project your-project-id

Bạn sẽ thấy một phản hồi như sau, cho bạn biết nơi tìm thấy ứng dụng của mình:

Service [imageapp] revision [imageapp-00001-t48] has been deployed and is serving 100 percent of traffic.
Service URL: https://imageapp-708208532564.us-central1.run.app```

9. Dọn dẹp

Mặc dù Cloud Run không tính phí khi bạn không sử dụng dịch vụ, nhưng bạn vẫn có thể phải trả phí để lưu trữ hình ảnh vùng chứa trong CSDL cấu phần phần mềm. Bạn có thể xoá kho lưu trữ hoặc xoá dự án trên Cloud để tránh bị tính phí. Việc xoá dự án trên Google Cloud sẽ dừng tính phí cho tất cả tài nguyên được sử dụng trong dự án đó.

Cách xoá kho lưu trữ hình ảnh vùng chứa:

gcloud artifacts repositories delete cloud-run-source-deploy \
  --location $REGION

Cách xoá dịch vụ Cloud Run:

gcloud run services delete imageapp \
  --platform managed \
  --region $REGION

Cách xoá dự án trên Google Cloud:

  1. Truy xuất mã dự án hiện tại của bạn:
PROJECT_ID=$(gcloud config get-value core/project)
  1. Hãy đảm bảo đây là dự án bạn muốn xoá:
echo $PROJECT_ID
  1. Xoá dự án:
gcloud projects delete $PROJECT_ID

10. Xin chúc mừng

Xin chúc mừng! Bạn đã tạo thành công một ứng dụng web hiển thị hình ảnh do Imagen tạo. Bạn có thể sử dụng tính năng này trong ứng dụng của mình như thế nào?

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 đọc thêm