Das AI Edge Function Calling SDK (FC SDK) ist eine Bibliothek, mit der Entwickler Funktionsaufrufe mit On-Device-LLMs verwenden können. Mit Funktionsaufrufen können Sie Modelle mit externen Tools und APIs verbinden, sodass Modelle bestimmte Funktionen mit den erforderlichen Parametern aufrufen können, um reale Aktionen auszuführen.
Anstatt nur Text zu generieren, kann ein LLM mit dem FC SDK einen strukturierten Aufruf einer Funktion generieren, die eine Aktion ausführt, z. B. die Suche nach aktuellen Informationen, das Stellen von Weckern oder das Reservieren von Tickets.
In diesem Leitfaden erfahren Sie, wie Sie einer Android-Anwendung die LLM Inference API mit dem FC SDK hinzufügen. In diesem Leitfaden geht es vorrangig darum, einem On-Device-LLM Funktionen zum Aufrufen von Funktionen hinzuzufügen. Weitere Informationen zur Verwendung der LLM Inference API finden Sie im Leitfaden für LLM-Inferenzen für Android.
Kurzanleitung
So verwenden Sie das FC SDK in Ihrer Android-Anwendung: In diesem Quickstart wird die LLM Inference API mit Hammer 2.1 (1,5 Mrd.) verwendet. Die LLM Inference API ist für High-End-Android-Geräte wie Google Pixel 8 und Samsung S23 oder höher optimiert und unterstützt Geräteemulatoren nicht zuverlässig.
Abhängigkeiten hinzufügen
Das FC SDK verwendet die Bibliothek com.google.ai.edge.localagents:localagents-fc
und die LLM Inference API die Bibliothek com.google.mediapipe:tasks-genai
. Fügen Sie der build.gradle
-Datei Ihrer Android-App beide Abhängigkeiten hinzu:
dependencies {
implementation 'com.google.mediapipe:tasks-genai:0.10.23'
implementation 'com.google.ai.edge.localagents:localagents-fc:0.1.0'
}
Fügen Sie für Geräte mit Android 12 (API 31) oder höher die Abhängigkeit von der nativen OpenCL-Bibliothek hinzu. Weitere Informationen finden Sie in der Dokumentation zum Tag uses-native-library
.
Fügen Sie der Datei AndroidManifest.xml
die folgenden uses-native-library
-Tags hinzu:
<uses-native-library android:name="libOpenCL.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-car.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-pixel.so" android:required="false"/>
Modell herunterladen
Laden Sie Gemma-3 1B in einem 4‑Bit-Quantisierungsformat von Hugging Face herunter. Weitere Informationen zu den verfügbaren Modellen finden Sie in der Modelldokumentation.
Übertragen Sie den Inhalt des Ordners gemma3-1b-it-int4.task
auf das Android-Gerät.
$ adb shell rm -r /data/local/tmp/llm/ # Remove any previously loaded models
$ adb shell mkdir -p /data/local/tmp/llm/
$ adb push gemma3-1b-it-int4.task /data/local/tmp/llm/gemma3-1b-it-int4.task
Funktionsdefinitionen deklarieren
Definieren Sie die Funktionen, die dem Modell zur Verfügung gestellt werden. Zur Veranschaulichung des Vorgangs enthält diese Kurzanleitung zwei Funktionen als statische Methoden, die hartcodierte Antworten zurückgeben. Eine praktischere Implementierung würde Funktionen definieren, die eine REST API aufrufen oder Informationen aus einer Datenbank abrufen.
Hier werden die Funktionen getWeather
und getTime
definiert:
class ToolsForLlm {
public static String getWeather(String location) {
return "Cloudy, 56°F";
}
public static String getTime(String timezone) {
return "7:00 PM " + timezone;
}
private ToolsForLlm() {}
}
Verwenden Sie FunctionDeclaration
, um jede Funktion zu beschreiben, ihr einen Namen und eine Beschreibung zu geben und die Typen anzugeben. So wird dem Modell mitgeteilt, was die Funktionen tun und wann Funktionsaufrufe erfolgen sollen.
var getWeather = FunctionDeclaration.newBuilder()
.setName("getWeather")
.setDescription("Returns the weather conditions at a location.")
.setParameters(
Schema.newBuilder()
.setType(Type.OBJECT)
.putProperties(
"location",
Schema.newBuilder()
.setType(Type.STRING)
.setDescription("The location for the weather report.")
.build())
.build())
.build();
var getTime = FunctionDeclaration.newBuilder()
.setName("getTime")
.setDescription("Returns the current time in the given timezone.")
.setParameters(
Schema.newBuilder()
.setType(Type.OBJECT)
.putProperties(
"timezone",
Schema.newBuilder()
.setType(Type.STRING)
.setDescription("The timezone to get the time from.")
.build())
.build())
.build();
Fügen Sie die Funktionsdeklarationen einem Tool
-Objekt hinzu:
var tool = Tool.newBuilder()
.addFunctionDeclarations(getWeather)
.addFunctionDeclarations(getTime)
.build();
Inferenz-Backend erstellen
Erstellen Sie ein Inferenz-Backend mit der LLM Inference API und übergeben Sie ihm ein Formatierungsobjekt für Ihr Modell. Der FC SDK-Formatierer (ModelFormatter
) dient sowohl als Formatierer als auch als Parser. Da in dieser Kurzanleitung Gemma-3 1B verwendet wird, verwenden wir GemmaFormatter
:
var llmInferenceOptions = LlmInferenceOptions.builder()
.setModelPath(modelFile.getAbsolutePath())
.build();
var llmInference = LlmInference.createFromOptions(context, llmInferenceOptions);
var llmInferenceBackend = new llmInferenceBackend(llmInference, new GemmaFormatter());
Weitere Informationen finden Sie unter Konfigurationsoptionen für LLM-Inferenz.
Modell instanziieren
Verwenden Sie das GenerativeModel
-Objekt, um das Inferenz-Backend, den Systemprompt und die Tools zu verbinden. Wir haben bereits das Inferenz-Backend und die Tools, sodass wir nur noch den Systemvorschlag erstellen müssen:
var systemInstruction = Content.newBuilder()
.setRole("system")
.addParts(Part.newBuilder().setText("You are a helpful assistant."))
.build();
Instanziere das Modell mit GenerativeModel
:
var generativeModel = new GenerativeModel(
llmInferenceBackend,
systemInstruction,
List.of(tool),
)
Chatsitzung starten
Der Einfachheit halber wird in dieser Kurzanleitung eine einzelne Chatsitzung gestartet. Sie können auch mehrere unabhängige Sitzungen erstellen.
Starten Sie mit der neuen Instanz von GenerativeModel
eine Chatsitzung:
var chat = generativeModel.startChat();
Senden Sie über die Chatsitzung Prompts an das Modell, indem Sie die Methode sendMessage
verwenden:
var response = chat.sendMessage("How's the weather in San Francisco?");
Modellantwort analysieren
Nachdem ein Prompt an das Modell übergeben wurde, muss die Anwendung die Antwort prüfen, um zu bestimmen, ob ein Funktionsaufruf ausgeführt oder Text in natürlicher Sprache ausgegeben werden soll.
// Extract the model's message from the response.
var message = response.getCandidates(0).getContent().getParts(0);
// If the message contains a function call, execute the function.
if (message.hasFunctionCall()) {
var functionCall = message.getFunctionCall();
var args = functionCall.getArgs().getFieldsMap();
var result = null;
// Call the appropriate function.
switch (functionCall.getName()) {
case "getWeather":
result = ToolsForLlm.getWeather(args.get("location").getStringValue());
break;
case "getTime":
result = ToolsForLlm.getWeather(args.get("timezone").getStringValue());
break;
default:
throw new Exception("Function does not exist:" + functionCall.getName());
}
// Return the result of the function call to the model.
var functionResponse =
FunctionResponse.newBuilder()
.setName(functionCall.getName())
.setResponse(
Struct.newBuilder()
.putFields("result", Value.newBuilder().setStringValue(result).build()))
.build();
var response = chat.sendMessage(functionResponse);
} else if (message.hasText()) {
Log.i(message.getText());
}
Der Beispielcode ist eine stark vereinfachte Implementierung. Weitere Informationen dazu, wie eine Anwendung Modellantworten prüfen kann, finden Sie unter Formatierung und Parsen.
Funktionsweise
In diesem Abschnitt finden Sie ausführlichere Informationen zu den wichtigsten Konzepten und Komponenten des Function Calling SDK for Android.
Modelle
Für das Function Calling SDK ist ein Modell mit einem Formatierer und Parser erforderlich. Das FC SDK enthält einen integrierten Formatierer und Parser für die folgenden Modelle:
- Gemma: Verwenden Sie die
GemmaFormatter
. - Lama: Verwenden Sie das
LlamaFormatter
. - Hammer: Verwenden Sie das
HammerFormatter
.
Wenn Sie ein anderes Modell mit dem FC SDK verwenden möchten, müssen Sie einen eigenen Formatierer und Parser entwickeln, der mit der LLM Inference API kompatibel ist.
Formatierung und Parsen
Ein wichtiger Teil der Unterstützung von Funktionsaufrufen ist die Formatierung von Prompts und das Parsen der Modellausgabe. Das sind zwar zwei separate Prozesse, das FC SDK übernimmt jedoch sowohl das Formatieren als auch das Parsen mit der ModelFormatter
-Oberfläche.
Der Formatierer ist dafür verantwortlich, die strukturierten Funktionsdeklarationen in Text umzuwandeln, Funktionsantworten zu formatieren und Tokens einzufügen, um den Beginn und das Ende von Unterhaltungsrunden sowie die Rollen dieser Runden anzugeben (z.B. „Nutzer“, „Modell“).
Der Parser ist dafür verantwortlich zu erkennen, ob die Modellantwort einen Funktionsaufruf enthält. Wenn der Parser einen Funktionsaufruf erkennt, wird er in einen strukturierten Datentyp geparst. Andernfalls wird der Text als Antwort in natürlicher Sprache behandelt.
Eingeschränkte Decodierung
Die eingeschränkte Dekodierung ist ein Verfahren, mit dem die Ausgabe von LLMs so gesteuert wird, dass sie einem vordefinierten strukturierten Format entspricht, z. B. JSON-Objekten oder Python-Funktionsaufrufen. Durch die Durchsetzung dieser Einschränkungen formatiert das Modell seine Ausgabe so, dass sie den vordefinierten Funktionen und ihren entsprechenden Parametertypen entspricht.
Wenn Sie die eingeschränkte Dekodierung aktivieren möchten, definieren Sie die Einschränkungen in einem ConstraintOptions
-Objekt und rufen Sie die Methode enableConstraint
einer ChatSession
-Instanz auf.
Wenn diese Einschränkung aktiviert ist, enthält die Antwort nur die Tools, die mit der GenerativeModel
verknüpft sind.
Das folgende Beispiel zeigt, wie die eingeschränkte Dekodierung konfiguriert wird, um die Antwort auf Toolaufrufe zu beschränken. Der Toolaufruf muss mit dem Präfix ```tool_code\n
beginnen und mit dem Suffix \n```
enden.
ConstraintOptions constraintOptions = ConstraintOptions.newBuilder()
.setToolCallOnly( ConstraintOptions.ToolCallOnly.newBuilder()
.setConstraintPrefix("```tool_code\n")
.setConstraintSuffix("\n```"))
.build(); chatSession.enableConstraint(constraintOptions);
Wenn Sie die aktive Einschränkung innerhalb derselben Sitzung deaktivieren möchten, verwenden Sie die Methode disableConstraint
:
chatSession.disableConstraint()