תהליכי עבודה מבוססי-סוכנים במכשיר (באמצעות המחלקה AgentRunner) מספקים סשנים מנוהלים עם כמה פניות, שמתעדים את היסטוריית השיחות בזיכרון באופן אוטומטי בין הפניות, כך שלא צריך לנהל את התמלילים באופן ידני. (אם אתם מעדיפים לנהל את היסטוריית הצ'אט בעצמכם, אתם יכולים להעביר אובייקט List<Content> עם כמה פניות, עם התפקידים USER ו-MODEL וערך sessionId לאובייקט GenerateContentRequest באמצעות גישה ישירה למודל).
בדף הזה מוסבר איך לנהל מופעים של AgentSession במחזורי חיים של רכיבי Android, בשינויים בהגדרות ובבקשות להחזרת זיכרון.
סשנים עם כמה שלבים
לנהל שיחות עם כמה סבבים באמצעות מופעים של AgentSession עם היקף שהתקבלו באמצעות השיטה runner.getOrCreateSession(sessionId). השיחה (הודעות המשתמש, הפעלת הכלים והתשובות של המודל) נשמרת בזיכרון באופן אוטומטי במהלך הסשן. בקריאות הבאות ל-method 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 בתוך מחלקה של ViewModel ב-AndroidX:
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)כדי לפנות באופן סינכרוני את הזיכרון שהוקצה לפלטים של הכלים ולתורות הקודמים. לחלופין, קריאה ל-methodsession.close()שולחת פינוי ברקע. - ניקוי נתונים ביציאה מהחשבון: מפעילים את השיטה
runner.clearAllSessions()כשהמשתמש יוצא מהחשבון או מוחק את נתוני האפליקציה. - ניקוי הסשן בסוף מחזור החיים: קוראים ל-method
session.close()כשהמחלקהViewModelאו רכיב ההורה מושמדים באופן סופי (ב-methodonCleared()). הפעולה הזו מבטלת את ה-coroutines שבהמתנה ומפעילה פינוי ברקע של הסשן של השיחה הזו.
הרצה זמנית בסבב שיחה אחד
למשימות חד-פעמיות של הנציג (כמו יצירת סיכום מהיר, אימות קלט או מענה על שאלה עצמאית) שבהן לא נדרש הקשר קודם, צריך להפעיל את השיטה 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 מקצה סשן זמני באופן פנימי ומנקה באופן אוטומטי את כל מצב השיחה מהזיכרון ברגע שזרם התגובות מסתיים או מתבטל, כדי למנוע דליפות זיכרון.
השלבים הבאים
- מחברים את ה-reactive stream של הסוכן ל-Compose באירועי סטרימינג ושילוב ממשק משתמש.
- מידע נוסף על הגדרת כלים זמין במאמר הגדרת כלים.