การนำ Imagen ไปใช้งานใน Cloud Run

1. เกี่ยวกับ Codelab นี้

อัปเดตล่าสุด: 11-10-2024

เขียนโดย: Laurie White

การสร้างรูปภาพ

ยอมรับกันตามตรงว่าการสร้างรูปภาพด้วยโมเดลภาษาขนาดใหญ่ (LLM) นั้นสนุกดี แน่นอนว่ามีแอปพลิเคชันทางธุรกิจมากมายสำหรับการสร้างรูปภาพจากพรอมต์ ตั้งแต่การโฆษณาที่กำหนดเองไปจนถึงงานนำเสนอที่น่าสนใจ (เว็บไซต์ Google Cloud มีการใช้งานที่เฉพาะเจาะจงมากมายของบริษัทที่ใช้ Creative Agent) แต่การดูผลลัพธ์เมื่อคุณค้นหารูปภาพ "สุนัขสีเขียวที่มีความสุขในทุ่งนา" ก็ค่อนข้างสนุกดี

ไม่ว่าคุณจะสนใจการสร้างรูปภาพเพื่อเหตุผลด้านอาชีพหรือเพื่อการพักผ่อนหย่อนใจ (หรือทั้ง 2 อย่าง) ก็อาจพบปัญหาบางอย่างระหว่างการใช้โปรแกรมสร้างรูปภาพกับการติดตั้งใช้งานในเว็บแอปพลิเคชัน ห้องทดลองนี้จะช่วยคุณรับมือกับความท้าทายเหล่านั้น

สิ่งที่คุณจะสร้าง

ในโค้ดแล็บนี้ คุณจะได้สร้างแอปที่จะรับพรอมต์ข้อความและแสดงผลหน้าเว็บที่มีรูปภาพที่สร้างขึ้นโดยใช้พรอมต์นั้น

สิ่งที่จะได้เรียนรู้

ในชั้นเรียนนี้ คุณจะได้เรียนรู้สิ่งต่อไปนี้

  • วิธีใช้ Google Imagen เพื่อสร้างรูปภาพจากพรอมต์ข้อความในสภาพแวดล้อมโน้ตบุ๊ก
  • ปัญหาในการย้ายโค้ด Imagen จากโน้ตบุ๊คไปยังเว็บแอป
  • วิธีทำให้แอปพลิเคชัน Cloud Run ที่ใช้ Imagen เพื่อสร้างรูปภาพใช้งานได้
  • วิธีใส่รูปภาพจาก Imagen ใน HTML

โค้ดแล็บนี้จะเน้นที่ Imagen และการใช้งาน แนวคิดและบล็อกโค้ดที่ไม่เกี่ยวข้องจะได้รับการอธิบายอย่างคร่าวๆ และให้คุณคัดลอกและวางได้ง่ายๆ

สิ่งที่คุณต้องมี

ดูโค้ดที่สมบูรณ์ของ Codelab นี้ได้ที่ https://github.com/Annie29/imagen-deployment

2. เปิดใช้ API

เลือกโปรเจ็กต์ที่จะใช้สำหรับ Codelab นี้ คุณอาจต้องสร้างโปรเจ็กต์ใหม่เพื่อให้นำงานทั้งหมดออกได้ง่ายขึ้นเมื่อเสร็จแล้ว

คุณต้องเปิดใช้ API บางรายการก่อนจึงจะเริ่มใช้งาน Imagen ได้

  1. ไปที่ Google Cloud Console
  2. ไปที่แดชบอร์ด Vertex AI
  3. เลือก "เปิดใช้ API ที่แนะนําทั้งหมด"

a8f336f7380a9eab.png

3. สำรวจ Google Imagen (ไม่บังคับ)

หากคุ้นเคยกับ Imagen อยู่แล้ว ให้ข้ามส่วนนี้

ก่อนพยายามสร้างเว็บแอปที่ใช้ Imagen คุณควรดูว่า Imagen ทำอะไรได้บ้าง ซึ่งโชคดีที่มีโน้ตบุ๊คหลายรายการที่เรียกใช้โค้ด Imagen แบบง่าย ดังนั้นเรามาเริ่มด้วยโน้ตบุ๊ครายการใดรายการหนึ่งกัน

  1. ไปที่โน้ตบุ๊กที่ https://github.com/GoogleCloudPlatform/generative-ai/blob/main/vision/getting-started/image_generation.ipynb
  2. เลือก "เปิดใน Colab" เพื่อเปิดสมุดบันทึกในเซิร์ฟเวอร์สมุดบันทึกของ Google
  3. เลือก "ไฟล์ -> บันทึกสำเนาในไดรฟ์" หรือคลิก "คัดลอกไปยังไดรฟ์" ที่ด้านบนของหน้าเพื่อสร้างสำเนาสมุดบันทึกนี้ของคุณเอง
  4. ปิดสำเนาต้นฉบับ (เพื่อไม่ให้ทำงานในสำเนาที่ไม่ถูกต้อง)
  5. คุณจะต้องเชื่อมต่อกับรันไทม์โดยคลิกปุ่มเชื่อมต่อที่ด้านขวาบน 2afdc8fa660a89bd.png
  6. เริ่มทํางานกับแต่ละเซลล์ในสมุดบันทึก
  7. หากต้องการเรียกใช้เซลล์ ให้คลิกใน [] หรือลูกศรทางด้านซ้ายของเซลล์ หรือใช้ตัวเลือกเรียกใช้การเลือกจากเมนูรันไทม์ (หรือแป้นพิมพ์ลัด) dfec032ef6c31296.png
  8. เมื่อรีสตาร์ทรันไทม์ปัจจุบัน คุณจะได้รับข้อความว่าระบบขัดข้อง ไม่ต้องตกใจ ซึ่งเป็นเรื่องปกติ
  9. คุณจะต้องตรวจสอบสิทธิ์สภาพแวดล้อมของโน้ตบุ๊ก
  10. คุณสามารถป้อนรหัสโปรเจ็กต์ (ไม่ใช่ชื่อ) และตำแหน่ง (us-central1 จะใช้งานได้หากคุณไม่ได้ตั้งค่าตำแหน่ง) ในช่องทางด้านขวาของโค้ด แล้วให้ Colab แทรกรหัสและตำแหน่งลงในโค้ดให้คุณ
  11. เมื่อไปที่ "สร้างรูปภาพ" คุณจะเห็นความสามารถของ Imagen เปลี่ยนพรอมต์และเรียกใช้เซลล์อีกครั้งเพื่อดูรูปภาพหลากหลายรูปแบบที่คุณได้รับ
  12. ตอนนี้คุณควรทราบแล้วว่า Imagen สร้างรูปภาพจากโน้ตบุ๊กได้อย่างไร โปรดใช้สมุดบันทึกนี้เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับพารามิเตอร์รูปภาพในตอนนี้หรือเมื่อสะดวก

4. เริ่มสร้างเว็บแอปพลิเคชันเพื่อแสดงรูปภาพ

เราจะใช้ Python โดยใช้เฟรมเวิร์ก Flask ใน Cloud Run เพื่อสร้างแอป

แอป Python Flask จะตั้งค่าในโฟลเดอร์ดังนี้

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

เทมเพลตคือไฟล์ที่มี HTML ซึ่งมักจะมีตัวยึดตําแหน่งที่มีชื่อซึ่งโปรแกรมจะแทรกข้อความที่สร้างขึ้น main.py คือแอปเว็บเซิร์ฟเวอร์เอง และ requirements.txt คือรายการไลบรารีที่ไม่ใช่มาตรฐานทั้งหมดที่ main.py ใช้

แอปพลิเคชันจะมี 2 หน้า โดยหน้าแรกจะแสดงพรอมต์ ส่วนหน้าที่สองจะแสดงรูปภาพและอนุญาตให้ผู้ใช้ป้อนพรอมต์อื่น

ก่อนอื่นให้สร้างเฟรมเวิร์กของโปรเจ็กต์

การสร้างโครงสร้างไฟล์

Codelab นี้จะถือว่าโปรเจ็กต์ของคุณอยู่ในโฟลเดอร์ imageapp หากคุณใช้ชื่ออื่น โปรดอัปเดตคำสั่งตามความเหมาะสม

เข้าสู่ Cloud Shell โดยเลือกไอคอนพรอมต์ที่ด้านขวาบนของหน้าจอ

28135f700c5b12b0.png

คุณจะมีพื้นที่ทำงานมากขึ้นหากย้ายเชลล์ไปยังแท็บใหม่โดยใช้ลูกศรที่ด้านบนของหน้าต่างเชลล์ ดังนี้

310422ac131813e1.png

จากไดเรกทอรีหลักใน Cloud Shell ให้สร้างโฟลเดอร์ imageapp แล้วเปลี่ยนเป็นโฟลเดอร์นั้น จากนั้นสร้างโฟลเดอร์ templates ซึ่งทําได้จากบรรทัดคําสั่งหรือเครื่องมือแก้ไข Cloud Shell

สร้างเทมเพลต

แอปพลิเคชันจะมี 2 หน้า ได้แก่ หน้าแรก (ซึ่งเราจะเรียกว่า home.html) เพื่อรับพรอมต์ และหน้า 2 (ซึ่งเราจะเรียกว่า display.html) เพื่อแสดงรูปภาพและอนุญาตให้ผู้ใช้ป้อนพรอมต์อื่น

สร้างเทมเพลต 2 รายการโดยใช้เครื่องมือแก้ไข Cloud Shell หรือเครื่องมือแก้ไข Linux ที่คุณเลือก จากโฟลเดอร์ imageapp/templates ให้สร้างหน้าแรก home.html ที่ผู้ใช้จะเห็น โดยใช้ตัวแปร prompt เพื่อแสดงผลคําอธิบายที่ผู้ใช้ป้อน

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>

จากนั้นสร้าง display.html ซึ่งจะแสดงรูปภาพ โปรดทราบว่าตำแหน่งของรูปภาพจะอยู่ใน 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. การเริ่มต้นโค้ด

คุณจะต้องสร้างไฟล์ requirements.txt เพื่อให้แน่ใจว่ามีไลบรารีทั้งหมดที่โปรแกรมของคุณต้องใช้ ในระหว่างนี้ ให้ใส่ flask ในไฟล์ requirements.txt

ไฟล์ main.py มีโค้ดที่จะแสดงคําขอเว็บ เรามีเพียง 2 คำขอที่ต้องจัดการ ได้แก่ คำขอ GET สำหรับหน้าแรก และคำขอ POST ที่ส่งแบบฟอร์มที่อธิบายรูปภาพที่ต้องการสร้าง

ใช้เครื่องมือแก้ไข Cloud Shell หรือเครื่องมือแก้ไข Linux ที่คุณเลือกเพื่อสร้างไฟล์ main.py ในโฟลเดอร์ imageapp เราจะเริ่มต้นด้วยโครงร่างด้านล่าง

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)

จริงๆ แล้วเกือบจะเป็นทั้งแอปแล้ว มีความคิดเห็น 3 รายการใน display_image ที่ต้องเขียนโค้ด Python เพิ่มเติม

มาเริ่มเติมส่วนที่ขาดหายไปกัน Flask ช่วยให้ดึงข้อมูลพรอมต์ได้ง่าย เพิ่มบรรทัดหลังความคิดเห็นดังที่แสดงด้านล่าง

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

หากต้องการทดสอบแอปตอนนี้ ให้เพิ่มบรรทัดก่อนคำสั่ง return ใน display_image เพื่อกำหนดค่าให้กับ image_url (URL ที่ถูกต้องซึ่งชี้ไปยังรูปภาพ)

เช่น image_url="<your url here>"

คุณสามารถเรียกใช้โปรแกรมในเครื่องจาก Cloud Shell (โดยใช้คําสั่ง python main.py) และดูตัวอย่างได้โดยใช้ "แสดงตัวอย่างบนพอร์ต 8080" ที่ด้านขวาบนของหน้าจอ

a80b4abd28cb7eed.png

คุณจะเห็นว่ารูปภาพใน URL ที่คุณระบุจะปรากฏอยู่เสมอ ไปดูวิธีรับค่าดังกล่าวจากแอปกัน อย่าลืมนําบรรทัดที่กําหนดค่าคงที่ให้กับ image_url ออก

6. การสร้างรูปภาพ

Google Cloud มี Python API สําหรับ Generative AI ใน Vertex AI หากต้องการใช้ เราต้องเพิ่มบรรทัดการนําเข้าพร้อมกับการนําเข้าอื่นๆ ไว้ที่ด้านบนของโปรแกรม

from vertexai.vision_models import ImageGenerationModel

และใส่ vertexai ในไฟล์ requirements.txt

เอกสารประกอบสำหรับ ImageGenerationModel จะแสดงวิธีใช้ เราจะสร้างโมเดล จากนั้นสร้างรูปภาพจากโมเดลตามพรอมต์ เพิ่มโค้ดลงใน main.py สำหรับขั้นตอนที่ 2 ซึ่งก็คือการสร้างรูปภาพและจัดเก็บไว้ใน response

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

คุณสร้างรูปภาพได้สูงสุด 4 รูปพร้อมกัน โดยขึ้นอยู่กับพารามิเตอร์ที่ส่งไปยัง generate_images ดังนั้นค่าที่แสดงผลจะเป็นรายการ GeneratedImage แม้ว่าจะมีรูปภาพเพียงรูปเดียวที่แสดงผลก็ตาม ดังในกรณีนี้

ตอนนี้เราต้องแสดงรูปภาพในหน้า WWW GeneratedImage มีวิธีการ show รูปภาพ แต่ใช้ได้เฉพาะในสภาพแวดล้อมโน้ตบุ๊กเท่านั้น แต่มีวิธีบันทึกรูปภาพ เราจะบันทึกรูปภาพและส่ง URL ของรูปภาพที่บันทึกไว้เมื่อแสดงผลเทมเพลต

ซึ่งอาจทําได้หลายวิธีและค่อนข้างยุ่งยาก มาดูวิธีการที่ง่ายที่สุดแบบทีละขั้นตอนกัน (และยังมีรูปภาพขั้นตอนด้านล่างหากคุณเป็นบุคคลที่เรียนรู้ด้วยภาพมากกว่า)

ก่อนอื่นเราต้องบันทึกรูปภาพ แต่เราจะตั้งชื่ออะไรดี การใช้ชื่อแบบคงที่อาจทำให้เกิดปัญหาได้เนื่องจากโปรแกรมนี้ใช้ได้โดยผู้ใช้หลายคนพร้อมกัน แม้ว่าเราจะสร้างชื่อรูปภาพแยกกันสำหรับผู้ใช้แต่ละรายได้ (โดยใช้ UUID) แต่วิธีที่ง่ายกว่านั้นคือการใช้ไลบรารี tempfile ของ Python ซึ่งจะสร้างไฟล์ชั่วคราวที่มีชื่อที่ไม่ซ้ำกัน โค้ดด้านล่างจะสร้างไฟล์ชั่วคราว รับชื่อ และเขียนการตอบกลับของขั้นตอนการสร้างรูปภาพลงในไฟล์ชั่วคราว เราจะยังไม่ป้อนข้อมูลดังกล่าวในโค้ดของเรา เนื่องจากเราต้องได้รับ 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

การประมวลผลไฟล์ที่บันทึกไว้มีหลายวิธี แต่วิธีที่ง่ายที่สุดและปลอดภัยที่สุดวิธีหนึ่งคือการใช้ URL ของข้อมูล

URL ของข้อมูลช่วยให้ส่งข้อมูลจริงใน URL ได้ ไม่ใช่แค่เส้นทางไปยังข้อมูล ไวยากรณ์ของ URL ข้อมูลมีดังนี้

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

หากต้องการรับการเข้ารหัส Base64 ของรูปภาพ เราจะต้องเปิดไฟล์ที่ tempfile บันทึกไว้และอ่านไฟล์ลงในตัวแปร ใช่ สตริงนี้จะยาวมาก แต่เบราว์เซอร์และเซิร์ฟเวอร์สมัยใหม่น่าจะรองรับได้ จากนั้นเราจะใช้ไลบรารี base64 เพื่อเข้ารหัสข้อมูลดังกล่าวให้เป็นสตริงที่ส่งใน URL ของข้อมูลได้

โค้ดสุดท้ายสําหรับทําขั้นตอนที่ 3 (การสร้าง URL) จะเป็นดังนี้

# 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}"

คุณดูขั้นตอนทั้งหมดนี้ได้ในรูปภาพด้านล่าง

268876579dc02376.png

คุณจะต้องนําเข้า tempfile และ base64 ที่จุดเริ่มต้นของโปรแกรม

import tempfile
import base64

ลองเรียกใช้โปรแกรมจาก Cloud Shell โดยตรวจสอบว่าคุณอยู่ในโฟลเดอร์ที่มี main.py และเรียกใช้คําสั่งต่อไปนี้

python main.py

จากนั้นคุณสามารถดูตัวอย่างได้โดยใช้ "แสดงตัวอย่างบนพอร์ต 8080" ที่ด้านขวาบนของหน้าจอ

a80b4abd28cb7eed.png

7. ข้อผิดพลาดที่พบบ่อย

ในบางครั้ง คุณอาจสังเกตเห็นว่าเมื่อเรียกใช้โปรแกรม (ขณะทดสอบหรือหลังจากติดตั้งใช้งาน) คุณได้รับข้อความดังต่อไปนี้

2366c3bba6273517.png

ปัญหานี้อาจเกิดจากพรอมต์ที่ละเมิดแนวทางปฏิบัติสำหรับการใช้ AI อย่างมีความรับผิดชอบของ Google พรอมต์ที่เรียบง่ายอย่าง "ลูกแมวเล่นกับลูกบอลหลากสี" อาจทำให้เกิดปัญหานี้ได้ (แต่ไม่ต้องกังวลไป คุณสามารถดูรูปภาพ "ลูกแมวเล่นกับของเล่นสีสันสดใส" ได้)

เราจะเพิ่มโค้ดเพื่อจับข้อยกเว้นที่เกิดขึ้นเมื่อพยายามสร้างรูปภาพเพื่อจัดการกับข้อผิดพลาดนี้ หากมี เราจะแสดงผลเทมเพลต home.html อีกครั้งพร้อมแสดงข้อความ

ก่อนอื่น ให้เพิ่ม div ในเทมเพลต 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>
       {% 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>

จากนั้นเพิ่มโค้ดใน main.py เพื่อจับข้อยกเว้นที่อาจเกิดขึ้นเมื่อเรียกใช้โค้ด generate_images ใน display_image หากมีข้อยกเว้น โค้ดจะแสดงผลเทมเพลต home.html พร้อมข้อความ

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

ฟีเจอร์นี้ไม่ใช่ฟีเจอร์ AI อย่างรับผิดชอบเพียงอย่างเดียวของ Imagen มีฟีเจอร์หลายอย่างที่ปกป้องการสร้างภาพบุคคลและเด็ก รวมถึงฟิลเตอร์ทั่วไปในรูปภาพ ดูข้อมูลเพิ่มเติมเกี่ยวกับฟีเจอร์เหล่านี้ได้ที่นี่

8. การนำแอปไปใช้งานบนเว็บ

คุณสามารถทำให้แอปใช้งานได้กับเว็บโดยใช้คำสั่งจากโฟลเดอร์ imageapp ใน Cloud Shell โปรดตรวจสอบว่าคุณใช้รหัสโปรเจ็กต์จริงในคำสั่ง

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

คุณควรเห็นการตอบกลับดังต่อไปนี้ซึ่งบอกตำแหน่งที่จะพบใบสมัคร

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. การล้างข้อมูล

แม้ว่า Cloud Run จะไม่เรียกเก็บเงินเมื่อไม่ได้ใช้งานบริการ แต่คุณอาจยังคงถูกเรียกเก็บเงินสำหรับการจัดเก็บอิมเมจคอนเทนเนอร์ใน Artifact Registry คุณสามารถลบที่เก็บหรือลบโปรเจ็กต์ที่อยู่ในระบบคลาวด์เพื่อหลีกเลี่ยงการเรียกเก็บเงิน การลบโปรเจ็กต์ในระบบคลาวด์จะหยุดการเรียกเก็บเงินสำหรับทรัพยากรทั้งหมดที่ใช้ภายในโปรเจ็กต์นั้น

วิธีลบที่เก็บรูปภาพคอนเทนเนอร์

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

วิธีลบบริการ Cloud Run

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

วิธีลบโปรเจ็กต์ Google Cloud

  1. เรียกดูรหัสโปรเจ็กต์ปัจจุบัน
PROJECT_ID=$(gcloud config get-value core/project)
  1. ตรวจสอบว่านี่คือโปรเจ็กต์ที่คุณต้องการลบ
echo $PROJECT_ID
  1. วิธีลบโปรเจ็กต์
gcloud projects delete $PROJECT_ID

10. ขอแสดงความยินดี

ยินดีด้วย คุณสร้างเว็บแอปพลิเคชันที่แสดงรูปภาพที่ Imagen สร้างขึ้นเรียบร้อยแล้ว คุณใช้ข้อมูลนี้ในแอปพลิเคชันได้อย่างไร

ขั้นตอนถัดไป

ลองดู Codelab เหล่านี้...

อ่านเพิ่มเติม