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

۱. درباره این آزمایشگاه کد

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

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

تولید تصویر

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

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

آنچه خواهید ساخت

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

آنچه یاد خواهید گرفت

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

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

این آزمایشگاه کد بر روی Imagen و استقرار آن تمرکز دارد. مفاهیم و بلوک‌های کد نامربوط حذف شده‌اند و برای کپی و چسباندن ساده در اختیار شما قرار گرفته‌اند.

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

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

۲. فعال کردن APIها

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

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

  1. به کنسول ابری گوگل بروید.
  2. به داشبورد هوش مصنوعی ورتکس بروید.
  3. گزینه «فعال کردن همه APIهای پیشنهادی» را انتخاب کنید.

a8f336f7380a9eab.png

۳. بررسی Google Imagen (اختیاری)

اگر با Imagen آشنا هستید، می‌توانید از این بخش صرف نظر کنید.

قبل از تلاش برای ایجاد یک برنامه وب که از Imagen استفاده می‌کند، مفید است که ببینید Imagen چه کارهایی می‌تواند انجام دهد. خوشبختانه، تعدادی نوت‌بوک وجود دارد که کد ساده Imagen را اجرا می‌کنند، بنابراین بیایید با یکی از آنها شروع کنیم.

  1. به دفترچه یادداشت در آدرس https://github.com/GoogleCloudPlatform/generative-ai/blob/main/vision/getting-started/image_generation.ipynb بروید.
  2. برای باز کردن دفترچه یادداشت در سرور دفترچه یادداشت گوگل، گزینه «باز کردن در Colab» را انتخاب کنید.
  3. برای ایجاد نسخه خودتان از این دفترچه یادداشت، یا «فایل -> ذخیره یک کپی در درایو» را انتخاب کنید یا روی «کپی در درایو» در بالای صفحه کلیک کنید.
  4. نسخه اصلی را ببندید (فقط برای اینکه از کار کردن روی نسخه اشتباه خودداری کنید!).
  5. شما باید با کلیک روی دکمه Connect در بالا سمت راست، به یک محیط اجرا متصل شوید. 2afdc8fa660a89bd.png
  6. شروع به کار روی تک تک سلول‌های دفترچه یادداشت کنید.
  7. برای اجرای یک سلول، می‌توانید روی [] یا فلش سمت چپ سلول کلیک کنید یا از گزینه Run Selection از منوی Runtime (یا میانبر آن) استفاده کنید: dfec032ef6c31296.png
  8. وقتی سیستم فعلی را مجدداً راه‌اندازی می‌کنید، پیامی مبنی بر خرابی سیستم دریافت خواهید کرد. نگران نباشید. این طبیعی است.
  9. شما باید محیط نوت‌بوک خود را احراز هویت کنید.
  10. می‌توانید شناسه پروژه (نه نام) و مکان (اگر مکان را تعیین نکرده باشید، us-central1 کار می‌کند) خود را در کادرهای سمت راست کد وارد کنید و از Colab بخواهید آنها را برای شما در کد وارد کند.
  11. وقتی به «ایجاد تصویر» رسیدید، فرصتی خواهید داشت تا ببینید Imagen چه کارهایی می‌تواند انجام دهد. می‌توانید اعلان را تغییر دهید و سلول را دوباره اجرا کنید تا تنوع تصاویری را که می‌توانید دریافت کنید، ببینید.
  12. در این مرحله، شما باید ایده خوبی از نحوه ایجاد تصاویر توسط Imagen از یک دفترچه یادداشت داشته باشید. برای کسب اطلاعات بیشتر در مورد پارامترهای تصویر، می‌توانید این دفترچه یادداشت را همین حالا یا در زمان مناسب تکمیل کنید.

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

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

برنامه‌های پایتون فلسک در پوشه‌ای به شکل زیر تنظیم می‌شوند:

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

قالب‌ها فایل‌هایی حاوی HTML هستند که معمولاً دارای متغیرهایی با نام هستند که برنامه متن تولید شده را در آنها وارد می‌کند. main.py خود برنامه وب سرور است و requirements.txt لیستی از تمام کتابخانه‌های غیر استانداردی است که main.py از آنها استفاده می‌کند.

این برنامه دو صفحه خواهد داشت - صفحه اول برای دریافت یک اعلان و صفحه دوم برای نمایش تصویر و اجازه دادن به کاربر برای وارد کردن اعلان دیگری.

ابتدا چارچوب پروژه را ایجاد کنید.

ایجاد ساختار فایل

این آزمایشگاه کد فرض می‌کند که پروژه شما در پوشه imageapp قرار دارد. اگر از نام دیگری استفاده می‌کنید، حتماً دستورات را به صورت مناسب به‌روزرسانی کنید.

با انتخاب نماد اعلان در سمت راست بالای صفحه، وارد Cloud Shell شوید.

28135f700c5b12b0.png

اگر پوسته را با استفاده از فلش بالای پنجره پوسته به یک برگه جدید منتقل کنید، می‌توانید فضای بیشتری برای کار داشته باشید:

۳۱۰۴۲۲ac۱۳۱۸۱۳e۱.png

از دایرکتوری خانگی خود در Cloud Shell، پوشه imageapp را ایجاد کنید، به آن تغییر دهید و پوشه‌های templates را ایجاد کنید. می‌توانید این کار را یا از خط فرمان یا ویرایشگر Cloud Shell انجام دهید.

قالب‌ها را ایجاد کنید

این برنامه دو صفحه خواهد داشت - صفحه اول (که آن را home.html می‌نامیم) برای دریافت یک اعلان و صفحه دوم (که آن را display.html می‌نامیم) برای نمایش تصویر و اجازه دادن به کاربر برای وارد کردن اعلان دیگری.

با استفاده از ویرایشگر Cloud Shell یا ویرایشگر لینوکس مورد نظر خود، دو قالب ایجاد کنید. از پوشه imageapp/templates ، صفحه اولیه‌ای که کاربر خواهد دید، home.html ، را ایجاد کنید. این صفحه از متغیر prompt برای برگرداندن توضیحی که کاربر وارد می‌کند، استفاده می‌کند.

قالب‌ها/خانه.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 خواهد بود.

قالب‌ها/نمایش.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>

۵. شروع کد

برای اطمینان از اینکه تمام کتابخانه‌های مورد نیاز برنامه شما در دسترس هستند، باید فایل requirements.txt را ایجاد کنید. فعلاً، فقط flask در فایل requirements.txt قرار دهید.

فایل main.py شامل کدی است که درخواست‌های وب را ارائه می‌دهد. فقط دو درخواست وجود دارد که باید مدیریت کنیم: یک درخواست GET برای صفحه اصلی و یک درخواست POST که فرم توصیف تصویری را که می‌خواهیم تولید شود، ارسال می‌کند.

با استفاده از ویرایشگر Cloud Shell یا ویرایشگر لینوکس مورد نظر خود، فایل main.py را در پوشه imageapp ایجاد کنید. ما با اسکلت زیر شروع خواهیم کرد:

فایل اصلی.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>"

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

a80b4abd28cb7eed.png

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

۶. خلق تصویر

گوگل کلود یک API پایتون برای Generative AI روی Vertex AI دارد. برای استفاده از آن، باید خطی اضافه کنیم که آن را به همراه سایر importها در بالای برنامه وارد کند:

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 ، می‌توان حداکثر ۴ تصویر را همزمان ایجاد کرد، بنابراین مقدار بازگشتی لیستی از GeneratedImage خواهد بود، حتی اگر فقط یک تصویر بازگردانده شده باشد، همانطور که در این مورد وجود دارد.

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

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

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

تمام این مراحل را می‌توانید در تصویر زیر مشاهده کنید:

۲۶۸۸۷۶۵۷۹dc02376.png

شما باید tempfile و base64 را در ابتدای برنامه خود وارد کنید.

import tempfile
import base64

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

python main.py

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

a80b4abd28cb7eed.png

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

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

2366c3bba6273517.png

این مشکل به احتمال زیاد ناشی از فراخوانی است که رویه‌های هوش مصنوعی مسئولانه گوگل را نقض می‌کند. فراخوانی به سادگی «بچه‌گربه‌ها در حال بازی با توپ‌های رنگارنگ» می‌تواند این مشکل را ایجاد کند. (اما نگران نباشید، می‌توانید تصاویری از «بچه‌گربه‌ها در حال بازی با اسباب‌بازی‌های رنگارنگ» دریافت کنید.)

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

۸. انتشار برنامه در وب

شما می‌توانید با استفاده از دستور موجود در پوشه 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```

۹. تمیز کردن

اگرچه 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

۱۰. تبریک

تبریک می‌گویم، شما با موفقیت یک برنامه وب ساختید که تصاویر ایجاد شده توسط Imagen را نمایش می‌دهد. چگونه می‌توانید از این در برنامه خود استفاده کنید؟

بعدش چی؟

به برخی از این آزمایشگاه‌های کد نگاهی بیندازید...

مطالعه بیشتر