פריסה של Imagen ב-Cloud Run

1. מידע על Codelab זה

תאריך עדכון אחרון: 11 באוקטובר 2024

כתיבה: Laurie White

יצירת תמונות

בואו נודה באמת: יצירת תמונות באמצעות מודלים גדולים של שפה (LLM) יכולה להיות מהנה. כמובן שיש הרבה יישומים עסקיים ליצירת תמונות לפי הנחיה, החל מפרסום מותאם אישית ועד למצגות אטרקטיביות. (באתר של Google Cloud יש הרבה שימושים ספציפיים של חברות שמשתמשות בסוכני קריאייטיב). עם זאת, יכול להיות שתהנו לראות את התוצאות שמתקבלות כשמחפשים תמונה של 'כלבים ירוקים שמחים בשדה'.

בין אם אתם רוצים ליצור תמונות מסיבות מקצועיות או למטרות פנאי (או גם וגם!), יש כמה אתגרים שצריך להתמודד איתם כשמשתמשים בתוכנית ליצירת תמונות או כשפורסים אותה באפליקציית אינטרנט. בעזרת שיעור ה-Lab הזה תוכלו להתגבר על האתגרים האלה.

מה תפַתחו

בקודלאב הזה תלמדו ליצור אפליקציה שתקבל הנחיה בטקסט ותחזיר דף אינטרנט עם תמונה שנוצרה באמצעות ההנחיה הזו.

מה תלמדו

בשיעור ה-Lab הזה תלמדו:

  • איך משתמשים ב-Google Imagen כדי ליצור תמונות מהנחיות טקסט בסביבות של מחברות
  • הקשיים בהעברת קוד של Imagen מיומן ל-notebook לאפליקציית אינטרנט
  • איך פורסים אפליקציית Cloud Run שמשתמשת ב-Imagen ליצירת תמונות
  • איך לכלול תמונה מ-Imagen ב-HTML

סדנת הקוד הזו מתמקדת ב-Imagen ובפריסה. מושגים וקטעי קוד לא רלוונטיים מוצגים בקצרה, וניתן פשוט להעתיק ולהדביק אותם.

מה נדרש

הקוד המלא של Codelab הזה זמין בכתובת https://github.com/Annie29/imagen-deployment .

2. הפעלת ממשקי API

בוחרים פרויקט לשימוש ב-Codelab הזה. מומלץ ליצור פרויקט חדש כדי שיהיה קל יותר להסיר את כל העבודה בסיום.

לפני שתתחילו להשתמש ב-Imagen, תצטרכו להפעיל כמה ממשקי API.

  1. נכנסים למסוף Google Cloud.
  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. כדי ליצור עותק משלכם של המחברות, בוחרים באפשרות 'קובץ -> שמירת עותק ב-Drive' או לוחצים על 'העתקה ל-Drive' בחלק העליון של הדף.
  4. סוגרים את העותק המקורי (רק כדי לא לעבוד על העותק הלא נכון!).
  5. כדי להתחבר לסביבת זמן ריצה, לוחצים על הלחצן Connect (התחברות) בפינה השמאלית העליונה. 2afdc8fa660a89bd.png
  6. מתחילים לעבוד עם כל התאים ב-notebook.
  7. כדי להריץ תא, אפשר ללחוץ על [] או על החץ שמשמאל לתא, או להשתמש באפשרות Run Selection (הפעלת הבחירה) בתפריט Runtime (זמן ריצה) (או בקיצור הדרך שלה): 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, שבדרך כלל מכילים placeholders (תוספי טקסט ריקים) עם שם, שבהם התוכנה תוסיף טקסט שנוצר. main.py היא אפליקציית שרת האינטרנט עצמה, ו-requirements.txt היא רשימה של כל הספריות הלא סטנדרטיות שבהן main.py משתמשת.

לאפליקציה יהיו שני דפים – הראשון להצגת הנחיה והשני להצגת התמונה ולאפשרות של המשתמש להזין הנחיה נוספת.

קודם יוצרים את מסגרת הפרויקט.

יצירת מבנה הקבצים

בקודלאב הזה נניח שהפרויקט נמצא בתיקייה imageapp. אם משתמשים בשם אחר, חשוב לעדכן את הפקודות בהתאם.

כדי להיכנס ל-Cloud Shell, לוחצים על סמל ההנחיה בפינה השמאלית העליונה של המסך.

28135f700c5b12b0.png

כדי לקבל יותר מקום לעבודה, אפשר להעביר את המעטפת לכרטיסייה חדשה באמצעות החץ בחלק העליון של חלון המעטפת:

310422ac131813e1.png

בספריית הבית ב-Cloud Shell, יוצרים את התיקייה imageapp, עוברים אליה ויוצרים את התיקיות templates. אפשר לעשות זאת דרך שורת הפקודה או דרך עורך Cloud Shell.

יצירת התבניות

לאפליקציה יהיו שני דפים – הראשון (שנקרא home.html) להצגת ההנחיה, והשני (שנקרא display.html) להצגת התמונה ולאפשרות להזין הנחיה נוספת.

יוצרים שתי תבניות באמצעות עורך 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 מכיל את הקוד שיספק בקשות אינטרנט. אנחנו צריכים לטפל רק בשתי בקשות: בקשה מסוג GET לדף הבית, ובקשה מסוג POST ששולחת את הטופס שמתאר את התמונה שאנחנו רוצים ליצור.

יוצרים את הקובץ main.py בתיקייה imageapp באמצעות עורך Cloud Shell או עורך Linux לבחירתכם. נתחיל עם השלד הבא:

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)

למעשה, זה כמעט כל האפליקציה. יש שלושה תגובות ב-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 ל-AI גנרטיבי ב-Vertex AI. כדי להשתמש בו, צריך להוסיף שורה שמייבאת אותו עם שאר הייבוא בחלק העליון של התוכנית:

from vertexai.vision_models import ImageGenerationModel

וכוללים את vertexai בקובץ requirements.txt.

במסמכי התיעוד של ImageGenerationModel מוסבר איך משתמשים בו. נוצר מודל ולאחר מכן נייצר ממנו תמונה, על סמך הנחיה. מוסיפים קוד ל-main.py בשביל השלב השני, יצירת התמונה ושמירתה ב-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 את התמונה, אבל היא פועלת רק בסביבת notebook. אבל יש דרך לשמור את התמונה. נשמור את התמונה ונשלח את כתובת ה-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 של הנתונים.

הקוד הסופי שלנו לביצוע השלב השלישי (יצירת כתובת ה-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)

זו לא התכונה היחידה של Imagen שמבוססת על AI אחראי. יש כמה תכונות שמגינות על יצירת אנשים וילדים ועל מסננים כלליים בתמונות. מידע נוסף זמין כאן.

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. כדי להימנע מחיובים, אפשר למחוק את המאגר או את פרויקט Cloud. מחיקת הפרויקט ב-Cloud תפסיק את החיוב על כל המשאבים שבהם נעשה שימוש באותו פרויקט.

כדי למחוק את מאגר קובצי האימג' בקונטיינר:

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…

מקורות מידע נוספים