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

1. מידע על ה-Codelab הזה

העדכון האחרון: 11 באוקטובר 2024

נכתב על ידי: Laurie White

יצירת תמונות

האמת היא שיצירת תמונות על ידי מודלים גדולים של שפה (LLM) יכולה להיות כיפית. כמובן שיש הרבה שימושים עסקיים ליצירת תמונות מהנחיה, החל מפרסום בהתאמה אישית ועד מצגות מושכות. (באתר Google Cloud יש הרבה דוגמאות ספציפיות לשימוש בחברות שמשתמשות ב-Creative Agents). אבל עדיין, יכול להיות משעשע לראות מה קורה כשמבקשים תמונה של "כלבים ירוקים שמחים בשדה".

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

מה תפַתחו

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

מה תלמדו

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

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

ה-Codelab הזה מתמקד ב-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' כדי לפתוח את ה-notebook בשרת ה-notebook של Google.
  3. כדי ליצור עותק משלכם של המחברת הזו, בוחרים באפשרות 'קובץ -> שמירת עותק ב-Drive' או לוחצים על 'העתקה ל-Drive' בחלק העליון של הדף.
  4. סוגרים את העותק המקורי (רק כדי שלא תעבדו בטעות על העותק הלא נכון).
  5. כדי להתחבר לסביבת זמן ריצה, לוחצים על הלחצן 'התחברות' בפינה השמאלית העליונה. 2afdc8fa660a89bd.png
  6. מתחילים לעבוד על כל אחד מהתאים ב-notebook.
  7. כדי להפעיל תא, אפשר ללחוץ על [] או על החץ שמשמאל לתא, או להשתמש באפשרות 'הפעלת הבחירה' מהתפריט 'זמן ריצה' (או בקיצור הדרך שלו): dfec032ef6c31296.png
  8. כשמפעילים מחדש את זמן הריצה הנוכחי, מוצגת הודעה שהמערכת קרסה. אל דאגה. זהו נוהל רגיל.
  9. תצטרכו לאמת את סביבת המחברת.
  10. אפשר להזין את מזהה הפרויקט (לא את השם) ואת המיקום (us-central1 פועל אם לא הגדרתם מיקום) בתיבות משמאל לקוד, ו-Colab יוסיף אותם לקוד בשבילכם.
  11. כשמגיעים לשלב 'יצירת תמונה', אפשר לראות מה Imagen יכול לעשות. מומלץ לשנות את ההנחיה ולהריץ מחדש את התא כדי לראות את מגוון התמונות שאפשר לקבל.
  12. בשלב הזה כבר אמורה להיות לכם הבנה טובה לגבי האופן שבו Imagen יכול ליצור תמונות ממחברת. אתם מוזמנים להשלים את המחברת הזו כדי לקבל מידע נוסף על פרמטרים של תמונות עכשיו או בזמן שנוח לכם.

4. מתחילים ליצור אפליקציית אינטרנט להצגת תמונה

נשתמש ב-Python באמצעות ה-framework של Flask ב-Cloud Run כדי ליצור את האפליקציה.

אפליקציות Python Flask מוגדרות בתיקייה באופן הבא:

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

תבניות הן קבצים שמכילים HTML, בדרך כלל עם פלייסהולדרים בעלי שמות שבהם התוכנה תזין טקסט שנוצר. ‫main.py היא אפליקציית שרת האינטרנט עצמה, ו-requirements.txt היא רשימה של כל הספריות הלא סטנדרטיות שבהן נעשה שימוש ב-main.py.

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

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

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

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

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

28135f700c5b12b0.png

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

310422ac131813e1.png

בספריית הבית ב-Cloud Shell, יוצרים את התיקייה , עוברים אליה ויוצרים את התיקיות .imageapptemplates אפשר לעשות את זה משורת הפקודה או מהעורך של Cloud Shell.

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

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

בעזרת Cloud Shell Editor או עורך 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 לשליחת הטופס עם תיאור התמונה שאנחנו רוצים ליצור.

באמצעות Cloud Shell Editor או עורך 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)

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

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. איך אפשר להשתמש בזה באפליקציה?

מה השלב הבא?

כדאי לעיין ב-Codelabs הבאים…

קריאה נוספת