Двунаправленная потоковая передача с использованием API Gemini Live Двунаправленная потоковая передача с использованием API Gemini Live 


Gemini Live API обеспечивает двунаправленное текстовое и голосовое взаимодействие с Gemini с минимальной задержкой. Используя Live API , вы можете предоставить конечным пользователям возможность естественного голосового общения, максимально приближенного к человеческому, с возможностью прерывать ответы модели текстовыми или голосовыми командами. Модель может обрабатывать текстовый и аудиоввод (скоро появится видео!), а также выводить текстовый и аудиовывод.

Вы можете создавать прототипы с помощью подсказок и Live API в Vertex AI Studio .

Live API — это API с отслеживанием состояния, которое создаёт WebSocket-соединение для установления сеанса между клиентом и сервером Gemini. Подробнее см. в справочной документации Live API .

Прежде чем начать

Доступно только при использовании API Vertex AI Gemini в качестве поставщика API.

Если вы еще этого не сделали, ознакомьтесь с руководством по началу работы , в котором описывается, как настроить проект Firebase, подключить приложение к Firebase, добавить SDK, инициализировать внутреннюю службу для API Vertex AI Gemini и создать экземпляр LiveModel .

Модели, поддерживающие эту возможность

Live API поддерживается только gemini-2.0-flash-live-preview-04-09 (но не gemini-2.0-flash ).

Также обратите внимание, что gemini-2.0-flash-live-preview-04-09 поддерживается только в расположении us-central1 .

Используйте стандартные функции Live API

В этом разделе описывается, как использовать стандартные функции Live API , в частности, для потоковой передачи различных типов входных и выходных данных:

Генерация потокового текста из входного потокового текста

Прежде чем приступить к работе с этим примером, выполните указания раздела «Перед началом работы» данного руководства, чтобы настроить свой проект и приложение.
В этом разделе вы также нажмете кнопку для выбранного вами поставщика API Gemini , чтобы увидеть на этой странице контент, специфичный для этого поставщика .

Вы можете отправлять и получать потоковые текстовые данные. Обязательно создайте экземпляр liveModel и установите модальность ответа Text .

Быстрый

Live API пока не поддерживается приложениями платформы Apple, но проверьте позже!

Kotlin

// Initialize the Vertex AI Gemini API backend service
// Set the location to `us-central1` (the flash-live model is only supported in that location)
// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
val model = Firebase.ai(backend = GenerativeBackend.vertexAI(location = "us-central1")).liveModel(
    modelName = "gemini-2.0-flash-live-preview-04-09",
    // Configure the model to respond with text
    generationConfig = liveGenerationConfig {
        responseModality = ResponseModality.TEXT 
   }
)

val session = model.connect()

// Provide a text prompt
val text = "tell a short story"

session.send(text)

var outputText = ""
session.receive().collect {
    if(it.status == Status.TURN_COMPLETE) {
        // Optional: if you don't require to send more requests.
        session.stopReceiving();
    }
    outputText = outputText + it.text
}

// Output received from the server.
println(outputText)

Java

ExecutorService executor = Executors.newFixedThreadPool(1);
// Initialize the Vertex AI Gemini API backend service
// Set the location to `us-central1` (the flash-live model is only supported in that location)
// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
LiveGenerativeModel lm = FirebaseAI.getInstance(GenerativeBackend.vertexAI("us-central1")).liveModel(
        "gemini-2.0-flash-live-preview-04-09",
        // Configure the model to respond with text
        new LiveGenerationConfig.Builder()
                .setResponseModalities(ResponseModality.TEXT)
                .build()
);
LiveModelFutures model = LiveModelFutures.from(lm);
ListenableFuture<LiveSession> sessionFuture =  model.connect();
class LiveContentResponseSubscriber implements Subscriber<LiveContentResponse> {
    @Override
    public void onSubscribe(Subscription s) {
        s.request(Long.MAX_VALUE); // Request an unlimited number of items
    }
    @Override
    public void onNext(LiveContentResponse liveContentResponse) {
       // Handle the response from the server.
	System.out.println(liveContentResponse.getText());
    }
    @Override
    public void onError(Throwable t) {
        System.err.println("Error: " + t.getMessage());
    }
    @Override
    public void onComplete() {
        System.out.println("Done receiving messages!");
    }
}
Futures.addCallback(sessionFuture, new FutureCallback<LiveSession>() {
    @Override
    public void onSuccess(LiveSession ses) {
	  LiveSessionFutures session = LiveSessionFutures.from(ses);
        // Provide a text prompt
        String text = "tell me a short story?";
        session.send(text);
        Publisher<LiveContentResponse> publisher = session.receive();
        publisher.subscribe(new LiveContentResponseSubscriber());
    }
    @Override
    public void onFailure(Throwable t) {
        // Handle exceptions
    }
}, executor);

Web

Live API пока не поддерживается для веб-приложений, но проверьте позже!

Dart

import 'package:firebase_ai/firebase_ai.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';

late LiveModelSession _session;

await Firebase.initializeApp(
  options: DefaultFirebaseOptions.currentPlatform,
);

// Initialize the Vertex AI Gemini API backend service
// Set the location to `us-central1` (the flash-live model is only supported in that location)
// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
final model = FirebaseAI.vertexAI(location: 'us-central1').liveModel(
  model: 'gemini-2.0-flash-live-preview-04-09',
  // Configure the model to respond with text
  config: LiveGenerationConfig(responseModalities: [ResponseModality.text]),
);

_session = await model.connect();

// Provide a text prompt
final prompt = Content.text('tell a short story');
await _session.send(input: prompt, turnComplete: true);

// In a separate thread, receive the response
await for (final message in _session.receive()) {
   // Process the received message 
}

Единство

using Firebase;
using Firebase.AI;

async Task SendTextReceiveText() {
  // Initialize the Vertex AI Gemini API backend service
  // Set the location to `us-central1` (the flash-live model is only supported in that location)
  // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
  var model = FirebaseAI.GetInstance(FirebaseAI.Backend.VertexAI(location: "us-central1")).GetLiveModel(
    modelName: "gemini-2.0-flash-live-preview-04-09",
    // Configure the model to respond with text
    liveGenerationConfig: new LiveGenerationConfig(
        responseModalities: new[] { ResponseModality.Text })
  );

  LiveSession session = await model.ConnectAsync();

  // Provide a text prompt
  var prompt = ModelContent.Text("tell a short story");
  await session.SendAsync(content: prompt, turnComplete: true);

  // Receive the response
  await foreach (var message in session.ReceiveAsync()) {
    // Process the received message
    if (!string.IsNullOrEmpty(message.Text)) {
      UnityEngine.Debug.Log("Received message: " + message.Text);
    }
  }
}

Генерация потокового аудио из потокового аудиовхода

Прежде чем приступить к работе с этим примером, выполните указания раздела «Перед началом работы» данного руководства, чтобы настроить свой проект и приложение.
В этом разделе вы также нажмете кнопку для выбранного вами поставщика API Gemini , чтобы увидеть на этой странице контент, специфичный для этого поставщика .

Вы можете отправлять потоковое аудиовход и получать потоковое аудиовыход. Обязательно создайте экземпляр LiveModel и установите модальность ответа Audio .

Узнайте, как настроить и персонализировать голосовой ответ (далее на этой странице).

Быстрый

Live API пока не поддерживается приложениями платформы Apple, но проверьте позже!

Kotlin

// Initialize the Vertex AI Gemini API backend service
// Set the location to `us-central1` (the flash-live model is only supported in that location)
// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
val model = Firebase.ai(backend = GenerativeBackend.vertexAI(location = "us-central1")).liveModel(
    modelName = "gemini-2.0-flash-live-preview-04-09",
    // Configure the model to respond with text
    generationConfig = liveGenerationConfig {
        responseModality = ResponseModality.AUDIO 
   }
)

val session = model.connect()

// This is the recommended way.
// However, you can create your own recorder and handle the stream.
session.startAudioConversation()

Java

ExecutorService executor = Executors.newFixedThreadPool(1);
// Initialize the Vertex AI Gemini API backend service
// Set the location to `us-central1` (the flash-live model is only supported in that location)
// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
LiveGenerativeModel lm = FirebaseAI.getInstance(GenerativeBackend.vertexAI("us-central1")).liveModel(
        "gemini-2.0-flash-live-preview-04-09",
        // Configure the model to respond with text
        new LiveGenerationConfig.Builder()
                .setResponseModalities(ResponseModality.TEXT)
                .build()
);
LiveModelFutures model = LiveModelFutures.from(lm);
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);

Web

Live API пока не поддерживается для веб-приложений, но проверьте позже!

Dart

import 'package:firebase_ai/firebase_ai.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
import 'package:your_audio_recorder_package/your_audio_recorder_package.dart';

late LiveModelSession _session;
final _audioRecorder = YourAudioRecorder();

await Firebase.initializeApp(
  options: DefaultFirebaseOptions.currentPlatform,
);

// Initialize the Vertex AI Gemini API backend service
// Set the location to `us-central1` (the flash-live model is only supported in that location)
// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
final model = FirebaseAI.vertexAI(location: 'us-central1').liveModel(
  model: 'gemini-2.0-flash-live-preview-04-09',
   // Configure the model to respond with audio
   config: LiveGenerationConfig(responseModalities: [ResponseModality.audio]),
);

_session = await model.connect();

final audioRecordStream = _audioRecorder.startRecordingStream();
// Map the Uint8List stream to InlineDataPart stream
final mediaChunkStream = audioRecordStream.map((data) {
  return InlineDataPart('audio/pcm', data);
});
await _session.startMediaStream(mediaChunkStream);

// In a separate thread, receive the audio response from the model
await for (final message in _session.receive()) {
   // Process the received message 
}

Единство

using Firebase;
using Firebase.AI;

async Task SendTextReceiveAudio() {
  // Initialize the Vertex AI Gemini API backend service
  // Set the location to `us-central1` (the flash-live model is only supported in that location)
  // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
  var model = FirebaseAI.GetInstance(FirebaseAI.Backend.VertexAI(location: "us-central1")).GetLiveModel(
    modelName: "gemini-2.0-flash-live-preview-04-09",
    // Configure the model to respond with audio
    liveGenerationConfig: new LiveGenerationConfig(
        responseModalities: new[] { ResponseModality.Audio })
  );

  LiveSession session = await model.ConnectAsync();

  // Start a coroutine to send audio from the Microphone
  var recordingCoroutine = StartCoroutine(SendAudio(session));

  // Start receiving the response
  await ReceiveAudio(session);
}

IEnumerator SendAudio(LiveSession liveSession) {
  string microphoneDeviceName = null;
  int recordingFrequency = 16000;
  int recordingBufferSeconds = 2;

  var recordingClip = Microphone.Start(microphoneDeviceName, true,
                                       recordingBufferSeconds, recordingFrequency);

  int lastSamplePosition = 0;
  while (true) {
    if (!Microphone.IsRecording(microphoneDeviceName)) {
      yield break;
    }

    int currentSamplePosition = Microphone.GetPosition(microphoneDeviceName);

    if (currentSamplePosition != lastSamplePosition) {
      // The Microphone uses a circular buffer, so we need to check if the
      // current position wrapped around to the beginning, and handle it
      // accordingly.
      int sampleCount;
      if (currentSamplePosition > lastSamplePosition) {
        sampleCount = currentSamplePosition - lastSamplePosition;
      } else {
        sampleCount = recordingClip.samples - lastSamplePosition + currentSamplePosition;
      }

      if (sampleCount > 0) {
        // Get the audio chunk
        float[] samples = new float[sampleCount];
        recordingClip.GetData(samples, lastSamplePosition);

        // Send the data, discarding the resulting Task to avoid the warning
        _ = liveSession.SendAudioAsync(samples);

        lastSamplePosition = currentSamplePosition;
      }
    }

    // Wait for a short delay before reading the next sample from the Microphone
    const float MicrophoneReadDelay = 0.5f;
    yield return new WaitForSeconds(MicrophoneReadDelay);
  }
}

Queue audioBuffer = new();

async Task ReceiveAudio(LiveSession liveSession) {
  int sampleRate = 24000;
  int channelCount = 1;

  // Create a looping AudioClip to fill with the received audio data
  int bufferSamples = (int)(sampleRate * channelCount);
  AudioClip clip = AudioClip.Create("StreamingPCM", bufferSamples, channelCount,
                                    sampleRate, true, OnAudioRead);

  // Attach the clip to an AudioSource and start playing it
  AudioSource audioSource = GetComponent();
  audioSource.clip = clip;
  audioSource.loop = true;
  audioSource.Play();

  // Start receiving the response
  await foreach (var message in liveSession.ReceiveAsync()) {
    // Process the received message
    foreach (float[] pcmData in message.AudioAsFloat) {
      lock (audioBuffer) {
        foreach (float sample in pcmData) {
          audioBuffer.Enqueue(sample);
        }
      }
    }
  }
}

// This method is called by the AudioClip to load audio data.
private void OnAudioRead(float[] data) {
  int samplesToProvide = data.Length;
  int samplesProvided = 0;

  lock(audioBuffer) {
    while (samplesProvided < samplesToProvide && audioBuffer.Count > 0) {
      data[samplesProvided] = audioBuffer.Dequeue();
      samplesProvided++;
    }
  }

  while (samplesProvided < samplesToProvide) {
    data[samplesProvided] = 0.0f;
    samplesProvided++;
  }
}



Создавайте более увлекательные и интерактивные впечатления

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

Изменить голос ответа

Live API использует Chirp 3 для поддержки синтезированных речевых ответов. При использовании Firebase AI Logic вы можете отправлять аудио на различных языках HD-голосов. Полный список и примеры звучания каждого голоса см. в статье Chirp 3: HD-голоса .

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

Быстрый

Live API пока не поддерживается приложениями платформы Apple, но проверьте позже!

Kotlin

// ...

val model = Firebase.ai(backend = GenerativeBackend.vertexAI()).liveModel(
    modelName = "gemini-2.0-flash-live-preview-04-09",
    // Configure the model to use a specific voice for its audio response
    generationConfig = liveGenerationConfig {
        responseModality = ResponseModality.AUDIO
        speechConfig = SpeechConfig(voice = Voices.FENRIR)
    }
)

// ...

Java

// ...

LiveModel model = FirebaseAI.getInstance(GenerativeBackend.vertexAI()).liveModel(
    "gemini-2.0-flash-live-preview-04-09",
    // Configure the model to use a specific voice for its audio response
    new LiveGenerationConfig.Builder()
        .setResponseModalities(ResponseModality.AUDIO)
        .setSpeechConfig(new SpeechConfig(Voices.FENRIR))
        .build()
);

// ...

Web

Live API пока не поддерживается для веб-приложений, но проверьте позже!

Dart

// ...

final model = FirebaseAI.vertexAI().liveGenerativeModel(
  model: 'gemini-2.0-flash-live-preview-04-09',
  // Configure the model to use a specific voice for its audio response
  config: LiveGenerationConfig(
    responseModality: ResponseModality.audio,
    speechConfig: SpeechConfig(voiceName: 'Fenrir'),
  ),
);

// ...

Единство

var model = FirebaseAI.GetInstance(FirebaseAI.Backend.VertexAI()).GetLiveModel(
  modelName: "gemini-2.0-flash-live-preview-04-09",
  liveGenerationConfig: new LiveGenerationConfig(
    responseModalities: new[] { ResponseModality.Audio },
    speechConfig: SpeechConfig.UsePrebuiltVoice("Fenrir"),
);

Для достижения наилучших результатов при запросе ответа модели на языке, отличном от английского, включите в системные инструкции следующее:

RESPOND IN LANGUAGE. YOU MUST RESPOND UNMISTAKABLY IN LANGUAGE.

Сохраняйте контекст между сеансами и запросами

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

Этот подход лучше всего подходит для коротких контекстов: вы можете отправлять пошаговые взаимодействия, чтобы отразить точную последовательность событий. Для более длинных контекстов мы рекомендуем предоставлять краткое изложение сообщения, чтобы освободить контекстное окно для последующих взаимодействий.

Управляйте прерываниями

Firebase AI Logic пока не поддерживает обработку прерываний. Следите за обновлениями!

Использовать вызов функций (инструменты)

Вы можете определить инструменты, например, доступные функции, для использования с Live API так же, как и со стандартными методами генерации контента. В этом разделе описываются некоторые нюансы использования Live API с вызовом функций. Полное описание и примеры вызова функций см. в руководстве по вызову функций .

Из одного запроса модель может генерировать несколько вызовов функций и код, необходимый для объединения их выходных данных. Этот код выполняется в изолированной среде, генерируя последующие сообщения BidiGenerateContentToolCall . Выполнение приостанавливается до тех пор, пока не станут доступны результаты каждого вызова функции, что обеспечивает последовательную обработку.

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

Клиент должен ответить BidiGenerateContentToolResponse .



Ограничения и требования

Помните о следующих ограничениях и требованиях Live API .

Транскрипция

Firebase AI Logic пока не поддерживает транскрипции. Следите за обновлениями!

Языки

Аудиоформаты

Live API поддерживает следующие аудиоформаты:

  • Формат входного аудио: Raw 16-битный PCM-аудио с частотой 16 кГц, прямой порядок байтов
  • Формат выходного аудио: Raw 16-битный PCM-аудио с частотой 24 кГц, прямой порядок байтов

Ограничения по скорости

Действуют следующие ограничения по ставкам:

  • 10 одновременных сеансов на проект Firebase
  • 4 млн токенов в минуту

Продолжительность сеанса

Продолжительность сеанса по умолчанию составляет 30 минут. При превышении этого лимита соединение разрывается.

Модель также ограничена размером контекста. Отправка больших объёмов входных данных может привести к преждевременному завершению сеанса.

Обнаружение голосовой активности (VAD)

Модель автоматически выполняет обнаружение голосовой активности (VAD) в непрерывном аудиопотоке. Функция VAD включена по умолчанию.

Подсчет токенов

API CountTokens нельзя использовать с Live API .


Оставьте отзыв о своем опыте работы с Firebase AI Logic