สร้างแอปแนะนำท่าโยคะตามบริบทด้วย Firestore, Vector Search และ Gemini 2.0

1. ภาพรวม

ในโลกของแอปสุขภาพและความแข็งแรงสมบูรณ์ สิ่งสำคัญคือการมอบประสบการณ์การใช้งานที่สมบูรณ์และดึงดูดให้ผู้ใช้มีส่วนร่วม สําหรับแอปโยคะ หมายความว่าต้องนำเสนอมากกว่าคำอธิบายท่าทางแบบข้อความธรรมดา รวมถึงให้ข้อมูล เนื้อหามัลติมีเดีย และความสามารถในการค้นหาอัจฉริยะที่ครอบคลุม ในบล็อกนี้ เราจะอธิบายวิธีสร้างฐานข้อมูลท่าโยคะที่มีประสิทธิภาพโดยใช้ Firestore ของ Google Cloud, ใช้ประโยชน์จากส่วนขยายการค้นหาเวกเตอร์สำหรับการจับคู่ตามบริบท และผสานรวมความสามารถของ Gemini 2.0 Flash (เวอร์ชันทดลอง) เพื่อทำงานกับเนื้อหาแบบหลายมิติ

เหตุผลที่ควรใช้ Firestore

Firestore ซึ่งเป็นฐานข้อมูลเอกสาร NoSQL แบบ Serverless ของ Google Cloud เป็นตัวเลือกที่ยอดเยี่ยมในการสร้างแอปพลิเคชันที่ปรับขนาดได้และเป็นแบบไดนามิก เหตุผลที่ฟีเจอร์นี้เหมาะกับแอปโยคะของเรามีดังนี้

  • ความสามารถในการปรับขนาดและประสิทธิภาพ: Firestore จะปรับขนาดโดยอัตโนมัติเพื่อรองรับผู้ใช้หลายล้านคนและชุดข้อมูลขนาดใหญ่ เพื่อให้แอปของคุณยังคงตอบสนองได้แม้จะมีจำนวนผู้ใช้เพิ่มขึ้น
  • การอัปเดตแบบเรียลไทม์: การซิงค์แบบเรียลไทม์ในตัวช่วยให้ข้อมูลในไคลเอ็นต์ที่เชื่อมต่อทั้งหมดสอดคล้องกัน จึงเหมาะอย่างยิ่งสำหรับฟีเจอร์ต่างๆ เช่น คลาสสดหรือการฝึกแบบร่วมมือ
  • โมเดลข้อมูลที่ยืดหยุ่น: โครงสร้างแบบเอกสารของ Firestore ช่วยให้คุณจัดเก็บข้อมูลประเภทต่างๆ ได้ ซึ่งรวมถึงข้อความ รูปภาพ และแม้แต่การฝัง ทำให้เหมาะสําหรับแสดงข้อมูลท่าโยคะที่ซับซ้อน
  • การค้นหาที่มีประสิทธิภาพ: Firestore รองรับการค้นหาที่ซับซ้อน ซึ่งรวมถึงความเท่าเทียมกัน ความไม่เท่าเทียมกัน และตอนนี้ยังมีการค้นหาความคล้ายคลึงของเวกเตอร์ด้วยส่วนขยายใหม่
  • การรองรับการทำงานแบบออฟไลน์: Firestore จะแคชข้อมูลไว้ในเครื่อง ซึ่งช่วยให้แอปทำงานได้แม้ในขณะที่ผู้ใช้ออฟไลน์

การเพิ่มประสิทธิภาพการค้นหาด้วยส่วนขยายการค้นหาเวกเตอร์ของ Firestore

การค้นหาแบบดั้งเดิมที่อิงตามคีย์เวิร์ดอาจมีข้อจํากัดเมื่อจัดการกับแนวคิดที่ซับซ้อน เช่น ท่าโยคะ ผู้ใช้อาจค้นหาท่าที่ "เปิดสะโพก" หรือ "ปรับปรุงสมดุล" โดยที่ไม่รู้ชื่อท่าที่เฉพาะเจาะจง ด้วยเหตุนี้ การค้นหาด้วยเวกเตอร์จึงเข้ามามีบทบาท

การค้นหาเวกเตอร์ด้วย Firestore ช่วยให้คุณทําสิ่งต่อไปนี้ได้

  • สร้างการฝัง: เปลี่ยนรูปแบบคําอธิบายข้อความ และในอนาคตอาจเปลี่ยนรูปแบบรูปภาพและเสียงเป็นการแสดงผลเวกเตอร์เชิงตัวเลข (การฝัง) ที่จับความหมายเชิงอรรถศาสตร์โดยใช้โมเดล เช่น โมเดลที่มีอยู่ใน Vertex AI หรือโมเดลที่กําหนดเอง
  • จัดเก็บการฝัง: จัดเก็บการฝังเหล่านี้ในเอกสาร Firestore โดยตรง
  • ทำการค้นหาแบบคล้ายกัน: ค้นหาฐานข้อมูลเพื่อหาเอกสารที่คล้ายกันตามความหมายกับเวกเตอร์การค้นหาหนึ่งๆ ซึ่งจะเปิดใช้การจับคู่ตามบริบท

การผสานรวม Gemini 2.0 Flash (เวอร์ชันทดลอง)

Gemini 2.0 Flash เป็นโมเดล AI แบบหลายมิติข้อมูลล้ำสมัยของ Google แม้ว่าจะยังอยู่ระหว่างการทดสอบ แต่ฟีเจอร์นี้เปิดโอกาสที่น่าสนใจในการยกระดับแอปโยคะของเรา

  • การสร้างข้อความ: ใช้ Gemini 2.0 Flash เพื่อสร้างคำอธิบายท่าโยคะอย่างละเอียด ซึ่งรวมถึงประโยชน์ การปรับท่า และข้อห้าม
  • การสร้างรูปภาพ (เลียนแบบ): แม้ว่าการสร้างรูปภาพโดยตรงด้วย Gemini จะยังไม่พร้อมให้บริการแก่สาธารณะ แต่เราได้จำลองสิ่งนี้โดยใช้ Imagen ของ Google ซึ่งสร้างรูปภาพที่แสดงภาพท่าทาง
  • การสร้างเสียง (เลียนแบบ): ในทำนองเดียวกัน เราสามารถใช้บริการการอ่านออกเสียงข้อความ (TTS) เพื่อสร้างวิธีการแบบเสียงสำหรับท่าแต่ละท่าเพื่อแนะนำผู้ใช้ในการฝึก

เราอาจเสนอการผสานรวมเพื่อปรับปรุงแอปให้ใช้ฟีเจอร์ต่อไปนี้ของโมเดล

  • Multimodal Live API: API ใหม่นี้ช่วยให้คุณสร้างแอปพลิเคชันสตรีมมิงภาพและเสียงแบบเรียลไทม์ด้วยการใช้เครื่องมือ
  • ความเร็วและประสิทธิภาพ: Gemini 2.0 Flash ปรับปรุงเวลาในการรับโทเค็นแรก (TTFT) ได้อย่างมากเมื่อเทียบกับ Gemini 1.5 Flash
  • ประสบการณ์การใช้งานที่ดีขึ้น: Gemini 2.0 มีการปรับปรุงความเข้าใจแบบมัลติโมเดล การเขียนโค้ด การทำตามคำสั่งที่ซับซ้อน และการเรียกใช้ฟังก์ชัน การปรับปรุงเหล่านี้ทำงานร่วมกันเพื่อรองรับประสบการณ์การใช้งานที่ดีขึ้น

ดูรายละเอียดเพิ่มเติมได้ที่หน้า%20over%20Gemini%201.5%20Flash) ของเอกสารประกอบนี้

เราสามารถผสานรวม Google Search เพื่อตรวจสอบข้อมูลที่ได้จากแอปของเราเพื่อเพิ่มความน่าเชื่อถือและมอบแหล่งข้อมูลเพิ่มเติมได้ ซึ่งหมายความว่า

  • การค้นหาตามบริบท: เมื่อผู้ใช้ที่ดูแลระบบป้อนรายละเอียดของท่าทาง เราสามารถใช้ชื่อท่าทางเพื่อทำการค้นหาใน Google
  • การดึงข้อมูล URL: เราดึงข้อมูล URL ที่เกี่ยวข้อง เช่น บทความ วิดีโอ หรือเว็บไซต์โยคะที่มีชื่อเสียง ออกจากผลการค้นหาได้ และแสดงภายในแอป

สิ่งที่คุณจะสร้าง

คุณจะทําสิ่งต่อไปนี้ได้

  1. สร้างคอลเล็กชัน Firestore และโหลดเอกสาร Yoga
  2. ดูวิธีสร้างแอปพลิเคชัน CRUD ด้วย Firestore
  3. สร้างคำอธิบายท่าโยคะด้วย Gemini 2.0 Flash
  4. เปิดใช้ Firebase Vector Search ด้วยการผสานรวม Firestore
  5. สร้างการฝังจากคำอธิบายโยคะ
  6. ทำการค้นหาความคล้ายคลึงกันของข้อความค้นหาของผู้ใช้

ข้อกำหนด

  • เบราว์เซอร์ เช่น Chrome หรือ Firefox
  • โปรเจ็กต์ Google Cloud ที่เปิดใช้การเรียกเก็บเงิน

2. ก่อนเริ่มต้น

สร้างโปรเจ็กต์

  1. ในคอนโซล Google Cloud ให้เลือกหรือสร้างโปรเจ็กต์ Google Cloud ในหน้าตัวเลือกโปรเจ็กต์
  2. ตรวจสอบว่าเปิดใช้การเรียกเก็บเงินสำหรับโปรเจ็กต์ Cloud แล้ว ดูวิธีตรวจสอบว่าเปิดใช้การเรียกเก็บเงินในโปรเจ็กต์หรือไม่
  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. เปิดใช้ API ที่จำเป็น
gcloud services enable firestore.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       run.googleapis.com \
                       cloudbuild.googleapis.com \
                       cloudfunctions.googleapis.com \
                       aiplatform.googleapis.com \
                       storage.googleapis.com \ 
                       secretmanager.googleapis.com \ 
                       texttospeech.googleapis.com

อีกทางเลือกหนึ่งสำหรับคำสั่ง gcloud คือผ่านคอนโซลโดยค้นหาผลิตภัณฑ์แต่ละรายการหรือใช้ลิงก์นี้

หากมี API ใดขาดหายไป คุณจะเปิดใช้ได้เสมอในระหว่างการติดตั้งใช้งาน

โปรดดูคำสั่งและการใช้งาน gcloud ในเอกสารประกอบ

3. การตั้งค่าฐานข้อมูล

เอกสารประกอบมีขั้นตอนที่สมบูรณ์ยิ่งขึ้นเกี่ยวกับวิธีตั้งค่าอินสแตนซ์ Firestore ขั้นตอนคร่าวๆ ในการเริ่มต้นมีดังนี้

1 ไปที่ Firestore Viewer แล้วเลือก Firestore ในโหมดเนทีฟจากหน้าจอ "เลือกบริการฐานข้อมูล"

  1. เลือกตำแหน่งสำหรับ Firestore
  2. คลิกสร้างฐานข้อมูล (หากเป็นการใช้งานครั้งแรก ให้ปล่อยเป็นฐานข้อมูล "(default)")

เมื่อสร้างโปรเจ็กต์ Firestore ระบบจะเปิดใช้ API ในเครื่องมือจัดการ Cloud API ด้วย

  1. สำคัญ: เลือกกฎความปลอดภัยเวอร์ชันทดสอบ (ไม่ใช่เวอร์ชันที่ใช้งานจริง) เพื่อให้เข้าถึงข้อมูลได้
  2. เมื่อตั้งค่าแล้ว คุณควรเห็นมุมมองฐานข้อมูล คอลเล็กชัน และเอกสาร Firestore ในโหมดเนทีฟดังที่แสดงในภาพด้านล่าง

f7136d53253c59a.png

  1. คุณยังไม่ต้องทำขั้นตอนนี้ แต่โปรดทราบว่าคุณสามารถคลิก "เริ่มคอลเล็กชัน" และสร้างคอลเล็กชันใหม่ได้ ตั้งรหัสคอลเล็กชันเป็น "poses" คลิกปุ่มบันทึก

a26eb470aa9bfda9.png

เคล็ดลับสำหรับมือโปรสำหรับการใช้งานเวอร์ชันที่ใช้งานจริง

  1. เมื่อสร้างโมเดลข้อมูลและระบุผู้ที่ควรมีสิทธิ์เข้าถึงเอกสารประเภทต่างๆ แล้ว คุณสามารถสร้าง แก้ไข และตรวจสอบกฎความปลอดภัยจากอินเทอร์เฟซ Firebase ได้ คุณเข้าถึงกฎความปลอดภัยได้จากลิงก์นี้ https://console.firebase.google.com/u/0/project/<<your_project_id>>/firestore/rules
  2. อย่าลืมแก้ไข ตรวจสอบ และทดสอบกฎด้านความปลอดภัยก่อนทำให้โปรเจ็กต์ใช้งานได้จริงจากระยะการพัฒนา เนื่องจากกฎเหล่านี้มักเป็นสาเหตุที่ทำให้แอปทำงานต่างออกไปโดยที่คุณไม่รู้ตัว :)

ในการสาธิตนี้ เราจะใช้โหมดทดสอบ

4. Firestore REST API

  1. REST API มีประโยชน์สําหรับกรณีการใช้งานต่อไปนี้a. การเข้าถึง Firestore จากสภาพแวดล้อมที่มีทรัพยากรจํากัดซึ่งไม่สามารถเรียกใช้คลังไคลเอ็นต์ที่สมบูรณ์ได้ การทำให้การบํารุงจัดการฐานข้อมูลเป็นไปโดยอัตโนมัติหรือดึงข้อมูลเมตาฐานข้อมูลที่ละเอียด
  2. วิธีที่ง่ายที่สุดในการใช้ Firestore คือการใช้ไลบรารีไคลเอ็นต์แบบเนทีฟอย่างใดอย่างหนึ่ง แต่ก็มีบางกรณีที่การเรียก REST API โดยตรงจะมีประโยชน์
  3. ในขอบเขตของบล็อกนี้ คุณจะเห็นการใช้งานและการสาธิต Firestore REST API ไม่ใช่ไลบรารีไคลเอ็นต์เนทีฟ
  4. Firestore REST API ยอมรับโทเค็นรหัสการตรวจสอบสิทธิ์ Firebase หรือโทเค็น OAuth 2.0 ของข้อมูลประจำตัวของ Google สำหรับการตรวจสอบสิทธิ์ ดูข้อมูลเพิ่มเติมเกี่ยวกับหัวข้อการตรวจสอบสิทธิ์และการให้สิทธิ์ได้ที่เอกสารประกอบ
  5. ปลายทาง REST API ทั้งหมดอยู่ภายใต้ URL พื้นฐาน https://firestore.googleapis.com/v1/

Spring Boot และ Firestore API

โซลูชันนี้ในเฟรมเวิร์ก Spring Boot มีไว้เพื่อสาธิตแอปพลิเคชันไคลเอ็นต์ที่ใช้ Firestore API เพื่อรวบรวมและแก้ไขรายละเอียดท่าโยคะและการหายใจด้วยประสบการณ์การโต้ตอบของผู้ใช้

ดูคำอธิบายแบบทีละขั้นตอนโดยละเอียดเกี่ยวกับโซลูชัน CRUD ของ Firestore ในแอปท่าโยคะได้ที่ลิงก์บล็อก

หากต้องการมุ่งเน้นที่โซลูชันปัจจุบันและเรียนรู้ส่วน CRUD ในระหว่างเดินทาง ให้โคลนโซลูชันทั้งหมดที่มุ่งเน้นที่บล็อกนี้จากที่เก็บข้อมูลด้านล่างจากเทอร์มินัล Cloud Shell และรับสำเนาของโค้ดเบส

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

โปรดทราบว่า

  1. เมื่อโคลนที่เก็บข้อมูลนี้แล้ว คุณต้องทำการเปลี่ยนแปลงเพียงเล็กน้อยเกี่ยวกับรหัสโปรเจ็กต์, API ฯลฯ เท่านั้น ไม่จำเป็นต้องทำการเปลี่ยนแปลงอื่นๆ เพื่อทำให้แอปพลิเคชันใช้งานได้ องค์ประกอบแต่ละอย่างของแอปพลิเคชันจะอธิบายไว้ในส่วนถัดไป รายการการเปลี่ยนแปลงมีดังนี้
  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]" ด้วยคีย์ API สำหรับ 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 และเพิ่มไฟล์ src และไฟล์เทมเพลตจาก repo ไปยังโปรเจ็กต์ใหม่ในโฟลเดอร์ที่เกี่ยวข้อง (เนื่องจากระบบไม่ได้ตั้งค่าโปรเจ็กต์ repo ของ GitHub ปัจจุบันไว้สำหรับการกำหนดค่าการทำให้ใช้งานได้ของ Cloud Run โดยค่าเริ่มต้น) ขั้นตอนที่ต้องทำในกรณีดังกล่าว (แทนการโคลนที่เก็บที่มีอยู่) มีดังนี้
  2. ไปที่เครื่องมือแก้ไข Cloud Shell (ตรวจสอบว่าเครื่องมือแก้ไขเปิดอยู่ ไม่ใช่เทอร์มินัล) คลิกไอคอนชื่อโปรเจ็กต์ Google Cloud ทางด้านซ้ายของแถบสถานะ (ส่วนที่บล็อกในภาพหน้าจอด้านล่าง)

d3f0de417094237d.png

  1. เลือกแอปพลิเคชันใหม่ -> แอปพลิเคชัน 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. Dockerfile
  2. คุณต้องทําการเปลี่ยนแปลงในไฟล์ที่เกี่ยวข้องเพื่อแทนที่รหัสโปรเจ็กต์และคีย์ API ด้วยค่าที่เกี่ยวข้อง (ขั้นตอนที่ 1 ก ข ค และ ง ด้านบน)

5. การนำเข้าข้อมูล

ข้อมูลของแอปพลิเคชันอยู่ในไฟล์ data.json นี้ https://github.com/AbiramiSukumaran/firestore-poserecommender/blob/main/data.json

หากต้องการเริ่มต้นด้วยข้อมูลที่กําหนดไว้ล่วงหน้า ให้คัดลอก JSON มาแทนที่ "<<YOUR_PROJECT_ID>>" ทั้งหมดด้วยค่าของคุณ

  • ไปที่ Firestore Studio
  • ตรวจสอบว่าคุณได้สร้างคอลเล็กชันชื่อ "poses" แล้ว
  • เพิ่มเอกสารจากไฟล์ repo ที่กล่าวถึงข้างต้นทีละรายการด้วยตนเอง

หรือจะนําเข้าข้อมูลในครั้งเดียวจากชุดที่กําหนดไว้ล่วงหน้าที่เราสร้างไว้ให้คุณก็ได้ โดยทําตามขั้นตอนต่อไปนี้

  1. ไปที่เทอร์มินัล Cloud Shell และตรวจสอบว่าได้ตั้งค่าโปรเจ็กต์ 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. คลิก "นำเข้า"

การนําเข้าจะใช้เวลา 2-3 วินาที เมื่อพร้อมแล้ว คุณสามารถตรวจสอบฐานข้อมูล Firestore และคอลเล็กชันได้โดยไปที่ https://console.cloud.google.com/firestore/databases เลือกฐานข้อมูลเริ่มต้นและคอลเล็กชันท่าดังที่แสดงด้านล่าง

  1. อีกวิธีหนึ่งคือคุณสร้างระเบียนด้วยตนเองผ่านแอปพลิเคชันได้ด้วยเมื่อติดตั้งใช้งานโดยใช้การดำเนินการ "สร้างท่าทางใหม่"

6. การค้นหาเวกเตอร์

เปิดใช้ส่วนขยายการค้นหาเวกเตอร์ของ Firestore

ใช้ส่วนขยายนี้เพื่อฝังและค้นหาเอกสาร Firestore โดยอัตโนมัติด้วยฟีเจอร์การค้นหาเวกเตอร์ใหม่ ซึ่งจะนำคุณไปยังฮับส่วนขยาย Firebase

เมื่อติดตั้งส่วนขยายการค้นหาเวกเตอร์ คุณต้องระบุคอลเล็กชันและชื่อช่องเอกสาร การเพิ่มหรืออัปเดตเอกสารที่มีฟิลด์นี้จะทริกเกอร์ส่วนขยายนี้ให้คํานวณการฝังเวกเตอร์สําหรับเอกสาร ระบบจะเขียนการฝังเวกเตอร์นี้กลับไปยังเอกสารเดิม และจัดทำดัชนีเอกสารในสตอเรจเวกเตอร์ให้พร้อมสำหรับการค้นหา

มาดูขั้นตอนต่างๆ กัน

ติดตั้งส่วนขยาย:

ติดตั้งส่วนขยาย "การค้นหาเวกเตอร์ด้วย Firestore" จาก Firebase Extensions Marketplace โดยคลิก "ติดตั้งในคอนโซล Firebase"

สำคัญ:

เมื่อครั้งแรกที่คุณไปที่หน้าส่วนขยายนี้ คุณจะต้องเลือกโปรเจ็กต์เดียวกับที่คุณกําลังทํางานในคอนโซล Google Cloud ที่แสดงในคอนโซล Firebase

715426b97c732649.png

หากโปรเจ็กต์ไม่แสดงในรายการ ให้เพิ่มโปรเจ็กต์ใน Firebase (เลือกโปรเจ็กต์ Google Cloud ที่มีอยู่จากรายการ)

กําหนดค่าส่วนขยาย:

ระบุคอลเล็กชัน ("poses") ฟิลด์ที่มีข้อความที่จะฝัง ("posture") และพารามิเตอร์อื่นๆ เช่น มิติข้อมูลการฝัง

หากมี API ที่ต้องเปิดใช้ในขั้นตอนนี้ หน้าการกําหนดค่าจะอนุญาตให้คุณดำเนินการดังกล่าว โดยทําตามขั้นตอนที่เกี่ยวข้อง

หากหน้าเว็บไม่ตอบสนองหลังจากเปิดใช้ API ไปสักพัก ให้รีเฟรชหน้าเว็บแล้วคุณควรจะเห็น API ที่เปิดใช้

5ba59b45710c567b.png

ในขั้นตอนใดขั้นตอนหนึ่งต่อไปนี้ คุณจะสามารถใช้ LLM ที่ต้องการเพื่อสร้างการฝังได้ เลือก "Vertex AI"

bb528a04ebb5f976.png

การตั้งค่า 2-3 รายการถัดไปเกี่ยวข้องกับคอลเล็กชันและช่องที่ต้องการฝัง

LLM: Vertex AI

เส้นทางของคอลเล็กชัน: poses

ขีดจํากัดการค้นหาเริ่มต้น: 3

การวัดระยะทาง: โคไซน์

ชื่อช่องป้อน: posture

ชื่อช่องเอาต์พุต: ฝัง

ชื่อฟิลด์สถานะ: status

ฝังเอกสารที่มีอยู่: ใช่

อัปเดตการฝังที่มีอยู่: ใช่

ตำแหน่ง Cloud Functions: us-central1

เปิดใช้เหตุการณ์: ไม่ได้เลือก

fb8cdf1163fac7cb.png

เมื่อตั้งค่าทั้งหมดแล้ว ให้คลิกปุ่ม "ติดตั้งส่วนขยาย" ซึ่งจะใช้เวลา 3-5 นาที

สร้างการฝัง:

เมื่อคุณเพิ่มหรืออัปเดตเอกสารในคอลเล็กชัน "ท่าทาง" ส่วนขยายจะสร้างการฝังโดยอัตโนมัติโดยใช้โมเดลที่ผ่านการฝึกอบรมไว้ล่วงหน้าหรือโมเดลที่คุณเลือกผ่านปลายทาง API ในกรณีนี้ เราเลือก 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 ของ Firestore Java SDK เพื่อทำการค้นหาด้วยเวกเตอร์และรับผลลัพธ์ใกล้เคียงที่สุด ดังนี้

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

การผสานรวม Gemini 2.0 Flash (สําหรับการสร้างคําอธิบาย)

มาดูกันว่าแอปพลิเคชันที่สร้างขึ้นใหม่จัดการการผสานรวม 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 Experimental สามารถสร้างผลลัพธ์แบบมัลติโมเดลได้ แต่เรายังไม่ได้ลงชื่อสมัครใช้การทดลองใช้ก่อนเปิดตัว จึงจำลองเอาต์พุตรูปภาพและเสียงด้วย Imagen และ TTS API ตามลำดับ ลองนึกภาพว่าการสร้างทั้งหมดนี้ด้วยการเรียก API เพียงครั้งเดียวไปยัง 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 Search:

หากตรวจสอบโค้ดการเรียกใช้ Gemini ในขั้นตอนที่ 6 คุณจะเห็นข้อมูลโค้ดต่อไปนี้เพื่อเปิดใช้การอ้างอิงข้อมูลของ Google Search สําหรับคําตอบ LLM

 /**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. การดำเนินการ CRUD ของ Firestore (สร้าง อ่าน อัปเดต ลบ)
  2. การค้นหาคีย์เวิร์ด
  3. การสร้างบริบทตาม Generative AI
  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, การค้นหาเวกเตอร์ และ Gemini 2.0 Flash

ขั้นตอนที่ไม่บังคับ:

หากต้องการทำให้ใช้งานได้ใน Cloud Run (สมมติว่าคุณได้เริ่มต้นแอปพลิเคชันใหม่ด้วย Dockerfile และคัดลอกไฟล์ตามต้องการแล้ว) ให้เรียกใช้คำสั่งต่อไปนี้จาก Cloud Shell Terminal ภายในไดเรกทอรีโปรเจ็กต์

gcloud run deploy --source .

ระบุชื่อแอปพลิเคชัน รหัสภูมิภาค (เลือกรหัสสำหรับ us-central1) และเลือกการเรียกใช้ที่ไม่ผ่านการตรวจสอบสิทธิ์ "Y" ตามข้อความแจ้ง คุณควรได้รับปลายทางแอปพลิเคชันในเทอร์มินัลเมื่อการทําให้ใช้งานได้สําเร็จ

9. ล้างข้อมูล

โปรดทำตามขั้นตอนต่อไปนี้เพื่อเลี่ยงไม่ให้เกิดการเรียกเก็บเงินกับบัญชี Google Cloud สำหรับทรัพยากรที่ใช้ในโพสต์นี้

  1. ในคอนโซล Google Cloud ให้ไปที่หน้าจัดการทรัพยากร
  2. ในรายการโปรเจ็กต์ ให้เลือกโปรเจ็กต์ที่ต้องการลบ แล้วคลิกลบ
  3. ในกล่องโต้ตอบ ให้พิมพ์รหัสโปรเจ็กต์ แล้วคลิกปิดเพื่อลบโปรเจ็กต์

10. ขอแสดงความยินดี

ยินดีด้วย คุณใช้ Firestore เพื่อสร้างแอปพลิเคชันการจัดการท่าโยคะที่มีประสิทธิภาพและชาญฉลาดได้สําเร็จ การรวมความสามารถของ Firestore, ส่วนขยายการค้นหาเวกเตอร์ และความสามารถของ Gemini 2.0 Flash (ที่มีการสร้างภาพและเสียงจำลอง) ทำให้เราสร้างแอปโยคะที่มีส่วนร่วมและให้ข้อมูลอย่างแท้จริงเพื่อใช้การดำเนินการ CRUD, ทำการค้นหาตามคีย์เวิร์ด, การค้นหาเวกเตอร์ตามบริบท และสร้างเนื้อหามัลติมีเดีย

แนวทางนี้ไม่ได้จำกัดไว้เพียงแอปโยคะ เมื่อโมเดล AI เช่น Gemini พัฒนาอย่างต่อเนื่อง โอกาสในการสร้างประสบการณ์การใช้งานที่สมจริงและเหมาะกับผู้ใช้มากขึ้นก็จะยิ่งเพิ่มขึ้น อย่าลืมติดตามการพัฒนาและเอกสารประกอบล่าสุดจาก Google Cloud และ Firebase เพื่อใช้ประโยชน์จากเทคโนโลยีเหล่านี้อย่างเต็มศักยภาพ

หากต้องการขยายการให้บริการแอปนี้ ฉันจะพยายามทํา 2 อย่างต่อไปนี้ด้วย Gemini 2.0 Flash

  1. ใช้ Multimodal Live API โดยสร้างการสตรีมภาพและเสียงแบบเรียลไทม์สำหรับกรณีการใช้งาน
  2. ใช้โหมดการคิดเพื่อสร้างความคิดที่อยู่เบื้องหลังคำตอบสำหรับการโต้ตอบกับข้อมูลแบบเรียลไทม์เพื่อให้ประสบการณ์การใช้งานสมจริงยิ่งขึ้น

โปรดลองใช้และส่งคำขอดึงข้อมูลมา :>D!!!