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

1. ภาพรวม

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

ทำไมต้อง Firestore

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

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

การปรับปรุง Search ด้วยส่วนขยาย Firestore Vector Search

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

Vector Search ด้วย Firestore ช่วยให้คุณทำสิ่งต่อไปนี้ได้

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

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

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

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

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

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

ดูรายละเอียดเพิ่มเติมได้ที่หน้าเอกสารนี้เกี่ยวกับ Gemini 1.5 Flash

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

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

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

ในห้องทดลองนี้ คุณจะทำสิ่งต่อไปนี้

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

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

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

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

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

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

  1. เลือกสถานที่ตั้งสำหรับ Firestore (ตรวจสอบว่าได้เลือก us-central1 และทำตามนี้ทุกครั้งที่คุณเลือกภูมิภาค / สถานที่ตั้งตลอดทั้ง Codelab นี้)
  2. คลิกสร้างฐานข้อมูล (หากเป็นครั้งแรก ให้ปล่อยเป็นฐานข้อมูล "(default)")

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

  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 มีประโยชน์สำหรับกรณีการใช้งานต่อไปนี้ ก. การเข้าถึง Firestore จากสภาพแวดล้อมที่มีข้อจำกัดด้านทรัพยากรซึ่งไม่สามารถเรียกใช้ไลบรารีของไคลเอ็นต์ที่สมบูรณ์ได้ การทำให้การดูแลระบบฐานข้อมูลเป็นไปโดยอัตโนมัติหรือการดึงข้อมูลเมตาของฐานข้อมูลแบบละเอียด
  2. วิธีที่ง่ายที่สุดในการใช้ Firestore คือการใช้ไลบรารีของไคลเอ็นต์ดั้งเดิมอย่างใดอย่างหนึ่ง แต่ก็มีบางกรณีที่การเรียกใช้ REST API โดยตรงจะมีประโยชน์
  3. ในขอบเขตของบล็อกนี้ คุณจะเห็นการใช้งานและการสาธิต REST API ของ Firestore และไม่ใช่ไลบรารีของไคลเอ็นต์ดั้งเดิม
  4. สำหรับการตรวจสอบสิทธิ์ Firestore REST API จะยอมรับโทเค็นรหัสการตรวจสอบสิทธิ์ Firebase หรือโทเค็น OAuth 2.0 ของ Google Identity ดูข้อมูลเพิ่มเติมเกี่ยวกับหัวข้อการตรวจสอบสิทธิ์และการให้สิทธิ์ได้ที่เอกสารประกอบ
  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 Editor และเพิ่มไฟล์ src และไฟล์เทมเพลตจากที่เก็บไปยังโปรเจ็กต์ใหม่ในโฟลเดอร์ที่เกี่ยวข้อง (เนื่องจากโปรเจ็กต์ที่เก็บ GitHub ปัจจุบันไม่ได้ตั้งค่าไว้โดยค่าเริ่มต้นสำหรับการกำหนดค่าการทำให้ใช้งานได้ของ Cloud Run) ในกรณีนี้ ให้ทำตามขั้นตอนต่อไปนี้ (แทนการโคลนที่เก็บที่มีอยู่)
  2. ไปที่ Cloud Shell Editor (ตรวจสอบว่าเปิด Editor อยู่ ไม่ใช่เทอร์มินัล) คลิกไอคอนชื่อโปรเจ็กต์ Google Cloud ที่ด้านซ้ายของแถบสถานะ (ส่วนที่ถูกบล็อกในภาพหน้าจอด้านล่าง)

d3f0de417094237d.png

  1. เลือก New application -> Cloud Run Application -> 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. คุณต้องทำการเปลี่ยนแปลงในไฟล์ที่เกี่ยวข้องเพื่อแทนที่ PROJECT ID และ API KEY ด้วยค่าที่เกี่ยวข้อง (ขั้นตอนที่ 1 ก ข ค และ ง ด้านบน)

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

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

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

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

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

  1. ไปที่เทอร์มินัล Cloud Shell และตรวจสอบว่าได้ตั้งค่าโปรเจ็กต์ที่อยู่ในระบบคลาวด์ Google Cloud ที่ใช้งานอยู่แล้ว และตรวจสอบว่าคุณได้รับอนุญาต สร้าง Bucket ในโปรเจ็กต์ด้วยคำสั่ง gsutil ที่ระบุไว้ด้านล่าง แทนที่ตัวแปร <PROJECT_ID> ในคำสั่งด้านล่างด้วยรหัสโปรเจ็กต์ Google Cloud ของคุณ

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

  1. เมื่อสร้าง Bucket แล้ว เราต้องคัดลอกการส่งออกฐานข้อมูลที่เราเตรียมไว้ลงใน Bucket นี้ก่อนจึงจะนำเข้าไปยังฐานข้อมูล 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 Vector Search

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

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

มาดูขั้นตอนกัน

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

ติดตั้งส่วนขยาย "Vector Search with 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

เส้นทางการรวบรวม: ท่าทาง

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

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

ชื่อช่องป้อนข้อมูล: ท่าทาง

ชื่อฟิลด์เอาต์พุต: การฝัง

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

ฝังเอกสารที่มีอยู่: ได้

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

ตำแหน่ง 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, Vector Search และ Gemini 2.0 Flash

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

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

gcloud run deploy --source .

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

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

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

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

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

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

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

หากจะขยายแอปนี้ ฉันจะลองทำ 2 สิ่งด้วย Gemini 2.0 Flash

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

ลองใช้และส่ง Pull Request ได้เลย :>D!!!