درطول گردش کار عاملی، کلاس AgentRunner و میانای AgentSession
جریانهای رویداد واکنشی را منتشر میکنند که نشاندهنده فرایند استدلال مدل، فراخوانیهای
ابزار، و پاسخهای متنی است. این صفحه نشان میدهد که چگونه رویدادها را جمعآوری کنید
و آنها را بااستفاده از Kotlin Coroutines و Jetpack Compose به میانای کاربر خود متصل کنید.
آشنایی با میانای AgentEvent
روشهای AgentSession.runAsync() و AgentRunner.runSingleTurnAsync() یک
جاریسازی Flow<AgentEvent> را برمیگردانند. بهجای اینکه منتظر بمانید تا کل حلقه استدلال تمام شود،
برنامهتان بهروزرسانیهای همزمان را هنگام اجرای عامل دریافت میکند:
نوع رویداد |
شرح |
کنش معمول میانای کاربر |
|
تکههای نوشتاری افزایشی ( |
وقتی |
|
وقتی Gemini Nano ابزاری را انتخاب میکند و برای اجرای آن آماده میشود، این رویداد صادر میشود ( |
نشانگر درحال انجام را نمایش دهید (برای مثال، «درحال بررسی وضعیت سفارش...»). |
|
وقتی برنامه اجرای تابع ابزار را بهپایان میرساند، منتشر میشود ( |
وضعیت ابزار را به تکمیلشده تغییر دهید. |
جمعآوری رویدادها در کلاس ViewModel
از کلاس ViewModel Android برای هماهنگ کردن ارسال پیامواره و نمایش وضعیت میانای کاربر به
صفحههای Compose استفاده کنید:
package com.example.ai.agent.ui
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.mlkit.genai.agent.AgentEvent
import com.google.mlkit.genai.agent.AgentRunner
import com.google.mlkit.genai.agent.AgentSession
import com.google.mlkit.genai.common.GenAiException
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.catch
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
data class AgentUiState(
val messages: List<String> = emptyList(),
val currentResponse: String = "",
val activeToolStatus: String? = null,
val isLoading: Boolean = false,
val errorMessage: String? = null
)
class ChatViewModel(
private val runner: AgentRunner,
private val sessionId: String = "default_chat_session"
) : ViewModel() {
private val session: AgentSession = runner.getOrCreateSession(sessionId)
private val _uiState = MutableStateFlow(AgentUiState())
val uiState: StateFlow<AgentUiState> = _uiState.asStateFlow()
fun sendMessage(userText: String) {
_uiState.update {
it.copy(
messages = it.messages + userText,
currentResponse = "",
activeToolStatus = null,
isLoading = true,
errorMessage = null
)
}
viewModelScope.launch {
val content = Content.builder().text(userText).build()
session.runAsync(content)
.catch { e ->
val message = when {
e is GenAiException && e.errorCode == GenAiException.ErrorCode.MAX_TURNS_EXCEEDED ->
"Agent exceeded the maximum reasoning turns allowed."
e is GenAiException && e.errorCode == GenAiException.ErrorCode.NOT_AVAILABLE ->
"On-device AI is currently unavailable."
e is GenAiException && e.errorCode == GenAiException.ErrorCode.BUSY ->
"On-device AI is busy. Please try again."
else -> e.localizedMessage ?: "Agent error"
}
_uiState.update {
it.copy(
isLoading = false,
activeToolStatus = null,
errorMessage = message
)
}
}
.collect { event ->
when (event) {
is AgentEvent.TextMessage -> {
_uiState.update {
it.copy(
currentResponse = if (event.isPartial) {
it.currentResponse + event.text
} else {
event.text.ifEmpty { it.currentResponse }
},
activeToolStatus = null
)
}
}
is AgentEvent.FunctionCall -> {
_uiState.update {
it.copy(
activeToolStatus =
"Executing ${event.name}..."
)
}
}
is AgentEvent.FunctionResponse -> {
_uiState.update {
it.copy(
activeToolStatus =
"Received data from ${event.name}"
)
}
}
else -> {}
}
}
// Finalize message once stream completes
_uiState.update {
it.copy(
messages = it.messages + it.currentResponse,
currentResponse = "",
activeToolStatus = null,
isLoading = false
)
}
}
}
override fun onCleared() {
super.onCleared()
// Release session memory and cancel active coroutines
session.close()
}
}
استخراج مستقیم دادهواحدهای نوشتاری
برای میاناهای مکالمهای که جزئیات اجرای ابزار نیازی به نمایش جداگانه در میانای کاربر ندارند، از تابع افزونه textTokens() در میانای Flow<AgentEvent> استفاده کنید:
import com.google.mlkit.genai.agent.textTokens
import com.google.mlkit.genai.prompt.Content
val content = Content.builder().text(userText).build()
session.runAsync(content)
.textTokens()
.collect { token ->
appendTokenToChatBubble(token)
}
پرداز زدن در Jetpack Compose
از حالت AgentUiState در یک تابع ترکیبپذیر برای ارائه نوشتار جاریشده و فعالیت ابزار زنده استفاده کنید:
package com.example.ai.agent.ui
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun AgentChatScreen(
viewModel: ChatViewModel,
modifier: Modifier = Modifier
) {
val state by viewModel.uiState.collectAsState()
var inputText by remember { mutableStateOf("") }
Column(modifier = modifier.fillMaxSize().padding(16.dp)) {
LazyColumn(
modifier = Modifier.weight(1f).fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
items(state.messages) { message ->
Card(modifier = Modifier.fillMaxWidth()) {
Text(text = message, modifier = Modifier.padding(12.dp))
}
}
if (state.activeToolStatus != null) {
item {
Text(
text = state.activeToolStatus ?: "",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.secondary
)
}
}
if (state.currentResponse.isNotEmpty()) {
item {
Card(
colors = CardDefaults.cardColors(
containerColor =
MaterialTheme.colorScheme.surfaceVariant
),
modifier = Modifier.fillMaxWidth()
) {
Text(
text = state.currentResponse,
modifier = Modifier.padding(12.dp)
)
}
}
}
}
Row(
modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
TextField(
value = inputText,
onValueChange = { inputText = it },
modifier = Modifier.weight(1f),
placeholder = { Text("Ask about an order...") }
)
Button(
onClick = {
if (inputText.isNotBlank()) {
viewModel.sendMessage(inputText)
inputText = ""
}
},
enabled = !state.isLoading
) {
Text("Send")
}
}
}
}
مراحل بعدی
- در تعریف ابزارها با نحوه تعریف ابزارها آشنا شوید.
- مدیریت حافظه جلسه و رسیدگی به چرخشها در مدیریت جلسهها و چرخه حیات.