Gemini Live API

Für Anwendungen, die Sprachunterstützung in Echtzeit und mit niedriger Latenz erfordern, z. B. Chatbots oder Agent-Interaktionen, bietet die Gemini Live API eine optimierte Möglichkeit, sowohl Eingabe als auch Ausgabe für ein Gemini-Modell zu streamen. Mit Firebase AI Logic können Sie die Gemini Live API direkt über Ihre Android-App aufrufen, ohne dass eine Backend-Integration erforderlich ist. In dieser Anleitung erfahren Sie, wie Sie die Gemini Live API in Ihrer Android-App mit Firebase AI Logic verwenden.

Erste Schritte

Bevor Sie beginnen, muss Ihre App auf API‑Level 21 oder höher ausgerichtet sein.

Falls noch nicht geschehen, richten Sie ein Firebase-Projekt ein und verbinden Sie Ihre App mit Firebase. Weitere Informationen finden Sie in der Firebase AI Logic-Dokumentation.

Android-Projekt einrichten

Fügen Sie die Firebase AI Logic-Bibliotheksabhängigkeit der Datei build.gradle.kts oder build.gradle auf App-Ebene hinzu. Verwenden Sie die Firebase Android BoM, um Bibliotheksversionen zu verwalten.

dependencies {
  // Import the Firebase BoM
  implementation(platform("com.google.firebase:firebase-bom:34.1.0"))
  // Add the dependency for the Firebase AI Logic library
  // When using the BoM, you don't specify versions in Firebase library dependencies
  implementation("com.google.firebase:firebase-ai")
}

Nachdem Sie die Abhängigkeit hinzugefügt haben, synchronisieren Sie Ihr Android-Projekt mit Gradle.

Firebase AI Logic einbinden und ein generatives Modell initialisieren

Fügen Sie die Berechtigung RECORD_AUDIO der Datei AndroidManifest.xml Ihrer Anwendung hinzu:

<uses-permission android:name="android.permission.RECORD_AUDIO" />

Initialisieren Sie den Backend-Dienst der Gemini Developer API und greifen Sie auf LiveModel zu. Verwenden Sie ein Modell, das die Live API unterstützt, z. B. gemini-2.0-flash-live-preview-04-09. Verfügbare Modelle finden Sie in der Firebase-Dokumentation.

Wenn Sie eine Stimme angeben möchten, legen Sie den Stimmennamen im speechConfig-Objekt als Teil der Modellkonfiguration fest. Wenn Sie keine Stimme angeben, wird standardmäßig Puck verwendet.

Kotlin

// Initialize the `LiveModel`
val model = Firebase.ai(backend = GenerativeBackend.googleAI()).liveModel(
       modelName = "gemini-2.0-flash-live-preview-04-09",
       generationConfig = liveGenerationConfig {
          responseModality = ResponseModality.AUDIO
          speechConfig = SpeechConfig(voice= Voice("FENRIR"))
       })

Java

// Initialize the `LiveModel`
LiveGenerativeModel model = FirebaseAI
       .getInstance(GenerativeBackend.googleAI())
       .liveModel(
              "gemini-2.0-flash-live-preview-04-09",
              new LiveGenerationConfig.Builder()
                     .setResponseModality(ResponseModality.AUDIO)
                     .setSpeechConfig(new SpeechConfig(new Voice("FENRIR"))
              ).build(),
        null,
        null
);

Optional können Sie eine Persona oder Rolle definieren, die das Modell spielt, indem Sie eine Systemanweisung festlegen:

Kotlin

val systemInstruction = content {
            text("You are a helpful assistant, you main role is [...]")}

val model = Firebase.ai(backend = GenerativeBackend.googleAI()).liveModel(
       modelName = "gemini-2.0-flash-live-preview-04-09",
       generationConfig = liveGenerationConfig {
          responseModality = ResponseModality.AUDIO
          speechConfig = SpeechConfig(voice= Voice("FENRIR"))
       },
       systemInstruction = systemInstruction,
)

Java

Content systemInstruction = new Content.Builder()
       .addText("You are a helpful assistant, you main role is [...]")
       .build();

LiveGenerativeModel model = FirebaseAI
       .getInstance(GenerativeBackend.googleAI())
       .liveModel(
              "gemini-2.0-flash-live-preview-04-09",
              new LiveGenerationConfig.Builder()
                     .setResponseModality(ResponseModality.AUDIO)
                     .setSpeechConfig(new SpeechConfig(new Voice("FENRIR"))
              ).build(),
        tools, // null if you don't want to use function calling
        systemInstruction
);

Sie können die Unterhaltung mit dem Modell weiter spezialisieren, indem Sie Systemanweisungen verwenden, um Kontext für Ihre App bereitzustellen, z. B. den In-App-Aktivitätsverlauf des Nutzers.

Live API-Sitzung initialisieren

Nachdem Sie die LiveModel-Instanz erstellt haben, rufen Sie model.connect() auf, um ein LiveSession-Objekt zu erstellen und eine dauerhafte Verbindung zum Modell mit Streaming mit geringer Latenz herzustellen. Über LiveSession können Sie mit dem Modell interagieren, indem Sie die Sprachsitzung starten und beenden sowie Text senden und empfangen.

Anschließend können Sie startAudioConversation() aufrufen, um die Unterhaltung mit dem Modell zu starten:

Kotlin

val session = model.connect()
session.startAudioConversation()

Java

LiveModelFutures model = LiveModelFutures.from(liveModel);
ListenableFuture<LiveSession> sessionFuture =  model.connect();

Futures.addCallback(sessionFuture, new FutureCallback<LiveSession>() {
    @Override
    public void onSuccess(LiveSession ses) {
         LiveSessionFutures session = LiveSessionFutures.from(ses);
        session.startAudioConversation();
    }
    @Override
    public void onFailure(Throwable t) {
        // Handle exceptions
    }
}, executor);

Das Modell kann Unterbrechungen nicht verarbeiten. Wir planen, diese Funktion in Zukunft hinzuzufügen.

Sie können die Gemini Live API auch verwenden, um gestreamtes Audio aus Text zu generieren und Text aus gestreamtem Audio zu generieren. Die Live API ist bidirektional. Sie verwenden also dieselbe Verbindung zum Senden und Empfangen von Inhalten. Sie werden auch Bilder und einen Live-Videostream an das Modell senden können.

Funktionsaufrufe: Gemini Live API mit Ihrer App verbinden

Sie können das Modell auch so einrichten, dass es mithilfe von Funktionsaufrufen direkt mit der Logik Ihrer App interagiert.

Funktionsaufrufe (oder Tool-Aufrufe) sind eine Funktion von generativen KI-Implementierungen, mit der das Modell Funktionen auf eigene Initiative aufrufen kann, um Aktionen auszuführen. Wenn die Funktion eine Ausgabe hat, fügt das Modell sie seinem Kontext hinzu und verwendet sie für nachfolgende Generierungen.

Diagramm, das veranschaulicht, wie die Gemini Live API es ermöglicht, dass ein Nutzer-Prompt von einem Modell interpretiert wird, wodurch eine vordefinierte Funktion mit relevanten Argumenten in einer Android-App ausgelöst wird, die dann eine Bestätigungsantwort vom Modell erhält.
Abbildung 1:Diagramm zur Veranschaulichung, wie die Gemini Live API es ermöglicht, dass ein Nutzer-Prompt von einem Modell interpretiert wird, wodurch eine vordefinierte Funktion mit relevanten Argumenten in einer Android-App ausgelöst wird, die dann eine Bestätigungsantwort vom Modell erhält.

Wenn Sie Funktionsaufrufe in Ihrer App implementieren möchten, erstellen Sie zuerst ein FunctionDeclaration-Objekt für jede Funktion, die Sie dem Modell zur Verfügung stellen möchten.

Wenn Sie beispielsweise eine addList-Funktion, die einen String an eine Liste von Strings anhängt, für Gemini verfügbar machen möchten, erstellen Sie zuerst eine FunctionDeclaration-Variable mit einem Namen und einer kurzen Beschreibung der Funktion und ihrer Parameter in einfachem Englisch:

Kotlin

val itemList = mutableListOf<String>()

fun addList(item: String){
   itemList.add(item)
}

val addListFunctionDeclaration = FunctionDeclaration(
        name = "addList",
        description = "Function adding an item the list",
        parameters = mapOf("item" to Schema.string("A short string
            describing the item to add to the list"))
        )

Java

HashMap<String, Schema> addListParams = new HashMap<String, Schema>(1);

addListParams.put("item", Schema.str("A short string describing the item
    to add to the list"));

FunctionDeclaration addListFunctionDeclaration = new FunctionDeclaration(
    "addList",
    "Function adding an item the list",
    addListParams,
    Collections.emptyList()
);

Übergeben Sie dann FunctionDeclaration als Tool an das Modell, wenn Sie es instanziieren:

Kotlin

val addListTool = Tool.functionDeclarations(listOf(addListFunctionDeclaration))

val model = Firebase.ai(backend = GenerativeBackend.googleAI()).liveModel(
       modelName = "gemini-2.0-flash-live-preview-04-09",
       generationConfig = liveGenerationConfig {
          responseModality = ResponseModality.AUDIO
          speechConfig = SpeechConfig(voice= Voice("FENRIR"))
       },
       systemInstruction = systemInstruction,
       tools = listOf(addListTool)
)

Java

LiveGenerativeModel model = FirebaseAI.getInstance(
    GenerativeBackend.googleAI()).liveModel(
        "gemini-2.0-flash-live-preview-04-09",
  new LiveGenerationConfig.Builder()
        .setResponseModalities(ResponseModality.AUDIO)
        .setSpeechConfig(new SpeechConfig(new Voice("FENRIR")))
        .build(),
  List.of(Tool.functionDeclarations(List.of(addListFunctionDeclaration))),
               null,
               systemInstruction
        );

Implementieren Sie schließlich eine Handler-Funktion, um den Tool-Aufruf des Modells zu verarbeiten und die Antwort zurückzugeben. Diese Handler-Funktion, die LiveSession beim Aufrufen von startAudioConversation bereitgestellt wird, verwendet den Parameter FunctionCallPart und gibt FunctionResponsePart zurück:

Kotlin

session.startAudioConversation(::functionCallHandler)

// ...

fun functionCallHandler(functionCall: FunctionCallPart): FunctionResponsePart {
    return when (functionCall.name) {
        "addList" -> {
            // Extract function parameter from functionCallPart
            val itemName = functionCall.args["item"]!!.jsonPrimitive.content
            // Call function with parameter
            addList(itemName)
            // Confirm the function call to the model
            val response = JsonObject(
                mapOf(
                    "success" to JsonPrimitive(true),
                    "message" to JsonPrimitive("Item $itemName added to the todo list")
                )
            )
            FunctionResponsePart(functionCall.name, response)
        }
        else -> {
            val response = JsonObject(
                mapOf(
                    "error" to JsonPrimitive("Unknown function: ${functionCall.name}")
                )
            )
            FunctionResponsePart(functionCall.name, response)
        }
    }
}

Java

Futures.addCallback(sessionFuture, new FutureCallback<LiveSessionFutures>() {

    @RequiresPermission(Manifest.permission.RECORD_AUDIO)
    @Override
    @OptIn(markerClass = PublicPreviewAPI.class)
    public void onSuccess(LiveSessionFutures ses) {
        ses.startAudioConversation(::handleFunctionCallFuture);
    }

    @Override
    public void onFailure(Throwable t) {
        // Handle exceptions
    }
}, executor);

// ...

ListenableFuture<JsonObject> handleFunctionCallFuture = Futures.transform(response, result -> {
    for (FunctionCallPart functionCall : result.getFunctionCalls()) {
        if (functionCall.getName().equals("addList")) {
            Map<String, JsonElement> args = functionCall.getArgs();
            String item =
                    JsonElementKt.getContentOrNull(
                            JsonElementKt.getJsonPrimitive(
                                    locationJsonObject.get("item")));
            return addList(item);
        }
    }
    return null;
}, Executors.newSingleThreadExecutor());

Nächste Schritte