Przepływy pracy oparte na agentach na urządzeniu (korzystające z klasy AgentRunner) zapewniają zarządzane sesje wieloturowe, które automatycznie rejestrują historię rozmów w pamięci, dzięki czemu nie musisz ręcznie zarządzać transkrypcjami. (Jeśli wolisz bezpośrednio zarządzać własną historią czatu, możesz przekazać obiekt wieloetapowy List<Content> z rolami USER i MODEL oraz wartością sessionId do obiektu GenerateContentRequest, korzystając z bezpośredniego dostępu do modelu).
Na tej stronie opisujemy zarządzanie instancjami AgentSession w cyklach życia komponentów Androida, zmianach konfiguracji i odzyskiwaniu pamięci.
Sesje wieloetapowe
Zarządzaj rozmowami wieloetapowymi za pomocą instancji AgentSession o określonym zakresie uzyskanych za pomocą metody runner.getOrCreateSession(sessionId). Tury dialogu (wiadomości użytkownika, wywołania narzędzi i odpowiedzi modelu) są automatycznie zapisywane w pamięci w ramach sesji. Kolejne wywołania metody session.runAsync(content) zachowują poprzednie tury jako kontekst.
Identyfikatory sesji nie mogą być puste, mogą mieć maksymalnie 128 znaków i zawierać tylko znaki alfanumeryczne, podkreślenia, łączniki lub kropki (^[a-zA-Z0-9_.-]+$, z wyjątkiem . i ..). Ciągi UUID wygenerowane za pomocą metody UUID.randomUUID().toString() są zgodne z tymi ograniczeniami.
Aby rozpocząć rozmowę wieloturową, utwórz identyfikator sesji i pobierz instancję AgentSession z instancji AgentRunner:
val sessionId = "user_chat_${System.currentTimeMillis()}"
val session = runner.getOrCreateSession(sessionId)
Każde wywołanie metody session.runAsync(content) wysyła nową turę prompta w ramach tej sesji. Model zachowuje kontekst z poprzednich etapów rozmowy.
Zachowywanie sesji mimo zmian konfiguracji
Interfejs AgentSession przechowuje historię dialogu w pamięci i nie implementuje interfejsu Parcelable. W aplikacjach na Androida aktywności i fragmenty są niszczone i tworzone ponownie podczas zmian konfiguracji (np. obracania ekranu). Jeśli przechowujesz sesję bezpośrednio w aktywności, historia rozmowy zostanie utracona po obróceniu.
Aby zachować historię rozmów po zmianach konfiguracji, zachowaj instancję AgentSession w klasie 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()
}
}
Zarządzanie pamięcią i czyszczenie sesji
Aby utrzymać wydajność aplikacji, ogranicz stan rozmowy w pamięci:
- Jawne usuwanie sesji: gdy użytkownik opuści wątek rozmowy lub kliknie „Nowy czat”, wywołaj metodę
session.delete()lubrunner.deleteSession(sessionId), aby synchronicznie zwolnić pamięć przydzieloną na poprzednie tury i dane wyjściowe narzędzia. Możesz też wywołać metodęsession.close(), aby wysłać żądanie usunięcia w tle. - Czyszczenie po wylogowaniu: wywołaj metodę
runner.clearAllSessions(), gdy użytkownik się wyloguje lub wyczyści dane aplikacji. - Czyszczenie sesji na koniec cyklu życia: wywołaj metodę
session.close(), gdy klasaViewModellub komponent nadrzędny zostaną trwale zniszczone (w metodzieonCleared()). Spowoduje to anulowanie oczekujących współprogramów i uruchomienie w tle usuwania tej sesji rozmowy.
Jednoetapowe wykonywanie efemeryczne
W przypadku jednorazowych zadań agenta (takich jak generowanie krótkiego podsumowania, sprawdzanie danych wejściowych lub odpowiadanie na samodzielne pytanie), w których nie jest potrzebny wcześniejszy kontekst, wywołaj bezpośrednio metodę 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)
}
}
Podczas bezpośredniego wywoływania metody runner.runSingleTurnAsync(content) klasa AgentRunner wewnętrznie przydziela tymczasową sesję i automatycznie usuwa z pamięci cały stan rozmowy po zakończeniu lub anulowaniu strumienia odpowiedzi, co pozwala uniknąć wycieków pamięci.
Dalsze kroki
- Połącz strumień reaktywny agenta z Compose w sekcji Zdarzenia strumieniowe i integracja z interfejsem.
- Więcej informacji o konfigurowaniu narzędzi znajdziesz w artykule Definiowanie narzędzi.