Управление сеансами и жизненным циклом

Рабочие процессы с агентами на устройстве (с использованием класса AgentRunner) обеспечивают управляемые многоэтапные сеансы, в которых история разговоров автоматически записывается в память на всех этапах, поэтому вам не нужно управлять расшифровками вручную. Если вы хотите управлять историей чата самостоятельно, передайте объект List<Content> с ролями USER и MODEL и значением sessionId в объект GenerateContentRequest, используя прямой доступ к модели.

На этой странице рассказывается, как управлять экземплярами AgentSession в жизненных циклах компонентов Android, изменениях конфигурации и восстановлении памяти.

Многоэтапные сеансы

Управляйте многоэтапными разговорами, используя экземпляры AgentSession с ограниченной областью действия, полученные с помощью метода runner.getOrCreateSession(sessionId). Реплики диалога (сообщения пользователя, вызовы инструментов и ответы модели) автоматически записываются в память в течение сеанса. Последующие вызовы метода session.runAsync(content) сохраняют предыдущие ходы в качестве контекста.

Идентификаторы сеансов не должны быть пустыми, могут содержать не более 128 символов и состоять только из букв, цифр, символов подчеркивания, дефисов и точек (^[a-zA-Z0-9_.-]+$, за исключением . и ..). Строки UUID, созданные с помощью метода UUID.randomUUID().toString(), соответствуют этим требованиям.

Чтобы начать многоэтапный разговор, создайте идентификатор сеанса и получите экземпляр AgentSession из экземпляра AgentRunner:

val sessionId = "user_chat_${System.currentTimeMillis()}"
val session = runner.getOrCreateSession(sessionId)

Каждый вызов метода session.runAsync(content) отправляет новый запрос в рамках этого сеанса. Модель сохраняет контекст предыдущих реплик в разговоре.

Сохранение сеансов при изменении конфигурации

Интерфейс AgentSession хранит историю диалога в памяти и не реализует интерфейс Parcelable. В приложениях для Android действия и фрагменты удаляются и создаются заново при изменении конфигурации (например, при повороте экрана). Если вы сохраните сеанс непосредственно в Activity, история разговора будет потеряна при повороте.

Чтобы сохранить историю чата при изменении конфигурации, сохраните экземпляр AgentSession в классе AndroidX ViewModel:

package com.example.ai.agent.ui

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.mlkit.genai.agent.AgentRunner
import com.google.mlkit.genai.agent.AgentSession
import com.google.mlkit.genai.agent.textTokens
import com.google.mlkit.genai.prompt.Content
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class ChatViewModel(
    private val runner: AgentRunner,
    private val sessionId: String = "default_chat_session"
) : ViewModel() {

    // Retain the session inside the ViewModel to survive screen rotations
    private val session: AgentSession = runner.getOrCreateSession(sessionId)

    private val _responseText = MutableStateFlow("")
    val responseText: StateFlow<String> = _responseText.asStateFlow()

    fun sendMessage(userPrompt: String) {
        viewModelScope.launch {
            val content = Content.builder().text(userPrompt).build()
            session.runAsync(content)
                .textTokens()
                .collect { token ->
                    _responseText.update { it + token }
                }
        }
    }

    override fun onCleared() {
        super.onCleared()
        // Release session memory and cancel active coroutines when ViewModel is destroyed
        session.close()
    }
}

Управление памятью и очистка сеансов

Чтобы поддерживать производительность приложения, ограничьте состояние разговора в памяти:

  • Явное удаление сеанса. Когда пользователь покидает чат или нажимает "Новый чат", вызовите метод session.delete() или runner.deleteSession(sessionId), чтобы синхронно освободить память, выделенную для прошлых реплик и выходных данных инструментов. Вы также можете вызвать метод session.close(), чтобы запустить фоновое удаление.
  • Очистка данных при выходе. Вызовите метод runner.clearAllSessions(), когда пользователь выходит из аккаунта или удаляет данные приложения.
  • Очистка сеанса в конце жизненного цикла. Вызовите метод session.close(), когда класс ViewModel или родительский компонент будет окончательно удален (в методе onCleared()). Это отменяет ожидающие сопрограммы и запускает фоновое удаление для этого сеанса чата.

Однократное выполнение

Для разовых задач агента (например, создания краткого пересказа, проверки входных данных или ответа на отдельный вопрос), где прошлый контекст не нужен, вызовите метод runner.runSingleTurnAsync(content) напрямую:

import com.google.mlkit.genai.agent.AgentEvent
import com.google.mlkit.genai.prompt.Content

val content = Content.builder()
    .text("Summarize order history for customer #1042: ...")
    .build()

runner.runSingleTurnAsync(content)
    .collect { event ->
        if (event is AgentEvent.TextMessage && !event.isPartial) {
            displaySummary(event.text)
        }
    }

При непосредственном вызове метода runner.runSingleTurnAsync(content) класс AgentRunner выделяет временный сеанс внутри и автоматически удаляет все состояния разговора из памяти после завершения или отмены потока ответов, избегая утечек памяти.

Дальнейшие действия