📌 前言

近期将模型从 deepseek-chat 切换到 deepseek-v4-flash 后,调用 API 时报错:

The `reasoning_content` in the thinking mode must be passed back to the API

💡 问题背景

报错信息

400 Bad Request: {"error":{"message":"The `reasoning_content` in the thinking mode must be passed back to the API","type":"invalid_request_error","param":null,"code":"invalid_request_error"}}

DeepSeek V4 Flash 模型特性

根据 DeepSeek 官方文档,V4 Flash 模型支持思考模式(Thinking Mode),会返回 reasoning_content 字段。

当思考模式开启时,API 要求客户端必须将 reasoning_content 回传,否则会报错。


🔍 问题分析

1. 官方文档说明

DeepSeek 的 thinking 参数格式:

{
  "thinking": {
    "type": "enabled"   // 启用思考模式
  }
}

{
  "thinking": {
    "type": "disabled"  // 禁用思考模式
  }
}

2. 尝试过的方案(均无效)

方案 格式 结果
extraParam("thinking", false) "thinking": false ❌ 类型错误
enableThinking(false) 不会序列化到请求中 ❌ 无效
extraBody(Map.of("thinking", false)) "thinking": false ❌ 类型错误
thinking: { "type": "auto", "enabled": false } 参数缺失 type ❌ 缺少必需字段

3. 最终有效方案

根据官方文档,正确格式为:

"thinking": {
  "type": "disabled"
}

🛠️ 解决方案

核心思路

在底层 API 调用时统一拦截请求,强制添加 thinking: {"type": "disabled"} 参数。

修改文件

核心修改文件:

  1. /src/main/java/org/springframework/ai/openai/api/OpenAiApi.java

代码实现

1. 核心拦截逻辑
// OpenAiApi.java
private ChatCompletionRequest ensureThinkingDisabled(ChatCompletionRequest chatRequest) {
    Map<String, Object> extraBody = chatRequest.extraBody();
    if (extraBody == null) {
        extraBody = new HashMap<>();
    }
    
    // 根据 DeepSeek 官方文档设置
    Map<String, Object> thinkingOptions = new HashMap<>();
    thinkingOptions.put("type", "disabled");
    extraBody.put("thinking", thinkingOptions);
    
    return new OpenAiApi.ChatCompletionRequest(
        // ... 传递原有参数,将 extraBody 替换为修改后的版本
    );
}
2. 在 API 调用处应用
// chatCompletionEntity 方法
ChatCompletionRequest modifiedRequest = ensureThinkingDisabled(chatRequest);
HttpEntity<ChatCompletionRequest> requestEntity = new HttpEntity<>(modifiedRequest, headers);

// chatCompletionStream 方法同样处理
ChatCompletionRequest modifiedRequest = ensureThinkingDisabled(chatRequest);
return this.webClient.post()
    .bodyValue(modifiedRequest)
    .retrieve()
    .bodyToFlux(String.class);

📊 技术要点总结

1. 为什么之前的方案无效?

❌ "thinking": false              // API 期望对象,不是布尔值
❌ "thinking": {"enabled": false} // 缺少必需的 type 字段
✅ "thinking": {"type": "disabled"} // 正确格式

2. 为什么在底层拦截?

  • 统一处理:所有模块(规划模块、意图识别模块)都会使用底层 AP

3. 代码架构

┌─────────────────────────────────────┐
│        业务代码(调用 ChatModel)      │
└─────────────────┬───────────────────┘
                  │
                  ▼
┌─────────────────────────────────────┐
│       OpenAiChatModel (SAA)          │
└─────────────────┬───────────────────┘
                  │
                  ▼
┌─────────────────────────────────────┐
│      OpenAiApi (底层拦截点)           │
│  ┌─────────────────────────────────┐ │
│  │ ensureThinkingDisabled()        │ │
│  │   ↓                             │ │
│  │ 添加 thinking: {"type": "disabled"} │
│  └─────────────────────────────────┘ │
└─────────────────┬───────────────────┘
                  │
                  ▼
┌─────────────────────────────────────┐
│       DeepSeek API (V4 Flash)       │
└─────────────────────────────────────┘

✅ 验证结果

修改后重新编译运行,API 调用正常返回,不再报错。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐