نشر Imagen على Cloud Run

1. لمحة عن هذا الدرس التطبيقي حول الترميز

تاريخ آخر تعديل: 2024-10-11

من تأليف: "لوري وايت"

إنشاء الصور

لنكن صريحين، يمكن أن يكون إنشاء الصور بواسطة النماذج اللغوية الكبيرة (LLM) أمرًا ممتعًا. بالطبع، هناك العديد من التطبيقات التجارية لإنشاء الصور من خلال طلب، بدءًا من الإعلانات المخصّصة إلى العروض التقديمية الجذابة. (يتضمّن موقع Google Cloud الإلكتروني العديد من الاستخدامات المحدّدة للشركات التي تستخدم "الوكلاء الإبداعيين"). ومع ذلك، يمكن أن يكون من المسلّي جدًا رؤية النتائج عند طلب صورة "كلاب خضراء سعيدة في حقل".

سواء كنت مهتمًا بإنشاء الصور لأسباب مهنية أو ترفيهية (أو كليهما)، هناك بعض التحديات بين استخدام برنامج لإنشاء الصور ونشره في تطبيق ويب. سيساعدك هذا الدرس التطبيقي على التغلّب على هذه التحديات.

ما ستنشئه

في هذا الدرس التطبيقي حول الترميز، ستنشئ تطبيقًا يتلقّى طلبًا نصيًا ويعرض صفحة ويب تتضمّن صورة تم إنشاؤها باستخدام هذا الطلب.

ما ستتعلمه

في هذا التمرين العملي، ستتعرّف على ما يلي:

  • كيفية استخدام Google Imagen لإنشاء صور من الطلبات النصية في بيئات دفاتر الملاحظات
  • الصعوبات التي تواجه نقل رمز Imagen من دفتر ملاحظات إلى تطبيق ويب
  • كيفية نشر تطبيق Cloud Run يستخدم Imagen لإنشاء الصور
  • كيفية تضمين صورة من Imagen في HTML

يركّز هذا الدرس التطبيقي حول الترميز على Imagen وعملية النشر. يتم تجاهل المفاهيم ومجموعات الرموز غير ذات الصلة، ويتم توفيرها لك لنسخها ولصقها ببساطة.

المتطلبات

يتوفّر الرمز الكامل لهذا الدرس التطبيقي حول الترميز على https://github.com/Annie29/imagen-deployment .

2. تفعيل واجهات برمجة التطبيقات

اختَر مشروعًا لاستخدامه في هذا الدرس العملي. قد تحتاج إلى إنشاء مشروع جديد لتسهيل إزالة كل عملك عند الانتهاء.

قبل البدء باستخدام Imagen، عليك تفعيل بعض واجهات برمجة التطبيقات.

  1. انتقِل إلى Google Cloud Console.
  2. انتقِل إلى "لوحة بيانات Vertex AI".
  3. اختَر "تفعيل جميع واجهات برمجة التطبيقات المقترَحة"

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. ابدأ العمل على كل خلية في ورقة الملاحظات.
  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، وعادةً ما تتضمّن عناصر نائبة مسماة حيث سيُدرج البرنامج النص الذي تم إنشاؤه. 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 يرسل النموذج الذي يصف الصورة التي نريد إنشاءها.

باستخدام محرّر 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)

في الواقع، هذا هو التطبيق بأكمله تقريبًا، إذ يتضمّن ثلاثة تعليقات في 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 لـ الذكاء الاصطناعي التوليدي على 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 الخاص بالصورة المحفوظة عند عرض النموذج.

هذا الأمر معقّد بعض الشيء وهناك العديد من الطرق لتنفيذه. لنلقِ نظرة على أحد الأساليب الأبسط، خطوة بخطوة. (تتوفّر صورة للخطوات أدناه إذا كنتم تفضّلون طريقة التعلّم المرئي).

أولاً، علينا حفظ الصورة. ولكن ما هو الاسم الذي سيُطلق عليه؟ قد تحدث مشاكل عند استخدام اسم ثابت لأنّه يمكن أن يستخدم البرنامج العديد من الأشخاص في الوقت نفسه. على الرغم من أنّه يمكننا إنشاء أسماء صور منفصلة لكل مستخدم (باستخدام معرّف فريد عالميًا مثلاً)، إلا أنّ الطريقة الأسهل هي استخدام مكتبة 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

من المرجّح أن يكون السبب في ذلك هو طلب ينتهك أفضل ممارسات تصميم الذكاء الاصطناعي المسؤول في 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. كيف يمكنك استخدام ذلك في تطبيقك؟

ما هي الخطوات التالية؟

اطّلِع على بعض دروس الترميز التطبيقية هذه...

Further reading