เพิ่มการค้นหาเวกเตอร์ของ Firestore ในแอปบนอุปกรณ์เคลื่อนที่ด้วย Firebase Extensions

1. ภาพรวม

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

คอนโซล Cloud Firestore แสดงเอกสารบางรายการ ซึ่งจะปรากฏในแอป iOS ทางด้านขวามือด้วย

สิ่งที่คุณจะได้เรียนรู้

สิ่งที่คุณจะต้องมี

  • Xcode 15.3
  • โค้ดตัวอย่างของ Codelab คุณจะดาวน์โหลดได้ในขั้นตอนถัดไปของโค้ดแล็บ

2. สร้างและตั้งค่าโปรเจ็กต์ Firebase

คุณต้องมีโปรเจ็กต์ Firebase จึงจะใช้ส่วนขยายการค้นหาเวกเตอร์ของ Firebase ได้ ในส่วนนี้ของโค้ดแล็บ คุณจะสร้างโปรเจ็กต์ Firebase ใหม่และเปิดใช้งานบริการที่จำเป็น เช่น Cloud Firestore และ Firebase Authentication

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

  1. ลงชื่อเข้าใช้คอนโซล Firebase โดยใช้บัญชี Google
  2. คลิกปุ่มเพื่อสร้างโปรเจ็กต์ใหม่ แล้วป้อนชื่อโปรเจ็กต์ (เช่น Firestore Vector Search Codelab)
  3. คลิกต่อไป
  4. หากได้รับแจ้ง ให้อ่านและยอมรับข้อกำหนดของ Firebase แล้วคลิกต่อไป
  5. (ไม่บังคับ) เปิดใช้ความช่วยเหลือจาก AI ในคอนโซล Firebase (เรียกว่า "Gemini ใน Firebase")
  6. สำหรับ Codelab นี้ คุณไม่จำเป็นต้องใช้ Google Analytics ดังนั้นให้ปิดตัวเลือก Google Analytics
  7. คลิกสร้างโปรเจ็กต์ รอให้ระบบจัดสรรโปรเจ็กต์ แล้วคลิกดำเนินการต่อ

ดูข้อมูลเพิ่มเติมเกี่ยวกับโปรเจ็กต์ Firebase ได้ที่ทําความเข้าใจโปรเจ็กต์ Firebase

อัปเกรดแพ็กเกจราคาของ Firebase

หากต้องการใช้ Firebase Extensions และบริการระบบคลาวด์ที่เกี่ยวข้อง โปรเจ็กต์ Firebase ของคุณต้องอยู่ในแพ็กเกจราคาแบบจ่ายตามการใช้งาน (Blaze) ซึ่งหมายความว่าโปรเจ็กต์ต้องลิงก์กับบัญชีการเรียกเก็บเงินใน Cloud

หากต้องการอัปเกรดโปรเจ็กต์เป็นแพ็กเกจ Blaze ให้ทำตามขั้นตอนต่อไปนี้

  1. ในคอนโซล Firebase ให้เลือกอัปเกรดแพ็กเกจ
  2. เลือกแพ็กเกจ Blaze ทำตามวิธีการบนหน้าจอเพื่อลิงก์บัญชีสำหรับการเรียกเก็บเงินใน Cloud กับโปรเจ็กต์
    หากคุณต้องสร้างบัญชีสำหรับการเรียกเก็บเงินใน Cloud เป็นส่วนหนึ่งของการอัปเกรดนี้ คุณอาจต้องกลับไปที่ขั้นตอนการอัปเกรดใน Firebase Console เพื่อทำการอัปเกรดให้เสร็จสมบูรณ์

เปิดใช้และตั้งค่าผลิตภัณฑ์ Firebase ในคอนโซล

แอปที่คุณสร้างใช้ผลิตภัณฑ์ Firebase หลายอย่างที่พร้อมใช้งานสำหรับแอป Apple ดังนี้

  • การตรวจสอบสิทธิ์ Firebase เพื่อให้ผู้ใช้ลงชื่อเข้าใช้แอปของคุณได้อย่างง่ายดาย
  • Cloud Firestore เพื่อบันทึกข้อมูลที่มีโครงสร้างไว้ในระบบคลาวด์และรับการแจ้งเตือนทันทีเมื่อข้อมูลมีการเปลี่ยนแปลง
  • กฎการรักษาความปลอดภัยของ Firebase เพื่อรักษาความปลอดภัยให้ฐานข้อมูล

ผลิตภัณฑ์บางอย่างเหล่านี้ต้องมีการกำหนดค่าพิเศษหรือต้องเปิดใช้โดยใช้คอนโซล Firebase

เปิดใช้การตรวจสอบสิทธิ์แบบไม่ระบุชื่อสำหรับการตรวจสอบสิทธิ์ Firebase

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

  1. ในแผงด้านซ้ายของคอนโซล Firebase ให้คลิกสร้าง > การตรวจสอบสิทธิ์ จากนั้นคลิกเริ่มต้นใช้งานการเปิดใช้การตรวจสอบสิทธิ์ Firebase
  2. ตอนนี้คุณอยู่ในแดชบอร์ดการตรวจสอบสิทธิ์ ซึ่งคุณสามารถดูผู้ใช้ที่ลงชื่อสมัครใช้ กำหนดค่าผู้ให้บริการลงชื่อเข้าใช้ และจัดการการตั้งค่าได้
  3. เลือกแท็บวิธีการลงชื่อเข้าใช้ (หรือคลิกที่นี่เพื่อไปที่แท็บโดยตรง)
  4. คลิกไม่ระบุตัวตนจากตัวเลือกผู้ให้บริการ สลับปุ่มเป็นเปิดใช้ แล้วคลิกบันทึก

ตั้งค่า Cloud Firestore

แอปพลิเคชัน Swift นี้ใช้ Cloud Firestore เพื่อบันทึกโน้ต

วิธีตั้งค่า Cloud Firestore ในโปรเจ็กต์ Firebase มีดังนี้

  1. ในแผงด้านซ้ายของคอนโซล Firebase ให้ขยายสร้าง แล้วเลือกฐานข้อมูล Firestore
  2. คลิกสร้างฐานข้อมูล
  3. ตั้งค่ารหัสฐานข้อมูลเป็น (default) ไว้ดังเดิม
  4. เลือกตำแหน่งสำหรับฐานข้อมูล แล้วคลิกถัดไป
    สำหรับแอปจริง คุณควรเลือกตำแหน่งที่อยู่ใกล้กับผู้ใช้
  5. คลิกเริ่มในโหมดทดสอบ อ่านข้อจำกัดความรับผิดเกี่ยวกับกฎความปลอดภัย
    ในภายหลังใน Codelab นี้ คุณจะเพิ่มกฎความปลอดภัยเพื่อรักษาความปลอดภัยของข้อมูล อย่าเผยแพร่หรือเปิดเผยแอปต่อสาธารณะโดยไม่ได้เพิ่มกฎความปลอดภัยสำหรับฐานข้อมูล
  6. คลิกสร้าง

ตั้งค่า Cloud Storage for Firebase

เว็บแอปใช้ Cloud Storage for Firebase เพื่อจัดเก็บ อัปโหลด และแชร์รูปภาพ

วิธีตั้งค่า Cloud Storage for Firebase ในโปรเจ็กต์ Firebase มีดังนี้

  1. ในแผงด้านซ้ายของคอนโซล Firebase ให้ขยายสร้าง แล้วเลือก Storage
  2. คลิกเริ่มต้นใช้งาน
  3. เลือกตำแหน่งสำหรับที่เก็บข้อมูลเริ่มต้น
    ที่เก็บข้อมูลใน US-WEST1, US-CENTRAL1 และ US-EAST1 จะใช้ประโยชน์จากระดับ"ใช้งานฟรีเสมอ" สำหรับ Google Cloud Storage ได้ ที่เก็บข้อมูลในตำแหน่งอื่นๆ ทั้งหมดจะเป็นไปตามราคาและการใช้งาน Google Cloud Storage
  4. คลิกเริ่มในโหมดทดสอบ อ่านข้อจำกัดความรับผิดเกี่ยวกับกฎความปลอดภัย
    ในภายหลังใน Codelab นี้ คุณจะเพิ่มกฎความปลอดภัยเพื่อรักษาความปลอดภัยของข้อมูล อย่าเผยแพร่หรือแสดงแอปต่อสาธารณะโดยไม่ได้เพิ่มกฎความปลอดภัยสำหรับที่เก็บข้อมูล
  5. คลิกสร้าง

3. เชื่อมต่อแอปบนอุปกรณ์เคลื่อนที่

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

ดาวน์โหลดแอปตัวอย่าง

  1. ไปที่ https://github.com/FirebaseExtended/codelab-firestore-vectorsearch-ios แล้วโคลนที่เก็บไปยังเครื่องในเครื่อง
  2. เปิดโปรเจ็กต์ Notes.xcodeproj ใน Xcode

เชื่อมต่อแอปกับโปรเจ็กต์ Firebase

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับโปรเจ็กต์ Firebase ได้ที่ทําความเข้าใจโปรเจ็กต์ Firebase

  1. ในคอนโซล Firebase ให้ไปที่หน้าภาพรวมของโปรเจ็กต์ Firebaseหน้าภาพรวมของคอนโซล Firebase
  2. คลิกไอคอน iOS+ เพื่อเพิ่มแอป iOS
  3. ในหน้าจอเพิ่ม Firebase ลงในแอป Apple ให้แทรกรหัสแพ็กเกจจากโปรเจ็กต์ Xcode (com.google.firebase.codelab.Notes)
  4. คุณป้อนชื่อเล่นแอปได้หากต้องการ (Notes สำหรับ iOS)
  5. คลิกลงทะเบียนแอปเพื่อไปยังขั้นตอนถัดไป
  6. ดาวน์โหลดไฟล์ GoogleServices-Info.plist
  7. ลาก GoogleServices-Info.plist ไปยังโฟลเดอร์ Notes ของโปรเจ็กต์ Xcode วิธีที่ดีในการทำเช่นนี้คือการวางไว้ใต้ไฟล์ Assets.xcassetsการลากไฟล์ plist ไปยัง Xcode
  8. เลือกคัดลอกรายการหากจำเป็น ตรวจสอบว่าได้เลือกเป้าหมายหมายเหตุในเพิ่มไปยังเป้าหมายแล้ว และคลิกเสร็จสิ้นการเลือก "คัดลอกหากจำเป็น" ในกล่องโต้ตอบเลือกตัวเลือกสำหรับการเพิ่มไฟล์
  9. ในคอนโซล Firebase ตอนนี้คุณคลิกผ่านกระบวนการตั้งค่าที่เหลือได้แล้ว ตัวอย่างที่คุณดาวน์โหลดในช่วงต้นของส่วนนี้ได้ติดตั้ง Firebase Apple SDK และตั้งค่าการเริ่มต้นไว้แล้ว คุณสามารถสิ้นสุดกระบวนการได้โดยคลิกดำเนินการต่อเพื่อไปยังคอนโซล

เรียกใช้แอป

ตอนนี้ได้เวลาลองใช้แอปแล้ว

  1. กลับไปที่ Xcode แล้วเรียกใช้แอปในโปรแกรมจำลอง iOS ในเมนูแบบเลื่อนลงปลายทางการเรียกใช้ ให้เลือกโปรแกรมจำลอง iOS อย่างใดอย่างหนึ่งก่อนเลือกเครื่องจำลอง iOS ในเมนูแบบเลื่อนลงของปลายทางการเรียกใช้
  2. จากนั้นคลิกปุ่มเรียกใช้ หรือกด ⌘ + R
  3. เมื่อเปิดแอปในโปรแกรมจำลองสำเร็จแล้ว ให้เพิ่มโน้ต 2-3 รายการ
  4. ในคอนโซล Firebase ให้ไปที่เบราว์เซอร์ข้อมูล Firestore เพื่อให้คุณเห็นเอกสารใหม่ที่สร้างขึ้นขณะเพิ่มโน้ตใหม่ในแอปคอนโซล Cloud Firestore แสดงเอกสารบางรายการข้างๆ iOS Simulator ซึ่งแสดงเอกสารเดียวกัน

4. ติดตั้งส่วนขยายการค้นหาเวกเตอร์ด้วย Firestore

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

เริ่มติดตั้งส่วนขยาย

  1. ขณะที่ยังอยู่ในส่วน Firestore ให้คลิกแท็บส่วนขยายการเลือกแท็บส่วนขยาย Firebase ในคอนโซล Firestore
  2. คลิกสำรวจฮับส่วนขยายแท็บ Firebase Extensions ในคอนโซล Firestore
  3. พิมพ์ "เวกเตอร์"
  4. คลิก "การค้นหาเวกเตอร์ด้วยส่วนขยาย Firestore"หน้า Landing Page ของ Firebase Extensions Hub ซึ่งจะนำคุณไปยังหน้ารายละเอียดของส่วนขยาย ที่คุณสามารถอ่านข้อมูลเพิ่มเติมเกี่ยวกับส่วนขยาย วิธีการทำงาน บริการ Firebase ที่ต้องใช้ และวิธีกำหนดค่า
  5. คลิกติดตั้งในคอนโซล Firebaseปุ่มติดตั้งสำหรับส่วนขยายการค้นหาเวกเตอร์ด้วย Firestore
  6. คุณจะเห็นรายการโปรเจ็กต์ทั้งหมด
  7. เลือกโปรเจ็กต์ที่คุณสร้างในขั้นตอนแรกของ Codelab นี้หน้าจอเครื่องมือเลือกโปรเจ็กต์ Firebase

กำหนดค่าส่วนขยาย

  1. ตรวจสอบว่าเปิดใช้ API และสร้างทรัพยากรแล้วตรวจสอบ API ที่เปิดใช้
  2. เปิดใช้บริการที่จำเป็นการเปิดใช้บริการที่จำเป็น
  3. เมื่อเปิดใช้บริการทั้งหมดแล้ว ให้คลิกถัดไปคลิกถัดไปหลังจากเปิดใช้บริการทั้งหมด
  4. ตรวจสอบสิทธิ์เข้าถึงที่มอบให้ส่วนขยายนี้
  5. วิธีกําหนดค่าส่วนขยาย
    • เลือก Vertex AI เป็น LLM
    • เส้นทางการรวบรวม: notes
    • ขีดจํากัดการค้นหาเริ่มต้น: 3
    • ชื่อช่องป้อนข้อมูล: text
    • ชื่อฟิลด์เอาต์พุต: embedding
    • ชื่อฟิลด์สถานะ:* *status*
    • ฝังเอกสารที่มีอยู่: ได้
    • อัปเดตเอกสารที่มีอยู่: ได้
    • ตำแหน่งของ Cloud Function: us-central1
  6. คลิกติดตั้งส่วนขยายเพื่อสิ้นสุดการติดตั้ง

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

5. ข้อมูลเบื้องต้น

ในระหว่างที่รอการติดตั้งเสร็จสมบูรณ์ โปรดดูข้อมูลเบื้องต้นเกี่ยวกับวิธีการทำงานของส่วนขยายการค้นหาเวกเตอร์ด้วย Firestore

เวกเตอร์ การฝัง และฐานข้อมูลเวกเตอร์คืออะไร

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

การค้นหาเวกเตอร์ทำงานอย่างไร

การค้นหาเวกเตอร์ทํางานโดยการเปรียบเทียบเวกเตอร์การค้นหากับเวกเตอร์ทั้งหมดในฐานข้อมูล เวกเตอร์ที่คล้ายกับเวกเตอร์คำค้นหามากที่สุดจะแสดงเป็นผลการค้นหา

ความคล้ายคลึงกันระหว่างเวกเตอร์ 2 รายการสามารถวัดได้โดยใช้เมตริกระยะทางที่หลากหลาย เมตริกการวัดระยะทางที่ใช้กันมากที่สุดคือความคล้ายคลึงกันของโคไซน์ ซึ่งวัดมุมระหว่างเวกเตอร์ 2 ตัว

6. ลองใช้ส่วนขยายการค้นหาเวกเตอร์กับ Firestore

ก่อนใช้ส่วนขยายการค้นหาเวกเตอร์ด้วย Firestore ในแอป iOS ที่คุณดาวน์โหลดก่อนหน้านี้ในโค้ดแล็บนี้ คุณสามารถลองใช้ส่วนขยายในคอนโซล Firebase ได้

อ่านเอกสารประกอบ

Firebase Extensions มีเอกสารประกอบเกี่ยวกับวิธีการทำงาน

  1. เมื่อติดตั้งส่วนขยายเสร็จแล้ว ให้คลิกปุ่มเริ่มต้นใช้งาน หน้าภาพรวมของ Firebase Extension ในคอนโซล Firebase
  2. ดูแท็บ "วิธีการทำงานของส่วนขยายนี้" ซึ่งอธิบายสิ่งต่อไปนี้
    • วิธีคำนวณการฝังสำหรับเอกสารโดยการเพิ่มลงในคอลเล็กชัน notes
    • วิธีค้นหาดัชนีโดยเรียกใช้ext-firestore-vector-search-queryCallableฟังก์ชันที่เรียกใช้ได้
    • หรือวิธีค้นหาดัชนีโดยการเพิ่มเอกสารการค้นหาลงในคอลเล็กชัน _firestore-vector-search/index/queries
    • นอกจากนี้ ยังอธิบายวิธีตั้งค่าฟังก์ชันการฝังที่กำหนดเอง ซึ่งจะมีประโยชน์ในกรณีที่ LLM ที่ส่วนขยายรองรับไม่ตรงตามข้อกำหนดของคุณ และคุณต้องการใช้ LLM อื่นเพื่อคำนวณการฝัง เอกสารประกอบสำหรับส่วนขยาย Vector Search ด้วย Firestore
  3. คลิกลิงก์แดชบอร์ด Cloud Firestore เพื่อไปยังอินสแตนซ์ Firestore
  4. ไปที่_firestore-vector-search/indexเอกสาร โดยควรแสดงว่าส่วนขยายประมวลผลการฝังสำหรับเอกสารบันทึกทั้งหมดที่คุณสร้างในขั้นตอนก่อนหน้าใน Codelab นี้เสร็จแล้วการกำหนดค่าดัชนีภายในคอนโซล Firestore
  5. หากต้องการยืนยัน ให้เปิดเอกสารบันทึกย่อใดก็ได้ แล้วคุณจะเห็นช่องเพิ่มเติมชื่อ embedding ประเภท vector<768> รวมถึงช่อง statusฟิลด์การฝังเวกเตอร์ภายในคอนโซล Firestore

สร้างเอกสารตัวอย่าง

คุณสร้างเอกสารใหม่ในคอนโซล Firebase เพื่อดูการทำงานของส่วนขยายได้

  1. ในเครื่องมือสำรวจข้อมูล Firestore ให้ไปที่คอลเล็กชัน notes แล้วคลิก + เพิ่มเอกสาร ในคอลัมน์กลางการเพิ่มเอกสารใหม่
  2. คลิกรหัสอัตโนมัติเพื่อสร้างรหัสเอกสารที่ไม่ซ้ำกันใหม่
  3. เพิ่มฟิลด์ชื่อ text ประเภทสตริง แล้ววางข้อความลงในฟิลด์ค่า โปรดทราบว่าข้อความนี้ต้องไม่ใช่ข้อความลอเร็มอิปซัมหรือข้อความแบบสุ่มอื่นๆ เช่น เลือกบทความข่าวการเพิ่มช่องข้อความ
  4. คลิกบันทึก
    • สังเกตว่าส่วนขยายเพิ่มช่องสถานะเพื่อระบุว่ากำลังประมวลผลข้อมูล
    • หลังจากนั้นไม่นาน คุณจะเห็นฟิลด์ใหม่ embedding ที่มีค่าเป็น vector<768>
    การอัปเดตสถานะการฝังเวกเตอร์สำหรับเอกสารใหม่

ทำการค้นหา

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

  1. ในส่วน Firestore ของคอนโซล Firebase ให้ไปที่_firestore-vector-search/indexเอกสาร
  2. คลิก + เริ่มคอลเล็กชันการเพิ่มคอลเล็กชันย่อยใหม่
  3. สร้างคอลเล็กชันย่อยใหม่ชื่อ queries
  4. สร้างเอกสารใหม่และตั้งค่าฟิลด์ query เป็นข้อความที่อยู่ในเอกสารใดเอกสารหนึ่ง วิธีนี้เหมาะที่สุดสำหรับการค้นหาเชิงความหมาย เช่น "ฉันจะแมปเอกสาร Firestore กับ Swift ได้อย่างไร" (หากโน้ตที่คุณเพิ่มมีข้อความที่พูดถึงหัวข้อนี้อย่างน้อย 1 รายการ)การเพิ่มฟิลด์การค้นหา
  5. คุณอาจเห็นข้อผิดพลาดในสถานะเกิดข้อผิดพลาด
  6. เนื่องจากไม่มีดัชนี หากต้องการตั้งค่าการกำหนดค่าดัชนีที่ขาดหายไป ให้ไปที่คอนโซล Google Cloud สำหรับโปรเจ็กต์โดยทำตามลิงก์นี้ แล้วเลือกโปรเจ็กต์จากรายการการเลือกโปรเจ็กต์ที่ถูกต้อง
  7. ใน Cloud Log Explorer คุณควรเห็นข้อความแสดงข้อผิดพลาดที่ระบุว่า "FAILED_PRECONDITION: Missing vector index configuration. โปรดสร้างดัชนีที่จำเป็นด้วยคำสั่ง gcloud ต่อไปนี้ ..."ข้อความแสดงข้อผิดพลาดในเครื่องมือสำรวจบันทึก
  8. ข้อความแสดงข้อผิดพลาดจะมีคำสั่ง gcloud ที่คุณต้องเรียกใช้เพื่อกำหนดค่าดัชนีที่ขาดหายไป
  9. เรียกใช้คำสั่งต่อไปนี้จากบรรทัดคำสั่ง หากยังไม่ได้ติดตั้ง gcloud CLI ในเครื่อง ให้ทำตามวิธีการที่นี่เพื่อติดตั้ง
    gcloud alpha firestore indexes composite create --project=INSERT-YOUR=PROJECT-ID-HERE --collection-group=notes --query-scope=COLLECTION --field-config=vector-config='{"dimension":"768","flat": "{}"}',field-path=embedding
    
    การสร้างดัชนีจะใช้เวลา 2-3 นาที คุณตรวจสอบความคืบหน้าได้ในแท็บดัชนีในส่วน Firestore ของคอนโซล Firebaseสถานะของดัชนีใหม่
  10. เมื่อตั้งค่าดัชนีแล้ว คุณจะสร้างเอกสารการค้นหาใหม่ได้
  11. ตอนนี้คุณควรเห็นรายการรหัสเอกสารที่ตรงกันในช่องผลลัพธ์ผลลัพธ์ของการค้นหาเชิงความหมาย
  12. คัดลอกรหัสใดรหัสหนึ่ง แล้วกลับไปที่notesคอลเล็กชัน
  13. ใช้ ⌘+F เพื่อค้นหารหัสเอกสารที่คุณคัดลอกมา เอกสารนี้คือเอกสารที่ตรงกับคำค้นหาของคุณมากที่สุดการค้นหารหัสเอกสารในรายการเอกสาร

7. ใช้การค้นหาเชิงความหมาย

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

เชื่อมต่อฟังก์ชันที่เรียกใช้ได้เพื่อทำการค้นหา

ส่วนขยายการค้นหาเวกเตอร์ด้วย Firestore มี Cloud Functions ที่คุณเรียกใช้จากแอปบนอุปกรณ์เคลื่อนที่เพื่อค้นหาดัชนีที่สร้างไว้ก่อนหน้านี้ในโค้ดแล็บนี้ได้ ในขั้นตอนนี้ คุณจะสร้างการเชื่อมต่อระหว่างแอปบนอุปกรณ์เคลื่อนที่กับฟังก์ชันที่เรียกใช้ได้นี้ Swift SDK ของ Firebase มี API ที่ทำให้การเรียกใช้ฟังก์ชันระยะไกลเป็นไปอย่างราบรื่น

  1. กลับไปที่ Xcode และตรวจสอบว่าคุณอยู่ในโปรเจ็กต์ที่โคลนในขั้นตอนก่อนหน้าของ Codelab นี้
  2. เปิดไฟล์ NotesRepository.swift
  3. ค้นหาบรรทัดที่มี private lazy var vectorSearchQueryCallable: Callable = functions.httpsCallable("")

หากต้องการเรียกใช้ Cloud Function ที่เรียกใช้ได้ คุณต้องระบุชื่อของฟังก์ชันที่ต้องการเรียกใช้

  1. ไปที่คอนโซล Firebase สำหรับโปรเจ็กต์ แล้วเปิดรายการเมนู Functions ในส่วนสร้าง
  2. คุณจะเห็นรายการฟังก์ชันที่ส่วนขยายติดตั้งไว้
  3. ค้นหาตัวแปรที่ชื่อ ext-firestore-vector-search-queryCallable แล้วคัดลอกชื่อ
  4. วางชื่อลงในโค้ด ตอนนี้ควรมีข้อความว่า
    private lazy var vectorSearchQueryCallable: Callable<String, String> = functions.httpsCallable("ext-firestore-vector-search-queryCallable")
    

เรียกใช้ฟังก์ชันการค้นหา

  1. ค้นหาวิธีการ performQuery
  2. เรียกใช้ฟังก์ชันที่เรียกใช้ได้โดยการเรียกใช้
    let result = try await vectorSearchQueryCallable(searchTerm)
    

เนื่องจากเป็นการเรียกจากระยะไกล การเรียกนี้อาจไม่สำเร็จ

  1. เพิ่มการจัดการข้อผิดพลาดพื้นฐานเพื่อตรวจหาข้อผิดพลาดและบันทึกลงในคอนโซลของ Xcode
    private func performQuery(searchTerm: String) async -> [String] {
      do {
        let result = try await vectorSearchQueryCallable(searchTerm)
        return [result]
      }
      catch {
        print(error.localizedDescription)
        return []
      }
    }
    

เชื่อมต่อ UI

หากต้องการอนุญาตให้ผู้ใช้ค้นหาโน้ต คุณจะต้องติดตั้งแถบค้นหาในหน้าจอรายการโน้ต เมื่อผู้ใช้พิมพ์ข้อความค้นหา คุณจะต้องเรียกใช้เมธอด performQuery ที่คุณใช้ในขั้นตอนก่อนหน้า searchable และ task ตัวปรับมุมมองที่ SwiftUI มีให้ทำให้เราใช้โค้ดเพียงไม่กี่บรรทัด

  1. ก่อนอื่น ให้เปิด NotesListScreen.swift
  2. หากต้องการเพิ่มช่องค้นหาไปยังมุมมองรายการ ให้เพิ่มตัวแก้ไขมุมมอง .searchable(text: $searchTerm, prompt: "Search") เหนือบรรทัด .navigationTitle("Notes")
  3. จากนั้นเรียกใช้ฟังก์ชันการค้นหาโดยเพิ่มโค้ดต่อไปนี้ที่ด้านล่าง
.task(id: searchTerm, debounce: .milliseconds(800)) {
  await notesRepository.semanticSearch(searchTerm: searchTerm)
}

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

ตอนนี้โค้ดควรมีลักษณะดังนี้

...
List(repository.notes) { note in
  NavigationLink(value: note) {
    NoteRowView(note: note)
  }
  .swipeActions {
    Button(role: .destructive, action: { deleteNote(note: note) }) {
      Label("Delete", systemImage: "trash")
    }
  }
}
.searchable(text: $searchTerm, prompt: "Search")
.task(id: searchTerm, debounce: .milliseconds(800)) {
  await notesRepository.semanticSearch(searchTerm: searchTerm)
}
.navigationTitle("Notes")
...

เรียกใช้แอป

  1. กด ⌘ + R (หรือคลิกปุ่มเรียกใช้) เพื่อเปิดแอปใน iOS Simulator
  2. คุณควรเห็นโน้ตเดียวกันกับที่เพิ่มไว้ในแอปก่อนหน้านี้ใน Codelab นี้ รวมถึงโน้ตที่เพิ่มผ่านคอนโซล Firebase
  3. คุณควรเห็นช่องค้นหาที่ด้านบนของรายการโน้ต
  4. พิมพ์คำที่ปรากฏในเอกสารที่คุณเพิ่ม อีกครั้งที่ว่าวิธีนี้เหมาะที่สุดสำหรับคำค้นหาเชิงความหมาย เช่น "ฉันจะเรียกใช้ Firebase API แบบไม่พร้อมกันจาก Swift ได้อย่างไร" (โดยมีหมายเหตุอย่างน้อย 1 รายการที่คุณเพิ่มซึ่งมีข้อความที่พูดถึงหัวข้อนี้)
  5. คุณอาจคาดหวังว่าจะเห็นผลการค้นหา แต่กลับไม่เห็นอะไรในมุมมองรายการ และคอนโซล Xcode แสดงข้อความแสดงข้อผิดพลาดว่า "ฟังก์ชันถูกเรียกใช้ด้วยอาร์กิวเมนต์ที่ไม่ถูกต้อง"

แอปโน้ตที่มีรายการผลการค้นหาว่างเปล่า

ซึ่งหมายความว่าคุณส่งข้อมูลในรูปแบบที่ไม่ถูกต้อง

วิเคราะห์ข้อความแสดงข้อผิดพลาด

  1. หากต้องการดูว่ามีอะไรผิดพลาด ให้ไปที่คอนโซล Firebase
  2. ไปที่ส่วนฟังก์ชัน
  3. ค้นหาฟังก์ชัน ext-firestore-vector-search-queryCallable เปิดเมนูที่ซ่อนอยู่โดยคลิกจุดแนวตั้ง 3 จุด
  4. เลือกดูบันทึกเพื่อไปที่เครื่องมือสำรวจบันทึก
  5. คุณควรเห็นข้อผิดพลาด
Unhandled error ZodError: [
  {
    "code": "invalid_type",
    "expected": "object",
    "received": "string",
    "path": [],
    "message": "Expected object, received string"
  }
]

ซึ่งหมายความว่าคุณส่งข้อมูลในรูปแบบที่ไม่ถูกต้อง

ใช้ประเภทข้อมูลที่ถูกต้อง

หากต้องการดูว่าส่วนขยายคาดหวังให้พารามิเตอร์อยู่ในรูปแบบใด โปรดดูเอกสารประกอบของส่วนขยาย

  1. ไปที่ส่วนส่วนขยายในคอนโซล Firebase
  2. คลิกจัดการ ->การจัดการส่วนขยายการค้นหาเวกเตอร์ด้วย Firestore
  3. ในส่วนวิธีการทำงานของส่วนขยายนี้ คุณจะเห็นข้อกำหนดของพารามิเตอร์อินพุตและเอาต์พุตเอกสารประกอบของพารามิเตอร์อินพุตและค่าผลลัพธ์
  4. กลับไปที่ Xcode แล้วไปที่ NotesRepository.swift
  5. เพิ่มโค้ดต่อไปนี้ที่จุดเริ่มต้นของไฟล์
    private struct QueryRequest: Codable {
      var query: String
      var limit: Int?
      var prefilters: [QueryFilter]?
    }
    
    private struct QueryFilter: Codable {
      var field: String
      var `operator`: String
      var value: String
    
    }
    
    private struct QueryResponse: Codable {
      var ids: [String]
    }
    
    QueryRequest ตรงกับโครงสร้างของพารามิเตอร์อินพุตที่ส่วนขยายคาดหวังตามเอกสารประกอบของส่วนขยาย นอกจากนี้ ยังมีแอตทริบิวต์ prefilter ที่ซ้อนกันซึ่งคุณจะต้องใช้ในภายหลังQueryResponse ซึ่งตรงกับโครงสร้างของการตอบกลับของส่วนขยาย
  6. ค้นหาข้อกำหนดฟังก์ชันที่เรียกใช้ได้ แล้วอัปเดตประเภทอินพุตและเอาต์พุต
    private lazy var vectorSearchQueryCallable: Callable<QueryRequest, QueryResponse> = functions.httpsCallable("ext-firestore-vector-search-queryCallable")
    
  7. อัปเดตการเรียกใช้ฟังก์ชันที่เรียกใช้ได้ใน performQuery
    private func performQuery(searchTerm: String) async -> [String] {
      do {
        let queryRequest = QueryRequest(query: searchTerm,
                                        limit: 2)
        let result = try await vectorSearchQueryCallable(queryRequest)
        print(result.ids)
        return result.ids
      }
      catch {
        print(error.localizedDescription)
        return []
      }
    }
    

เรียกใช้แอปอีกครั้ง

  1. เรียกใช้แอปอีกครั้ง
  2. พิมพ์คำค้นหาที่มีคำที่รวมอยู่ในโน้ตรายการใดรายการหนึ่ง
  3. ตอนนี้คุณควรเห็นรายการโน้ตที่กรองแล้ว

ภาพหน้าจอของแอปที่มีผลลัพธ์ที่คาดไว้

กรองข้อมูลผู้ใช้ล่วงหน้า

ก่อนที่คุณจะเต้นฉลอง เราต้องแจ้งให้ทราบว่าแอปเวอร์ชันปัจจุบันมีปัญหาคือ ชุดผลลัพธ์มีข้อมูลของผู้ใช้ทั้งหมด

คุณยืนยันได้โดยการเรียกใช้แอปในโปรแกรมจำลองอื่นและเพิ่มเอกสารเพิ่มเติม เอกสารใหม่จะแสดงในโปรแกรมจำลองนั้นเท่านั้น หากคุณเรียกใช้แอปอีกครั้งในโปรแกรมจำลองอื่น คุณจะเห็นเฉพาะเอกสารที่สร้างในครั้งแรก

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

ใน performQuery ให้อัปเดตโค้ดดังนี้

  let prefilters: [QueryFilter] = if let uid = user?.uid {
    [QueryFilter(field: "userId", operator: "==", value: uid)]
  }
  else {
    []
  }

  let queryRequest = QueryRequest(query: searchTerm,
                                  limit: 2,
                                  prefilters: prefilters)

ซึ่งจะกรองข้อมูลล่วงหน้าตามรหัสของผู้ใช้ที่เข้าสู่ระบบ ตามที่คาดไว้ การดำเนินการนี้ต้องอัปเดตดัชนี Firestore

เรียกใช้คำสั่งต่อไปนี้จากบรรทัดคำสั่งเพื่อกำหนดดัชนี Firestore ใหม่ที่มีทั้ง userId และการฝังเวกเตอร์ในช่อง embedding

gcloud alpha firestore indexes composite create --project=INSERT-YOUR-PROJECT-ID-HERE --collection-group=notes --query-scope=COLLECTION --field-config=order=ASCENDING,field-path=userId --field-config=vector-config='{"dimension":"768","flat": "{}"}',field-path=embedding

เมื่อสร้างดัชนีเสร็จแล้ว ให้เรียกใช้แอปอีกครั้งเพื่อยืนยันว่าทำงานได้ตามที่คาดไว้

ชุดผลลัพธ์ที่กรองล่วงหน้า

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

ขอแสดงความยินดีที่ทำ Codelab นี้สำเร็จ

ในโค้ดแล็บนี้ คุณได้เรียนรู้วิธีทำสิ่งต่อไปนี้

  • ตั้งค่าฐานข้อมูล Cloud Firestore โดยเปิดใช้การค้นหาเชิงความหมาย
  • สร้างแอป SwiftUI อย่างง่ายเพื่อโต้ตอบกับฐานข้อมูล
  • ใช้แถบค้นหาโดยใช้ตัวแก้ไขมุมมองที่ค้นหาได้ของ SwiftUI และตัวแก้ไขงาน
  • เรียกใช้ Cloud Functions เพื่อทำการค้นหาเชิงความหมายในฐานข้อมูลโดยใช้อินเทอร์เฟซที่เรียกใช้ได้ของ Firestore SDK

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับฟิลด์เวกเตอร์ใหม่ของ Firestore และวิธีคำนวณการฝังเวกเตอร์ได้ที่เอกสารประกอบ