1. Wprowadzenie
Modele generatywnej AI doskonale rozumieją język naturalny i potrafią na niego odpowiadać. A co, jeśli potrzebujesz precyzyjnych, przewidywalnych wyników w przypadku zadań o kluczowym znaczeniu, takich jak standaryzacja adresów? Tradycyjne modele generatywne mogą czasami udzielać różnych odpowiedzi na te same prompty w różnych momentach, co może prowadzić do niespójności. W takich sytuacjach przydaje się funkcja wywoływania funkcji Gemini, która pozwala deterministycznie kontrolować elementy odpowiedzi AI.
To ćwiczenie ilustruje tę koncepcję na przykładzie uzupełniania i standaryzacji adresów. W tym celu utworzymy funkcję Cloud Functions w języku Java, która będzie wykonywać te zadania:
- Pobiera współrzędne szerokości i długości geograficznej.
- Wywołuje interfejs Google Maps Geocoding API, aby uzyskać odpowiednie adresy.
- korzysta z funkcji wywoływania funkcji Gemini 1.0 Pro, aby deterministycznie ujednolicać i podsumowywać te adresy w określonym formacie, którego potrzebujemy;
Zaczynajmy!
2. Wywoływanie funkcji w Gemini
Wywoływanie funkcji Gemini wyróżnia się w erze generatywnej AI, ponieważ umożliwia łączenie elastyczności generatywnych modeli językowych z precyzją tradycyjnego programowania.
Aby zaimplementować wywoływanie funkcji Gemini, musisz wykonać te zadania:
- Zdefiniuj funkcje: opisz funkcje w jasny sposób. Opisy muszą zawierać te informacje:
- Nazwa funkcji, np.
getAddress. - Parametry, których oczekuje funkcja, np.
latlngjako ciąg znaków. - Typ danych zwracanych przez funkcję, np. lista ciągów tekstowych adresów.
- Tworzenie narzędzi dla Gemini: pakuj opisy funkcji w formie specyfikacji interfejsu API w narzędzia. Narzędzie to specjalistyczny zestaw narzędzi, którego Gemini może używać do zrozumienia funkcjonalności interfejsu API.
- Orkiestracja interfejsów API za pomocą Gemini: gdy wysyłasz prompta do Gemini, może on analizować Twoją prośbę i rozpoznawać, gdzie może użyć udostępnionych przez Ciebie narzędzi. Gemini działa wtedy jako inteligentny aranżer, wykonując te zadania:
- Generuje niezbędne parametry interfejsu API do wywoływania zdefiniowanych funkcji. Gemini nie wywołuje interfejsu API w Twoim imieniu. Musisz wywołać interfejs API na podstawie parametrów i sygnatury wygenerowanych przez wywoływanie funkcji Gemini.
- Gemini przetwarza wyniki, przekazując je z powrotem do procesu generowania, i włącza informacje strukturalne do ostatecznej odpowiedzi. Możesz przetwarzać te informacje w dowolny sposób na potrzeby swojej aplikacji.
Obraz poniżej przedstawia przepływ danych, etapy implementacji i właściciela każdego etapu, np. aplikację, LLM lub interfejs API:

Co utworzysz
Utworzysz i wdrożysz funkcję w Cloud Functions w Javie, która będzie wykonywać te czynności:
- Pobiera współrzędne szerokości i długości geograficznej.
- Wywołuje interfejs Google Maps Geocoding API, aby uzyskać odpowiednie adresy.
- Wykorzystuje funkcję wywoływania funkcji Gemini 1.0 Pro, aby deterministycznie ujednolicać i podsumowywać te adresy w określonym formacie.
3. Wymagania
4. Zanim zaczniesz
- W konsoli Google Cloud na stronie selektora projektów wybierz lub utwórz projekt Google Cloud.
- Sprawdź, czy w projekcie Google Cloud włączone są płatności. Dowiedz się, jak sprawdzić, czy w projekcie są włączone płatności.
- Aktywuj Cloud Shell w konsoli Google Cloud. Więcej informacji znajdziesz w artykule Korzystanie z Cloud Shell.
- Jeśli projekt nie jest ustawiony, użyj tego polecenia, aby go ustawić:
gcloud config set project <YOUR_PROJECT_ID>
- W Cloud Shell ustaw te zmienne środowiskowe:
export GCP_PROJECT=<YOUR_PROJECT_ID>
export GCP_REGION=us-central1
- Włącz wymagane interfejsy Cloud APIs, wykonując w Cloud Shell te polecenia:
gcloud services enable cloudbuild.googleapis.com cloudfunctions.googleapis.com run.googleapis.com logging.googleapis.com storage-component.googleapis.com cloudaicompanion.googleapis.com aiplatform.googleapis.com
- Otwórz edytor Cloud Shell, kliknij Rozszerzenia, a następnie zainstaluj rozszerzenie Gemini + Google Cloud Code.
5. Implementowanie funkcji w Cloud Functions
- Uruchom edytor Cloud Shell.
- Kliknij Cloud Code, a następnie rozwiń sekcję Cloud Functions.
- Kliknij ikonę Utwórz funkcję (+).
- W oknie Create New Application (Utwórz nową aplikację) wybierz opcję Java: Hello World.
- Podaj nazwę projektu w ścieżce projektu, np. GeminiFunctionCalling.
- Kliknij Eksplorator, aby wyświetlić strukturę projektu, a następnie otwórz plik pom.xml. Na ilustracji poniżej widać strukturę projektu:

- Dodaj niezbędne zależności w tagu
<dependencies>... </dependencies>w plikupom.xml. Całypom.xmljest dostępny w repozytorium GitHub tego projektu. Skopiuj plik pom.xml i wklej go do edytowanego plikupom.xmlw bieżącym projekcie. - Skopiuj
HelloWorld.javaklasę z repozytorium GeminiFunctionCalling w GitHub. Musisz zastąpić symboleAPI_KEYiproject_idodpowiednio kluczem interfejsu Geocoding API i identyfikatorem projektu Google Cloud.
6. Wywoływanie funkcji na przykładzie klasy HelloWorld.java
Wpisz prompta
W tym przykładzie prompt wejściowy to: What's the address for the latlong value 40.714224,-73.961452 (Jaki jest adres dla wartości współrzędnych geograficznych 40.714224,-73.961452).
Oto fragment kodu odpowiadający promptowi wejściowemu w pliku:
String promptText = "What's the address for the latlong value '" + latlngString + "'?"; //40.714224,-73.961452
Specyfikacja interfejsu API
W tym przykładzie użyto interfejsu Reverse Geocoding API. Specyfikacja interfejsu API:
/* Declare the function for the API to invoke (Geo coding API) */
FunctionDeclaration functionDeclaration =
FunctionDeclaration.newBuilder()
.setName("getAddress")
.setDescription("Get the address for the given latitude and longitude value.")
.setParameters(
Schema.newBuilder()
.setType(Type.OBJECT)
.putProperties(
"latlng",
Schema.newBuilder()
.setType(Type.STRING)
.setDescription("This must be a string of latitude and longitude coordinates separated by comma")
.build())
.addRequired("latlng")
.build())
.build();
Orkiestracja prompta za pomocą Gemini
Dane wejściowe prompta i specyfikacja interfejsu API są wysyłane do Gemini:
// Add the function to a "tool"
Tool tool = Tool.newBuilder()
.addFunctionDeclarations(functionDeclaration)
.build();
// Invoke the Gemini model with the use of the tool to generate the API parameters from the prompt input.
GenerativeModel model = GenerativeModel.newBuilder()
.setModelName(modelName)
.setVertexAi(vertexAI)
.setTools(Arrays.asList(tool))
.build();
GenerateContentResponse response = model.generateContent(promptText);
Content responseJSONCnt = response.getCandidates(0).getContent();
Odpowiedź to parametry w formacie JSON przekazywane do interfejsu API. Oto przykładowe dane wyjściowe:
role: "model"
parts {
function_call {
name: "getAddress"
args {
fields {
key: "latlng"
value {
string_value: "40.714224,-73.961452"
}
}
}
}
}
Przekaż do interfejsu API Reverse Geocoding ten parametr: "latlng=40.714224,-73.961452"
Dopasuj wynik zorkiestrowany do formatu "latlng=VALUE".
Wywoływanie interfejsu API
Oto fragment kodu, który wywołuje interfejs API:
// Create a request
String url = API_STRING + "?key=" + API_KEY + params;
java.net.http.HttpRequest request = java.net.http.HttpRequest.newBuilder()
.uri(URI.create(url))
.GET()
.build();
// Send the request and get the response
java.net.http.HttpResponse<String> httpresponse = client.send(request, java.net.http.HttpResponse.BodyHandlers.ofString());
// Save the response
String jsonResult = httpresponse.body().toString();
Ciąg znaków jsonResult zawiera odpowiedź z interfejsu Reverse Geocoding API. Oto sformatowana wersja danych wyjściowych:
"...277 Bedford Ave, Brooklyn, NY 11211, USA; 279 Bedford Ave, Brooklyn, NY 11211, USA; 277 Bedford Ave, Brooklyn, NY 11211, USA;..."
Przetwarzanie odpowiedzi interfejsu API i przygotowywanie promptu
Poniższy kod przetwarza odpowiedź z interfejsu API i przygotowuje prompt z instrukcjami dotyczącymi przetwarzania odpowiedzi:
// Provide an answer to the model so that it knows what the result
// of a "function call" is.
String promptString =
"You are an AI address standardizer for assisting with standardizing addresses accurately. Your job is to give the accurate address in the standard format as a JSON object containing the fields DOOR_NUMBER, STREET_ADDRESS, AREA, CITY, TOWN, COUNTY, STATE, COUNTRY, ZIPCODE, LANDMARK by leveraging the address string that follows in the end. Remember the response cannot be empty or null. ";
Content content =
ContentMaker.fromMultiModalData(
PartMaker.fromFunctionResponse(
"getAddress",
Collections.singletonMap("address", formattedAddress)));
String contentString = content.toString();
String address = contentString.substring(contentString.indexOf("string_value: \"") + "string_value: \"".length(), contentString.indexOf('"', contentString.indexOf("string_value: \"") + "string_value: \"".length()));
List<SafetySetting> safetySettings = Arrays.asList(
SafetySetting.newBuilder()
.setCategory(HarmCategory.HARM_CATEGORY_HATE_SPEECH)
.setThreshold(SafetySetting.HarmBlockThreshold.BLOCK_ONLY_HIGH)
.build(),
SafetySetting.newBuilder()
.setCategory(HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT)
.setThreshold(SafetySetting.HarmBlockThreshold.BLOCK_ONLY_HIGH)
.build()
);
Wywoływanie Gemini i zwracanie standardowego adresu
Poniższy kod przekazuje przetworzone dane wyjściowe z poprzedniego kroku jako prompt do Gemini:
GenerativeModel modelForFinalResponse = GenerativeModel.newBuilder()
.setModelName(modelName)
.setVertexAi(vertexAI)
.build();
GenerateContentResponse finalResponse = modelForFinalResponse.generateContent(promptString + ": " + address, safetySettings);
System.out.println("promptString + content: " + promptString + ": " + address);
// See what the model replies now
System.out.println("Print response: ");
System.out.println(finalResponse.toString());
String finalAnswer = ResponseHandler.getText(finalResponse);
System.out.println(finalAnswer);
Zmienna finalAnswer zawiera znormalizowany adres w formacie JSON. Oto przykładowe dane wyjściowe:
{"replies":["{ \"DOOR_NUMBER\": null, \"STREET_ADDRESS\": \"277 Bedford Ave\", \"AREA\": \"Brooklyn\", \"CITY\": \"New York\", \"TOWN\": null, \"COUNTY\": null, \"STATE\": \"NY\", \"COUNTRY\": \"USA\", \"ZIPCODE\": \"11211\", \"LANDMARK\": null} null}"]}
Teraz, gdy wiesz już, jak działa wywoływanie funkcji w Gemini w przypadku przypadku użycia standaryzacji adresów, możesz wdrożyć funkcję w Cloud Functions.
7. Wdrażanie i testowanie
- Jeśli projekt GeminiFunctionCalling został już utworzony i wdrożono w nim Cloud Function, przejdź do kroku 2. Jeśli nie masz jeszcze utworzonego projektu, otwórz terminal Cloud Shell i sklonuj to repozytorium:
git clonehttps://github.com/AbiramiSukumaran/GeminiFunctionCalling - Przejdź do folderu projektu:
cd GeminiFunctionCalling - Uruchom następującą instrukcję, aby skompilować i wdrożyć funkcję w Cloud Functions:
gcloud functions deploy gemini-fn-calling --gen2 --region=us-central1 --runtime=java11 --source=. --entry-point=cloudcode.helloworld.HelloWorld --trigger-http
Po wdrożeniu adres URL będzie miał format: https://us-central1-YOUR_PROJECT_ID.cloudfunctions.net/gemini-fn-calling
- Przetestuj funkcję Cloud Function, uruchamiając w terminalu to polecenie:
gcloud functions call gemini-fn-calling --region=us-central1 --gen2 --data '{"calls":[["40.714224,-73.961452"]]}'
Oto odpowiedź na losowy prompt: '{"replies":["{ "DOOR_NUMBER": "277", "STREET_ADDRESS": "Bedford Ave", "AREA": null, "CITY": "Brooklyn", "TOWN": null, "COUNTY": "Kings County", "STATE": "NY", "COUNTRY": "USA", "ZIPCODE": "11211", "LANDMARK": null}}```"]}'
8. Czyszczenie danych
Aby uniknąć obciążenia konta Google Cloud opłatami za zasoby użyte w tym poście, wykonaj te czynności:
- W konsoli Google Cloud otwórz stronę Zarządzanie zasobami.
- Z listy projektów wybierz projekt do usunięcia, a potem kliknij Usuń.
- W oknie wpisz identyfikator projektu i kliknij Wyłącz, aby usunąć projekt.
- Jeśli chcesz zachować projekt, pomiń powyższe kroki i usuń funkcję w chmurze. W tym celu otwórz Cloud Functions, na liście funkcji zaznacz tę, którą chcesz usunąć, i kliknij USUŃ.
9. Gratulacje
Gratulacje! Udało Ci się użyć funkcji wywoływania funkcji Gemini w aplikacji w języku Java i przekształcić zadanie realizowane z wykorzystaniem AI w deterministyczny, niezawodny proces. Więcej informacji o dostępnych modelach znajdziesz w dokumentacji produktu Vertex AI LLM.