管理会话和生命周期

设备端 Agentic Workflows(使用 AgentRunner 类)提供代管式多轮会话,可自动记录各轮对话的内存中对话记录,因此您无需手动管理转写内容。(如果您希望直接管理自己的对话记录,可以使用直接模型访问,将具有 USER 和 MODEL 角色以及 sessionId 值的多轮 List<Content> 对象传递给 GenerateContentRequest 对象。)

本页介绍了如何在 Android 组件生命周期、配置更改和内存回收过程中管理 AgentSession 实例。

多轮会话

使用通过 runner.getOrCreateSession(sessionId) 方法获取的作用域限定的 AgentSession 实例来管理多轮对话。对话轮次(用户消息、工具调用和模型回答)会在会话期间自动记录在记忆中。后续对 session.runAsync(content) 方法的调用会将之前的对话轮次保留为上下文。

会话标识符必须为非空,最多包含 128 个字符,并且只能包含字母数字字符、下划线、连字符或英文句点(^[a-zA-Z0-9_.-]+$,不包括 . 和 ..)。使用 UUID.randomUUID().toString() 方法生成的 UUID 字符串符合这些限制。

如需开始多轮对话,请创建一个会话标识符,并从 AgentRunner 实例中获取 AgentSession 实例:

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

每次调用 session.runAsync(content) 方法都会在该会话中发送一个新的提示轮次。模型会保留对话中先前轮次的上下文。

在配置变更后保留会话

AgentSession 接口在内存中保存对话历史记录,不实现 Parcelable 接口。在 Android 应用中,Activity 和 Fragment 会在配置更改(例如屏幕旋转)期间被销毁并重新创建。如果您将对话直接存储在 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() 方法。
  • 在生命周期结束时清理会话:当 ViewModel 类或父级组件被永久销毁时(在 onCleared() 方法中),调用 session.close() 方法。这会取消待处理的进行中协程,并为该对话会话分派后台逐出。

单轮临时执行

对于不需要过往上下文的一次性智能体任务(例如生成快速摘要、验证输入或回答独立问题),请直接调用 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 类会在内部临时分配一个会话,并在响应流完成或取消后自动从内存中清除所有对话状态,从而避免内存泄漏。

后续步骤