Thêm tính năng Tìm kiếm vectơ trên Firestore vào ứng dụng dành cho thiết bị di động bằng Tiện ích Firebase

1. Tổng quan

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách thêm các tính năng tìm kiếm mạnh mẽ vào ứng dụng bằng cách sử dụng tính năng Tìm kiếm vectơ tương tự Firestore. Bạn sẽ triển khai tính năng tìm kiếm ngữ nghĩa cho một ứng dụng ghi chú viết bằng Swift và SwiftUI.

Bảng điều khiển Cloud Firestore cho thấy một số tài liệu. Những tài liệu này cũng xuất hiện trong ứng dụng iOS ở phía bên phải.

Kiến thức bạn sẽ học được

  • Cách cài đặt tiện ích Tìm kiếm vectơ với Firestore để tính toán nhúng vectơ.
  • Cách gọi Hàm Cloud của Firebase từ ứng dụng Swift.
  • Cách lọc trước dữ liệu dựa trên người dùng đã đăng nhập.

Bạn cần có

  • Xcode 15.3
  • Mã mẫu của lớp học lập trình này. Bạn sẽ tải tệp này xuống trong bước sau của lớp học lập trình.

2. Tạo và thiết lập dự án Firebase

Để sử dụng tiện ích Tìm kiếm vectơ của Firebase, bạn cần có một dự án Firebase. Trong phần này của lớp học lập trình, bạn sẽ tạo một dự án Firebase mới và kích hoạt các dịch vụ bắt buộc như Cloud Firestore và Xác thực Firebase.

Tạo dự án Firebase

  1. Đăng nhập vào Firebase
  2. Trong bảng điều khiển của Firebase, hãy nhấp vào Add project (Thêm dự án), sau đó đặt tên cho dự án là Firestore Vector Search LabTạo một dự án, bước 1/3: chọn tên dự án
  3. Nhấp vào các tuỳ chọn tạo dự án. Chấp nhận các điều khoản của Firebase nếu được nhắc.
  4. Trên màn hình Google Analytics, hãy bỏ chọn hộp Bật Google Analytics cho dự án này, vì bạn sẽ không sử dụng Analytics cho ứng dụng này.
  5. Cuối cùng, hãy nhấp vào Create project (Tạo dự án).

Để tìm hiểu thêm về các dự án Firebase, hãy xem bài viết Tìm hiểu các dự án Firebase.

Bật và thiết lập các sản phẩm của Firebase trong bảng điều khiển

Ứng dụng mà bạn đang tạo dùng một số sản phẩm của Firebase có sẵn cho các ứng dụng của Apple:

  • Xác thực Firebase để dễ dàng cho phép người dùng đăng nhập vào ứng dụng của bạn.
  • Cloud Firestore để lưu dữ liệu có cấu trúc trên đám mây và nhận thông báo tức thì khi dữ liệu thay đổi.
  • Quy tắc bảo mật của Firebase để bảo mật cơ sở dữ liệu của bạn.

Một số sản phẩm trong số này cần có cấu hình đặc biệt hoặc cần được bật bằng bảng điều khiển của Firebase.

Bật tính năng xác thực ẩn danh cho tính năng Xác thực Firebase

Ứng dụng này tận dụng cơ chế xác thực ẩn danh để cho phép người dùng bắt đầu sử dụng ứng dụng mà không phải tạo tài khoản trước. Nhờ vậy, quy trình tham gia diễn ra suôn sẻ. Để tìm hiểu thêm về tính năng xác thực ẩn danh (và cách nâng cấp lên tài khoản được đặt tên), hãy xem bài viết Các phương pháp hay nhất để xác thực ẩn danh.

  1. Trong bảng điều khiển bên trái của bảng điều khiển Firebase, hãy nhấp vào Tạo > Xác thực. Sau đó, hãy nhấp vào Bắt đầu.Bật tính năng tự động tăng kích thước Firebase
  2. Bây giờ, bạn đang truy cập vào trang tổng quan về Xác thực. Tại đây, bạn có thể thấy những người dùng đã đăng ký, định cấu hình nhà cung cấp dịch vụ đăng nhập và quản lý các chế độ cài đặt.
  3. Chọn thẻ Phương thức đăng nhập (hoặc nhấp vào đây để chuyển thẳng đến thẻ đó).
  4. Nhấp vào Ẩn danh trong các tuỳ chọn dành cho nhà cung cấp, chuyển nút gạt sang vị trí Bật rồi nhấp vào Lưu.

Thiết lập Cloud Firestore

Ứng dụng Swift này sử dụng Cloud Firestore để lưu ghi chú. Sau đây là cách thiết lập Cloud Firestore:

  1. Trong bảng điều khiển bên trái của bảng điều khiển của Firebase, hãy nhấp vào Build > Firestore Database (Tạo > Cơ sở dữ liệu Firestore). Sau đó nhấp vào Tạo cơ sở dữ liệu.Bật Cloud Firestore
  2. Chọn vị trí cho cơ sở dữ liệu của bạn, nhớ chọn vị trí có cung cấp Gemini (bạn chỉ cần sử dụng us-central1). Tuy nhiên, lưu ý rằng bạn không thể thay đổi vị trí này sau đó. Nhấp vào Next (Tiếp theo).
  3. Chọn tuỳ chọn Bắt đầu ở chế độ thử nghiệm. Đọc tuyên bố từ chối trách nhiệm về các quy tắc bảo mật. Chế độ kiểm thử đảm bảo rằng bạn có thể thoải mái ghi vào cơ sở dữ liệu trong quá trình phát triển.Thiết lập Quy tắc bảo mật cho Firestore ở chế độ thử nghiệm
  4. Nhấp vào Tạo để tạo cơ sở dữ liệu.

3. Kết nối ứng dụng di động

Trong phần này của lớp học lập trình, bạn sẽ tải mã nguồn xuống cho một ứng dụng ghi chú đơn giản rồi kết nối ứng dụng đó với dự án Firebase bạn vừa tạo.

Tải ứng dụng mẫu xuống

  1. Truy cập vào https://github.com/FirebaseExtended/codelab-firestore-vectơsearch-ios rồi sao chép kho lưu trữ vào máy cục bộ của bạn
  2. Mở dự án Notes.xcodeproj trong Xcode

Kết nối ứng dụng với dự án Firebase

Để ứng dụng của bạn có thể truy cập vào các dịch vụ của Firebase, bạn cần thiết lập ứng dụng trong bảng điều khiển của Firebase. Bạn có thể kết nối nhiều ứng dụng khách với cùng một dự án Firebase, ví dụ: nếu bạn tạo một ứng dụng Android hoặc ứng dụng web, bạn nên kết nối các ứng dụng đó với cùng một dự án Firebase.

Để tìm hiểu thêm về các dự án Firebase, hãy xem bài viết Tìm hiểu các dự án Firebase.

  1. Trong bảng điều khiển của Firebase, hãy chuyển đến trang tổng quan của dự án Firebase.Trang tổng quan của bảng điều khiển của Firebase
  2. Nhấp vào biểu tượng iOS+ để thêm ứng dụng iOS của bạn.
  3. Trong màn hình Thêm Firebase vào ứng dụng Apple, hãy chèn mã gói từ dự án Xcode (com.google.firebase.codelab.Notes).
  4. Nếu muốn, bạn có thể nhập biệt hiệu của ứng dụng (Ghi chú dành cho iOS).
  5. Nhấp vào Đăng ký ứng dụng để chuyển sang bước tiếp theo.
  6. Tải tệp GoogleServices-Info.plist xuống.
  7. Kéo GoogleServices-Info.plist vào thư mục Notes của dự án Xcode. Bạn có thể thực hiện việc này bằng cách thả xuống dưới tệp Assets.xcAssets.Kéo tệp plist vào Xcode
  8. Chọn Copy items if need (Sao chép các mục nếu cần), hãy nhớ chọn mục tiêu Notes (Ghi chú) trong phần Add to targets (Thêm vào mục tiêu) rồi nhấp vào Finish (Hoàn tất).Chọn "Sao chép nếu cần" trong hộp thoại chọn tuỳ chọn để thêm tệp
  9. Trong bảng điều khiển của Firebase, bạn hiện có thể nhấp vào phần còn lại của quá trình thiết lập: mẫu mà bạn đã tải xuống ở đầu phần này đã được cài đặt Firebase Apple SDK và bước khởi chạy cũng được thiết lập. Bạn có thể hoàn tất quá trình này bằng cách nhấp vào Tiếp tục đến bảng điều khiển.

Chạy ứng dụng

Đã đến lúc bạn khám phá ứng dụng!

  1. Quay lại Xcode, hãy chạy ứng dụng trên Trình mô phỏng iOS. Trong trình đơn thả xuống Run Destinations (Chạy đích đến), trước tiên, hãy chọn một trong các Trình mô phỏng iOS.Chọn Trình mô phỏng iOS trong trình đơn thả xuống Run Destinations (Chạy đích đến)
  2. Sau đó, nhấp vào nút Run (Chạy) hoặc nhấn vào ⌘ + R
  3. Sau khi ứng dụng khởi chạy thành công trên Trình mô phỏng, hãy thêm một vài ghi chú.
  4. Trong bảng điều khiển của Firebase, hãy chuyển đến trình duyệt dữ liệu Firestore để bạn có thể thấy các tài liệu mới được tạo khi thêm ghi chú mới vào ứng dụng.Bảng điều khiển Cloud Firestore cho thấy một số tài liệu, cùng với Trình mô phỏng iOS cho thấy các tài liệu giống nhau

4. Cài đặt Vector Search bằng tiện ích Firestore

Trong phần này của lớp học lập trình, bạn sẽ cài đặt tiện ích Vector Search bằng Firestore và định cấu hình tiện ích này theo yêu cầu của ứng dụng ghi chú mà bạn đang xây dựng.

Bắt đầu cài đặt tiện ích

  1. Vẫn trong mục Firestore, hãy nhấp vào thẻ Extensions (Tiện ích).Chọn thẻ Tiện ích Firebase trong bảng điều khiển Firestore
  2. Nhấp vào Khám phá Trung tâm tiện ích.Thẻ Tiện ích của Firebase trong bảng điều khiển Firestore
  3. Nhập "vectơ".
  4. Nhấp vào "Vector Search with Firestore" (Tìm kiếm vectơ bằng tiện ích Firestore".Trang đích của Firebase Extensios Hub Thao tác này sẽ đưa bạn đến trang chi tiết của tiện ích. Tại đây, bạn có thể đọc thêm về tiện ích, cách hoạt động, các dịch vụ Firebase mà tiện ích yêu cầu và cách định cấu hình tiện ích.
  5. Nhấp vào Cài đặt trong bảng điều khiển của Firebase.Nút cài đặt cho tiện ích Vector Search with Firestore
  6. Bạn sẽ thấy danh sách tất cả các dự án của mình.
  7. Chọn dự án bạn đã tạo ở bước đầu tiên của lớp học lập trình này.Màn hình bộ chọn dự án Firebase

Định cấu hình tiện ích

Các tiện ích của Firebase sử dụng Chức năng đám mây cho Firebase, do đó, dự án của bạn phải sử dụng gói linh hoạt theo mô hình trả tiền theo mức dùng. Trước khi có thể sử dụng tiện ích Vector Search bằng tiện ích Firestore, bạn cần nâng cấp dự án.

  1. Nhấp vào Nâng cấp dự án để tiếp tục. Nâng cấp dự án lên gói linh hoạt
  2. Chọn tài khoản thanh toán hiện có hoặc tạo tài khoản mới. Nhấp vào tiếp tục.Chọn tài khoản thanh toán
  3. Đặt ngân sách (ví dụ: 100000 VND), nhấp vào Tiếp tục, rồi nhấp vào Mua.Thiết lập ngân sách
  4. Xem lại những API đã bật và các tài nguyên đã tạo.Xem xét các API đã bật
  5. Bật các dịch vụ được yêu cầu.Bật các dịch vụ bắt buộc
  6. Khi bật Cloud Storage, hãy chọn chế độ thử nghiệm đối với các quy tắc bảo mật.
  7. Xác nhận rằng Cloud Storage sẽ sử dụng cùng một vị trí với thực thể Cloud Firestore của bạn.
  8. Sau khi bật tất cả các dịch vụ, hãy nhấp vào Next (Tiếp theo).Nhấp vào tiếp theo sau khi bật tất cả dịch vụ
  9. Xem lại quyền truy cập đã cấp cho tiện ích này.
  10. Định cấu hình tiện ích:
    • Chọn Vertex AI làm LLM
    • Đường dẫn thu thập: ghi chú
    • Giới hạn truy vấn mặc định: 3
    • Tên trường nhập dữ liệu: văn bản
    • Tên trường đầu ra: nhúng
    • Tên trường trạng thái:* *trạng thái*
    • Nhúng tài liệu hiện có:
    • Cập nhật các tài liệu hiện có:
    • Vị trí chức năng của Cloud: us-central1
  11. Nhấp vào Cài đặt tiện ích để hoàn tất quá trình cài đặt.

Quá trình này có thể mất vài phút. Trong khi chờ quá trình cài đặt hoàn tất, hãy chuyển sang phần tiếp theo của hướng dẫn và đọc một số thông tin cơ bản về nhúng vectơ.

5. Thông tin khái quát

Trong khi đợi quá trình cài đặt hoàn tất, sau đây là một số thông tin cơ bản về cách hoạt động của tiện ích Vector Search with Firestore.

Vectơ, nhúng và Cơ sở dữ liệu vectơ là gì?

  • Vectơ là các đối tượng toán học biểu thị độ lớn và hướng của một đại lượng. Chúng có thể được dùng để trình bày dữ liệu theo cách giúp bạn so sánh và tìm kiếm dễ dàng hơn.
  • Nhúng là các vectơ biểu thị ý nghĩa của một từ hoặc cụm từ. Chúng được tạo ra bằng cách huấn luyện một mạng nơron trên một tập văn bản lớn và học mối quan hệ giữa các từ.
  • Cơ sở dữ liệu vectơ là cơ sở dữ liệu được tối ưu hoá để lưu trữ và tìm kiếm dữ liệu vectơ. Chúng cho phép tìm kiếm lân cận gần nhất có hiệu quả, đây là quá trình tìm các vectơ tương tự nhất với vectơ truy vấn cho trước.

Tìm kiếm vectơ hoạt động như thế nào?

Tìm kiếm vectơ hoạt động bằng cách so sánh vectơ truy vấn với tất cả vectơ trong cơ sở dữ liệu. Vectơ giống nhất với vectơ truy vấn sẽ được trả về dưới dạng kết quả tìm kiếm.

Sự tương đồng giữa hai vectơ có thể được đo lường bằng nhiều chỉ số khoảng cách. Số liệu khoảng cách phổ biến nhất là độ đồng dạng cosin, đo góc giữa hai vectơ.

6. Dùng thử Vector Search bằng tiện ích Firestore

Trước khi sử dụng tiện ích Tìm kiếm vectơ bằng Firestore trong ứng dụng dành cho iOS mà bạn đã tải xuống trước đó ở lớp học lập trình này, bạn có thể dùng thử tiện ích này trong bảng điều khiển của Firebase.

Đọc tài liệu

Tiện ích Firebase bao gồm tài liệu về cách hoạt động của các tiện ích này.

  1. Sau khi cài đặt xong phần mở rộng này, hãy nhấp vào nút Get started (Bắt đầu). Trang tổng quan về Tiện ích Firebase trong bảng điều khiển của Firebase
  2. Kiểm tra tab "Cách hoạt động của tiện ích mở rộng này" - tab giải thích:
    • cách tính toán các lượt nhúng cho tài liệu bằng cách thêm chúng vào bộ sưu tập notes,
    • cách truy vấn chỉ mục bằng cách gọi hàm ext-firestore-vector-search-queryCallable có thể gọi,
    • hoặc cách truy vấn chỉ mục bằng cách thêm tài liệu truy vấn vào bộ sưu tập _firestore-vector-search/index/queries.
    • Bài viết này cũng giải thích cách thiết lập hàm nhúng tuỳ chỉnh. Cách này rất hữu ích nếu không có LLM nào mà tiện ích hỗ trợ đáp ứng yêu cầu của bạn và bạn muốn sử dụng một LLM khác để tính toán lượt nhúng. Tài liệu về tiện ích Tìm kiếm vectơ bằng Firestore
  3. Nhấp vào đường liên kết Trang tổng quan Cloud Firestore để truy cập vào phiên bản Firestore của bạn
  4. Chuyển đến tài liệu _firestore-vector-search/index. Phần mở rộng sẽ cho thấy tiện ích đã tính toán xong thao tác nhúng cho tất cả tài liệu ghi chú mà bạn đã tạo ở bước trước của lớp học lập trình này.Cấu hình chỉ mục trong bảng điều khiển Firestore
  5. Để xác minh điều này, hãy mở một trong các tài liệu ghi chú và bạn sẽ thấy một trường bổ sung có tên embedding thuộc loại vector<768>, cũng như trường status.Trường nhúng vectơ bên trong bảng điều khiển Firestore

Tạo một tài liệu mẫu

Bạn có thể tạo một tài liệu mới trong bảng điều khiển của Firebase để xem tiện ích này hoạt động.

  1. Vẫn trong trình duyệt dữ liệu Firestore, hãy chuyển đến bộ sưu tập notes rồi nhấp vào + Thêm tài liệu ở cột giữa.Thêm tài liệu mới
  2. Nhấp vào Mã nhận dạng tự động để tạo một mã tài liệu duy nhất mới.
  3. Thêm trường có tên text của chuỗi và dán một số văn bản vào trường value. Quan trọng là văn bản này không phải là lorem ipsum hay một văn bản ngẫu nhiên khác. Chọn một tin bài chẳng hạn.Thêm trường văn bản
  4. Nhấp vào Lưu.
    • Hãy lưu ý cách tiện ích thêm trường trạng thái để cho biết đang xử lý dữ liệu.
    • Sau một lát, bạn sẽ thấy một trường mới embedding có giá trị vector<768>.
    Cập nhật trạng thái nhúng vectơ cho tài liệu mới này

Thực hiện truy vấn

Tiện ích Tìm kiếm vectơ với tiện ích Firestore có một tính năng nhỏ tiện lợi cho phép bạn truy vấn chỉ mục tài liệu mà không cần phải kết nối ứng dụng.

  1. Trong mục Firestore của bảng điều khiển của Firebase, hãy chuyển đến tài liệu _firestore-vector-search/index
  2. Nhấp vào + Bắt đầu thu thậpThêm một bộ sưu tập phụ mới
  3. Tạo một bộ sưu tập phụ mới có tên là queries
  4. Tạo tài liệu mới và đặt trường query thành văn bản xuất hiện trên một trong các tài liệu của bạn. Cách này phù hợp nhất với các truy vấn ngữ nghĩa, chẳng hạn như "Cách ánh xạ các tài liệu trên Firestore bằng Swift" (hãy cung cấp ít nhất một trong các ghi chú mà bạn thêm có chứa văn bản thảo luận về chủ đề này).Thêm trường truy vấn
  5. Bạn có thể thấy lỗi trong trạng tháiĐã xảy ra lỗi
  6. Điều này là do thiếu chỉ mục. Để thiết lập cấu hình chỉ mục còn thiếu, hãy chuyển đến bảng điều khiển Google Cloud dành cho dự án của bạn bằng cách truy cập vào đường liên kết này, sau đó chọn dự án của bạn trong danh sáchChọn đúng dự án
  7. Trong Trình khám phá nhật ký trên đám mây, bạn sẽ thấy thông báo lỗi có nội dung "FAILED_PREcondition: Thiếu cấu hình chỉ mục vectơ. Vui lòng tạo chỉ mục được yêu cầu bằng lệnh gcloud sau đây: ..."Thông báo lỗi trong trình khám phá nhật ký
  8. Thông báo lỗi cũng chứa lệnh gcloud mà bạn cần chạy để định cấu hình chỉ mục bị thiếu.
  9. Chạy lệnh sau từ dòng lệnh. Nếu bạn chưa cài đặt CLI gcloud trên máy của mình, hãy làm theo hướng dẫn tại đây để cài đặt.
    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
    
    Quá trình tạo chỉ mục sẽ mất vài phút. Bạn có thể kiểm tra tiến trình trên thẻ Chỉ mục trong phần Firestore của bảng điều khiển của Firebase.Trạng thái của chỉ mục mới
  10. Sau khi thiết lập chỉ mục, bạn có thể tạo một tài liệu truy vấn mới.
  11. Bây giờ, bạn sẽ thấy danh sách các mã tài liệu trùng khớp trong trường kết quảKết quả của việc thực hiện truy vấn ngữ nghĩa
  12. Sao chép một trong các mã nhận dạng đó rồi quay lại bộ sưu tập notes.
  13. Sử dụng phím ⌘+F để tìm kiếm mã tài liệu mà bạn đã sao chép – tài liệu này là tài liệu phù hợp nhất với truy vấn của bạn.Tìm mã tài liệu trong danh sách tài liệu

7. Triển khai tính năng tìm kiếm ngữ nghĩa

Cuối cùng, cũng đã đến lúc kết nối ứng dụng di động của bạn với tiện ích Vector Search bằng Firestore và triển khai tính năng tìm kiếm ngữ nghĩa cho phép người dùng tìm kiếm ghi chú của họ bằng các truy vấn bằng ngôn ngữ tự nhiên.

Kết nối hàm có thể gọi để thực hiện truy vấn

Tiện ích Vector Search with Firestore bao gồm một Hàm Cloud mà bạn có thể gọi qua ứng dụng di động để truy vấn chỉ mục đã tạo trước đó trong lớp học lập trình này. Trong bước này, bạn sẽ thiết lập kết nối giữa ứng dụng dành cho thiết bị di động và hàm có thể gọi này. SDK Swift của Firebase bao gồm các API giúp gọi các hàm từ xa một cách liền mạch.

  1. Quay lại Xcode và đảm bảo bạn đang ở trong dự án mà bạn đã sao chép ở bước trước trong lớp học lập trình này.
  2. Mở tệp NotesRepository.swift.
  3. Tìm dòng chứa private lazy var vectorSearchQueryCallable: Callable = functions.httpsCallable("")

Để gọi một hàm đám mây có thể gọi, bạn cần cung cấp tên hàm mà bạn muốn gọi.

  1. Chuyển đến bảng điều khiển của Firebase cho dự án của bạn rồi mở mục trong trình đơn Function trong phần Build (Tạo).
  2. Bạn sẽ thấy danh sách các hàm mà tiện ích đã cài đặt.
  3. Tìm kiếm tiện ích có tên ext-firestore-vector-search-queryCallable rồi sao chép tên của thiết bị đó.
  4. Dán tên vào mã của bạn. Bây giờ, mã sẽ đọc được
    private lazy var vectorSearchQueryCallable: Callable<String, String> = functions.httpsCallable("ext-firestore-vector-search-queryCallable")
    

Gọi hàm truy vấn

  1. Tìm phương thức performQuery
  2. Gọi hàm có thể gọi bằng cách gọi
    let result = try await vectorSearchQueryCallable(searchTerm)
    

Vì đây là lệnh gọi từ xa nên có thể không thực hiện được.

  1. Hãy thêm một số cách xử lý lỗi cơ bản để phát hiện lỗi và ghi lại các lỗi đó vào bảng điều khiển của Xcode.
    private func performQuery(searchTerm: String) async -> [String] {
      do {
        let result = try await vectorSearchQueryCallable(searchTerm)
        return [result]
      }
      catch {
        print(error.localizedDescription)
        return []
      }
    }
    

Kết nối giao diện người dùng

Để cho phép người dùng tìm kiếm ghi chú của họ, bạn sẽ triển khai thanh tìm kiếm trong màn hình danh sách ghi chú. Khi người dùng nhập cụm từ tìm kiếm, bạn cần gọi phương thức performQuery mà bạn đã triển khai ở bước trước. Nhờ có đối tượng sửa đổi chế độ xem searchabletask do SwiftUI cung cấp, nên việc này chỉ yêu cầu một vài dòng mã.

  1. Trước tiên, hãy mở NotesListScreen.swift
  2. Để thêm hộp tìm kiếm vào chế độ xem danh sách, hãy thêm đối tượng sửa đổi chế độ xem .searchable(text: $searchTerm, prompt: "Search") ngay phía trên dòng .navigationTitle("Notes")
  3. Sau đó, hãy gọi chức năng tìm kiếm này bằng cách thêm mã sau ngay bên dưới:
.task(id: searchTerm, debounce: .milliseconds(800)) {
  await notesRepository.semanticSearch(searchTerm: searchTerm)
}

Đoạn mã này gọi phương thức semanticSearch một cách không đồng bộ. Bằng cách cung cấp thời gian chờ 800 mili giây, bạn ra lệnh cho phương thức sửa đổi tác vụ giảm tốc hoạt động đầu vào của người dùng 0,8 giây. Điều này có nghĩa là semanticSearch sẽ chỉ được gọi khi người dùng tạm dừng nhập trong hơn 0,8 giây.

Mã của bạn bây giờ sẽ có dạng như sau:

...
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")
...

Chạy ứng dụng

  1. Nhấn ⌘ + R (hoặc nhấp vào nút Chạy) để chạy ứng dụng trong Trình mô phỏng iOS
  2. Bạn sẽ thấy các ghi chú mà bạn đã thêm vào ứng dụng trước đó ở lớp học lập trình này, cũng như mọi ghi chú mà bạn đã thêm qua bảng điều khiển của Firebase
  3. Bạn sẽ thấy một trường tìm kiếm ở đầu danh sách Ghi chú
  4. Nhập cụm từ xuất hiện ở một trong những tài liệu mà bạn đã thêm. Xin nhắc lại, đây là cách hiệu quả nhất cho các truy vấn ngữ nghĩa, chẳng hạn như "Làm cách nào để gọi API Firebase không đồng bộ từ Swift" (miễn là ít nhất một trong các ghi chú mà bạn thêm có chứa văn bản thảo luận về chủ đề này).
  5. Bạn có thể sẽ thấy kết quả tìm kiếm, nhưng thay vào đó, chế độ xem danh sách lại trống và bảng điều khiển của Xcode hiển thị thông báo lỗi: "Hàm đã được gọi với đối số không hợp lệ"

Ứng dụng Ghi chú với danh sách kết quả trống

Tức là bạn đã gửi dữ liệu không đúng định dạng.

Phân tích thông báo lỗi

  1. Để tìm hiểu xem bạn đang gặp vấn đề gì, hãy chuyển đến bảng điều khiển của Firebase
  2. Chuyển đến phần Hàm
  3. Tìm hàm ext-firestore-vector-search-queryCallable, mở trình đơn mục bổ sung bằng cách nhấp vào biểu tượng ba dấu chấm dọc
  4. Chọn Xem nhật ký để chuyển đến trình khám phá nhật ký
  5. Bạn sẽ thấy lỗi
Unhandled error ZodError: [
  {
    "code": "invalid_type",
    "expected": "object",
    "received": "string",
    "path": [],
    "message": "Expected object, received string"
  }
]

Tức là bạn đã gửi dữ liệu không đúng định dạng.

Sử dụng đúng loại dữ liệu

Để tìm hiểu xem tiện ích dự kiến chứa các tham số ở định dạng nào, hãy xem tài liệu về tiện ích.

  1. Chuyển đến phần Tiện ích trên bảng điều khiển của Firebase
  2. Nhấp vào Quản lý ->Quản lý Vector Search bằng tiện ích Firestore
  3. Trong phần Cách hoạt động của tiện ích này, bạn sẽ thấy thông số kỹ thuật của các tham số đầu vào và đầu ra.Tài liệu về tham số đầu vào và giá trị kết quả
  4. Quay lại Xcode rồi chuyển đến NotesRepository.swift
  5. Thêm mã sau vào đầu tệp:
    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 khớp với cấu trúc của tham số đầu vào mà tiện ích dự kiến, theo tài liệu của tiện ích. Tệp này cũng chứa thuộc tính prefilter lồng nhau mà bạn sẽ cần đến sau này.QueryResponse khớp với cấu trúc phản hồi của tiện ích.
  6. Tìm thông số kỹ thuật của hàm có thể gọi cũng như cập nhật các loại dữ liệu đầu vào và đầu ra
    private lazy var vectorSearchQueryCallable: Callable<QueryRequest, QueryResponse> = functions.httpsCallable("ext-firestore-vector-search-queryCallable")
    
  7. Cập nhật lệnh gọi hàm có thể gọi trong 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 []
      }
    }
    

Chạy lại ứng dụng

  1. Chạy lại ứng dụng
  2. Nhập truy vấn tìm kiếm chứa các cụm từ có trong một trong các ghi chú của bạn
  3. Bây giờ, bạn sẽ thấy danh sách ghi chú đã lọc

Ảnh chụp màn hình ứng dụng có kết quả dự kiến

Lọc trước dữ liệu người dùng

Trước khi bạn nhảy múa để ăn mừng – đã xảy ra sự cố với phiên bản hiện tại của ứng dụng: tập hợp kết quả chứa dữ liệu của tất cả người dùng.

Bạn có thể xác minh điều này bằng cách chạy ứng dụng trên một trình mô phỏng khác và thêm các tài liệu khác. Tài liệu mới sẽ chỉ xuất hiện trong trình mô phỏng đó. Nếu chạy lại ứng dụng trên trình mô phỏng khác, bạn sẽ chỉ thấy tài liệu mà mình đã tạo vào lần đầu tiên.

Nếu thực hiện tìm kiếm, bạn sẽ nhận thấy lệnh gọi đến vectorSearchQueryCallable trả về mã nhận dạng tài liệu có thể thuộc về người dùng khác. Để ngăn chặn điều này, chúng ta cần sử dụng bộ lọc sơ bộ.

Trong performQuery, hãy cập nhật mã như sau:

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

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

Thao tác này sẽ lọc trước dữ liệu dựa trên mã nhận dạng của người dùng đã đăng nhập. Như bạn có thể mong đợi, việc này yêu cầu cập nhật chỉ mục Firestore.

Chạy lệnh sau từ dòng lệnh để xác định một chỉ mục Firestore mới bao gồm cả userId và các vectơ nhúng trong trường 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

Sau khi chỉ mục được tạo xong, hãy chạy lại ứng dụng để xác minh rằng ứng dụng hoạt động như dự kiến

Tập hợp kết quả được lọc trước

8. Xin chúc mừng

Chúc mừng bạn đã hoàn tất thành công lớp học lập trình này!

Trong lớp học lập trình này, bạn đã tìm hiểu cách:

  • Thiết lập cơ sở dữ liệu Cloud Firestore có bật tính năng tìm kiếm ngữ nghĩa.
  • Tạo một ứng dụng SwiftUI đơn giản để tương tác với cơ sở dữ liệu.
  • Triển khai thanh tìm kiếm bằng đối tượng sửa đổi khung hiển thị có thể tìm kiếm của SwiftUI và đối tượng sửa đổi tác vụ.
  • Gọi một Hàm đám mây để tìm kiếm ngữ nghĩa trên cơ sở dữ liệu, bằng cách sử dụng giao diện Có thể gọi của SDK Firestore.

Với kiến thức học được trong lớp học lập trình này, giờ đây bạn có thể xây dựng các ứng dụng mạnh mẽ có sử dụng tính năng tìm kiếm ngữ nghĩa của Cloud Firestore để cung cấp cho người dùng trải nghiệm tìm kiếm trực quan và hiệu quả hơn.

Để tìm hiểu thêm về trường vectơ mới của Firestore và cách tính toán nhúng vectơ, vui lòng xem tài liệu này.