استقرار Imagen در Cloud Run

1. درباره این کد لبه

آخرین به روز رسانی: 2024-10-11

نویسنده: لوری وایت

تولید تصویر

بیایید صادق باشیم، تولید تصویر توسط مدل های زبان بزرگ (LLM) می تواند سرگرم کننده باشد. البته برنامه های تجاری زیادی برای تولید تصاویر از طریق اعلان وجود دارد، از تبلیغات سفارشی گرفته تا ارائه های جذاب. ( وب‌سایت Google Cloud کاربردهای خاص بسیاری از شرکت‌هایی دارد که از عوامل خلاق استفاده می‌کنند.) با این وجود، دیدن نتایجی که هنگام درخواست تصویری از «سگ‌های سبز شاد در یک مزرعه» می‌تواند بسیار سرگرم‌کننده باشد.

چه به دلایل حرفه ای یا تفریحی (یا هر دو!) به تولید تصویر علاقه مند باشید، بین استفاده از یک برنامه تولید تصویر و استقرار آن در یک برنامه وب، چالش هایی وجود دارد. این آزمایشگاه به شما در غلبه بر این چالش ها کمک می کند.

چیزی که خواهی ساخت

در این لبه کد، شما یک برنامه می‌سازید که یک پیام متنی دریافت می‌کند و یک صفحه وب را با تصویری که با استفاده از آن درخواست ایجاد شده است، برمی‌گرداند.

چیزی که یاد خواهید گرفت

در این آزمایشگاه یاد خواهید گرفت:

  • نحوه استفاده از Google Imagen برای ایجاد تصاویر از پیام های متنی در محیط های نوت بوک
  • مشکلات انتقال کد Imagen از یک نوت بوک به یک برنامه وب
  • نحوه استقرار یک برنامه Cloud Run که از Imagen برای تولید تصاویر استفاده می کند
  • نحوه گنجاندن یک تصویر از Imagen در HTML

این Codelab بر روی Imagen و استقرار متمرکز شده است. مفاهیم غیر مرتبط و بلوک‌های کد محو شده‌اند و برای شما ارائه می‌شوند تا به سادگی کپی و جای‌گذاری کنید.

آنچه شما نیاز دارید

کد کامل این آزمایشگاه کد در https://github.com/Annie29/imagen-deployment موجود است.

2. API ها را فعال کنید

پروژه ای را برای استفاده برای این Codelab انتخاب کنید. ممکن است بخواهید یک پروژه جدید ایجاد کنید تا پس از اتمام کار، حذف تمام کارهایتان آسان تر شود.

قبل از اینکه بتوانید با Imagen شروع کنید، باید برخی از API ها را فعال کنید.

  1. به Google Cloud Console بروید.
  2. به داشبورد Vertex AI بروید.
  3. "Enable All Recommended APIs" را انتخاب کنید

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. برای باز کردن نوت بوک در سرور نوت بوک گوگل، Open in Colab را انتخاب کنید.
  3. "File -> Save a copy in Drive" را انتخاب کنید یا روی "Copy to Drive" در بالای صفحه کلیک کنید تا کپی خود را از این نوت بوک ایجاد کنید.
  4. نسخه اصلی را ببندید (فقط برای جلوگیری از کار در یک نسخه اشتباه!).
  5. شما باید با کلیک کردن روی دکمه Connect در بالا سمت راست به یک زمان اجرا متصل شوید. 2afdc8fa660a89bd.png
  6. شروع به کار از طریق هر یک از سلول های دفترچه یادداشت کنید.
  7. برای اجرای یک سلول، می توانید روی [] یا فلش سمت چپ سلول کلیک کنید یا از گزینه Run Selection از منوی Runtime (یا میانبر آن) استفاده کنید. dfec032ef6c31296.png
  8. هنگامی که زمان اجرا فعلی را مجددا راه اندازی می کنید، پیامی دریافت خواهید کرد که سیستم شما از کار افتاده است. وحشت نکنید. این طبیعی است.
  9. شما باید محیط نوت بوک خود را احراز هویت کنید.
  10. می‌توانید شناسه پروژه (نه نام) و مکان (اگر مکان تعیین نکرده‌اید us-central1 کار می‌کند) را در کادرهای سمت راست کد وارد کنید و از Colab بخواهید آنها را در کد برای شما درج کند.
  11. وقتی به "تولید یک تصویر" رسیدید، این فرصت را خواهید داشت که ببینید Imagen چه کاری می تواند انجام دهد. به راحتی می توانید درخواست را تغییر دهید و سلول را مجدداً اجرا کنید تا تصاویر متنوعی را که می توانید دریافت کنید مشاهده کنید.
  12. در این مرحله باید ایده خوبی در مورد اینکه Imagen چگونه می تواند تصاویر را از یک نوت بوک ایجاد کند، داشته باشید. برای مشاهده اطلاعات بیشتر در مورد پارامترهای تصویر اکنون یا در زمان مناسب، این نوت بوک را کامل کنید.

4. شروع به ساخت یک برنامه وب برای نمایش یک تصویر کنید

ما از پایتون با استفاده از چارچوب Flask در Cloud Run برای ساخت برنامه خود استفاده خواهیم کرد.

برنامه های Python Flask در یک پوشه به صورت زیر تنظیم می شوند:

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

الگوها فایل‌هایی هستند که حاوی HTML هستند، معمولاً دارای مکان‌هایی با نام هستند که برنامه متن تولید شده را در آن درج می‌کند. 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 یا ویرایشگر لینوکس مورد نظر خود، دو قالب ایجاد کنید. از پوشه 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 یا ویرایشگر لینوکس مورد نظر خود، فایل 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 وجود دارد که باید با کد پایتون تطبیق داده شود، و بس.

بیایید شروع کنیم به پر کردن آن بخش های گمشده. 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>"

می‌توانید برنامه را به صورت محلی از پوسته ابری (با استفاده از دستور python main.py ) اجرا کنید و با استفاده از Preview در پورت 8080 در سمت راست بالای صفحه‌نمایش، پیش‌نمایش آن را مشاهده کنید.

a80b4abd28cb7eed.png

همانطور که برنامه اکنون است، همیشه تصویر را در URL ارائه شده مشاهده خواهید کرد. بیایید ادامه دهیم و ببینیم چگونه می‌توان این مقدار را از برنامه دریافت کرد. مطمئن شوید که خطی که به image_url مقدار ثابت می دهد حذف کنید.

6. ایجاد تصویر

Google Cloud دارای یک API Python برای هوش مصنوعی Generative در 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]

بسته به پارامترهای ارسال شده به generate_images ، حداکثر 4 تصویر را می توان در یک زمان ایجاد کرد، بنابراین مقدار بازگشتی لیستی از GeneratedImage خواهد بود، حتی اگر فقط یک تصویر برگردانده شده باشد، همانطور که در این مورد وجود دارد.

حال باید تصویر را در یک صفحه WWW نمایش دهیم. GeneratedImage روشی برای show تصویر دارد، اما فقط در محیط نوت بوک کار می کند. اما روشی برای ذخیره تصویر وجود دارد. تصویر را ذخیره می کنیم و URL تصویر ذخیره شده را زمانی که الگو را ارائه می کنیم ارسال می کنیم.

این کمی مشکل است و راه های زیادی برای انجام این کار وجود دارد. بیایید به یکی از روش های ساده تر، قدم به قدم نگاه کنیم. (و اگر بیشتر یک یادگیرنده بصری هستید، تصویری از مراحل زیر وجود دارد.)

ابتدا باید تصویر را ذخیره کنیم. اما چه نامی خواهد داشت؟ ممکن است در استفاده از یک نام ثابت مشکلاتی وجود داشته باشد زیرا برنامه می تواند توسط افراد زیادی به طور همزمان استفاده شود. در حالی که می‌توانیم نام‌های تصویر جداگانه برای هر کاربر ایجاد کنیم (با چیزی مانند UUID)، یک راه ساده‌تر استفاده از کتابخانه tempfile پایتون است که یک فایل موقت با یک نام منحصر به فرد ایجاد می‌کند. کد زیر یک tempfile ایجاد می کند، نام آن را می گیرد و پاسخ مرحله تولید تصویر را به tempfile می نویسد. ما هنوز آن را در کد خود وارد نمی کنیم، زیرا ابتدا باید یک 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

با اطمینان از اینکه در پوشه main.py هستید و دستور را اجرا کنید، برنامه خود را از Cloud Shell اجرا کنید:

python main.py

سپس می‌توانید با استفاده از پیش‌نمایش در پورت 8080 در سمت راست بالای صفحه، آن را پیش‌نمایش کنید.

a80b4abd28cb7eed.png

7. یک خطای رایج

در برخی مواقع، ممکن است متوجه شوید که هنگام اجرای برنامه (چه در حین آزمایش یا پس از استقرار آن)، پیامی مانند زیر دریافت می کنید:

2366c3bba6273517.png

این به احتمال زیاد ناشی از درخواستی است که رویه‌های هوش مصنوعی مسئول 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 اضافه کنید تا هنگام فراخوانی کدgenere_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)

این تنها ویژگی Responsible 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 هزینه دریافت کنید. برای جلوگیری از تحمیل هزینه، می توانید مخزن خود را حذف کنید یا پروژه 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 را نمایش می دهد. چگونه می توانید از این در برنامه خود استفاده کنید؟

بعدش چی؟

برخی از این کدها را بررسی کنید...

در ادامه مطلب