1. Einführung
Modelle für generative KI sind bemerkenswert darin, natürliche Sprache zu verstehen und darauf zu reagieren. Aber was ist, wenn Sie präzise, vorhersehbare Ausgaben für wichtige Aufgaben wie die Standardisierung benötigen? Herkömmliche generative Modelle liefern manchmal zu unterschiedlichen Zeiten unterschiedliche Antworten für dieselben Prompts, was zu Inkonsistenzen führen kann. Hier kommt die Funktion „Funktionsaufruf“ von Gemini ins Spiel, mit der Sie Elemente der KI-Antwort deterministisch steuern können.
Dieses Codelab veranschaulicht dieses Konzept anhand des Anwendungsfalls zur Adressvervollständigung und Standardisierung. Dazu erstellen wir eine Cloud Functions-Funktion für Java, die die folgenden Aufgaben erledigt:
- Übernimmt Breiten- und Längengrade
- Ruft die Google Maps Geocoding API auf, um die entsprechenden Adressen abzurufen
- Verwendet die Funktion „Funktionsaufruf“ von Gemini 1.0 Pro, um diese Adressen deterministisch zu standardisieren und in einem bestimmten Format zusammenzufassen
Legen wir los!
2. Gemini-Funktionsaufrufe
Die Funktion „Funktionsaufrufe von Gemini“ hebt sich von der generativen KI ab, weil Sie damit die Flexibilität von generativen Sprachmodellen mit der Präzision herkömmlicher Programmierung verbinden können.
Hier sind die Aufgaben, die Sie ausführen müssen, um Gemini-Funktionsaufrufe zu implementieren:
- Funktionen definieren: Beschreiben Sie die Funktionen klar. Die Beschreibungen müssen die folgenden Informationen enthalten:
- Der Name der Funktion, z. B.
getAddress
. - Die Parameter, die die Funktion erwartet, z. B.
latlng
als String. - Der von der Funktion zurückgegebene Datentyp, z. B. eine Liste von Adressstrings.
- Tools für Gemini erstellen: Sie können Funktionsbeschreibungen in Form einer API-Spezifikation in Tools verpacken. Stellen Sie sich ein Tool als spezielle Toolbox vor, mit der Gemini die Funktionalität der API verstehen kann.
- APIs mit Gemini orchestrieren: Wenn Sie einen Prompt an Gemini senden, kann Gemini Ihre Anfrage analysieren und erkennen, wo die von Ihnen bereitgestellten Tools eingesetzt werden können. Gemini fungiert dann als intelligenter Orchestrator mit den folgenden Aufgaben:
- Erzeugt die erforderlichen API-Parameter zum Aufrufen der definierten Funktionen. Gemini ruft die API nicht in Ihrem Namen auf. Sie müssen die API basierend auf den Parametern und der Signatur aufrufen, die der Gemini-Funktionsaufruf für Sie generiert hat.
- Gemini verarbeitet die Ergebnisse, indem es die Ergebnisse aus Ihren API-Aufrufen in die Generierung einfließt und strukturierte Informationen in die endgültige Antwort einbindet. Sie können diese Informationen in der von Ihnen gewünschten Weise für Ihre Anwendung verarbeiten.
Die folgende Abbildung zeigt den Datenfluss, die Schritte der Implementierung und den Inhaber für jeden Schritt (z. B. Anwendung, LLM oder API):
Inhalt
Sie erstellen und stellen eine Cloud Functions-Funktion für Java bereit, die Folgendes ausführt:
- Übernimmt Breiten- und Längengrade.
- Ruft die Google Maps Geocoding API auf, um die entsprechenden Adressen abzurufen.
- Verwendet die Funktionsaufruffunktion von Gemini 1.0 Pro, um diese Adressen deterministisch zu standardisieren und in einem bestimmten Format zusammenzufassen.
3. Voraussetzungen
4. Hinweis
- Wählen Sie in der Google Cloud Console auf der Seite für die Projektauswahl ein Google Cloud-Projekt aus oder erstellen Sie eines.
- Die Abrechnung für Ihr Google Cloud-Projekt muss aktiviert sein. Hier erfahren Sie, wie Sie prüfen, ob die Abrechnung für ein Projekt aktiviert ist.
- Aktivieren Sie Cloud Shell über die Google Cloud Console. Weitere Informationen finden Sie unter Cloud Shell verwenden.
- Wenn Ihr Projekt nicht festgelegt ist, verwenden Sie den folgenden Befehl, um es einzurichten:
gcloud config set project <YOUR_PROJECT_ID>
- Legen Sie in Cloud Shell die folgenden Umgebungsvariablen fest:
export GCP_PROJECT=<YOUR_PROJECT_ID>
export GCP_REGION=us-central1
- Aktivieren Sie die erforderlichen Google Cloud APIs, indem Sie die folgenden Befehle in Cloud Shell ausführen:
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
- Öffnen Sie den Cloud Shell-Editor, klicken Sie auf Erweiterungen und installieren Sie dann die Erweiterung Gemini + Google Cloud Code.
5. Cloud Functions-Funktion implementieren
- Cloud Shell-Editor starten
- Klicken Sie auf Cloud Code und maximieren Sie dann den Abschnitt Cloud Functions.
- Klicken Sie auf das Symbol Funktion erstellen (+).
- Wählen Sie im Dialogfeld Neue Anwendung erstellen die Option Java: Hello World aus.
- Geben Sie im Projektpfad einen Namen für das Projekt an, z. B. GeminiFunctionCalling.
- Klicken Sie auf Explorer, um die Projektstruktur aufzurufen, und öffnen Sie dann die Datei pom.xml. Die folgende Abbildung zeigt die Projektstruktur:
- Fügen Sie die erforderlichen Abhängigkeiten in das
<dependencies>... </dependencies>
-Tag in der Dateipom.xml
ein. Sie können über das GitHub-Repository dieses Projekts auf das gesamtepom.xml
zugreifen. Kopieren Sie die Datei „pom.xml“ von dort in die Dateipom.xml
Ihres aktuellen Projekts, die Sie gerade bearbeiten. - Kopieren Sie die Klasse
HelloWorld.java
aus dem GitHub-Link zu GeminiFunctionCalling. Sie müssenAPI_KEY
undproject_id
jeweils mit Ihrem Geocoding API-Schlüssel bzw. der Google Cloud-Projekt-ID aktualisieren.
6. Funktionsaufrufe mithilfe der HelloWorld.java-Klasse verstehen
Prompt-Eingabe
In diesem Beispiel sieht der Eingabe-Prompt so aus: What's the address for the latlong value 40.714224,-73.961452.
Das folgende Code-Snippet entspricht dem Eingabe-Prompt in der Datei:
String promptText = "What's the address for the latlong value '" + latlngString + "'?"; //40.714224,-73.961452
API-Spezifikation
In diesem Beispiel wird die Reverse Geocoding API verwendet. Das ist die API-Spezifikation:
/* 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();
Prompt mit Gemini orchestrieren
Die Prompt-Eingabe und die API-Spezifikation werden an Gemini gesendet:
// 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();
Die Antwort daraus ist die orchestrierten JSON-Parameter für die API. Hier ist eine Beispielausgabe:
role: "model"
parts {
function_call {
name: "getAddress"
args {
fields {
key: "latlng"
value {
string_value: "40.714224,-73.961452"
}
}
}
}
}
Übergeben Sie den folgenden Parameter an die Reverse Geocoding
API: "latlng=40.714224,-73.961452"
Ordnen Sie das Orchestrierte Ergebnis dem Format "latlng=VALUE"
zu.
API aufrufen
Das ist der Codeabschnitt, der die API aufruft:
// 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();
Der String jsonResult
enthält die Antwort der umgekehrten Geocoding API. Im Folgenden sehen Sie eine formatierte Version der Ausgabe:
"...277 Bedford Ave, Brooklyn, NY 11211, USA; 279 Bedford Ave, Brooklyn, NY 11211, USA; 277 Bedford Ave, Brooklyn, NY 11211, USA;..."
API-Antwort verarbeiten und Prompt vorbereiten
Der folgende Code verarbeitet die Antwort der API und bereitet die Aufforderung mit Anweisungen zur Verarbeitung der Antwort vor:
// 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()
);
Gemini aufrufen und die standardisierte Adresse zurückgeben
Der folgende Code übergibt die verarbeitete Ausgabe des vorherigen Schritts als Prompt an 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);
Die Variable finalAnswer
hat die standardisierte Adresse im JSON-Format. Hier sehen Sie eine Beispielausgabe:
{"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}"]}
Nachdem Sie nun wissen, wie Gemini-Funktionsaufrufe mit Adressenstandardisierung funktionieren, können Sie die Cloud Functions-Funktion bereitstellen.
7. Bereitstellen und testen
- Wenn Sie das Projekt GeminiFunctionCalling bereits erstellt und die Cloud Functions-Funktion implementiert haben, fahren Sie mit Schritt 2 fort. Wenn Sie das Projekt noch nicht erstellt haben, rufen Sie das Cloud Shell-Terminal auf und klonen Sie dieses Repository:
git clone
https://github.com/AbiramiSukumaran/GeminiFunctionCalling - Rufen Sie den Projektordner auf:
cd GeminiFunctionCalling
- Führen Sie die folgende Anweisung aus, um die Cloud Functions-Funktion zu erstellen und bereitzustellen:
gcloud functions deploy gemini-fn-calling --gen2 --region=us-central1 --runtime=java11 --source=. --entry-point=cloudcode.helloworld.HelloWorld --trigger-http
Nach der Bereitstellung sieht das URL-Format so aus: https://us-central1-YOUR_PROJECT_ID.cloudfunctions.net/gemini-fn-calling
- Testen Sie die Cloud Functions-Funktion, indem Sie den folgenden Befehl im Terminal ausführen:
gcloud functions call gemini-fn-calling --region=us-central1 --gen2 --data '{"calls":[["40.714224,-73.961452"]]}'
Das ist eine Antwort für einen zufälligen Stichproben-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. Bereinigen
So vermeiden Sie, dass Ihrem Google Cloud-Konto die in diesem Beitrag verwendeten Ressourcen in Rechnung gestellt werden:
- Rufen Sie in der Google Cloud Console die Seite Ressourcen verwalten auf.
- Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie auf „Löschen“.
- Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf „Beenden“, um das Projekt zu löschen.
- Wenn Sie Ihr Projekt behalten möchten, überspringen Sie die obigen Schritte und löschen Sie die Cloud Functions-Funktion. Rufen Sie dazu Cloud Functions auf. Wählen Sie in der Liste der Funktionen die Funktion aus, die Sie löschen möchten, und klicken Sie auf LÖSCHEN.
9. Glückwunsch
Glückwunsch! Sie haben die Gemini-Funktion zum Aufrufen von Funktionen in einer Java-Anwendung erfolgreich verwendet und eine Aufgabe basierend auf generativer KI in einen deterministischen, zuverlässigen Prozess umgewandelt. Weitere Informationen zu verfügbaren Modellen finden Sie in der Produktdokumentation zu Vertex AI LLM.