Tạo ứng dụng đề xuất tư thế Yoga theo bối cảnh bằng Firestore, Vector Search và Gemini 2.0 (phiên bản Java)!

1. Tổng quan

Trong thế giới ứng dụng chăm sóc sức khoẻ và thể dục, việc mang đến cho người dùng trải nghiệm phong phú và hấp dẫn là yếu tố then chốt. Đối với một ứng dụng Yoga, điều này có nghĩa là bạn cần cung cấp thông tin toàn diện, nội dung đa phương tiện và khả năng tìm kiếm thông minh, chứ không chỉ đơn thuần là nội dung mô tả bằng văn bản về các tư thế. Trong blog này, chúng ta sẽ khám phá cách xây dựng một cơ sở dữ liệu tư thế Yoga mạnh mẽ bằng Firestore của Google Cloud, tận dụng Tiện ích tìm kiếm vectơ của Firestore để so khớp theo ngữ cảnh và tích hợp sức mạnh của Gemini 2.0 Flash (Thử nghiệm) để làm việc với nội dung đa phương thức.

Tại sao nên dùng Firestore?

Firestore, cơ sở dữ liệu dạng tài liệu NoSQL không máy chủ của Google Cloud, là lựa chọn tuyệt vời để xây dựng các ứng dụng có thể mở rộng và linh hoạt. Sau đây là lý do khiến tính năng này phù hợp với ứng dụng Yoga của chúng tôi:

  • Khả năng mở rộng và hiệu suất: Firestore tự động mở rộng quy mô để xử lý hàng triệu người dùng và các tập dữ liệu khổng lồ, đảm bảo ứng dụng của bạn vẫn phản hồi ngay cả khi phát triển.
  • Cập nhật theo thời gian thực: Tính năng đồng bộ hoá theo thời gian thực tích hợp sẵn giúp dữ liệu nhất quán trên tất cả các ứng dụng được kết nối, nhờ đó, đây là lựa chọn hoàn hảo cho các tính năng như lớp học trực tiếp hoặc thực hành cộng tác.
  • Mô hình dữ liệu linh hoạt: Cấu trúc dựa trên tài liệu của Firestore cho phép bạn lưu trữ nhiều loại dữ liệu, bao gồm cả văn bản, hình ảnh và thậm chí cả các mục nhúng. Nhờ đó, Firestore trở thành lựa chọn lý tưởng để biểu thị thông tin phức tạp về tư thế Yoga.
  • Truy vấn mạnh mẽ: Firestore hỗ trợ các truy vấn phức tạp, bao gồm cả truy vấn về sự bằng nhau, không bằng nhau và hiện tại, với tiện ích mới, tìm kiếm tương tự theo vectơ.
  • Hỗ trợ ngoại tuyến: Firestore lưu dữ liệu vào bộ nhớ đệm cục bộ, cho phép ứng dụng của bạn hoạt động ngay cả khi người dùng không kết nối mạng.

Nâng cao tính năng Tìm kiếm bằng Tiện ích Tìm kiếm vectơ của Firestore

Phương thức tìm kiếm truyền thống dựa trên từ khoá có thể bị hạn chế khi xử lý các khái niệm phức tạp như tư thế Yoga. Người dùng có thể tìm kiếm một tư thế "mở hông" hoặc "cải thiện khả năng giữ thăng bằng" mà không biết tên tư thế cụ thể. Đây là lúc tính năng Tìm kiếm vectơ phát huy tác dụng.

Tính năng Tìm kiếm vectơ bằng Firestore cho phép bạn:

  • Tạo vectơ nhúng: Chuyển đổi nội dung mô tả bằng văn bản (và có thể là hình ảnh và âm thanh trong tương lai) thành các biểu diễn vectơ bằng số (vectơ nhúng) để nắm bắt ý nghĩa ngữ nghĩa của nội dung đó bằng cách sử dụng các mô hình như mô hình có trong Vertex AI hoặc mô hình tuỳ chỉnh.
  • Nhúng cửa hàng: Lưu trữ các mục nhúng này trực tiếp trong tài liệu Firestore.
  • Thực hiện tìm kiếm tương tự: Truy vấn cơ sở dữ liệu của bạn để tìm những tài liệu có ngữ nghĩa tương tự như một vectơ truy vấn nhất định, cho phép so khớp theo ngữ cảnh.

Tích hợp Gemini 2.0 Flash (Thử nghiệm)

Gemini 2.0 Flash là mô hình AI đa phương thức tiên tiến của Google. Mặc dù vẫn đang trong giai đoạn thử nghiệm, nhưng tính năng này mang đến những khả năng thú vị để làm phong phú thêm ứng dụng Yoga của chúng tôi:

  • Tạo văn bản: Sử dụng Gemini 2.0 Flash để tạo nội dung mô tả chi tiết về các tư thế Yoga, bao gồm cả lợi ích, điểm cần lưu ý và chống chỉ định.
  • Tạo hình ảnh (Mô phỏng): Mặc dù tính năng tạo hình ảnh trực tiếp bằng Gemini chưa được cung cấp công khai, nhưng tôi đã mô phỏng tính năng này bằng Imagen của Google để tạo ra những hình ảnh thể hiện tư thế một cách trực quan.
  • Tạo âm thanh (Mô phỏng): Tương tự, chúng ta có thể sử dụng dịch vụ Chuyển văn bản sang lời nói (TTS) để tạo hướng dẫn bằng âm thanh cho từng tư thế, hướng dẫn người dùng thực hành.

Tôi dự định đề xuất tích hợp để nâng cao ứng dụng bằng cách sử dụng các tính năng sau của mô hình:

  • API Trực tiếp đa phương thức: API mới này giúp bạn tạo các ứng dụng phát trực tiếp hình ảnh và âm thanh theo thời gian thực bằng cách sử dụng công cụ.
  • Tốc độ và hiệu suất: Gemini 2.0 Flash có thời gian hiển thị token đầu tiên (TTFT) nhanh hơn đáng kể so với Gemini 1.5 Flash.
  • Cải thiện trải nghiệm dựa trên tác nhân: Gemini 2.0 cải thiện khả năng hiểu biết đa phương thức, lập trình, tuân theo chỉ dẫn phức tạp và gọi hàm. Những điểm cải tiến này kết hợp với nhau để hỗ trợ trải nghiệm dựa trên tác nhân tốt hơn.

Để biết thêm thông tin chi tiết, hãy tham khảo trang tài liệu này về Gemini 1.5 Flash.

Để tăng độ tin cậy và cung cấp thêm tài nguyên, chúng ta có thể tích hợp Google Tìm kiếm để xác thực thông tin do ứng dụng của chúng ta cung cấp. Điều này có nghĩa là:

  • Tìm kiếm theo bối cảnh: Khi người dùng quản trị viên nhập thông tin chi tiết về một tư thế, chúng ta có thể sử dụng tên tư thế đó để thực hiện Google Tìm kiếm.
  • Trích xuất URL: Từ kết quả tìm kiếm, chúng tôi có thể trích xuất các URL có liên quan, chẳng hạn như bài viết, video hoặc trang web Yoga uy tín, rồi hiển thị các URL đó trong ứng dụng.

Sản phẩm bạn sẽ tạo ra

Trong phần này của khoá học, bạn sẽ:

  1. Tạo một bộ sưu tập Firestore và tải tài liệu Yoga
  2. Tìm hiểu cách tạo ứng dụng CRUD bằng Firestore
  3. Tạo nội dung mô tả tư thế Yoga bằng Gemini 2.0 Flash
  4. Bật tính năng Tìm kiếm vectơ của Firebase bằng tính năng tích hợp Firestore
  5. Tạo các vectơ nhúng từ nội dung mô tả về Yoga
  6. Thực hiện tìm kiếm tương tự cho văn bản tìm kiếm của người dùng

Yêu cầu

  • Một trình duyệt, chẳng hạn như Chrome hoặc Firefox
  • Một dự án trên Google Cloud đã bật tính năng thanh toán.

2. Trước khi bắt đầu

Tạo dự án

  1. Trong Google Cloud Console, trên trang chọn dự án, hãy chọn hoặc tạo một dự án trên Google Cloud.
  2. Đảm bảo rằng bạn đã bật tính năng thanh toán cho dự án trên Cloud. Tìm hiểu cách kiểm tra xem tính năng thanh toán có được bật trong một dự án hay không .
  3. Bạn sẽ sử dụng Cloud Shell, một môi trường dòng lệnh chạy trong Google Cloud và được tải sẵn bq. Nhấp vào Kích hoạt Cloud Shell ở đầu bảng điều khiển Cloud.

Hình ảnh nút Kích hoạt Cloud Shell

  1. Sau khi kết nối với Cloud Shell, bạn có thể kiểm tra để đảm bảo rằng bạn đã được xác thực và dự án được đặt thành mã dự án của bạn bằng lệnh sau:
gcloud auth list
  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng lệnh gcloud biết về dự án của bạn.
gcloud config list project
  1. Nếu bạn chưa đặt dự án, hãy dùng lệnh sau để đặt:
gcloud config set project <YOUR_PROJECT_ID>
  1. Bật các API bắt buộc bằng cách truy cập vào đường liên kết này cho đến khi bạn có thể nhấp vào nút "Bật".

Nếu bỏ lỡ API nào, bạn luôn có thể bật API đó trong quá trình triển khai.

Tham khảo tài liệu để biết các lệnh và cách sử dụng gcloud.

3. Thiết lập cơ sở dữ liệu

Tài liệu này có các bước đầy đủ hơn về cách thiết lập một phiên bản Firestore. Để bắt đầu, tôi sẽ làm theo các bước sau:

Chuyển đến Firestore Viewer rồi chọn Firestore ở chế độ Gốc trên màn hình Chọn một dịch vụ cơ sở dữ liệu

  1. Chọn một vị trí cho Firestore (Nhớ chọn us-central1 và làm theo hướng dẫn này bất cứ khi nào bạn chọn vùng / vị trí trong suốt lớp học lập trình này)
  2. Nhấp vào Create Database (Tạo cơ sở dữ liệu) (nếu đây là lần đầu tiên, hãy để cơ sở dữ liệu là "(default)")

Khi bạn tạo một dự án Firestore, dự án đó cũng sẽ bật API trong Trình quản lý API trên đám mây

  1. QUAN TRỌNG: Chọn phiên bản THỬ NGHIỆM (không phải phiên bản SẢN XUẤT) của Quy tắc bảo mật để có thể truy cập vào dữ liệu
  2. Sau khi thiết lập, bạn sẽ thấy chế độ xem Cơ sở dữ liệu, Tập hợp và Tài liệu Firestore ở chế độ Gốc như trong hình bên dưới:

f7136d53253c59a.png

  1. Bạn chưa cần thực hiện bước này, nhưng để ghi nhớ, bạn có thể nhấp vào "Bắt đầu thu thập" và tạo một bộ sưu tập mới. Đặt mã bộ sưu tập là "poses". Nhấp vào nút Lưu.

a26eb470aa9bfda9.png

Mẹo chuyên nghiệp cho ứng dụng phát hành công khai:

  1. Sau khi hoàn tất mô hình dữ liệu và xác định những người có thể truy cập vào các loại tài liệu, bạn có thể tạo, chỉnh sửa và giám sát Quy tắc bảo mật trong giao diện Firebase. Bạn có thể truy cập vào Quy tắc bảo mật theo đường liên kết này: https://console.firebase.google.com/u/0/project/<<your_project_id>>/firestore/rules
  2. Hãy nhớ chỉnh sửa, giám sát và kiểm thử các quy tắc bảo mật trước khi triển khai / ra mắt dự án từ giai đoạn phát triển vì đây thường là nguyên nhân thầm lặng khiến ứng dụng của bạn hoạt động khác đi :)

Trong bản minh hoạ này, chúng ta sẽ sử dụng chế độ KIỂM THỬ.

4. API REST của Firestore

  1. API REST có thể hữu ích cho các trường hợp sử dụng sau:a. Truy cập vào Firestore từ một môi trường bị hạn chế về tài nguyên, nơi không thể chạy một thư viện ứng dụng hoàn chỉnh. Tự động hoá việc quản trị cơ sở dữ liệu hoặc truy xuất siêu dữ liệu chi tiết của cơ sở dữ liệu
  2. Cách dễ nhất để sử dụng Firestore là dùng một trong các thư viện ứng dụng gốc. Tuy nhiên, trong một số trường hợp, bạn nên gọi trực tiếp API REST
  3. Trong phạm vi của blog này, bạn sẽ thấy cách sử dụng và minh hoạ các API REST của Firestore chứ không phải thư viện ứng dụng gốc
  4. Để xác thực, API REST của Firestore chấp nhận mã thông báo nhận dạng Xác thực Firebase hoặc mã thông báo Google Identity OAuth 2.0. Để biết thêm thông tin về chủ đề Xác thực và uỷ quyền, hãy tham khảo tài liệu.
  5. Tất cả các điểm cuối API REST đều nằm trong URL cơ sở https://firestore.googleapis.com/v1/.

Spring Boot và API Firestore

Giải pháp này trong Khung Spring Boot là để minh hoạ một ứng dụng khách sử dụng các API Firestore để thu thập và sửa đổi tư thế Yoga cũng như thông tin chi tiết về hơi thở với trải nghiệm tương tác của người dùng.

Để xem giải thích chi tiết từng bước về giải pháp CRUD của Firestore trong ứng dụng Tư thế yoga, bạn có thể xem đường liên kết đến blog.

Để tập trung vào giải pháp hiện tại và tìm hiểu phần CRUD (Tạo, Đọc, Cập nhật, Xoá) ngay lập tức, hãy nhân bản toàn bộ giải pháp tập trung vào blog này từ kho lưu trữ bên dưới trong Cloud Shell Terminal và sao chép cơ sở mã.

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

Lưu ý:

  1. Sau khi sao chép kho lưu trữ này, bạn chỉ cần thực hiện một vài thay đổi về mã dự án, API, v.v. Bạn không cần thực hiện bất kỳ thay đổi nào khác để ứng dụng của mình hoạt động. Mỗi thành phần của ứng dụng sẽ được giải thích trong các phần sắp tới. Sau đây là danh sách các thay đổi:
  2. Trong tệp src/main/java/com/example/demo/GenerateImageSample.java, hãy thay thế "<<YOUR_PROJECT_ID>>" bằng mã dự án của bạn
  3. Trong tệp src/main/java/com/example/demo/GenerateEmbeddings.java, hãy thay thế "<<YOUR_PROJECT_ID>>" bằng mã dự án của bạn
  4. Trong src/main/java/com/example/demo/PoseController.java, hãy thay thế tất cả các trường hợp của "<<YOUR_PROJECT_ID>>" và tên cơ sở dữ liệu, trong trường hợp này là "(default)", bằng các giá trị thích hợp trong cấu hình của bạn:
  5. Trong src/main/java/com/example/demo/PoseController.java, hãy thay thế "[YOUR_API_KEY]" bằng API KEY của bạn cho Gemini 2.0 Flash. Bạn có thể lấy khoá này từ AI Studio.
  6. Nếu bạn muốn kiểm thử cục bộ, hãy chạy các lệnh sau từ thư mục dự án trong Cloud Shell Terminal:
mvn package

mvn spring-boot:run

Ngay bây giờ, bạn có thể xem ứng dụng đang chạy bằng cách nhấp vào lựa chọn "xem trước trên web" trong Cloud Shell Terminal. Chúng tôi chưa sẵn sàng thực hiện các bài kiểm tra và dùng thử ứng dụng.

  1. Không bắt buộc: Nếu muốn triển khai ứng dụng trong Cloud Run, bạn sẽ phải khởi động một ứng dụng Java Cloud Run hoàn toàn mới từ đầu trong Cloud Shell Editor, đồng thời thêm các tệp src và tệp mẫu từ repo vào dự án mới trong các thư mục tương ứng (vì dự án repo github hiện tại không được thiết lập theo mặc định cho cấu hình triển khai Cloud Run). Trong trường hợp đó, bạn cần làm theo các bước sau (thay vì sao chép kho lưu trữ hiện có):
  2. Chuyển đến Cloud Shell Editor (Đảm bảo bạn mở Trình chỉnh sửa chứ không phải cửa sổ dòng lệnh), nhấp vào biểu tượng tên Dự án trên Google Cloud ở bên trái thanh trạng thái (phần bị chặn trong ảnh chụp màn hình bên dưới)

d3f0de417094237d.png

  1. Chọn New application (Ứng dụng mới) -> Cloud Run Application (Ứng dụng Cloud Run) -> Java: Cloud Run (Java: Cloud Run) trong danh sách lựa chọn rồi đặt tên là "firestore-poserecommender"

d5ef8b4ca8bf3f85.png

  1. Giờ đây, bạn sẽ thấy một mẫu ngăn xếp đầy đủ cho Ứng dụng Java Cloud Run, được định cấu hình sẵn và sẵn sàng hoạt động
  2. Xoá lớp Controller hiện có và sao chép các tệp sau vào thư mục tương ứng trong cấu trúc dự án:

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. tệp Docker
  2. Bạn cần thực hiện các thay đổi trong các tệp tương ứng để thay thế PROJECT ID và API KEY bằng các giá trị tương ứng. (các bước 1 a,b, c và d ở trên).

5. Nhập dữ liệu

Dữ liệu cho ứng dụng có trong tệp data.json này: https://github.com/AbiramiSukumaran/firestore-poserecommender/blob/main/data.json

Nếu muốn bắt đầu với một số dữ liệu được xác định trước, bạn có thể sao chép tệp json và thay thế tất cả các trường hợp xuất hiện của "<<YOUR_PROJECT_ID>>" bằng giá trị của bạn

  • Chuyển đến Firestore Studio
  • Đảm bảo bạn đã tạo một bộ sưu tập có tên là "poses"
  • Thêm từng tài liệu theo cách thủ công từ tệp kho lưu trữ được đề cập ở trên

Ngoài ra, bạn có thể nhập dữ liệu trong một lần từ tập hợp được xác định trước mà chúng tôi đã tạo cho bạn bằng cách chạy các bước sau:

  1. Chuyển đến Cửa sổ dòng lệnh Cloud Shell, đảm bảo bạn đã thiết lập dự án trên đám mây Google Cloud đang hoạt động và đảm bảo bạn được uỷ quyền. Tạo một bộ chứa trong dự án của bạn bằng lệnh gsutil bên dưới. Thay thế biến <PROJECT_ID> trong lệnh bên dưới bằng mã dự án Google Cloud của bạn:

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

  1. Sau khi tạo vùng chứa, chúng ta cần sao chép dữ liệu xuất của cơ sở dữ liệu mà chúng ta đã chuẩn bị vào vùng chứa này, trước khi có thể nhập dữ liệu đó vào cơ sở dữ liệu Firebase. Sử dụng lệnh bên dưới:

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

Bây giờ, khi đã có dữ liệu để nhập, chúng ta có thể chuyển sang bước cuối cùng là nhập dữ liệu vào cơ sở dữ liệu Firebase (mặc định) mà chúng ta đã tạo.

  1. Truy cập vào bảng điều khiển Firestore ngay bây giờ rồi nhấp vào Nhập/Xuất trong trình đơn điều hướng ở bên trái.

Chọn Nhập rồi chọn đường dẫn đến Cloud Storage mà bạn vừa tạo và chuyển đến khi bạn có thể chọn tệp "yoga_poses.overall_export_metadata":

f5c1d16df7d5a64a.png

  1. Nhấp vào Nhập.

Quá trình nhập sẽ mất vài giây và sau khi hoàn tất, bạn có thể xác thực cơ sở dữ liệu Firestore và tập hợp bằng cách truy cập vào https://console.cloud.google.com/firestore/databases, chọn cơ sở dữ liệu mặc định và tập hợp poses như minh hoạ bên dưới:

  1. Một phương pháp khác là bạn cũng có thể tạo bản ghi theo cách thủ công thông qua ứng dụng sau khi triển khai bằng thao tác "Tạo tư thế mới".

6. Tìm kiếm vectơ

Bật Tiện ích Tìm kiếm vectơ của Firestore

Hãy sử dụng tiện ích này để tự động nhúng và truy vấn các tài liệu Firestore bằng tính năng của kết quả tìm kiếm vectơ mới! Thao tác này sẽ đưa bạn đến Trung tâm tiện ích Firebase.

Khi cài đặt tiện ích Tìm kiếm vectơ, bạn chỉ định một tên trường tài liệu và bộ sưu tập. Việc thêm hoặc cập nhật một tài liệu có trường này sẽ kích hoạt tiện ích này để tính toán một vectơ nhúng cho tài liệu. Thông tin nhúng vectơ này được ghi lại vào cùng một tài liệu và tài liệu được lập chỉ mục trong kho vectơ, sẵn sàng được truy vấn.

Hãy cùng xem các bước:

Cài đặt tiện ích:

Cài đặt tiện ích "Tìm kiếm vectơ bằng Firestore" từ Cửa hàng tiện ích Firebase bằng cách nhấp vào "Cài đặt trong Bảng điều khiển của Firebase".

QUAN TRỌNG:

Khi lần đầu tiên chuyển đến trang tiện ích này, bạn cần chọn cùng một dự án mà bạn đang thực hiện trong bảng điều khiển Cloud có trong bảng điều khiển của Firebase.

715426b97c732649.png

Nếu dự án của bạn không có trong danh sách, hãy thêm dự án đó vào Firebase (chọn dự án Google Cloud hiện có trong danh sách).

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

Chỉ định bộ sưu tập ("poses"), trường chứa văn bản cần nhúng ("posture") và các tham số khác như phương diện nhúng.

Nếu có những API cần được bật được liệt kê trong bước này, thì trang cấu hình sẽ cho phép bạn làm như vậy, hãy làm theo các bước cho phù hợp.

Nếu trang không phản hồi sau khi bạn bật API một lúc, hãy làm mới trang. Lúc này, bạn sẽ thấy các API đã bật.

5ba59b45710c567b.png

Trong một trong các bước sau, bạn có thể sử dụng LLM mà bạn chọn để tạo các vectơ nhúng. Chọn "Vertex AI".

bb528a04ebb5f976.png

Một số chế độ cài đặt tiếp theo có liên quan đến bộ sưu tập và trường mà bạn muốn nhúng:

LLM: Vertex AI

Đường dẫn đến bộ sưu tập: poses

Hạn mức truy vấn mặc định: 3

Đo khoảng cách: Cosin

Tên trường nhập dữ liệu: tư thế

Tên trường đầu ra: embedding

Tên trường trạng thái: status

Nhúng tài liệu hiện có: Có

Cập nhật các thành phần nhúng hiện có: Có

Vị trí của Cloud Functions: us-central1

Bật sự kiện: Chưa đánh dấu

fb8cdf1163fac7cb.png

Sau khi bạn thiết lập xong tất cả các bước này, hãy nhấp vào nút Cài đặt tiện ích. Quá trình này sẽ mất từ 3 đến 5 phút.

Tạo vectơ nhúng:

Khi bạn thêm hoặc cập nhật tài liệu trong bộ sưu tập "poses", tiện ích này sẽ tự động tạo các vectơ nhúng bằng cách sử dụng một mô hình được huấn luyện tiền kỳ hoặc một mô hình mà bạn chọn thông qua một điểm cuối API. Trong trường hợp này, chúng ta đã chọn Vertex AI trong cấu hình tiện ích.

Tạo chỉ mục

Thao tác này sẽ bắt buộc việc tạo Chỉ mục trên trường nhúng tại thời điểm sử dụng thành phần nhúng trong ứng dụng.

Firestore tự động tạo chỉ mục cho các truy vấn cơ bản; tuy nhiên, bạn có thể cho phép Firestore tạo cú pháp chỉ mục bằng cách chạy các truy vấn không có chỉ mục. Firestore sẽ cung cấp cho bạn một đường liên kết đến chỉ mục được tạo trong thông báo lỗi ở phía ứng dụng. Dưới đây là danh sách các bước để tạo chỉ mục vectơ:

  1. Chuyển đến Cửa sổ dòng lệnh Cloud Shell
  2. Chạy lệnh sau:
gcloud firestore indexes composite create --collection-group="poses" --query-scope=COLLECTION --database="(default)" --field-config vector-config='{"dimension":"768", "flat": "{}"}',field-path="embedding"

Đọc thêm về vấn đề này tại đây.

Sau khi tạo chỉ mục vectơ, bạn có thể thực hiện tìm kiếm lân cận nhất bằng các vectơ nhúng.

Lưu ý quan trọng:

Từ thời điểm này trở đi, bạn không cần phải thay đổi nguồn. Bạn chỉ cần làm theo để hiểu ứng dụng đang làm gì.

Hãy xem ứng dụng bạn mới tạo tiếp cận tính năng Tìm kiếm vectơ như thế nào. Sau khi lưu trữ các mục nhúng, bạn có thể sử dụng lớp VectorQuery của Firestore Java SDK để thực hiện Tìm kiếm vectơ và nhận kết quả về lân cận gần nhất:

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();

Đoạn mã này so sánh embeddings của văn bản tìm kiếm của người dùng với embeddings của các tài liệu trong Firestore và trích xuất tài liệu gần nhất theo ngữ cảnh.

7. Gemini 2.0 Flash

Tích hợp Gemini 2.0 Flash (để tạo nội dung mô tả)

Hãy xem ứng dụng bạn vừa tạo xử lý việc tích hợp Gemini 2.0 Flash để tạo nội dung mô tả như thế nào.

Giả sử một người dùng quản trị / huấn luyện viên Yoga muốn nhập thông tin chi tiết về các tư thế nhờ Gemini 2.0 Flash, sau đó thực hiện tìm kiếm để xem các kết quả phù hợp nhất. Điều này dẫn đến việc trích xuất thông tin chi tiết về các tư thế khớp cùng với các đối tượng đa phương thức hỗ trợ kết quả.

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);

a. Bắt chước tính năng tạo hình ảnh và âm thanh

Gemini 2.0 Flash Experimental có khả năng tạo kết quả đa phương thức, tuy nhiên tôi chưa đăng ký sử dụng phiên bản tiếp cận sớm nên tôi đã mô phỏng đầu ra hình ảnh và đầu ra âm thanh bằng API Imagen và TTS tương ứng. Hãy tưởng tượng xem sẽ tuyệt vời như thế nào khi bạn có thể tạo tất cả những nội dung này chỉ bằng một lệnh gọi API đến 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";
        }
}

b. Liên kết thực tế với Google Tìm kiếm:

Nếu kiểm tra mã gọi Gemini ở bước 6, bạn sẽ thấy đoạn mã sau để bật tính năng liên kết thực tế với Google Tìm kiếm cho câu trả lời của LLM (mô hình ngôn ngữ lớn):

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

Điều này nhằm đảm bảo rằng chúng tôi:

  • Dựa vào kết quả tìm kiếm thực tế để huấn luyện mô hình
  • Trích xuất các URL có liên quan được tham chiếu trong nội dung tìm kiếm

8. Chạy ứng dụng

Hãy cùng xem tất cả các chức năng của ứng dụng Java Spring Boot mà bạn vừa tạo bằng giao diện web Thymeleaf đơn giản:

  1. Các thao tác CRUD của Firestore (Tạo, Đọc, Cập nhật, Xoá)
  2. Tìm kiếm bằng từ khoá
  3. Tạo bối cảnh dựa trên AI tạo sinh
  4. Tìm kiếm theo ngữ cảnh (Tìm kiếm vectơ)
  5. Kết quả đầu ra đa phương thức liên quan đến nội dung tìm kiếm
  6. Chạy truy vấn của riêng bạn (Truy vấn ở định dạng structuredQuery)

Ví dụ: {"structuredQuery":{"select":{"fields":[{"fieldPath":"name"}]},"from":[{"collectionId":"fitness_poses"}]}}

Tất cả các tính năng đã thảo luận cho đến nay đều là một phần của ứng dụng mà bạn vừa tạo từ kho lưu trữ: https://github.com/AbiramiSukumaran/firestore-poserecommender

Để tạo, chạy và triển khai ứng dụng này, hãy chạy các lệnh sau từ Cloud Shell Terminal:

mvn package

mvn spring-boot:run

Bạn sẽ thấy kết quả và có thể dùng thử các tính năng của ứng dụng. Hãy xem video dưới đây để xem bản minh hoạ kết quả:

Ứng dụng đề xuất tư thế bằng Firestore, Tìm kiếm vectơ và Gemini 2.0 Flash

Bước không bắt buộc:

Để triển khai ứng dụng này trên Cloud Run (giả sử bạn đã khởi động một ứng dụng hoàn toàn mới bằng tệp Docker và sao chép các tệp khi cần), hãy chạy lệnh sau từ Cloud Shell Terminal trong thư mục dự án của bạn:

gcloud run deploy --source .

Cung cấp tên ứng dụng, mã khu vực (chọn mã cho us-central1) và chọn lệnh gọi chưa xác thực "Y" theo lời nhắc. Bạn sẽ nhận được điểm cuối ứng dụng trong thiết bị đầu cuối sau khi triển khai thành công.

9. Dọn dẹp

Để tránh bị tính phí vào tài khoản Google Cloud của bạn cho các tài nguyên được dùng trong bài đăng này, hãy làm theo các bước sau:

  1. Trong bảng điều khiển Cloud, hãy chuyển đến trang Quản lý tài nguyên.
  2. Trong danh sách dự án, hãy chọn dự án mà bạn muốn xoá, rồi nhấp vào Xoá.
  3. Trong hộp thoại, hãy nhập mã dự án rồi nhấp vào Tắt để xoá dự án.

10. Xin chúc mừng

Xin chúc mừng! Bạn đã sử dụng thành công Firestore để tạo một ứng dụng quản lý tư thế Yoga thông minh và mạnh mẽ. Bằng cách kết hợp sức mạnh của Firestore, Tiện ích tìm kiếm vectơ và các chức năng của Gemini 2.0 Flash (với tính năng tạo hình ảnh và âm thanh mô phỏng), chúng tôi đã tạo ra một ứng dụng Yoga thực sự hấp dẫn và giàu thông tin để triển khai các thao tác CRUD, thực hiện tìm kiếm dựa trên từ khoá, tìm kiếm vectơ theo ngữ cảnh và tạo nội dung đa phương tiện.

Phương pháp này không chỉ áp dụng cho các ứng dụng Yoga. Khi các mô hình AI như Gemini tiếp tục phát triển, khả năng tạo ra trải nghiệm người dùng sống động và được cá nhân hoá hơn nữa sẽ chỉ tăng lên. Hãy nhớ luôn cập nhật những thông tin mới nhất về các sản phẩm và tài liệu của Google Cloud và Firebase để khai thác tối đa tiềm năng của những công nghệ này.

Nếu muốn mở rộng ứng dụng này, tôi sẽ cố gắng làm hai việc với Gemini 2.0 Flash:

  1. Sử dụng API Multimodal Live bằng cách tạo luồng âm thanh và hình ảnh trực tiếp cho trường hợp sử dụng.
  2. Bật Chế độ suy nghĩ để tạo ra những suy nghĩ đằng sau câu trả lời cho hoạt động tương tác với dữ liệu theo thời gian thực, giúp trải nghiệm trở nên chân thực hơn.

Hãy thử và gửi yêu cầu kéo :>D!!!