Spring AI 无法获取大模型深度思考内容?解决方案来了

Luca Ju
2025-08-13 / 0 评论 / 201 阅读 / 正在检测是否收录...

大模型的 “深度思考” 能力(即生成回答前的推理过程)正在成为提升交互体验的关键



深度思考场景


比如下面图中所看到的,Qwen 等模型会将推理过程放在reasoning_content字段中,让用户看到 “思考过程” 而非直接得到结果。但在 Java 开发中,使用 Spring AI 或 LangChain4J 等框架时,你可能会发现:这些框架会忽略reasoning_content字段,只返回最终回答


接口返回参数截图

 这篇文章就来拆解这个问题的原因,并提供一套通过自定义接口调用实现 “获取完整思考过程” 的解决方案。

问题:为什么框架无法获取深度思考内容?

目前主流 Java 框架(Spring AI、LangChain4J)在设计时,默认只处理大模型的 “最终回答”(通常在content字段),而忽略了部分模型新增的 “思考过程” 字段(如reasoning_content)。具体表现为:

  1. 字段被过滤:框架的响应解析逻辑中,没有处理reasoning_content的代码,导致这部分数据被直接丢弃。
  2. 交互体验割裂:大模型的生成逻辑是 “先思考、后输出”,但框架会等待完整结果生成后才返回,用户需要长时间等待,且看不到中间思考过程。

举个例子:当你调用 Qwen 模型时,原始接口返回会包含两部分内容:

  • reasoning_content:“用户问我是谁,我需要先介绍自己的名字,再说明我的能力,还要保持友好的语气……”(思考过程)
  • content:“我是通义千问,由通义实验室研发的超大规模语言模型。我能够帮助用户回答问题、创作文字,以及进行对话交流。如果你有任何问题或需要帮助,随时告诉我!”(最终回答)

但通过 Spring AI 调用时,你只能拿到content部分,错失了展示 “思考过程” 的机会。

解决方案:自定义接口调用,掌控原始数据

既然框架的封装会丢失信息,那最直接的方案就是:绕过框架的限制,直接调用大模型的原生 API,获取完整响应数据。

这种方式的优势在于:

  • 可获取所有字段(包括reasoning_contentusage等元数据);
  • 灵活控制流式输出逻辑,实现 “思考过程” 和 “最终回答” 的实时展示;
  • 便于业务扩展(如自定义缓存、日志、过滤规则等)。

下面以 “调用硅基流动接口获取 Qwen 模型的思考过程” 为例,演示具体实现。

实战:用 Spring WebFlux 调用硅基流动 API

硅基流动是一个大模型聚合平台,支持 Qwen、GPT 等模型的调用,其 API 会返回完整的reasoning_content字段。我们用 Spring WebFlux(响应式 HTTP 客户端)实现调用,既能处理流式输出,又能获取原始响应。

步骤 1:了解接口参数

参考硅基流动官方 API 文档,核心请求参数如下:

  • messages:对话历史(包含rolecontent);
  • model:模型名称(如moonshotai/Kimi-Dev-72B);
  • stream:是否开启流式输出(设为true,实时获取思考和回答);
  • temperature:控制输出随机性(0-1 之间)。

步骤 2:编码实现(获取完整响应)

import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;

public class SiliconFlowTest {

    // 硅基流动API地址
    private static final String API_URL = "https://api.siliconflow.cn/v1/chat/completions";
    // 你的API Key(从硅基流动控制台获取)
    private static final String API_KEY = "your api-key";
      private static final String NULL_MESSAGE = "null";

    @Test
    public void testGetReasoningContent() {
        // 1. 构建请求体(包含对话和参数)
        String requestBody = """
            {
              "messages":
              [
                  {
                      "content": "你是一个聊天大师,请回答用户的问题。",
                      "role": "system"
                  },
                  {
                      "content": "什么是Java响应式编程?",
                      "role": "user"
                  }
              ],
              "model": "Qwen/Qwen3-8B",
              "stream": true,
              "temperature": 0.7
            }
                """;

        // 2. 用WebClient发送POST请求(响应式客户端)
        WebClient webClient = WebClient.create(API_URL);
        Flux<String> responseFlux = webClient.post()
                .contentType(MediaType.APPLICATION_JSON)
                .header("Authorization", "Bearer " + API_KEY) // 认证头
                .bodyValue(requestBody)
                .retrieve()
                .bodyToFlux(String.class); // 流式接收原始响应

        // 3. 处理响应(提取思考过程和最终回答)
        responseFlux.subscribe(
            // 每收到一段流式数据(SSE格式)
            chunk -> {
                    // 解析原始响应(实际项目中建议用JSON工具解析)
                    String reasoning = extractField(chunk, "reasoning_content");
                    String answer = extractField(chunk, "content");
                    if (!NULL_MESSAGE.equals(reasoning)) {

                        System.out.println("[思考过程] " + reasoning);
                    }
                    if (!NULL_MESSAGE.equals(answer)) {
                        System.out.println("[最终回答] " + answer);
                    }
                },
            // 错误处理
            error -> System.err.println("请求错误:" + error.getMessage()),
            // 完成回调
            () -> System.out.println("\n=== 输出结束 ===")
        );

        // 阻塞等待(测试环境用,实际项目无需此代码)
        try { Thread.sleep(30000); } catch (InterruptedException e) { e.printStackTrace(); }
    }

    // 简易提取字段的工具方法(实际项目建议用Jackson/Gson解析)
    private String extractField(String chunk, String field) {
        String prefix = "\"" + field + "\":";
        if (chunk.contains(prefix)) {
            String sub = chunk.split(prefix)[1].split(",\"")[0];
            return sub.replace("\"", "").replace("\\n", "\n").trim();
        }
        return "";
    }
}

代码说明

  1. 请求构建:通过 JSON 字符串定义对话和参数,重点开启stream: true以实时获取数据。
  2. 响应处理

    • Flux<String>接收流式响应(SSE 格式,每段是一个 JSON 片段);
    • 通过subscribe()回调实时解析reasoning_content(思考过程)和content(最终回答);
    • 实际项目中建议用 Jackson 等工具解析 JSON,替代示例中的简易字符串处理。
  3. 核心价值:通过直接处理原始响应,同时获取 “思考过程” 和 “最终回答”,为前端展示(如分区域显示思考和回答)提供数据支持。

业务扩展:如何在前端展示思考过程?

获取到reasoning_content后,可通过以下方式提升用户体验:

  1. 分区域展示:前端用两个容器,一个实时显示思考过程(灰色小字),一个显示最终回答(黑色大字)。
  2. 格式标记:在后端给思考过程加上特殊标记(如<think></think>),前端解析时按标记区分:
  3. 加载动画:在思考过程输出时,前端显示 “正在思考…” 的动画,降低用户等待焦虑。

总结

当 Spring AI 等框架无法满足 “获取大模型深度思考内容” 的需求时,直接调用原生 API 是最灵活的解决方案。通过 Spring WebFlux 处理流式响应,既能实时获取reasoning_contentcontent,又能保留扩展空间,轻松实现个性化业务逻辑。

如果你需要更复杂的功能(如多模型切换、对话历史管理),可以在此基础上封装工具类,或结合响应式编程框架(如 Project Reactor)优化数据流处理。

最后,附上两个链接:

1

评论 (0)

取消