feat(server): consolidate adjacent model content in chat history

- Consolidates consecutive model messages into a single message in the chat history.
- This prevents multiple model messages from being displayed in a row, improving readability.
- This may also address some instances of 500 errors that could have been caused by multiple, rapidly succeeding model messages.
- Adds tests for the new consolidation logic.

Fixes https://b.corp.google.com/issues/421010429
This commit is contained in:
Taylor Mullen
2025-05-29 23:53:35 -07:00
committed by N. Taylor Mullen
parent 7c4a5464f6
commit 9537ff4762
2 changed files with 321 additions and 1 deletions

View File

@@ -313,6 +313,44 @@ export class GeminiChat {
} else {
this.history.push(userInput);
}
this.history.push(...outputContents);
// Consolidate adjacent model roles in outputContents
const consolidatedOutputContents: Content[] = [];
for (const content of outputContents) {
const lastContent =
consolidatedOutputContents[consolidatedOutputContents.length - 1];
if (
lastContent &&
lastContent.role === 'model' &&
content.role === 'model' &&
lastContent.parts
) {
lastContent.parts.push(...(content.parts || []));
} else {
consolidatedOutputContents.push(content);
}
}
if (consolidatedOutputContents.length > 0) {
const lastHistoryEntry = this.history[this.history.length - 1];
// Only merge if AFC history was NOT just added, to prevent merging with last AFC model turn.
const canMergeWithLastHistory =
!automaticFunctionCallingHistory ||
automaticFunctionCallingHistory.length === 0;
if (
canMergeWithLastHistory &&
lastHistoryEntry &&
lastHistoryEntry.role === 'model' &&
lastHistoryEntry.parts &&
consolidatedOutputContents[0].role === 'model'
) {
lastHistoryEntry.parts.push(
...(consolidatedOutputContents[0].parts || []),
);
consolidatedOutputContents.shift(); // Remove the first element as it's merged
}
this.history.push(...consolidatedOutputContents);
}
}
}