agentscope-ai / agentscope-ai/agentscope-java

[Bug] AutoContextMemory 可能将压缩生成的 assistant 消息误判为最终 assistant 回复

Aberta
#1,483 1 comentário 0 reações 1 responsável Reivindicada por @carterkong-1 Ver no GitHub
area/ext/memory bug
Linguagem predominante
Java
Estrelas
5.6k
Forks
1.3k
Merge médio
4d 12h
PRs com merge (30d)
77

Descrição

## 问题描述

`AutoContextMemory` 目前可能会将某些“压缩流程生成的 assistant 摘要消息”误判为真实的最终 assistant 回复(final assistant response)。

这个问题在历史 tool 消息被 Strategy 1 压缩后尤其明显。Strategy 1 会把一段历史 tool 消息替换成一个新的 `ASSISTANT` 文本消息,而后续逻辑可能会把这个 synthetic assistant 当成真实的最终 assistant 回复处理。

这样会导致 `latestAssistantIndex` 的判断错误,而这个边界又被多个压缩策略复用,所以影响不止 Strategy 4。

## 预期行为

压缩流程生成的 synthetic assistant 消息,不应该被当成真实的最终 assistant 回复。

只有真正面向用户的 final assistant reply,才应该参与以下逻辑:

- latest assistant 边界判定
- previous round 的轮次闭合
- interaction message 提取

## 实际行为

在历史 tool 消息经过 Strategy 1 压缩后,生成的 `ASSISTANT` 文本摘要消息,可能会被 `MsgUtils.isFinalAssistantResponse()` 识别为真实 final assistant response。

这样会导致:

- `latestAssistantIndex` 错误
- Strategy 4 无法按整轮总结 previous round
- Strategy 1/2/3 的历史边界保护范围错误
- `getInteractionMsgs()` 可能把 synthetic summary 当成真实 assistant reply 导出

## 触发结构示例

原始轮次结构:

`user -> tool_use/tool_result... -> assistant_final`

经过 Strategy 1 后可能变成:

`user -> assistant_tool_summary -> assistant_final`

如果 `assistant_tool_summary` 被误判为真实 final assistant response,那么 previous round 的轮次闭合就会提前发生,导致后续历史压缩逻辑失真。

## 影响范围

从源码来看,这个问题会影响多个依赖 `isFinalAssistantResponse()` 或 `latestAssistantIndex` 的位置。

### 1. Strategy 1 历史 tool 压缩边界

历史 tool 消息的搜索范围依赖 latest assistant 边界。

如果 synthetic assistant 被误判为真实 assistant,那么搜索边界会前移,后面的历史 tool 段会被错误保护,导致历史 tool 压缩不完整。

### 2. Strategy 2/3 历史大消息 offload

历史大消息 offload 只处理 latest assistant 之前的消息。

如果 latest assistant 判错,那么本该压缩/offload 的历史大消息会被错误保留。

### 3. Strategy 4 previous round summary

Strategy 4 当前按 user + “第一个 final assistant”做 previous round 配对。

如果中间插入了 synthetic assistant,那么一轮可能被提前闭合,导致:

- previous round 无法整轮压缩
- assistant final reply 被落在轮外
- 某些轮次直接被跳过

### 4. getInteractionMsgs()

`getInteractionMsgs()` 会提取 USER 和 final ASSISTANT 消息。

如果 synthetic assistant 被判成 final assistant,那么导出的 interaction view 会混入压缩摘要消息,这可能进一步影响:

- 交互展示
- 会话导出
- 训练/分析数据准备

### 5. 压缩策略整体顺序会被扰动

由于 Strategy 1/2/3/4 都依赖 latest assistant 边界,如果历史压缩范围被缩小,系统可能更早落到 Strategy 5/6,变成优先压当前轮,而不是先清理历史轮次。

这会使整体压缩行为偏离设计预期。

## 根因分析

`MsgUtils.isFinalAssistantResponse()` 当前会排除:

- 包含 `ToolUseBlock` 的 assistant 消息
- 包含 `ToolResultBlock` 的 assistant 消息
- 带有 `compressed_current_round=true` 标记的压缩消息

但是它没有排除 Strategy 1 这类“历史压缩生成的 synthetic assistant summary”。

与此同时,Strategy 1 生成的替换消息具备以下特征:

- `role = ASSISTANT`
- 纯文本内容
- 带 `_compress_meta`

因此它在后续逻辑里看起来很像一个普通 final assistant reply。

## 建议方向

建议显式区分“真实 final assistant reply”和“压缩流程生成的 synthetic assistant”。

例如可以考虑:

- 给 Strategy 1 生成的 synthetic summary 打专门的 metadata 标记
- 让 `isFinalAssistantResponse()` 忽略这类 synthetic assistant 消息

这与当前对 `compressed_current_round=true` 的特殊处理思路是一致的。

## 补充说明

我最初是从 Strategy 4 不按整轮压缩的问题开始排查的,但进一步看代码后发现,这不是单独的 Strategy 4 问题,而是 `final assistant` 边界定义被多个历史压缩逻辑复用,且 synthetic assistant 没有被排除所引起的系统性问题。

Guia de contribuição

Abrir o guia de contribuição

Avaliação

Esta issue ainda não foi avaliada.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.