agentscope-ai / agentscope-ai/agentscope-java

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

Abierto
#1,483 1 comentario 0 reacciones 1 asignado Reclamado por @carterkong-1 Ver en GitHub
area/ext/memory bug
Lenguaje dominante
Java
Estrellas
5.6k
Forks
1.3k
Merge medio
4 d 12 h
PR fusionados (30 d)
77

Descripción

## 问题描述

`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 没有被排除所引起的系统性问题。

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.