أنشئ تطبيقًا مقترِحًا لـ "وضعيات اليوغا" بالاستناد إلى السياق باستخدام Firestore وVector Search وGemini 2.0 (إصدار Java).

1. نظرة عامة

في عالم تطبيقات الصحة واللياقة البدنية، من المهم تقديم تجربة ثرية وجذابة للمستخدمين. بالنسبة إلى تطبيق يوجا، يعني ذلك تقديم معلومات شاملة ومحتوى وسائط متعدّدة وإمكانات بحث ذكية، وليس مجرد أوصاف نصية بسيطة لوضعيات اليوجا. في هذه المدونة، سنستكشف كيفية إنشاء قاعدة بيانات قوية لأوضاع اليوغا باستخدام Firestore من Google Cloud، والاستفادة من إضافة Vector Search لمطابقة المحتوى حسب السياق، ودمج إمكانات Gemini 2.0 Flash (التجريبي) للتعامل مع المحتوى المتعدد الوسائط.

لماذا Firestore؟

‫Firestore، وهي قاعدة بيانات مستنِدة إلى تنسيق NoSQL وبدون خادم من Google Cloud، هي خيار ممتاز لإنشاء تطبيقات قابلة للتوسّع وديناميكية. إليك سبب ملاءمته لتطبيق اليوغا:

  • قابلية التوسّع والأداء: تتوسّع خدمة Firestore تلقائيًا للتعامل مع ملايين المستخدمين ومجموعات البيانات الضخمة، ما يضمن بقاء تطبيقك سريع الاستجابة حتى مع نموه.
  • التعديلات في الوقت الفعلي: تضمن المزامنة المضمّنة في الوقت الفعلي اتساق البيانات على جميع الأجهزة المتصلة، ما يجعلها مثالية لميزات مثل الدروس المباشرة أو التمارين التعاونية.
  • نموذج بيانات مرن: تتيح لك بنية المستندات في Firestore تخزين أنواع متنوعة من البيانات، بما في ذلك النصوص والصور وحتى التضمينات، ما يجعلها مثالية لتمثيل معلومات معقّدة عن وضعيات اليوغا.
  • طلبات البحث الفعّالة: تتيح Firestore إجراء طلبات بحث معقّدة، بما في ذلك المساواة وعدم المساواة، والآن، باستخدام الإضافة الجديدة، عمليات البحث عن التشابه المتّجه.
  • إتاحة الاستخدام بلا إنترنت: تخزِّن Firestore البيانات مؤقتًا على الجهاز، ما يتيح لتطبيقك العمل حتى عندما يكون المستخدمون غير متصلين بالإنترنت.

تحسين البحث باستخدام إضافة "البحث عن المتّجهات" على Firestore

يمكن أن يكون البحث التقليدي المستند إلى الكلمات الرئيسية محدودًا عند التعامل مع مفاهيم معقّدة، مثل أوضاع اليوجا. قد يبحث المستخدم عن وضعية "تفتح الوركين" أو "تحسّن التوازن" بدون معرفة اسم الوضعية المحدّد. وهنا يأتي دور Vector Search.

تتيح لك ميزة "البحث عن المتّجهات" في Firestore إجراء ما يلي:

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

دمج Gemini 2.0 Flash (تجريبي)

Gemini 2.0 Flash هو نموذج الذكاء الاصطناعي المتطوّر ومتعدد الوسائط من Google. على الرغم من أنّها لا تزال تجريبية، إلا أنّها توفّر إمكانات رائعة لإثراء تطبيق Yoga:

  • إنشاء نص: يمكنك استخدام ‎2.0 Flash في Gemini لإنشاء أوصاف تفصيلية لوضعيات اليوغا، بما في ذلك الفوائد والتعديلات وموانع الاستخدام.
  • إنشاء الصور (محاكاة): على الرغم من أنّ ميزة إنشاء الصور مباشرةً باستخدام Gemini غير متاحة للجميع بعد، فقد حاكيتُ هذه الميزة باستخدام Imagen من Google، ما أدّى إلى إنشاء صور تمثّل الوضعيات بصريًا.
  • إنشاء الصوت (محاكاة): يمكننا أيضًا استخدام خدمة تحويل النص إلى كلام (TTS) لإنشاء تعليمات صوتية لكل وضعية، ما يوجّه المستخدمين خلال التمرين.

أفكر في اقتراح دمج النموذج لتحسين التطبيق من خلال استخدام الميزات التالية:

  • Multimodal Live API: تساعدك واجهة برمجة التطبيقات الجديدة هذه في إنشاء تطبيقات لبث الصوت والفيديو في الوقت الفعلي مع إمكانية استخدام الأدوات.
  • السرعة والأداء: يتميّز نموذج ‎2.0 Flash في Gemini بوقت استجابة أسرع بكثير من نموذج ‎1.5 Flash في Gemini.
  • تجارب محسّنة بالذكاء الاصطناعي الوكيل: يقدّم Gemini 2.0 تحسينات على فهم الوسائط المتعددة والترميز واتّباع التعليمات المعقّدة واستدعاء الدوال. وتعمل هذه التحسينات معًا لتقديم تجارب أفضل.

لمزيد من التفاصيل، يُرجى الرجوع إلى صفحة%20المستندات%20حول%20Gemini%201.5%20Flash).

لتعزيز المصداقية وتوفير المزيد من المراجع، يمكننا دمج "بحث Google" لتأكيد المعلومات التي يقدّمها تطبيقنا، ما يعني:

  • البحث السياقي: عندما يُدخل مستخدم مشرف تفاصيل وضعية معيّنة، يمكننا استخدام اسم الوضعية لإجراء بحث Google.
  • استخراج عناوين URL: يمكننا استخراج عناوين URL ذات صلة من نتائج البحث، مثل المقالات أو الفيديوهات أو المواقع الإلكترونية الموثوقة التي تتناول مواضيع حول اليوغا، وعرضها داخل التطبيق.

ما ستنشئه

في هذا الدرس التطبيقي، ستنفّذ ما يلي:

  1. إنشاء مجموعة Firestore وتحميل مستندات Yoga
  2. التعرّف على كيفية إنشاء تطبيقات CRUD باستخدام Firestore
  3. إنشاء وصف لوضعية اليوغا باستخدام ‎2.0 Flash في Gemini
  4. تفعيل ميزة "البحث عن المتّجهات" على Firebase من خلال دمجها مع Firestore
  5. إنشاء تضمينات من وصف تطبيق Yoga
  6. إجراء بحث عن التشابه في نص بحث المستخدم

المتطلبات

  • متصفّح، مثل Chrome أو Firefox
  • مشروع Google Cloud تم تفعيل الفوترة فيه

2. قبل البدء

إنشاء مشروع

  1. في Google Cloud Console، ضمن صفحة اختيار المشروع، اختَر مشروعًا على Google Cloud أو أنشِئه.
  2. تأكَّد من تفعيل الفوترة لمشروعك على السحابة الإلكترونية. تعرَّف على كيفية التحقّق مما إذا كانت الفوترة مفعَّلة في مشروع .
  3. ستستخدم Cloud Shell، وهي بيئة سطر أوامر تعمل في Google Cloud ومحمّلة مسبقًا بأداة bq. انقر على "تفعيل Cloud Shell" في أعلى "وحدة تحكّم Google Cloud".

صورة زر تفعيل Cloud Shell

  1. بعد الاتصال بـ Cloud Shell، يمكنك التأكّد من أنّك قد أثبتّ هويتك وأنّ المشروع مضبوط على رقم تعريف مشروعك باستخدام الأمر التالي:
gcloud auth list
  1. نفِّذ الأمر التالي في Cloud Shell للتأكّد من أنّ أمر gcloud يعرف مشروعك.
gcloud config list project
  1. إذا لم يتم ضبط مشروعك، استخدِم الأمر التالي لضبطه:
gcloud config set project <YOUR_PROJECT_ID>
  1. فعِّل واجهات برمجة التطبيقات المطلوبة باتّباع هذا الرابط إلى أن تتمكّن من النقر على الزر "تفعيل".

في حال عدم توفّر أي واجهة برمجة تطبيقات، يمكنك تفعيلها في أي وقت أثناء عملية التنفيذ.

راجِع المستندات لمعرفة أوامر gcloud وطريقة استخدامها.

3- إعداد قاعدة البيانات

تتضمّن المستندات خطوات أكثر اكتمالاً حول كيفية إعداد مثيل Firestore. على مستوى عالٍ، للبدء، سأتّبع الخطوات التالية:

‫1 انتقِل إلى عارض Firestore، ومن شاشة "اختيار خدمة قاعدة بيانات"، اختَر Firestore في الوضع الأصلي.

  1. اختَر موقعًا جغرافيًا لخدمة Firestore (احرص على اختيار us-central1 واتّباع ذلك في أي مكان تختاره فيه منطقة أو موقعًا جغرافيًا خلال هذا الدرس التطبيقي حول الترميز)
  2. انقر على "إنشاء قاعدة بيانات" (Create Database) (إذا كانت هذه هي المرة الأولى، اترِكها كقاعدة بيانات "(default)")

عند إنشاء مشروع Firestore، يتم أيضًا تفعيل واجهة برمجة التطبيقات في Cloud API Manager

  1. ملاحظة مهمة: اختَر إصدار TEST (وليس PRODUCTION) من "قواعد الأمان" لكي يمكن الوصول إلى البيانات.
  2. بعد إعدادها، من المفترض أن تظهر لك قاعدة بيانات Firestore وعرض المجموعة والمستند في "الوضع الأصلي" كما هو موضّح في الصورة أدناه:

f7136d53253c59a.png

  1. لا تنفّذ هذه الخطوة بعد، ولكن يمكنك النقر على "بدء التجميع" وإنشاء مجموعة جديدة. اضبط معرّف المجموعة على "poses". انقر على الزر حفظ.

a26eb470aa9bfda9.png

نصائح للمحترفين بشأن استخدام التطبيق في مرحلة الإنتاج:

  1. بعد الانتهاء من نموذج البيانات وتحديد المستخدمين الذين يجب أن يتمكّنوا من الوصول إلى أنواع مختلفة من المستندات، يمكنك إنشاء قواعد الأمان وتعديلها ومراقبتها من واجهة Firebase. يمكنك الوصول إلى "قواعد الأمان" من خلال هذا الرابط: https://console.firebase.google.com/u/0/project/<<your_project_id>>/firestore/rules
  2. احرص على تعديل قواعد الأمان ومراقبتها واختبارها قبل نشر المشروع أو طرحه من مرحلة التطوير، لأنّها غالبًا ما تكون السبب الخفي وراء اختلاف طريقة عمل تطبيقك :)

في هذا العرض التوضيحي، سنستخدمه في وضع TEST.

4. Firestore REST API

  1. يمكن أن تكون واجهة REST API مفيدة في حالات الاستخدام التالية:أ. الوصول إلى Firestore من بيئة محدودة الموارد لا يمكن فيها تشغيل مكتبة عملاء كاملة أتمتة إدارة قاعدة البيانات أو استرداد بيانات تعريف تفصيلية لقاعدة البيانات
  2. أسهل طريقة لاستخدام Firestore هي استخدام إحدى مكتبات البرامج الأصلية للعملاء، ولكن هناك بعض الحالات التي يكون فيها من المفيد طلب REST API مباشرةً.
  3. في نطاق هذه المدونة، ستطّلع على استخدام واجهات برمجة تطبيقات REST في Firestore وعرضها، وليس مكتبات البرامج الأصلية للعملاء.
  4. للمصادقة، تقبل واجهة برمجة التطبيقات REST الخاصة بخدمة Firestore إما رمزًا مميزًا لمعرّف مصادقة Firebase أو رمزًا مميزًا لبروتوكول OAuth 2.0 من Google Identity. لمزيد من المعلومات حول موضوع المصادقة والترخيص، يُرجى الرجوع إلى المستندات.
  5. تتوفّر جميع نقاط نهاية REST API ضمن عنوان URL الأساسي https://firestore.googleapis.com/v1/.

Spring Boot وFirestore API

يهدف هذا الحلّ في إطار عمل Spring Boot إلى عرض تطبيق عميل يستخدم واجهات برمجة تطبيقات Firestore لجمع تفاصيل وضعيات اليوغا والتنفّس وتعديلها من خلال تجربة تفاعلية مع المستخدم.

للحصول على شرح مفصّل خطوة بخطوة حول جزء حلّ CRUD في Firestore الخاص بتطبيق "أوضاع اليوغا"، يمكنك الانتقال إلى رابط المدونة.

للتركيز على الحلّ الحالي والتعرّف على جزء CRUD أثناء التنقل، استنسِخ الحلّ الكامل الذي يركّز على هذه المدونة من المستودع أدناه من "وحدة Cloud Shell الطرفية" واحصل على نسخة من قاعدة الرموز البرمجية.

git clone https://github.com/AbiramiSukumaran/firestore-poserecommender

ملاحظة:

  1. بعد استنساخ هذا المستودع، ما عليك سوى إجراء بعض التغييرات على رقم تعريف مشروعك وواجهات برمجة التطبيقات وما إلى ذلك. ولا يلزم إجراء أي تغيير آخر لتشغيل تطبيقك. سيتم شرح كل مكوّن من مكوّنات التطبيق في الأقسام القادمة. في ما يلي قائمة بالتغييرات:
  2. في ملف src/main/java/com/example/demo/GenerateImageSample.java، استبدِل "<<YOUR_PROJECT_ID>>" برقم تعريف مشروعك.
  3. في ملف src/main/java/com/example/demo/GenerateEmbeddings.java، استبدِل "<<YOUR_PROJECT_ID>>" برقم تعريف مشروعك.
  4. في src/main/java/com/example/demo/PoseController.java، استبدِل جميع مثيلات "<<YOUR_PROJECT_ID>>" واسم قاعدة البيانات, في هذه الحالة "(default)", بقيم مناسبة من الإعدادات:
  5. في src/main/java/com/example/demo/PoseController.java، استبدِل "[YOUR_API_KEY]" بمفتاح واجهة برمجة التطبيقات الخاص بـ Gemini 2.0 Flash. يمكنك الحصول على هذه المعلومات من AI Studio.
  6. إذا أردت إجراء الاختبار محليًا، نفِّذ الأوامر التالية من مجلد المشروع في "وحدة Cloud Shell الطرفية":
mvn package

mvn spring-boot:run

في الوقت الحالي، يمكنك عرض تطبيقك قيد التشغيل من خلال النقر على خيار "معاينة الويب" من "وحدة طرفية Cloud Shell". لسنا مستعدين لإجراء الاختبارات وتجربة التطبيق بعد.

  1. اختياري: إذا كنت تريد تفعيل التطبيق في Cloud Run، عليك إنشاء تطبيق Java Cloud Run جديد تمامًا من البداية من Cloud Shell Editor، وإضافة ملفات src وملفات النماذج من المستودع إلى مشروعك الجديد في المجلدات المعنية (لأنّ مشروع مستودع GitHub الحالي غير معدّ حاليًا بشكل تلقائي لإعدادات التفعيل في Cloud Run). في هذه الحالة، يجب اتّباع الخطوات التالية (بدلاً من استنساخ المستودع الحالي):
  2. انتقِل إلى محرِّر Cloud Shell (تأكَّد من فتح المحرِّر وليس الوحدة الطرفية)، وانقر على رمز اسم مشروع Google Cloud في الجانب الأيمن من شريط الحالة (الجزء المحجوب في لقطة الشاشة أدناه).

d3f0de417094237d.png

  1. اختَر "تطبيق جديد" (New application) -> "تطبيق Cloud Run" (Cloud Run Application) -> "Java: Cloud Run" (Java: Cloud Run) من قائمة الخيارات، ثم أطلِق عليه الاسم "firestore-poserecommender".

d5ef8b4ca8bf3f85.png

  1. من المفترض أن يظهر لك الآن نموذج كامل لتطبيق Java Cloud Run، تم إعداده مسبقًا وأصبح جاهزًا للاستخدام
  2. أزِل فئة Controller الحالية وانسخ الملفات التالية إلى المجلدات الخاصة بها في بنية المشروع:

firestore-poserecommender/src/main/java/com/example/demo/

  1. FirestoreSampleApplication.java
  2. GenerateEmbeddings.java
  3. GenerateImageSample.java
  4. Pose.java
  5. PoseController.java
  6. ServletInitializer.java
             firestore-poserecommender/src/main/resources/static/
    
  7. Index.html

firestore-poserecommender/src/main/resources/templates/

  1. contextsearch.html
  2. createpose.html
  3. errmessage.html
  4. pose.html
  5. ryoq.html
  6. searchpose.html
  7. showmessage.html

firestore-poserecommender/

  1. ملف شامل
  2. عليك إجراء التغييرات في الملفات ذات الصلة لاستبدال PROJECT ID وAPI KEY بالقيم الخاصة بك. (الخطوات من 1 أ إلى 1 د أعلاه).

5- نقل البيانات

تتوفّر بيانات التطبيق في ملف data.json هذا: https://github.com/AbiramiSukumaran/firestore-poserecommender/blob/main/data.json

إذا أردت البدء ببعض البيانات المحدّدة مسبقًا، يمكنك نسخ ملف json واستبدال جميع مواضع "<<YOUR_PROJECT_ID>>" بالقيمة التي تريدها.

  • الانتقال إلى Firestore Studio
  • تأكَّد من إنشاء مجموعة باسم "أوضاع"
  • أضِف المستندات من ملف المستودع المذكور أعلاه يدويًا واحدًا تلو الآخر

يمكنك بدلاً من ذلك استيراد البيانات في خطوة واحدة من المجموعة المحدّدة مسبقًا التي أنشأناها لك باتّباع الخطوات التالية:

  1. انتقِل إلى Cloud Shell Terminal وتأكَّد من ضبط مشروع Google Cloud النشط ومن حصولك على الإذن اللازم. أنشئ حزمة في مشروعك باستخدام أمر gsutil الموضّح أدناه. استبدِل المتغيّر <PROJECT_ID> في الأمر أدناه برقم تعريف مشروع Google Cloud:

gsutil mb -l us gs://<PROJECT_ID>-yoga-poses-bucket

  1. بعد إنشاء الحزمة، علينا نسخ عملية تصدير قاعدة البيانات التي أعددناها إلى هذه الحزمة، قبل أن نتمكّن من استيرادها إلى قاعدة بيانات Firebase. استخدِم الأمر الموضّح أدناه:

gsutil cp -r gs://demo-bq-gemini-public/yoga_poses gs://<PROJECT_ID>-yoga-poses-bucket

بعد أن توفّرت لدينا البيانات المطلوب استيرادها، يمكننا الانتقال إلى الخطوة الأخيرة من عملية استيراد البيانات إلى قاعدة بيانات Firebase (الخيار التلقائي) التي أنشأناها.

  1. انتقِل إلى وحدة تحكّم Firestore الآن وانقر على استيراد/تصدير من قائمة التنقّل على يمين الصفحة.

انقر على "استيراد" واختَر مسار Cloud Storage الذي أنشأته للتو، ثم انتقِل إلى أن تتمكّن من اختيار الملف "yoga_poses.overall_export_metadata":

f5c1d16df7d5a64a.png

  1. انقر على "استيراد".

سيستغرق الاستيراد بضع ثوانٍ، وبعد أن يصبح جاهزًا، يمكنك التحقّق من صحة قاعدة بيانات Firestore والمجموعة من خلال الانتقال إلى https://console.cloud.google.com/firestore/databases، واختيار قاعدة البيانات التلقائية والمجموعة poses كما هو موضّح أدناه:

  1. هناك طريقة أخرى وهي أنّه يمكنك أيضًا إنشاء السجلات يدويًا من خلال التطبيق بعد النشر باستخدام الإجراء "إنشاء وضعية جديدة".

6. البحث عن المتّجهات

تفعيل إضافة "البحث عن المتّجهات" على Firestore

استخدِم هذه الإضافة لتضمين مستندات Firestore وطلب البحث فيها تلقائيًا باستخدام ميزة البحث عن المتّجهات الجديدة. سينقلك هذا الإجراء إلى "مركز إضافات Firebase".

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

لنتعرّف على الخطوات:

تثبيت الإضافة:

ثبِّت إضافة "البحث عن المتّجهات باستخدام Firestore" من "سوق إضافات Firebase" بالنقر على "التثبيت في وحدة تحكّم Firebase".

ملاحظة مهمة:

عند الانتقال لأول مرة إلى صفحة الإضافات هذه، عليك اختيار المشروع نفسه الذي تعمل عليه في وحدة تحكّم Google Cloud والمدرَج في "وحدة تحكّم Firebase".

715426b97c732649.png

إذا لم يكن مشروعك مُدرَجًا، يمكنك إضافته في Firebase (اختَر مشروع Google Cloud الحالي من القائمة).

ضبط الإضافة:

حدِّد المجموعة ("poses") والحقل الذي يحتوي على النص المراد تضمينه ("posture") والمعلَمات الأخرى، مثل أبعاد التضمين.

إذا كانت هناك واجهات برمجة تطبيقات يجب تفعيلها ومدرَجة في هذه الخطوة، ستسمح لك صفحة الإعدادات بذلك، لذا اتّبِع الخطوات وفقًا لذلك.

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

5ba59b45710c567b.png

في إحدى الخطوات التالية، يتيح لك استخدام النموذج اللغوي الكبير الذي تختاره لإنشاء التضمينات. اختَر "Vertex AI".

bb528a04ebb5f976.png

تتعلّق الإعدادات القليلة التالية بمجموعتك والحقل الذي تريد تضمينه:

النموذج اللغوي الكبير: Vertex AI

مسار المجموعة: المواقف

الحدّ الأقصى التلقائي لطلبات البحث: 3

مقياس المسافة: جيب التمام

اسم حقل الإدخال: الوضعية

اسم حقل الإخراج: embedding

اسم حقل الحالة: الحالة

تضمين المستندات الحالية: نعم

تعديل التضمينات الحالية: نعم

موقع Cloud Functions: us-central1

تفعيل الأحداث: لم يتم وضع علامة في المربّع

fb8cdf1163fac7cb.png

بعد إعداد كل ذلك، انقر على الزر "تثبيت الإضافة". ستستغرق هذه العملية من 3 إلى 5 دقائق.

إنشاء عمليات تضمين:

عند إضافة مستندات أو تعديلها في مجموعة "الوضعيات"، ستنشئ الإضافة تلقائيًا تضمينات باستخدام نموذج مدرَّب مسبقًا أو نموذج من اختيارك عبر نقطة نهاية واجهة برمجة التطبيقات. في هذه الحالة، اخترنا Vertex AI في إعدادات الإضافة.

إنشاء الفهرس

سيفرض إنشاء فهرس في حقل التضمين عند استخدام التضمين في التطبيق.

تنشئ Firestore تلقائيًا فهارس لطلبات البحث الأساسية، ولكن يمكنك السماح لـ Firestore بإنشاء بنية الفهرس من خلال تنفيذ طلبات بحث ليس لها فهرس، وستوفّر لك رابطًا إلى الفهرس الذي تم إنشاؤه في رسالة الخطأ على جانب التطبيق. في ما يلي قائمة بالخطوات اللازمة لإنشاء فهرس متّجه:

  1. الانتقال إلى "وحدة طرفية Cloud Shell"
  2. نفِّذ الأمر التالي:
gcloud firestore indexes composite create --collection-group="poses" --query-scope=COLLECTION --database="(default)" --field-config vector-config='{"dimension":"768", "flat": "{}"}',field-path="embedding"

يمكنك الاطّلاع على مزيد من المعلومات حول هذا الموضوع هنا.

بعد إنشاء فهرس متّجه، يمكنك إجراء بحث عن أقرب عنصر مجاور باستخدام عمليات التضمين المتّجهة.

ملاحظة مهمة:

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

لنلقِ نظرة على الطريقة التي يتعامل بها تطبيقك الذي تم إنشاؤه حديثًا مع "البحث المتّجه". بعد تخزين التضمينات، يمكنك استخدام فئة VectorQuery في حزمة تطوير البرامج (SDK) الخاصة بلغة Java في Firestore لإجراء "البحث المتّجه" والحصول على نتائج أقرب تطابق:

CollectionReference coll = firestore.collection("poses");
    VectorQuery vectorQuery = coll.findNearest(
        "embedding",
        userSearchTextEmbedding, 
        /* limit */ 3,
        VectorQuery.DistanceMeasure.EUCLIDEAN,
        VectorQueryOptions.newBuilder().setDistanceResultField("vector_distance")
         .setDistanceThreshold(2.0)
          .build());
ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();
List<Pose> posesList = new ArrayList<Pose>();
// Get the ID of the closest document (assuming results are sorted by distance)
String closestDocumentId = vectorQuerySnapshot.getDocuments().get(0).getId();

تقارن هذه المقتطفة بين تضمين نص بحث المستخدم وتضمينات المستندات في Firestore، ثم تستخرج المقتطفة الأقرب سياقيًا.

7. ‫Gemini 2.0 Flash

دمج ‎2.0 Flash في Gemini (لإنشاء الأوصاف)

لنلقِ نظرة على كيفية تعامل تطبيقك الذي تم إنشاؤه حديثًا مع عملية دمج Gemini 2.0 Flash لإنشاء الأوصاف.

لنفترض الآن أنّ أحد مشرفي النظام أو مدرّب اليوغا يريد إدخال تفاصيل الأوضاع بمساعدة Gemini 2.0 Flash، ثم إجراء بحث للاطّلاع على النتائج الأقرب تطابقًا. ويؤدي ذلك إلى استخراج تفاصيل الوضعيات المطابقة مع الكائنات المتعددة الوسائط التي تدعم النتائج.

String apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=[YOUR_API_KEY]";
Map<String, Object> requestBody = new HashMap<>();
List<Map<String, Object>> contents = new ArrayList<>();
List<Map<String, Object>> tools = new ArrayList<>();
Map<String, Object> content = new HashMap<>();
List<Map<String, Object>> parts = new ArrayList<>();
Map<String, Object> part = new HashMap<>();
part.put("text", prompt);
parts.add(part);
content.put("parts", parts);
contents.add(content);
requestBody.put("contents", contents);
/**Setting up Grounding*/
Map<String, Object> googleSearchTool = new HashMap<>();
googleSearchTool.put("googleSearch", new HashMap<>());
tools.add(googleSearchTool);
requestBody.put("tools", tools);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.exchange(apiUrl, HttpMethod.POST, requestEntity, String.class);
System.out.println("Generated response: " + response);
String responseBody = response.getBody();
JSONObject jsonObject = new JSONObject(responseBody);
JSONArray candidates = jsonObject.getJSONArray("candidates");
JSONObject candidate = candidates.getJSONObject(0);
JSONObject contentResponse = candidate.getJSONObject("content");
JSONArray partsResponse = contentResponse.getJSONArray("parts");
JSONObject partResponse = partsResponse.getJSONObject(0);
String generatedText = partResponse.getString("text");
System.out.println("Generated Text: " + generatedText);

أ- محاكاة إنشاء الصور والمقاطع الصوتية

بإمكان الإصدار التجريبي من ‎Gemini 2.0 Flash إنشاء نتائج متعددة الوسائط، ولكن لم أشترك في برنامج استخدامه قبل إطلاقه بعد، لذا حاكيت مخرجات الصور ومصدر إخراج الصوت باستخدام واجهات برمجة التطبيقات Imagen وTTS على التوالي. تخيّل مدى روعة الحصول على كل هذا المحتوى من خلال طلب بيانات من واجهة برمجة التطبيقات إلى ‎Gemini 2.0‎ Flash.

try (PredictionServiceClient predictionServiceClient =
          PredictionServiceClient.create(predictionServiceSettings)) {
  
        final EndpointName endpointName =
            EndpointName.ofProjectLocationPublisherModelName(
                projectId, location, "google", "imagen-3.0-generate-001");
  
        Map<String, Object> instancesMap = new HashMap<>();
        instancesMap.put("prompt", prompt);
        Value instances = mapToValue(instancesMap);
  
        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("sampleCount", 1);
        paramsMap.put("aspectRatio", "1:1");
        paramsMap.put("safetyFilterLevel", "block_few");
        paramsMap.put("personGeneration", "allow_adult");
        Value parameters = mapToValue(paramsMap);
  
        PredictResponse predictResponse =
            predictionServiceClient.predict(
                endpointName, Collections.singletonList(instances), parameters);
  
        for (Value prediction : predictResponse.getPredictionsList()) {
          Map<String, Value> fieldsMap = prediction.getStructValue().getFieldsMap();
          if (fieldsMap.containsKey("bytesBase64Encoded")) {
            bytesBase64Encoded = fieldsMap.get("bytesBase64Encoded").getStringValue();
       }
      }
      return bytesBase64Encoded;
    }
 try {
            // Create a Text-to-Speech client
            try (TextToSpeechClient textToSpeechClient = TextToSpeechClient.create()) {
                // Set the text input to be synthesized
                SynthesisInput input = SynthesisInput.newBuilder().setText(postureString).build();

                // Build the voice request, select the language code ("en-US") and the ssml
                // voice gender
                // ("neutral")
                VoiceSelectionParams voice =
                        VoiceSelectionParams.newBuilder()
                                .setLanguageCode("en-US")
                                .setSsmlGender(SsmlVoiceGender.NEUTRAL)
                                .build();

                // Select the type of audio file you want returned
                AudioConfig audioConfig =
                        AudioConfig.newBuilder().setAudioEncoding(AudioEncoding.MP3).build();

                // Perform the text-to-speech request on the text input with the selected voice
                // parameters and audio file type
                SynthesizeSpeechResponse response =
                        textToSpeechClient.synthesizeSpeech(input, voice, audioConfig);

                // Get the audio contents from the response
                ByteString audioContents = response.getAudioContent();

                // Convert to Base64 string
                String base64Audio = Base64.getEncoder().encodeToString(audioContents.toByteArray());

                // Add the Base64 encoded audio to the Pose object
               return base64Audio;
            }

        } catch (Exception e) {
            e.printStackTrace(); // Handle exceptions appropriately. For a real app, log and provide user feedback.
            return "Error in Audio Generation";
        }
}

ب. تحديد المصادر باستخدام "بحث Google":

إذا تحقّقت من رمز استدعاء Gemini في الخطوة 6، ستلاحظ مقتطف الرمز التالي لتفعيل ميزة تحديد مصدر المعلومات الخاصة بـ "بحث Google" لردّ النموذج اللغوي الكبير:

 /**Setting up Grounding*/
Map<String, Object> googleSearchTool = new HashMap<>();
googleSearchTool.put("googleSearch", new HashMap<>());
tools.add(googleSearchTool);
requestBody.put("tools", tools);

ويتم ذلك لضمان ما يلي:

  • توجيه نموذجنا إلى نتائج البحث الفعلية
  • استخراج عناوين URL ذات صلة تمت الإشارة إليها في البحث

8. تشغيل تطبيقك

لنلقِ نظرة على جميع إمكانات تطبيق Java Spring Boot الذي تم إنشاؤه حديثًا باستخدام واجهة ويب بسيطة من Thymeleaf:

  1. عمليات الإنشاء والقراءة والتعديل والحذف في Firestore
  2. البحث عن الكلمات الرئيسية
  3. إنشاء السياق استنادًا إلى الذكاء الاصطناعي التوليدي
  4. البحث السياقي (البحث عن المتّجهات)
  5. نتائج متعددة الوسائط ذات صلة بطلب البحث
  6. تشغيل طلب البحث الخاص بك (طلبات البحث بتنسيق structuredQuery)

مثال: {"structuredQuery":{"select":{"fields":[{"fieldPath":"name"}]},"from":[{"collectionId":"fitness_poses"}]}}

جميع الميزات التي تمّت مناقشتها حتى الآن هي جزء من التطبيق الذي أنشأته للتو من المستودع: https://github.com/AbiramiSukumaran/firestore-poserecommender

لإنشاء التطبيق وتشغيله وتفعيله، شغِّل الأوامر التالية من "وحدة Cloud Shell الطرفية":

mvn package

mvn spring-boot:run

من المفترض أن تظهر لك النتيجة وأن تتمكّن من تجربة ميزات تطبيقاتك. يمكنك مشاهدة الفيديو أدناه للاطّلاع على العرض التوضيحي للناتج:

تطبيق لاقتراح أوضاع اليوغا باستخدام Firestore وVector Search وGemini 2.0 Flash

خطوة اختيارية:

لنشر التطبيق على Cloud Run (بافتراض أنّك أعددت تطبيقًا جديدًا تمامًا باستخدام Dockerfile ونسخت الملفات حسب الحاجة)، شغِّل الأمر التالي من "وحدة Cloud Shell الطرفية" من داخل دليل مشروعك:

gcloud run deploy --source .

أدخِل اسم التطبيق ورمز المنطقة (اختَر الرمز الخاص بـ us-central1) واختَر "Y" لتفعيل خيار الاستدعاء غير المصادق عليه كما هو مطلوب. من المفترض أن تتلقّى نقطة نهاية تطبيقك في نافذة الأوامر بعد اكتمال عملية النشر بنجاح.

9- تَنظيم

لتجنُّب تحمّل رسوم في حسابك على Google Cloud مقابل الموارد المستخدَمة في هذه المشاركة، اتّبِع الخطوات التالية:

  1. في Google Cloud Console، انتقِل إلى صفحة إدارة الموارد.
  2. في قائمة المشاريع، اختَر المشروع الذي تريد حذفه، ثم انقر على حذف.
  3. في مربّع الحوار، اكتب رقم تعريف المشروع، ثم انقر على إيقاف لحذف المشروع.

10. تهانينا

تهانينا! لقد استخدمت Firestore بنجاح لإنشاء تطبيق قوي وذكي لإدارة أوضاع اليوغا. من خلال الجمع بين فعالية Firestore وVector Search Extension وإمكانات Gemini 2.0 Flash (مع إنشاء صور وأصوات محاكاة)، أنشأنا تطبيق يوغا جذابًا ومفيدًا لتنفيذ عمليات الإنشاء والقراءة والتعديل والحذف، وإجراء عمليات بحث مستندة إلى الكلمات الرئيسية، وعمليات بحث متّجهة حسب السياق، وإنشاء محتوى وسائط متعدّدة.

ولا يقتصر هذا النهج على تطبيقات اليوغا. مع استمرار تطوّر نماذج الذكاء الاصطناعي، مثل Gemini، ستتزايد إمكانات إنشاء تجارب مستخدم أكثر جاذبية وتخصيصًا. تذكَّر أنّه عليك البقاء على اطّلاع على آخر التطورات والمستندات من Google Cloud وFirebase للاستفادة من الإمكانات الكاملة لهذه التقنيات.

إذا أردت توسيع نطاق هذا التطبيق، سأحاول إجراء ما يلي باستخدام Gemini 2.0 Flash:

  1. استخدِم واجهة برمجة التطبيقات Multimodal Live من خلال إنشاء بث مباشر للرؤية والصوت في الوقت الفعلي لحالة الاستخدام.
  2. فعِّل وضع التفكير لإنشاء الأفكار التي تستند إليها الردود عند التفاعل مع البيانات في الوقت الفعلي، ما يجعل التجربة أكثر واقعية.

يمكنك تجربة ذلك وإرسال طلب سحب :>D!!!