Utwórz kontekstową aplikację do rekomendowania asan jogi za pomocą Firestore, wyszukiwania wektorowego i Gemini 2.0 (wersja w języku Java).

1. Przegląd

W przypadku aplikacji do dbania o zdrowie i kondycję kluczowe jest zapewnienie użytkownikom bogatych i atrakcyjnych wrażeń. W przypadku aplikacji do jogi oznacza to, że nie wystarczy prosty opis tekstowy pozycji. Należy też udostępnić wyczerpujące informacje, treści multimedialne i inteligentne funkcje wyszukiwania. Z tego posta na blogu dowiesz się, jak utworzyć solidną bazę danych pozycji jogi za pomocą Firestore od Google Cloud, wykorzystać jej rozszerzenie do wyszukiwania wektorowego w celu dopasowywania kontekstowego oraz zintegrować możliwości Gemini 2.0 Flash (wersja eksperymentalna) do pracy z treściami multimodalnymi.

Dlaczego warto wybrać Firestore?

Firestore, bezserwerowa baza danych dokumentów NoSQL w Google Cloud, to doskonały wybór do tworzenia skalowalnych i dynamicznych aplikacji. Oto dlaczego idealnie pasuje do naszej aplikacji do jogi:

  • Skalowalność i wydajność: Firestore automatycznie skaluje się, aby obsługiwać miliony użytkowników i ogromne zbiory danych, dzięki czemu aplikacja zachowuje responsywność nawet w miarę rozwoju.
  • Aktualizacje w czasie rzeczywistym: wbudowana synchronizacja w czasie rzeczywistym zapewnia spójność danych na wszystkich połączonych klientach, dzięki czemu idealnie nadaje się do funkcji takich jak zajęcia na żywo czy wspólne ćwiczenia.
  • Elastyczny model danych: dokumentowa struktura Firestore umożliwia przechowywanie różnych typów danych, w tym tekstu, obrazów, a nawet osadzeń, dzięki czemu idealnie nadaje się do reprezentowania złożonych informacji o pozycjach jogi.
  • Zaawansowane zapytania: Firestore obsługuje złożone zapytania, w tym zapytania dotyczące równości i nierówności, a dzięki nowemu rozszerzeniu także wyszukiwanie podobieństwa wektorowego.
  • Obsługa offline: Firestore buforuje dane lokalnie, dzięki czemu aplikacja może działać nawet wtedy, gdy użytkownicy są offline.

Ulepszanie wyszukiwania za pomocą rozszerzenia wyszukiwania wektorowego w Firestore

Tradycyjne wyszukiwanie oparte na słowach kluczowych może być ograniczone w przypadku złożonych pojęć, takich jak pozycje jogi. Użytkownik może wyszukać pozycję, która „otwiera biodra” lub „poprawia równowagę”, nie znając jej nazwy. Właśnie tu przydaje się wyszukiwanie wektorowe.

Wyszukiwanie wektorowe w Firestore umożliwia:

  • Generowanie wektorów dystrybucyjnych: przekształcanie opisów tekstowych, a w przyszłości także obrazów i dźwięków, w numeryczne reprezentacje wektorowe (wektory dystrybucyjne), które odzwierciedlają ich znaczenie semantyczne, za pomocą modeli takich jak te dostępne w Vertex AI lub modeli niestandardowych.
  • Przechowywanie wektorów dystrybucyjnych: Przechowuj te wektory dystrybucyjne bezpośrednio w dokumentach Firestore.
  • Przeprowadzanie wyszukiwań podobieństwa: wysyłaj zapytania do bazy danych, aby znaleźć dokumenty podobne semantycznie do danego wektora zapytania, co umożliwia dopasowywanie kontekstowe.

Integracja Gemini 2.0 Flash (wersja eksperymentalna)

Gemini 2.0 Flash to najnowocześniejszy multimodalny model AI od Google. Chociaż ta funkcja jest nadal w fazie eksperymentów, otwiera ekscytujące możliwości wzbogacenia naszej aplikacji do jogi:

  • Generowanie tekstu: używaj Gemini 2.0 Flash do generowania szczegółowych opisów pozycji jogi, w tym korzyści, modyfikacji i przeciwwskazań.
  • Generowanie obrazów (symulowane): chociaż bezpośrednie generowanie obrazów za pomocą Gemini nie jest jeszcze publicznie dostępne, zasymulowałem je za pomocą modelu Imagen od Google, generując obrazy, które wizualnie przedstawiają pozycje.
  • Generowanie dźwięku (imitacja): podobnie możemy użyć usługi zamiany tekstu na mowę (TTS), aby utworzyć instrukcje audio dla każdej pozycji, które będą prowadzić użytkowników przez ćwiczenie.

Potencjalnie planuję zaproponować integrację, aby ulepszyć aplikację i umożliwić jej korzystanie z tych funkcji modelu:

  • Multimodalny interfejs Live API: ten nowy interfejs API pomaga tworzyć aplikacje do przesyłania strumieniowego wideo i audio w czasie rzeczywistym z użyciem narzędzi.
  • Szybkość i wydajność: Gemini 2.0 Flash ma znacznie krótszy czas do pierwszego tokena (TTFT) niż Gemini 1.5 Flash.
  • Ulepszone funkcje agentowe: Gemini 2.0 lepiej radzi sobie z rozumieniem multimodalnym, kodowaniem, wykonywaniem złożonych instrukcji i wywoływaniem funkcji. Te ulepszenia wspólnie zapewniają lepsze wrażenia związane z korzystaniem z technologii agentów.

Więcej informacji znajdziesz na tej stronie.

Aby zwiększyć wiarygodność i zapewnić dodatkowe zasoby, możemy zintegrować wyszukiwarkę Google, aby uwiarygodnić informacje podawane przez naszą aplikację. Oznacza to:

  • Wyszukiwanie kontekstowe: gdy użytkownik z uprawnieniami administracyjnymi wprowadzi szczegóły pozycji, możemy użyć nazwy pozycji do przeprowadzenia wyszukiwania w Google.
  • Wyodrębnianie adresów URL: z wyników wyszukiwania możemy wyodrębniać odpowiednie adresy URL, np. artykułów, filmów lub wiarygodnych stron o jodze, i wyświetlać je w aplikacji.

Co utworzysz

W ramach tego laboratorium:

  1. Tworzenie kolekcji Firestore i wczytywanie dokumentów Yoga
  2. Dowiedz się, jak tworzyć aplikacje CRUD za pomocą Firestore
  3. Generowanie opisu pozycji jogi za pomocą Gemini 2.0 Flash
  4. Włącz integrację wyszukiwania wektorowego w Firebase z Firestore
  5. Generowanie wektorów dystrybucyjnych na podstawie opisu jogi
  6. Przeprowadzanie wyszukiwania podobieństw dla tekstu wyszukiwanego przez użytkownika

Wymagania

  • przeglądarka, np. Chrome lub Firefox;
  • Projekt Google Cloud z włączonymi płatnościami.

2. Zanim zaczniesz

Utwórz projekt

  1. W konsoli Google Cloud na stronie selektora projektów wybierz lub utwórz projekt Google Cloud.
  2. Sprawdź, czy w projekcie Cloud włączone są płatności. Dowiedz się, jak sprawdzić, czy w projekcie są włączone płatności .
  3. Będziesz używać Cloud Shell, czyli środowiska wiersza poleceń działającego w Google Cloud, które jest wstępnie załadowane narzędziem bq. U góry konsoli Google Cloud kliknij Aktywuj Cloud Shell.

Obraz przycisku aktywowania Cloud Shell

  1. Po połączeniu z Cloud Shell sprawdź, czy uwierzytelnianie zostało już przeprowadzone, a projekt jest już ustawiony na Twój identyfikator projektu, używając tego polecenia:
gcloud auth list
  1. Aby potwierdzić, że polecenie gcloud zna Twój projekt, uruchom w Cloud Shell to polecenie:
gcloud config list project
  1. Jeśli projekt nie jest ustawiony, użyj tego polecenia, aby go ustawić:
gcloud config set project <YOUR_PROJECT_ID>
  1. Włącz wymagane interfejsy API, klikając ten link, aż pojawi się przycisk „Włącz”.

Jeśli pominiesz jakiś interfejs API, możesz go włączyć w trakcie wdrażania.

Informacje o poleceniach gcloud i ich użyciu znajdziesz w dokumentacji.

3. Konfiguracja bazy danych

W dokumentacji znajdziesz pełniejsze instrukcje konfigurowania instancji Firestore. Aby zacząć, wykonam te czynności:

1. Otwórz przeglądarkę Firestore i na ekranie Wybierz usługę bazy danych wybierz Firestore w trybie natywnym.

  1. Wybierz lokalizację Firestore (pamiętaj, aby wybrać us-central1 i postępować zgodnie z tą instrukcją, gdy w tym ćwiczeniu wybierzesz region lub lokalizację).
  2. Kliknij Utwórz bazę danych (jeśli robisz to po raz pierwszy, pozostaw domyślną bazę danych „(default)”).

Gdy tworzysz projekt Firestore, interfejs API jest też włączany w Cloud API Manager.

  1. WAŻNE: wybierz wersję TESTOWĄ (nie PRODUKCYJNĄ) reguł zabezpieczeń, aby dane były dostępne.
  2. Po skonfigurowaniu w trybie natywnym powinny być widoczne baza danych Firestore, kolekcja i dokument, jak na ilustracji poniżej:

f7136d53253c59a.png

  1. Nie wykonuj jeszcze tego kroku, ale dla porządku: możesz kliknąć „Rozpocznij kolekcję” i utworzyć nową kolekcję. Ustaw identyfikator kolekcji na „poses”. Kliknij przycisk Zapisz.

a26eb470aa9bfda9.png

Profesjonalne wskazówki dotyczące aplikacji produkcyjnej:

  1. Gdy sfinalizujesz model danych i określisz, kto powinien mieć dostęp do różnych rodzajów dokumentów, możesz tworzyć, edytować i monitorować reguły zabezpieczeń w interfejsie Firebase. Do reguł zabezpieczeń możesz uzyskać dostęp, klikając ten link: https://console.firebase.google.com/u/0/project/<<your_project_id>>/firestore/rules
  2. Zanim wdrożysz projekt z fazy programowania, pamiętaj, aby edytować, monitorować i testować reguły bezpieczeństwa. Często są one cichym winowajcą, który sprawia, że aplikacja działa inaczej.

Na potrzeby tej demonstracji użyjemy go w trybie TEST.

4. Firestore REST API

  1. Interfejs API REST może być przydatny w tych przypadkach: Dostęp do Firestore ze środowiska o ograniczonych zasobach, w którym nie można uruchomić pełnej biblioteki klienta. automatyzowanie administrowania bazą danych lub pobieranie szczegółowych metadanych bazy danych;
  2. Najprostszym sposobem korzystania z Firestore jest użycie jednej z natywnych bibliotek klienta. W niektórych sytuacjach przydatne jest jednak bezpośrednie wywoływanie interfejsu REST API.
  3. W tym artykule na blogu zobaczysz przykłady użycia interfejsów Firestore REST API, a nie natywnych bibliotek klienta.
  4. Do uwierzytelniania interfejs Firestore REST API akceptuje token tożsamości uwierzytelniania Firebase lub token OAuth 2.0 Google Identity. Więcej informacji o uwierzytelnianiu i autoryzacji znajdziesz w dokumentacji.
  5. Wszystkie punkty końcowe interfejsu REST API znajdują się pod podstawowym adresem URL https://firestore.googleapis.com/v1/.

Spring Boot i Firestore API

To rozwiązanie w Spring Boot Framework ma na celu zaprezentowanie aplikacji klienckiej, która korzysta z interfejsów API Firestore do zbierania i modyfikowania szczegółów dotyczących pozycji jogi i oddechu, zapewniając użytkownikom interaktywność.

Szczegółowe wyjaśnienie krok po kroku rozwiązania CRUD Firestore w aplikacji do jogi znajdziesz na blogu.

Aby skupić się na bieżącym rozwiązaniu i nauczyć się części CRUD w trakcie pracy, sklonuj całe rozwiązanie opisane w tym blogu z repozytorium poniżej z terminala Cloud Shell i uzyskaj kopię bazy kodu.

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

Uwaga:

  1. Po sklonowaniu tego repozytorium wystarczy wprowadzić kilka zmian dotyczących identyfikatora projektu, interfejsów API itp. Aby uruchomić aplikację, nie musisz wprowadzać żadnych innych zmian. Poszczególne komponenty aplikacji zostały omówione w dalszej części tego artykułu. Oto lista zmian:
  2. W pliku src/main/java/com/example/demo/GenerateImageSample.java zastąp ciąg "<<YOUR_PROJECT_ID>>" identyfikatorem projektu.
  3. W pliku src/main/java/com/example/demo/GenerateEmbeddings.java zastąp ciąg "<<YOUR_PROJECT_ID>>" identyfikatorem projektu.
  4. src/main/java/com/example/demo/PoseController.java zastąp wszystkie wystąpienia ciągu „<<YOUR_PROJECT_ID>>" i nazwa bazy danych,, w tym przypadku "(default)",” odpowiednimi wartościami z konfiguracji:
  5. src/main/java/com/example/demo/PoseController.java zastąp „[YOUR_API_KEY]” kluczem interfejsu API Gemini 2.0 Flash. Możesz go uzyskać w AI Studio.
  6. Jeśli chcesz przetestować lokalnie, uruchom te polecenia z folderu projektu w terminalu Cloud Shell:
mvn package

mvn spring-boot:run

Obecnie możesz wyświetlić działającą aplikację, klikając opcję „Podgląd w przeglądarce” w terminalu Cloud Shell. Nie jesteśmy jeszcze gotowi na przeprowadzenie testów i wypróbowanie aplikacji.

  1. Opcjonalnie: jeśli chcesz wdrożyć aplikację w Cloud Run, musisz utworzyć nową aplikację Java Cloud Run od zera w edytorze Cloud Shell i dodać pliki źródłowe oraz pliki szablonów z repozytorium do nowego projektu w odpowiednich folderach (ponieważ bieżący projekt repozytorium GitHub nie jest domyślnie skonfigurowany pod kątem wdrożenia w Cloud Run). W takim przypadku wykonaj te czynności (zamiast klonować istniejące repozytorium):
  2. Otwórz edytor Cloud Shell (upewnij się, że otwarty jest edytor, a nie terminal). Kliknij ikonę nazwy projektu Google Cloud po lewej stronie paska stanu (zaciemniona część na zrzucie ekranu poniżej).

d3f0de417094237d.png

  1. Na liście opcji wybierz Nowa aplikacja –> Aplikacja Cloud Run –> Java: Cloud Run i nadaj jej nazwę „firestore-poserecommender”.

d5ef8b4ca8bf3f85.png

  1. Powinien się teraz wyświetlić szablon pełnego stosu dla aplikacji Java Cloud Run, wstępnie skonfigurowany i gotowy do użycia.
  2. Usuń istniejącą klasę Controller i skopiuj te pliki do odpowiednich folderów w strukturze projektu:

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. W odpowiednich plikach musisz wprowadzić zmiany, aby zastąpić PROJECT ID i API KEY odpowiednimi wartościami. (kroki 1a,b, c i d powyżej).

5. Pozyskiwanie danych

Dane aplikacji są dostępne w tym pliku data.json: https://github.com/AbiramiSukumaran/firestore-poserecommender/blob/main/data.json

Jeśli chcesz zacząć od wstępnie zdefiniowanych danych, możesz skopiować kod JSON i zastąpić wszystkie wystąpienia ciągu „<<YOUR_PROJECT_ID>>” swoją wartością.

  • Otwórz Firestore Studio
  • Sprawdź, czy masz utworzoną kolekcję o nazwie „poses”.
  • Dodaj ręcznie dokumenty z pliku repozytorium wspomnianego powyżej, po jednym na raz.

Możesz też zaimportować dane jednorazowo z wstępnie zdefiniowanego zestawu, który został utworzony dla Ciebie. Aby to zrobić, wykonaj te czynności:

  1. Otwórz terminal Cloud Shell i sprawdź, czy aktywny projekt w chmurze Google Cloud jest ustawiony i czy masz uprawnienia. Utwórz zasobnik w projekcie za pomocą podanego poniżej polecenia gsutil. W poniższym poleceniu zastąp zmienną <PROJECT_ID> identyfikatorem projektu Google Cloud:

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

  1. Po utworzeniu zasobnika musimy skopiować do niego przygotowany eksport bazy danych, zanim będziemy mogli go zaimportować do bazy danych Firebase. Użyj polecenia podanego poniżej:

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

Teraz, gdy mamy dane do zaimportowania, możemy przejść do ostatniego kroku, czyli zaimportowania danych do utworzonej przez nas bazy danych Firebase (domyślnej).

  1. Otwórz teraz konsolę Firestore i w menu nawigacyjnym po lewej stronie kliknij Import/eksport.

Kliknij Importuj i wybierz utworzoną ścieżkę Cloud Storage. Przejdź do pliku „yoga_poses.overall_export_metadata”:

f5c1d16df7d5a64a.png

  1. Kliknij Importuj.

Importowanie potrwa kilka sekund. Po zakończeniu możesz sprawdzić bazę danych Firestore i kolekcję, otwierając stronę https://console.cloud.google.com/firestore/databases, wybierając bazę danych default i kolekcję poses, jak pokazano poniżej:

  1. Inną metodą jest ręczne utworzenie rekordów w aplikacji po wdrożeniu za pomocą działania „Utwórz nową pozę”.

6. Wyszukiwanie wektorowe

Włącz rozszerzenie wyszukiwania wektorowego Firestore

Użyj tego rozszerzenia, aby automatycznie osadzać dokumenty Firestore i wykonywać na nich zapytania za pomocą nowej funkcji wyszukiwania wektorowego. Nastąpi przekierowanie do centrum rozszerzeń w Firebase.

Podczas instalowania rozszerzenia Wyszukiwanie wektorowe określasz kolekcję i nazwę pola dokumentu. Dodanie lub zaktualizowanie dokumentu z tym polem powoduje, że to rozszerzenie oblicza wektor dystrybucyjny dokumentu. Ten wektor dystrybucyjny jest zapisywany z powrotem w tym samym dokumencie, a dokument jest indeksowany w magazynie wektorów i gotowy do wysyłania zapytań.

Wykonaj te czynności:

Zainstaluj rozszerzenie:

Zainstaluj rozszerzenie „Wyszukiwanie wektorowe w Firestore” z Rynku rozszerzeń w Firebase, klikając „Zainstaluj w konsoli Firebase”.

WAŻNE:

Gdy po raz pierwszy przejdziesz na tę stronę rozszerzeń, musisz wybrać ten sam projekt, nad którym pracujesz w konsoli Google Cloud, który jest wymieniony w konsoli Firebase.

715426b97c732649.png

Jeśli Twojego projektu nie ma na liście, dodaj go w Firebase (wybierz z listy istniejący projekt Google Cloud).

Skonfiguruj rozszerzenie:

Określ kolekcję („poses”), pole zawierające tekst do osadzenia („posture”) i inne parametry, np. wymiary osadzania.

Jeśli na tym etapie pojawią się interfejsy API, które należy włączyć, na stronie konfiguracji będzie można to zrobić. Postępuj zgodnie z instrukcjami.

Jeśli po włączeniu interfejsów API strona nie odpowiada przez dłuższy czas, odśwież ją. Powinny się na niej pojawić włączone interfejsy API.

5ba59b45710c567b.png

W jednym z kolejnych kroków możesz użyć wybranego przez siebie modelu LLM do wygenerowania wektorów. Wybierz „Vertex AI”.

bb528a04ebb5f976.png

Kolejne ustawienia są związane z kolekcją i polem, które chcesz osadzić:

LLM: Vertex AI

Ścieżka kolekcji: pozy

Domyślny limit zapytań: 3

Miara odległości: kosinusowa

Nazwa pola do wprowadzania danych: stan

Nazwa pola wyjściowego: embedding

Nazwa pola stanu: status

Umieść istniejące dokumenty: tak

Aktualizuj istniejące wektory dystrybucyjne: tak

Lokalizacja Cloud Functions: us-central1

Włącz zdarzenia: niezaznaczone

fb8cdf1163fac7cb.png

Gdy wszystko będzie gotowe, kliknij przycisk Zainstaluj rozszerzenie. Potrwa to 3–5 minut.

Generowanie wektorów dystrybucyjnych:

Gdy dodasz lub zaktualizujesz dokumenty w kolekcji „poses”, rozszerzenie automatycznie wygeneruje osadzanie za pomocą wstępnie wytrenowanego modelu lub wybranego przez Ciebie modelu za pomocą punktu końcowego interfejsu API. W tym przypadku w konfiguracji rozszerzenia wybraliśmy Vertex AI.

Tworzenie indeksu

Wymaga to utworzenia indeksu w polu osadzania w momencie użycia osadzania w aplikacji.

Firestore automatycznie tworzy indeksy dla zapytań podstawowych. Możesz jednak pozwolić Firestore generować składnię indeksu, uruchamiając zapytania, które nie mają indeksu. W komunikacie o błędzie po stronie aplikacji znajdziesz link do wygenerowanego indeksu. Aby utworzyć indeks wektorowy:

  1. Otwórz terminal Cloud Shell
  2. Uruchom to polecenie:
gcloud firestore indexes composite create --collection-group="poses" --query-scope=COLLECTION --database="(default)" --field-config vector-config='{"dimension":"768", "flat": "{}"}',field-path="embedding"

Więcej informacji na ten temat znajdziesz tutaj.

Po utworzeniu indeksu wektorowego możesz przeprowadzić wyszukiwanie najbliższych sąsiadów za pomocą wektorów dystrybucyjnych.

Ważna uwaga:

Od tego momentu nie musisz wprowadzać żadnych zmian w źródle. Po prostu śledź instrukcje, aby zrozumieć, co robi aplikacja.

Przyjrzyjmy się, jak nowo utworzona aplikacja korzysta z wyszukiwania wektorowego. Po zapisaniu wektorów dystrybucyjnych możesz użyć klasy VectorQuery z pakietu SDK Firestore Java, aby przeprowadzić wyszukiwanie wektorowe i uzyskać wyniki najbliższych sąsiadów:

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

Ten fragment kodu porównuje wektor dystrybucyjny tekstu wyszukiwanego przez użytkownika z wektorami dystrybucyjnymi dokumentów w Firestore i wyodrębnia ten, który jest najbliższy kontekstowo.

7. Gemini 2.0 Flash

Integracja Gemini 2.0 Flash (do generowania opisów)

Przyjrzyjmy się, jak nowo utworzona aplikacja obsługuje integrację z modelem Gemini 2.0 Flash w celu generowania opisów.

Załóżmy, że administrator lub instruktor jogi chce wprowadzić szczegóły pozycji za pomocą Gemini 2.0 Flash, a następnie wyszukać najbliższe dopasowania. W efekcie wyodrębniane są szczegóły pasujących póz wraz z obiektami multimodalnymi, które potwierdzają wyniki.

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. Mimicking Image and Audio Generation

Gemini 2.0 Flash Experimental potrafi generować wyniki multimodalne, ale nie mam jeszcze dostępu do tej wersji, więc wygenerowane obrazy i dźwięk są wynikiem działania interfejsów Imagen API i TTS API. Wyobraź sobie, jak wspaniale byłoby wygenerować to wszystko za pomocą jednego wywołania interfejsu 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";
        }
}

b. Powiązanie ze źródłem informacji przy użyciu wyszukiwarki Google:

Jeśli w kroku 6 sprawdzisz kod wywołania Gemini, zauważysz ten fragment kodu, który umożliwia oparcie na faktach odpowiedzi LLM przy użyciu wyszukiwarki Google:

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

Dzięki temu:

  • Opieranie modelu na rzeczywistych wynikach wyszukiwania
  • wyodrębniać odpowiednie adresy URL, do których odwołuje się wyszukiwanie;

8. Uruchamianie aplikacji

Przyjrzyjmy się wszystkim możliwościom nowo utworzonej aplikacji Spring Boot w Javie z prostym interfejsem internetowym Thymeleaf:

  1. Operacje CRUD w Firestore (tworzenie, odczytywanie, aktualizowanie, usuwanie)
  2. Wyszukiwanie słów kluczowych
  3. Tworzenie kontekstu na podstawie generatywnej AI
  4. Wyszukiwanie kontekstowe (wyszukiwanie wektorowe)
  5. Wyniki multimodalne powiązane z wyszukiwaniem
  6. Uruchamianie własnego zapytania (zapytania w formacie structuredQuery)

Przykład: {"structuredQuery":{"select":{"fields":[{"fieldPath":"name"}]},"from":[{"collectionId":"fitness_poses"}]}}

Wszystkie omówione do tej pory funkcje są częścią aplikacji, którą właśnie utworzyliśmy z repozytorium: https://github.com/AbiramiSukumaran/firestore-poserecommender

Aby skompilować, uruchomić i wdrożyć aplikację, uruchom w terminalu Cloud Shell te polecenia:

mvn package

mvn spring-boot:run

Powinien pojawić się wynik, a Ty będziesz mieć możliwość wypróbowania funkcji aplikacji. Obejrzyj poniższy film, aby zobaczyć prezentację wyników:

Aplikacja do rekomendowania pozycji z Firestore, wyszukiwaniem wektorowym i Gemini 2.0 Flash

Krok opcjonalny:

Aby wdrożyć ją w Cloud Run (zakładając, że masz nową aplikację z Dockerfile i skopiowane pliki), uruchom to polecenie w terminalu Cloud Shell w katalogu projektu:

gcloud run deploy --source .

Podaj nazwę aplikacji, kod regionu (wybierz kod dla us-central1) i wybierz wywołanie bez uwierzytelniania „Y” zgodnie z instrukcjami. Po pomyślnym wdrożeniu w terminalu powinien pojawić się punkt końcowy aplikacji.

9. Czyszczenie danych

Aby uniknąć obciążenia konta Google Cloud opłatami za zasoby użyte w tym poście, wykonaj te czynności:

  1. W konsoli Google Cloud otwórz stronę Zarządzanie zasobami.
  2. Z listy projektów wybierz projekt do usunięcia, a potem kliknij Usuń.
  3. W oknie wpisz identyfikator projektu i kliknij Wyłącz, aby usunąć projekt.

10. Gratulacje

Gratulacje! Udało Ci się utworzyć za pomocą Firestore niezawodną i inteligentną aplikację do zarządzania pozycjami jogi. Łącząc możliwości Firestore, rozszerzenia wyszukiwania wektorowego i Gemini 2.0 Flash (z symulowanym generowaniem obrazów i dźwięku), stworzyliśmy niezwykle angażującą i informacyjną aplikację do jogi, która umożliwia wykonywanie operacji CRUD, wyszukiwanie na podstawie słów kluczowych, kontekstowe wyszukiwanie wektorowe i generowanie treści multimedialnych.

To podejście nie ogranicza się do aplikacji do jogi. W miarę rozwoju modeli AI, takich jak Gemini, możliwości tworzenia jeszcze bardziej wciągających i spersonalizowanych wrażeń użytkownika będą się tylko zwiększać. Pamiętaj, aby być na bieżąco z najnowszymi informacjami i dokumentacją Google Cloud i Firebase, aby w pełni wykorzystać potencjał tych technologii.

Jeśli chciałbym rozbudować tę aplikację, spróbowałbym zrobić 2 rzeczy za pomocą Gemini 2.0 Flash:

  1. Wykorzystaj interfejs Multimodal Live API, tworząc strumieniowanie obrazu i dźwięku w czasie rzeczywistym na potrzeby danego przypadku użycia.
  2. Włącz tryb myślenia, aby generować myśli stojące za odpowiedziami w interakcji z danymi w czasie rzeczywistym, co sprawi, że doświadczenie będzie bardziej realistyczne.

Wypróbuj go i wyślij żądanie pull :>D!!!