agentscope-ai / agentscope-ai/agentscope-java

[Bug]:AutoContextMemory#summaryPreviousRoundMessages implementation and comment inconsistent

未关闭
#1,178 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
area/ext/memory bug
主要语言
Java
星标
5.6k
派生
1.3k
平均合并
4 天 12 小时
30 天内合并 PR
77

描述

**AgentScope-Java is an open-source project. To involve a broader community, we recommend asking your questions in English.**

**Describe the bug**
AutoContextMemory#summaryPreviousRoundMessages implementation and comment inconsistent.
Original comment:
> /**
* Summarize all previous rounds of conversation messages before the latest assistant.
*
*

This method finds the latest assistant message and summarizes all conversation rounds
* before it. Each round consists of messages between a user message and its corresponding
* assistant message (typically including tool calls/results and the assistant message itself).
*
*

Example transformation:
* Before: "user1-tools-assistant1, user2-tools-assistant2, user3-tools-assistant3, user4"
* After: "user1-summary, user2-summary, user3-summary, user4"
* Where each summary contains the compressed information from tools and assistant of that round.
*
*

Strategy:
* 1. Find the latest assistant message (this is the current round, not to be summarized)
* 2. From the beginning, find all user-assistant pairs before the latest assistant
* 3. For each pair, summarize messages between user and assistant (including assistant message)
* 4. Replace those messages (including assistant) with summary (process from back to front to avoid index shifting)
*
* @param rawMessages the list of messages to process
* @return true if summary was actually performed, false otherwise
*/

According to 'Summarize all previous rounds of conversation messages before the latest assistant' in comment and code implementation, for 'the 'Example transformation', 'user3-tools-assistant3' will not be summarized. The correct content is as follows:
> * Before: "user1-tools-assistant1, user2-tools-assistant2, user3-tools-assistant3, user4"
* After: "user1-summary, user2-summary, **user3-tools-assistant3,** user4"

AutoContextMemory#summaryPreviousRoundMessages will not summary last pair, when last pair has too many messages, it will trigger a large amount of context.

**To Reproduce**
Steps to reproduce the behavior:

Branch: release/1.0.10
Method: AutoContextMemory#summaryPreviousRoundMessages

1. You code
```java
private boolean summaryPreviousRoundMessages(List rawMessages) {
if (rawMessages == null || rawMessages.isEmpty()) {
return false;
}

// Step 1: Find the latest assistant message that is a final response (not a tool call)
int latestAssistantIndex = -1;
for (int i = rawMessages.size() - 1; i >= 0; i--) {
Msg msg = rawMessages.get(i);
if (MsgUtils.isFinalAssistantResponse(msg)) {
latestAssistantIndex = i;
break;
}
}

// If no assistant message found, nothing to summarize
if (latestAssistantIndex < 0) {
return false;
}

// Step 2: Find all user-assistant pairs before the latest assistant
// We'll collect them as pairs: (userIndex, assistantIndex)
List> userAssistantPairs = new ArrayList<>();
int currentUserIndex = -1;

for (int i = 0; i < latestAssistantIndex; i++) {
Msg msg = rawMessages.get(i);
if (msg.getRole() == MsgRole.USER) {
currentUserIndex = i;
} else if (MsgUtils.isFinalAssistantResponse(msg) && currentUserIndex >= 0) {
// Found a user-assistant pair (assistant message is a final response, not a tool
// call)
if (i - currentUserIndex != 1) {
userAssistantPairs.add(new Pair<>(currentUserIndex, i));
}

currentUserIndex = -1; // Reset to find next pair
}
}

// If no pairs found, nothing to summarize
if (userAssistantPairs.isEmpty()) {
return false;
}

log.info(
"Found {} user-assistant pairs to summarize before latest assistant at index {}",
userAssistantPairs.size(),
latestAssistantIndex);

// Step 3: Process pairs from back to front to avoid index shifting issues
boolean hasSummarized = false;
for (int pairIdx = userAssistantPairs.size() - 1; pairIdx >= 0; pairIdx--) {
Pair pair = userAssistantPairs.get(pairIdx);
int userIndex = pair.first();
int assistantIndex = pair.second();

// Messages to summarize: from user to assistant (inclusive of both)
// Include user message for context, but we'll only remove messages after user
int startIndex = userIndex + 1; // Messages to remove start after user
int endIndex = assistantIndex; // Include assistant message in removal

// If no messages between user and assistant (including assistant), skip
if (startIndex > endIndex) {
log.info(
"No messages to summarize between user at index {} and assistant at index"
+ " {}",
userIndex,
assistantIndex);
continue;
}

// Include user message in messagesToSummarize for context, but keep it in the final
// list
List messagesToSummarize = new ArrayList<>();
messagesToSummarize.add(rawMessages.get(userIndex)); // Include user message for context
for (int i = startIndex; i <= endIndex; i++) {
messagesToSummarize.add(rawMessages.get(i));
}

log.info(
"Summarizing round {}: user at index {}, messages [{}, {}], totalCount={}"
+ " (includes user message for context)",
pairIdx + 1,
userIndex,
startIndex,
endIndex,
messagesToSummarize.size());

// Step 4: Check if original token count is sufficient for compression
// Skip compression if tokens are below threshold to avoid compression overhead
int originalTokens = TokenCounterUtil.calculateToken(messagesToSummarize);
int threshold = autoContextConfig.getMinCompressionTokenThreshold();
if (originalTokens < threshold) {
log.info(
"Skipping conversation summary for round {}: original tokens ({}) is below"
+ " threshold ({})",
pairIdx + 1,
originalTokens,
threshold);
continue;
}

log.info(
"Proceeding with conversation summary for round {}: original tokens: {},"
+ " threshold: {}",
pairIdx + 1,
originalTokens,
threshold);

// Step 5: Offload original messages if contextOffLoader is available
String uuid = UUID.randomUUID().toString();
offload(uuid, messagesToSummarize);
log.info("Offloaded messages to be summarized: uuid={}", uuid);

// Step 6: Generate summary
Msg summaryMsg = summaryPreviousRoundConversation(messagesToSummarize, uuid);

// Build metadata for compression event
Map metadata = new HashMap<>();
if (summaryMsg.getChatUsage() != null) {
metadata.put("inputToken", summaryMsg.getChatUsage().getInputTokens());
metadata.put("outputToken", summaryMsg.getChatUsage().getOutputTokens());
metadata.put("time", summaryMsg.getChatUsage().getTime());
}

// Record compression event (before removing messages to preserve indices)
recordCompressionEvent(
CompressionEvent.PREVIOUS_ROUND_CONVERSATION_SUMMARY,
startIndex,
endIndex,
rawMessages,
summaryMsg,
metadata);

// Step 7: Remove the messages between user and assistant (including assistant), then
// replace with summary
// Since we're processing from back to front, the indices are still accurate
// for the current pair (indices of pairs after this one have already been adjusted)

// Remove messages from startIndex to endIndex (including assistant, from back to front
// to avoid index shifting)
int removedCount = endIndex - startIndex + 1;
rawMessages.subList(startIndex, endIndex + 1).clear();

// After removal, the position where assistant was is now: assistantIndex - removedCount
// + 1
// But since we removed everything including assistant, we insert summary at the
// position after user
int insertIndex = userIndex + 1;

// Insert summary after user (replacing the removed messages including assistant)
rawMessages.add(insertIndex, summaryMsg);

log.info(
"Replaced {} messages [indices {}-{}] with summary at index {}",
removedCount,
startIndex,
endIndex,
insertIndex);

hasSummarized = true;
}

return hasSummarized;
}
```

2. How to execute
3. See error
**Expected behavior**

According to 'Summarize all previous rounds of conversation messages before the latest assistant' in comment and code implementation, for 'the 'Example transformation', 'user3-tools-assistant3' will not be summarized. The correct content is as follows:
> * Before: "user1-tools-assistant1, user2-tools-assistant2, user3-tools-assistant3, user4"
* After: "user1-summary, user2-summary, **user3-tools-assistant3,** user4"

AutoContextMemory#summaryPreviousRoundMessages will not summary last pair, when last pair has too many messages, it will trigger a large amount of context.

**Error messages**
Detailed error messages.

**Environment (please complete the following information):**

- AgentScope-Java Version: release/1.0.10
- Java Version: [e.g. 17]
- OS: [e.g. macos]

**Additional context**
Add any other context about the problem here.

贡献指南

打开贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。