Kreator półki: użyj Gemini, aby utworzyć funkcję w Cloud Functions dla aplikacji Gemini w Javie

1. Wprowadzenie

Czy uwielbiasz czytać książki, ale przytłacza Cię ich ogromna liczba? Wyobraź sobie aplikację z wykorzystaniem AI, która nie tylko poleca idealną książkę, ale też zawiera jej zwięzłe streszczenie na podstawie wybranego przez Ciebie gatunku, dzięki czemu możesz poznać esencję książki. W tym laboratorium programistycznym pokażę Ci, jak utworzyć taką aplikację za pomocą BigQuery i Cloud Functions z użyciem Gemini.

Przegląd projektu

Nasz przypadek użycia koncentruje się na 4 głównych komponentach:

  • Baza książek: ogromny publiczny zbiór książek z archiwum internetowego BigQuery pełni rolę naszego wyczerpującego katalogu książek.
  • Silnik podsumowywania AI: funkcje Google Cloud, korzystające z modelu językowego Gemini-Pro, będą generować trafne podsumowania dostosowane do żądań użytkowników.
  • Integracja z BigQuery: funkcja zdalna w BigQuery, która wywołuje naszą funkcję w Cloud Functions, aby dostarczać na żądanie podsumowania i motywy książek.
  • Interfejs: aplikacja internetowa hostowana w Cloud Run, która oferuje użytkownikom aplikację internetową do wyświetlania wyników.

Ćwiczenia z kodem podzieliliśmy na 3 części:

Ćwiczenie z programowania 1. Wykorzystanie Gemini do utworzenia funkcji w Cloud Functions dla aplikacji Gemini w języku Java.

Ćwiczenie z programowania 2: używanie Gemini do tworzenia aplikacji wykorzystujących generatywną AI tylko w języku SQL za pomocą BigQuery.

Codelab 3: użyj Gemini do utworzenia aplikacji internetowej Java Spring Boot, która będzie współpracować z BigQuery.

2. Korzystanie z Gemini do tworzenia bezserwerowej aplikacji generatywnej AI za pomocą funkcji Cloud Function w języku Java

Co utworzysz

Utwórz

  • Aplikacja Java Cloud Functions, która implementuje Gemini 1.0 Pro, aby przyjmować jako dane wejściowe określony prompt w formie tablicy JSON i zwracać odpowiedź (wartość JSON o nazwie „replies”).
  • Wykonywanie kroków kompilacji i wdrażania za pomocą Gemini

3. Wymagania

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

Oto wymagania wstępne:

Tworzenie projektu

  1. W konsoli Google Cloud na stronie selektora projektu 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.

Aktywowanie Cloud Shell

  1. Użyjesz Cloud Shell, czyli środowiska wiersza poleceń działającego w Google Cloud i zawierającego wstępnie zainstalowane narzędzie bq:

W prawym górnym rogu konsoli Cloud Console kliknij Aktywuj Cloud Shell: 6757b2fb50ddcc2d.png

  1. Po połączeniu z Cloud Shell powinieneś zobaczyć, że jesteś już uwierzytelniony i że projekt jest już ustawiony na identyfikator Twojego projektu. Aby potwierdzić uwierzytelnianie, uruchom w Cloud Shell to polecenie:
gcloud auth list
  1. Aby potwierdzić, że polecenie gcloud zna Twój projekt, uruchom to polecenie w Cloud Shell:
gcloud config list project
  1. Jeśli Twój projekt nie jest skonfigurowany, ustaw go za pomocą tego polecenia:
gcloud config set project <YOUR_PROJECT_ID>

Więcej informacji o poleceniach i sposobie korzystania z gcloud znajdziesz w dokumentacji.

4. Włączam Gemini dla Google Cloud i niezbędnych interfejsów API

Włącz Gemini

  1. Aby włączyć interfejs API, otwórz Gemini for Google Cloud w Marketplace. Możesz też użyć tego polecenia:
gcloud services enable cloudaicompanion.googleapis.com --project PROJECT_ID
  1. Otwórz stronę Gemini i kliknij „Rozpocznij czat”.

Ważne: wykonaj kroki 1 i 2 z tego ćwiczenia z programowania, aby zacząć korzystać z Gemini i włączyć Gemini w Cloud Shell IDE.

Włączanie innych wymaganych interfejsów API

Jak to zrobić? Czy możemy zapytać o to Gemini? Pamiętaj jednak, że:

Modele LLM nie są deterministyczne. Podczas testowania tych promptów możesz otrzymać odpowiedź, która będzie wyglądać inaczej niż na moim zrzucie ekranu.

Otwórz konsolę czatu Gemini, klikając ikonę „Otwórz Gemini” w prawym górnym rogu obok paska wyszukiwania w konsoli Google Cloud.

26e1491322855614.png

Wpisz to pytanie w sekcji „Wpisz prompt tutaj”:

How do I enable the cloud functions api using a gcloud command? 

Powinna pojawić się odpowiedź podobna do:

gcloud services enable cloudfunctions.googleapis.com

Skopiuj to polecenie (możesz użyć ikony kopiowania u góry fragmentu polecenia) i uruchom je w terminalu Cloud Shell, aby włączyć Cloud Functions. Zrób to samo w przypadku Cloud Run, ponieważ potrzebujemy obu usług do kompilowania i wdrażania funkcji w Cloud Functions:

gcloud services enable \
  cloudfunctions.googleapis.com \
  aiplatform.googleapis.com \
  run.googleapis.com \
  cloudbuild.googleapis.com

5. Przygotowywanie szablonu Cloud Functions za pomocą Gemini

Zakładam, że Gemini jest już włączone w środowisku IDE Cloud Shell.

Otwórz edytor Cloud Shell, klikając ikonę Otwórz edytor w prawym górnym rogu terminala Cloud Shell (zwykle wolę otworzyć terminal i edytor jednocześnie w osobnych kartach, aby móc pisać kod w jednej, a w drugiej).

edd258384bc74f1f.png

Po otwarciu edytora sprawdź, czy logo Gemini w prawym dolnym rogu konsoli edytora jest aktywne (czyli nie jest wyszarzone). Sprawdź też, czy Twój projekt Google Cloud w lewym dolnym rogu wskazuje na bieżący aktywny projekt, z którym chcesz pracować. Jeśli są nieaktywne, kliknij je, autoryzuj, wybierz projekt Google Cloud, do którego mają wskazywać, i aktywuj je.

Gdy oba te elementy są aktywne, kliknij nazwę projektu w lewym dolnym rogu. W otwartym oknie „Cloud Code” przewiń w dół do opcji „Nowa aplikacja”.

ca08602b576ebd57.png

Z tej listy wybierz aplikację Cloud Functions. Z listy, która się pojawi, wybierz Java:

ac2b44245949da68.png

Na wyświetlonej liście wpisz zamiast helloworld nazwę projektu „duetai-gemini-calling” i kliknij OK.

bf9cfe86e35cdced.png

Hurra! Udało Ci się uruchomić prostą aplikację Java Cloud Functions w Gemini przy pomocy Gemini. Oprócz włączenia i aktywacji konfiguracji niewiele zostało zadanych. Zgadza się?

Tak powinna wyglądać struktura projektu:

d56e410fb76f183f.png

Możesz teraz wdrożyć funkcję. Nie dlatego jednak zaczęliśmy to robić. Zbudujmy implementację interfejsu Gemini Pro API w tej funkcji Cloud Functions za pomocą pakietu Java SDK.

Teraz skompilujemy funkcję naszego przypadku użycia, która wywołuje model Gemini Pro w tej funkcji w Cloud Functions. Aby to zrobić, możesz dodać więcej promptów i uzyskiwać kod rozwijany stopniowo za pomocą Gemini lub napisać logikę samodzielnie. Zrobię mieszankę obu.

6. Dodaj zależności

W konsoli czatu Gemini (znajduje się ona w lewym panelu edytora Cloud Code) wpisz:

what is the maven dependency for com.google.cloud.vertexai library

Pytam o pakiet com.google.cloud.vertexai, ponieważ właśnie tego używam w kodzie źródłowym, w którym implementuję kod wywołania Gemini.

Mam ten wynik:

62c4295b9b4654e9.png

 <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-vertexai</artifactId>
      <version>0.1.0</version>
    </dependency>

Skopiuj ten kod i wklej go w pliku pom.xml tuż przed tagiem </dependencies>. Zastąp wersję 0.1.0 (jeśli używasz pliku BOM Spring Cloud GCP do zarządzania numerami wersji spring-cloud-gcp, możesz usunąć tag <version>).

Sekcja zależności powinna wyglądać tak:

1800f10af9331210.png

W razie potrzeby zaktualizuj numery wersji, tak aby były zgodne z numerami podanymi powyżej. Jak widać, dodałem też inną zależność:

    <dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
      <version>2.10</version>
    </dependency>

7. Modyfikowanie punktu wejścia funkcji i nazwy klasy

  1. Przejdź do pliku „launch.json” w folderze „.vscode”. Zmień nazwę funkcji z „function-hello-world” na „function-gemini-calling”.
  2. Zaktualizuj wartość entryPoint z „cloudcode.helloworld.HelloWorld” na „cloudcode.bookshelf.Bookshelf”.
  3. Teraz przejdź do pliku klasy Java „HelloWorld.java”. Zmień nazwę pakietu na package cloudcode.bookshelf. Gdy pojawi się komunikat o błędzie, kliknij żółtą żarówkę, a następnie opcję „Przenieś HelloWorld.java” do pakietu cloudcode.bookshelf.

38d721978bddc8a8.png

  1. Zmień nazwę klasy na Bookshelf i w wyświetlonym komunikacie o błędzie kliknij żółtą lampkę i wybierz „Zmień nazwę pliku na Bookshelf.java”. Wybierz tę opcję.

8. Tworzenie metody wywołującej Gemini Pro

Zaimplementujmy tę funkcję w klasie Bookshelf.java. Zastąp plik Bookshelf.java poniższym kodem:

package cloudcode.bookshelf;
import java.io.BufferedWriter;
import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.cloud.vertexai.VertexAI;
import com.google.cloud.vertexai.api.GenerateContentResponse;
import com.google.cloud.vertexai.api.GenerationConfig;
import com.google.cloud.vertexai.generativeai.preview.GenerativeModel;
import com.google.cloud.vertexai.generativeai.preview.ResponseHandler;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import java.util.Map;
import java.util.LinkedHashMap;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;

public class Bookshelf implements HttpFunction {
  private static final Gson gson = new Gson();

 @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    BufferedWriter writer = response.getWriter();

 // Get the request body as a JSON object.
 JsonObject requestJson = new Gson().fromJson(request.getReader(), JsonObject.class);
 JsonArray calls_array = requestJson.getAsJsonArray("calls");
 JsonArray calls = (JsonArray) calls_array.get(0);
 String context = calls.get(0).toString().replace("\"", "");

 //Invoke Gemini model
  String raw_result = callGemini(context);
  raw_result = raw_result.replace("\n","");
  String trimmed = raw_result.trim();
  List<String> result_list = Arrays.asList(trimmed);
  Map<String, List<String>> stringMap = new LinkedHashMap<>();
  stringMap.put("replies", result_list);
 
  // Serialization
  String return_value = gson.toJson(stringMap);
  writer.write(return_value);
    }
  public String callGemini(String context) throws IOException{
      String res = "";
        try (VertexAI vertexAi = new VertexAI("REPLACE_WITH_YOUR_PROJECT_ID", "us-central1"); ) {
          GenerationConfig generationConfig =
              GenerationConfig.newBuilder()
                  .setMaxOutputTokens(2048)
                  .setTemperature(0.4F)
                  .setTopK(32)
                  .setTopP(1)
                  .build();  
        GenerativeModel model = new GenerativeModel("gemini-pro", generationConfig, vertexAi);
        GenerateContentResponse response = model.generateContent(context);
        res = ResponseHandler.getText(response);
      }catch(Exception e){
        System.out.println(e);
        }
        return res;
    }
}

Ta klasa oczekuje danych wejściowych w strukturze JSON o tym kształcie:

{ "calls": [["YOUR_PROMPT_HERE"]] }

Odpowiedź będzie taka:

(JSON) Map<String, List<String>> {"replies": ["response"]}

Aby wyjaśnić kod, użyj opcji czatu Gemini w edytorze Cloud Shell w lewym panelu. Możesz też zaznaczyć cały kod, kliknąć żółtą żarówkę w lewym górnym rogu zaznaczenia i wybrać opcję „Wyjaśnij to”.

66fb67507793e368.png

9. Wdrażanie funkcji w Cloud Functions

Funkcja Cloud Functions jest już gotowa, więc poprośmy Gemini, jak ją wdrożyć. Otwórz czat Gemini w edytorze Cloud Code i wpisz:

   How to deploy this Cloud Function with a gcloud command?

Otrzymaliśmy taką odpowiedź:

9f9db98933841864.png

Teraz chcę to dokładniej sprawdzić. Poprosiłem Gemini o podanie pełnego polecenia wdrażania funkcji gcloud. Odpowiedź wygląda tak:

b77701c00dc3eaf1.png

Teraz nie mogę powiedzieć, czy otrzymasz taką samą odpowiedź, ale zupełnie ciekawe, że zawiera ona dodatkowe szczegóły, takie jak na ilustracji poniżej:

Format treści żądania:

82bf20304143a374.png

i

Format odpowiedzi:

ade55b3de5d823a6.png

Teraz wdróż funkcję, uruchamiając polecenie gcloud podane przez Gemini. W tym celu musimy otworzyć terminal Cloud Shell. Możesz otworzyć go w nowej karcie na stronie https://console.cloud.google.com i sprawdzić, czy wybrano odpowiedni projekt. Otwórz terminal Cloud Shell, klikając ikonę Aktywuj Cloud Shell w prawym górnym rogu konsoli, i sprawdź, czy jesteś w właściwym folderze projektu, wykonując to polecenie:

cd duetai-gemini-calling

A następnie to polecenie:

gcloud functions deploy bookshelf --runtime java17 --trigger-http --entry-point cloudcode.bookshelf.Bookshelf --allow-unauthenticated

Pojawi się pytanie „Zezwolić na nieuwierzytelnione wywołania nowej funkcji [półka na książki]?” Powiedz „y” i naciśnij Enter. W razie potrzeby otrzymasz kilka pytań, a w razie potrzeby wdrożysz bezserwerową funkcję w Cloud Functions przy użyciu wdrożonego adresu URL: https://us-central1-*******.cloudfunctions.net/bookshelf.

Teraz wywołajmy wdrożone funkcje w Cloud Functions i przetestujmy je.

Uwaga: jeśli przypadkowo pominiesz pytanie „Zezwalaj na wywołania bez uwierzytelniania” lub wybierzesz odpowiedź „Nie”, nie będziesz mieć dostępu do wyników funkcji Cloud Functions i bez dodatkowych ustawień uprawnień zobaczysz komunikat „Błąd uprawnień”. Zwróć na to uwagę.

10. Wywołanie wdrożonej funkcji w Cloud Functions

Zapytajmy o to Gemini. Wpisałem prompt

How to call the deployed cloud function?

Oto wynik: (możesz zobaczyć dokładnie taką samą odpowiedź, ale nie musi tak być. Możesz też zmienić prompt i sprawdzić, jak się zmienią odpowiedzi).

1d2242715571fe6f.png

Przeanalizuj czat za pomocą konkretnych pytań dotyczących alternatywnych sposobów wywoływania wdrożonej funkcji, wywołania za pomocą polecenia gcloud itp. Wysłałem/wysłałam ten prompt:

how to call the deployed cloud function using gcloud

Otrzymaliśmy taką odpowiedź: e7b29b2cfb57782c.png

Możesz użyć tej odpowiedzi (polecenia „gcloud features call”) w terminalu, wprowadzając poprawki, aby dostosować ją do naszego scenariusza. Możesz też przekazać parametry w samym prompcie i sprawdzić, czy w odpowiedzi uzyskasz szczegółowe wywołanie funkcji gcloud:

gcloud functions call bookshelf --region=us-central1 --gen2 --data '{"calls":[["Hello! This is my test prompt."]]}'

Oto mój wynik:

6f396d915251db78.png

11. Czyszczenie danych

Utworzone wcześniej funkcje w Cloud Functions możesz usunąć, klikając przycisk USUŃ na stronie z informacjami o funkcjach w Cloud Functions.

12. Gratulacje

Udało Ci się skompilować, wdrożyć i przetestować funkcję Java Cloud Functions, aby wywołać Gemini 1.0 Pro za pomocą Gemini. Aplikacja ta przyjmuje prompt dotyczący rekomendacji książek wraz z ich streszczeniem i tematem.