agentscope-ai / agentscope-ai/agentscope-java
[Bug]:AnthropicChatModel 将 ThinkingBlock 作为普通 text 传回 API,导致 400 错误
- Linguagem predominante
- Java
- Estrelas
- 5.6k
- Forks
- 1.3k
- Merge médio
- 4d 12h
- PRs com merge (30d)
- 77
Descrição
先撤销刚才的源码修改:
已撤销。以下是你可以提 issue 的完整描述:
---
## Issue:
### 环境信息
- AgentScope v2.0.0
- 模型:deepseek-v4-pro(通过 Anthropic 协议接入的第三方模型)
- 场景:多轮对话,ReActAgent
### 问题现象
多轮对话时,Anthropic API 报 400 错误:
```
The `content[].thinking` in the thinking mode must be passed back to the API.
```
### 根因
`AnthropicMessageConverter.java` 第131-137行,将 `ThinkingBlock` 转换为**普通 `TextBlockParam`** 传回 API:
```java
} else if (block instanceof ThinkingBlock thinkingBlock) {
contentBlocks.add(
ContentBlockParam.ofText(
TextBlockParam.builder()
.text(thinkingBlock.getThinking())
.build()));
}
```
问题在于:
1. 模型上一轮回复产生了 thinking 块,AgentScope 存入对话历史
2. 下一轮请求时,thinking 块被转成**普通 `text` 类型**传回 API
3. 但 Anthropic API 要求 thinking 内容必须用** `thinking` content type** 原样传回(包含 `thinking`、`signature` 等字段),不能用 `text` 类型
4. 如果对话经过 CompactionMiddleware 压缩,thinking 块可能被截断或丢失,传回不完整内容,API 直接报 400
### 触发条件
1. 使用 Anthropic 协议的模型(Claude / 第三方如 deepseek-v4-pro)
2. 开启了 thinking 模式(`enableThinking: true` 或 `thinkingBudget` 设了值)
3. 多轮对话(第二轮起),或对话历史经过 compaction 压缩后
### 建议修复
**方案A(推荐)**:ThinkingBlock 应该用 Anthropic 的 `thinking` content type 传回,包含 `thinking` 和 `signature` 字段,而不是转成 `text`:
```java
} else if (block instanceof ThinkingBlock thinkingBlock) {
// 用 Anthropic 原生的 thinking content type 传回
contentBlocks.add(ContentBlockParam.ofThinking(
ThinkingBlockParam.builder()
.type("thinking")
.thinking(thinkingBlock.getThinking())
.signature(thinkingBlock.getSignature()) // 需要在 ThinkingBlock 中保存 signature
.build()));
}
```
**方案B(兜底)**:如果无法保证 thinking 块的完整性(如 compaction 后),应该**跳过** ThinkingBlock,不传回 API:
```java
} else if (block instanceof ThinkingBlock) {
// Skip: thinking 块不完整时传回会导致 400
continue;
}
```
### 补充说明
- CompactionMiddleware 压缩后也会丢失 thinking 块的 `signature`,即使转成正确的 thinking type 也会失败
- 对于第三方模型(非 Claude 原生),thinking 的 signature 机制可能不适用
- 建议增加一个配置项:`stripThinkingBlocks=true`,在发送前移除所有 thinking 块
---
Guia de contribuição
Avaliação
Esta issue ainda não foi avaliada.