Skip to content

Commit 8aee09f

Browse files
Feat: Add extensive diagnostic logging for chat history transformation
To diagnose potential context loss leading to reduced AI performance (observed as 'history size: 2'), this commit introduces detailed logging throughout the chat history processing lifecycle: 1. **ScreenCaptureService:** * Logs the structure of the raw AI response received, including details of any `FunctionCallPart`s. 2. **PhotoReasoningViewModel:** * `updateAiMessage` and your message creation in `performReasoning`: Logs details of messages being added to the UI-facing `_chatState.messages`. * `rebuildChatHistory`: * Logs the size of the input `_chatState.messages` list. * Logs how each `PhotoReasoningMessage` is processed into text components for SDK `Content`. * Logs the size and detailed structure (parts and their types) of the final `List<SDK.Content>` it produces. * `sendMessageWithRetry`: * Logs the size and detailed structure of `chat.history` (the output of `rebuildChatHistory`) just before it's serialized with DTOs and sent to `ScreenCaptureService`. This logging aims to provide a clear trace to identify at what stage (AI response -> UI message store -> SDK history rebuild -> pre-serialization history) any discrepancies or loss of complex `Part` information might be occurring.
1 parent 09b84bc commit 8aee09f

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

app/src/main/kotlin/com/google/ai/sample/ScreenCaptureService.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import android.widget.Toast
2828
import com.google.ai.client.generativeai.GenerativeModel
2929
import com.google.ai.client.generativeai.type.Content
3030
import com.google.ai.client.generativeai.type.ImagePart // For instance check
31+
import com.google.ai.client.generativeai.type.FunctionCallPart // For logging AI response
3132
import com.google.ai.sample.feature.multimodal.dtos.ContentDto
3233
import com.google.ai.sample.feature.multimodal.dtos.toSdk
3334
import kotlinx.coroutines.CoroutineScope
@@ -248,6 +249,11 @@ class ScreenCaptureService : Service() {
248249
val tempChat = generativeModel.startChat(history = chatHistory) // Use the mapped SDK history
249250
Log.d(TAG, "Executing AI sendMessage with history size: ${chatHistory.size}")
250251
val aiResponse = tempChat.sendMessage(inputContent) // Use the mapped SDK inputContent
252+
Log.d(TAG, "Service received AI Response. Parts: ${aiResponse.parts.joinToString { it.javaClass.simpleName }}")
253+
// If a part is FunctionCallPart, log its name and args
254+
aiResponse.parts.filterIsInstance<com.google.ai.client.generativeai.type.FunctionCallPart>().forEach { fcp ->
255+
Log.d(TAG, " AI sent FunctionCallPart: name='${fcp.name}', args='${fcp.args}'")
256+
}
251257
responseText = aiResponse.text
252258
Log.d(TAG, "AI call successful. Response text available: ${responseText != null}")
253259

app/src/main/kotlin/com/google/ai/sample/feature/multimodal/PhotoReasoningViewModel.kt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,9 @@ class PhotoReasoningViewModel(
236236
imageUris = imageUrisForChat ?: emptyList(), // Use the new parameter here
237237
isPending = false
238238
)
239+
Log.d(TAG, "performReasoning: Adding user message to _chatState. Text: \"${userMessage.text.take(100)}...\", Images: ${userMessage.imageUris.size}")
239240
_chatState.addMessage(userMessage)
241+
Log.d(TAG, "performReasoning: _chatState now has ${_chatState.messages.size} messages.")
240242
_chatMessagesFlow.value = chatMessages
241243

242244
// Add AI message with pending status
@@ -379,6 +381,20 @@ class PhotoReasoningViewModel(
379381
// Add @file:UseSerializers(ContentSerializer::class, PartSerializer::class etc.) if needed at top of file
380382
// Or create DTOs. For this subtask, we'll assume direct serialization is possible.
381383

384+
Log.d(TAG, "sendMessageWithRetry: Preparing to serialize chat.history. Current chat.history size: ${chat.history.size}")
385+
chat.history.forEachIndexed { index, content ->
386+
Log.d(TAG, " ViewModel chat.history Content[$index]: role=${content.role}, parts=${content.parts.joinToString { it.javaClass.simpleName } { part ->
387+
when(part) {
388+
is com.google.ai.client.generativeai.type.TextPart -> "Text(\"${part.text.take(50)}...\")"
389+
is com.google.ai.client.generativeai.type.ImagePart -> "Image"
390+
is com.google.ai.client.generativeai.type.BlobPart -> "Blob(${part.mimeType})"
391+
is com.google.ai.client.generativeai.type.FunctionCallPart -> "FunctionCall(${part.name}, args=${part.args})"
392+
is com.google.ai.client.generativeai.type.FunctionResponsePart -> "FunctionResponse(${part.name})"
393+
else -> "UnknownPart"
394+
}
395+
}}")
396+
}
397+
382398
Log.d(TAG, "sendMessageWithRetry: Logging original Bitmap properties before DTO conversion and saving:")
383399

384400
// Log properties for inputContent's images
@@ -455,6 +471,7 @@ class PhotoReasoningViewModel(
455471
* Update the AI message in chat history
456472
*/
457473
private fun updateAiMessage(text: String, isPending: Boolean = false) {
474+
Log.d(TAG, "updateAiMessage: Adding to _chatState. Text: \"${text.take(100)}...\", Participant: MODEL, IsPending: $isPending")
458475
// Find the last AI message and update it or add a new one if no suitable message exists
459476
val messages = _chatState.messages.toMutableList()
460477
val lastAiMessageIndex = messages.indexOfLast { it.participant == PhotoParticipant.MODEL }
@@ -481,6 +498,7 @@ class PhotoReasoningViewModel(
481498

482499
// Update the flow
483500
_chatMessagesFlow.value = chatMessages
501+
Log.d(TAG, "updateAiMessage: _chatState now has ${_chatState.messages.size} messages.")
484502

485503
// Save chat history after updating message
486504
// Only save if the operation wasn't stopped, or if it's a deliberate update after stopping
@@ -634,6 +652,7 @@ class PhotoReasoningViewModel(
634652
* Rebuild the chat history for the AI based on the current messages
635653
*/
636654
private fun rebuildChatHistory(context: Context) { // Added context parameter
655+
Log.d(TAG, "rebuildChatHistory: Starting. Input _chatState.messages size: ${_chatState.messages.size}")
637656
// Convert the current chat messages to Content objects for the chat history
638657
val history = mutableListOf<Content>()
639658

@@ -687,6 +706,7 @@ class PhotoReasoningViewModel(
687706
continue
688707
}
689708
}
709+
Log.d(TAG, " Processed PhotoReasoningMessage: role=${message.participant}, text collected for current SDK Content part: \"${ (if (message.participant == PhotoParticipant.USER) currentUserContent else currentModelContent).take(100) }...\"")
690710
}
691711

692712
// Add any remaining content
@@ -697,6 +717,20 @@ class PhotoReasoningViewModel(
697717
history.add(content(role = "model") { text(currentModelContent) })
698718
}
699719

720+
Log.d(TAG, "rebuildChatHistory: Finished processing. Generated SDK history size: ${history.size}")
721+
history.forEachIndexed { index, content ->
722+
Log.d(TAG, " Generated SDK.Content[$index]: role=${content.role}, parts=${content.parts.joinToString { it.javaClass.simpleName } { part ->
723+
when(part) {
724+
is com.google.ai.client.generativeai.type.TextPart -> "Text(\"${part.text.take(50)}...\")"
725+
is com.google.ai.client.generativeai.type.ImagePart -> "Image" // Bitmaps are not easily loggable
726+
is com.google.ai.client.generativeai.type.BlobPart -> "Blob(${part.mimeType})"
727+
is com.google.ai.client.generativeai.type.FunctionCallPart -> "FunctionCall(${part.name}, args=${part.args})"
728+
is com.google.ai.client.generativeai.type.FunctionResponsePart -> "FunctionResponse(${part.name})"
729+
else -> "UnknownPart"
730+
}
731+
}}")
732+
}
733+
700734
// Create a new chat with the rebuilt history
701735
if (history.isNotEmpty()) {
702736
chat = generativeModel.startChat(

0 commit comments

Comments
 (0)