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

การปรับใช้บริการ Imagen ไปยัง Cloud Run

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

subjectอัปเดตล่าสุดเมื่อ ต.ค. 24, 2024
account_circleเขียนโดย Laurie White

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