API Gemini Live

Для приложений, которым требуется поддержка голосового управления в режиме реального времени с малой задержкой, таких как чат-боты или агентское взаимодействие, API Gemini Live предоставляет оптимизированный способ потоковой передачи входных и выходных данных для модели Gemini. Используя Firebase AI Logic, вы можете вызывать API Gemini Live непосредственно из своего приложения Android без необходимости интеграции с бэкендом. В этом руководстве показано, как использовать API Gemini Live в своем приложении Android с Firebase AI Logic.

Начать

Прежде чем начать, убедитесь, что ваше приложение ориентировано на API уровня 21 или выше .

Если вы ещё этого не сделали, настройте проект Firebase и подключите своё приложение к Firebase. Подробнее см. в документации по Firebase AI Logic .

Настройте свой Android-проект

Добавьте зависимость от библиотеки Firebase AI Logic в файл build.gradle.kts или build.gradle на уровне приложения. Используйте Firebase Android BoM для управления версиями библиотеки.

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

После добавления зависимости синхронизируйте свой Android-проект с Gradle.

Интеграция Firebase AI Logic и инициализация генеративной модели

Добавьте разрешение RECORD_AUDIO в файл AndroidManifest.xml вашего приложения:

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

Инициализируйте бэкэнд-службу Gemini Developer API и получите доступ LiveModel . Используйте модель с поддержкой Live API, например gemini-2.0-flash-live-preview-04-09 . Список доступных моделей см. в документации Firebase.

Чтобы указать голос, задайте его название в объекте speechConfig в конфигурации модели . Если голос не указан, по умолчанию используется Puck .

Котлин

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

Ява

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

При желании вы можете определить персону или роль, которую играет модель, установив системную инструкцию:

Котлин

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

Ява

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

Вы можете дополнительно специализировать диалог с моделью, используя системные инструкции для предоставления контекста, специфичного для вашего приложения (например, история действий пользователя в приложении).

Инициализировать сеанс Live API

После создания экземпляра LiveModel вызовите метод model.connect() , чтобы создать объект LiveSession и установить постоянное соединение с моделью с потоковой передачей данных с низкой задержкой. LiveSession позволяет взаимодействовать с моделью, запуская и останавливая голосовой сеанс, а также отправляя и получая текстовые сообщения.

Затем вы можете вызвать startAudioConversation() чтобы начать диалог с моделью:

Котлин

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

Ява

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

Также, общаясь с моделью, обратите внимание, что она не обрабатывает прерывания. Мы планируем добавить эту функцию в будущем.

Вы также можете использовать API Gemini Live для генерации потокового аудио из текста и текста из потокового аудио . Обратите внимание, что API Live является двунаправленным, поэтому для отправки и получения контента используется одно и то же соединение. В конечном итоге вы также сможете отправлять модели изображения и видеопоток в реальном времени.

Вызов функции: подключите API Gemini Live к своему приложению

Чтобы пойти еще дальше, вы также можете разрешить модели напрямую взаимодействовать с логикой вашего приложения с помощью вызова функций.

Вызов функций (или вызов инструментов) — это функция генеративных реализаций искусственного интеллекта, которая позволяет модели вызывать функции по собственной инициативе для выполнения действий. Если функция имеет выход, модель добавляет его в свой контекст и использует для последующих генераций.

Диаграмма, иллюстрирующая, как API Gemini Live позволяет модели интерпретировать запрос пользователя, запуская предопределенную функцию с соответствующими аргументами в приложении Android, которое затем получает подтверждение от модели.
Рисунок 1: Диаграмма, иллюстрирующая, как API Gemini Live позволяет модели интерпретировать запрос пользователя, вызывая предварительно определенную функцию с соответствующими аргументами в приложении Android, которое затем получает ответ с подтверждением от модели.

Чтобы реализовать вызов функций в вашем приложении, начните с создания объекта FunctionDeclaration для каждой функции, которую вы хотите предоставить модели.

Например, чтобы предоставить Gemini функцию addList , которая добавляет строку в список строк, начните с создания переменной FunctionDeclaration с именем и кратким описанием функции и ее параметров на простом английском языке:

Котлин

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

Ява

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

Затем передайте это FunctionDeclaration как Tool в модель при ее создании:

Котлин

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

Ява

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

Наконец, реализуйте функцию-обработчик для обработки вызова инструмента, выполняемого моделью, и передачи ей ответа. Эта функция-обработчик, предоставляемая LiveSession при вызове startAudioConversation , принимает параметр FunctionCallPart и возвращает FunctionResponsePart :

Котлин

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

Ява

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

Следующие шаги