API Gemini Live

Para aplicativos que exigem suporte de voz em tempo real e de baixa latência, como chatbots ou interações de agentes, a API Gemini Live oferece uma maneira otimizada de transmitir entrada e saída para um modelo do Gemini. Com o Firebase AI Logic, é possível chamar a API Gemini Live diretamente do seu app Android sem precisar de uma integração de back-end. Neste guia, mostramos como usar a API Gemini Live no seu app Android com a lógica de IA do Firebase.

Primeiros passos

Antes de começar, verifique se o app é destinado ao nível 21 da API ou mais recente.

Se você ainda não fez isso, configure um projeto do Firebase e conecte seu app a ele. Para mais detalhes, consulte a documentação da Lógica de IA do Firebase.

Configurar seu projeto do Android

Adicione a dependência da biblioteca Firebase AI Logic ao arquivo build.gradle.kts ou build.gradle do nível do app. Use a BoM do Firebase para Android para gerenciar as versões da biblioteca.

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")
}

Depois de adicionar a dependência, sincronize seu projeto do Android com o Gradle.

Integrar o Firebase AI Logic e inicializar um modelo generativo

Adicione a permissão RECORD_AUDIO ao arquivo AndroidManifest.xml do seu aplicativo:

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

Inicialize o serviço de back-end da API Gemini Developer e acesse LiveModel. Use um modelo compatível com a API Live, como gemini-2.0-flash-live-preview-04-09. Consulte a documentação do Firebase para ver os modelos disponíveis.

Para especificar uma voz, defina o nome da voz no objeto speechConfig como parte da configuração do modelo. Se você não especificar uma voz, o padrão será Puck.

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
);

Você pode definir um perfil ou uma função para o modelo definindo uma instrução do sistema:

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
);

Você pode especializar ainda mais a conversa com o modelo usando instruções do sistema para fornecer contexto específico ao seu app (por exemplo, histórico de atividade no app do usuário).

Inicializar uma sessão da API Live

Depois de criar a instância LiveModel, chame model.connect() para criar um objeto LiveSession e estabelecer uma conexão persistente com o modelo com streaming de baixa latência. Com o LiveSession, você pode interagir com o modelo iniciando e interrompendo a sessão de voz, além de enviar e receber texto.

Em seguida, chame startAudioConversation() para iniciar a conversa com o modelo:

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);

Além disso, nas suas conversas com o modelo, observe que ele não lida com interrupções. Pretendemos adicionar esse recurso no futuro.

Você também pode usar a API Gemini Live para gerar áudio transmitido de texto e gerar texto de áudio transmitido. A API Live é bidirecional, então você usa a mesma conexão para enviar e receber conteúdo. Com o tempo, você também poderá enviar imagens e uma transmissão de vídeo ao vivo para o modelo.

Chamada de função: conecte a API Gemini Live ao seu app

Para ir além, também é possível permitir que o modelo interaja diretamente com a lógica do seu app usando a chamada de função.

A chamada de função (ou chamada de ferramenta) é um recurso das implementações de IA generativa que permite que o modelo chame funções por iniciativa própria para realizar ações. Se a função tiver uma saída, o modelo a adicionará ao contexto e a usará para gerações subsequentes.

Diagrama que ilustra como a API Gemini Live permite que um comando do usuário
       seja interpretado por um modelo, acionando uma função predefinida com
       argumentos relevantes em um app Android, que recebe uma resposta de
       confirmação do modelo.
Figura 1:diagrama que ilustra como a API Gemini Live permite que um comando do usuário seja interpretado por um modelo, acionando uma função predefinida com argumentos relevantes em um app Android, que então recebe uma resposta de confirmação do modelo.

Para implementar a chamada de função no seu app, comece criando um objeto FunctionDeclaration para cada função que você quer expor ao modelo.

Por exemplo, para expor uma função addList que anexa uma string a uma lista de strings ao Gemini, comece criando uma variável FunctionDeclaration com um nome e uma breve descrição em inglês simples da função e do parâmetro dela:

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()
);

Em seguida, transmita esse FunctionDeclaration como um Tool ao modelo quando você o instanciar:

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
        );

Por fim, implemente uma função de gerenciador para processar a chamada de ferramenta feita pelo modelo e transmita a resposta de volta. Essa função de manipulador fornecida ao LiveSession quando você chama startAudioConversation, usa um parâmetro FunctionCallPart e retorna FunctionResponsePart:

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());

Próximas etapas