文章目录
- [1. 前言](#1. 前言)
- [2. ReactAgent](#2. ReactAgent)
-
- [2.1 开启深度思考](#2.1 开启深度思考)
- [2.2 AgentLlmNode 处理](#2.2 AgentLlmNode 处理)
- [2.3 获取思考内容](#2.3 获取思考内容)
-
- [2.3.1 同步调用](#2.3.1 同步调用)
- [2.3.2 流式输出](#2.3.2 流式输出)
- [3. Graph](#3. Graph)
1. 前言
思考模式下,模型先输出中间推理过程,再给出答案,在 Spring AI Alibaba 中如何实现深度思考 、输出思考内容呢?
2. ReactAgent
2.1 开启深度思考
Spring AI 中有两种方式:
application.yml全局配置- 请求时通过构建
ChatOptions
DashScope 对应的配置参数为 enable_thinking ,默认为不开启:

配置示例:
yml
spring:
application:
name: demo-ai
ai:
dashscope:
# 替换为你的阿里云百炼 API Key
api-key: sk-3d56ec506a8943d0b39f58f306
chat:
options:
model: qwen-plus
enable_thinking: true
DashScopeChatModel 中的参数:

2.2 AgentLlmNode 处理
在 Spring AI 中,思考内容从 AssistantMessage 中直接获取:
java
ChatResponse chatResponse= zhiPuAiChatClient.prompt("你好").options(chatOptions).call().chatResponse();
ZhiPuAiAssistantMessage output = (ZhiPuAiAssistantMessage)chatResponse.getResult().getOutput();
String reasoningContent = output.getReasoningContent();
AgentLlmNode 中会将 ChatResponse、AssistantMessage 封装为 ModelResponse :
java
// 构建并同步调用AI模型,获取完整的聊天响应
ChatResponse response = buildChatClientRequestSpec(request, config).call().chatResponse();
// 初始化默认的助手响应消息,防止模型无返回时出现空指针
AssistantMessage responseMessage = new AssistantMessage("Empty response from model for unknown reason");
// 校验模型响应非空,且存在有效结果
if (response != null && response.getResult() != null) {
// 从模型响应结果中提取正式的助手消息
responseMessage = response.getResult().getOutput();
}
// 如果开启了推理日志打印,则记录本轮Agent的思考返回信息
if (enableReasoningLog) {
logger.info("[ThreadId {}] Agent {} reasoning round {} returned: {}.",
config.threadId().orElse(THREAD_ID_DEFAULT), // 线程ID
agentName, // Agent名称
iterations.get(), // 当前推理轮次
responseMessage // 模型返回的消息
);
}
// 封装助手消息与原始响应,返回给上层流程使用
return ModelResponse.of(responseMessage, response);
ModelResponse 中的 messages 属性中包含了思考内容:

最后又将其更新到 messages 状态中:

2.3 获取思考内容
2.3.1 同步调用
同步调用 call 方法直接从 AssistantMessage 中就能拿到思考内容:
java
AssistantMessage assistantMessages = chatAgent.call("你好");
String content1 = assistantMessages.getMetadata().get("reasoningContent").toString();
System.out.println(content1);
text
好的,用户说"你好",我需要回应。首先看看有什么工具可以用。提供的工具都是获取时间、日期、星期几之类的。用户只是打招呼,可能不需要调用任何工具。不过可能需要确认是否需要提供当前时间或日期作为回应。但用户没有具体问题,可能只是测试。根据指示,如果不需要工具,就直接回复。所以应该不用调用任何函数,直接友好回应即可。
call方法只返回最终回复,对于多次调用时,自然也是只输出最后一个思考内容
invoke、invokeAndGetOutput 同步方法可以返回全局状态 ,其中的 messages 包含了所有对话,自然也能拿到所有思考内容:
java
OverAllState overAllState = chatAgent.invoke("今天星期几?几点了").get();
NodeOutput output = chatAgent.invokeAndGetOutput("今天星期几?几点了").get();
2.3.2 流式输出
流式输出获取思考内容示例:
java
// 1. 获取流式流
Flux<NodeOutput> agentStream = chatAgent.stream("今天星期几?几点了");
// 2. 直接订阅打印,不封装 SSE
agentStream
.filter(nodeOutput -> !(nodeOutput instanceof StreamingOutput<?> so
&& so.getOutputType() == OutputType.AGENT_MODEL_FINISHED))
.subscribe(nodeOutput -> {
try {
String node = nodeOutput.node();
Usage tokenUsage = nodeOutput.tokenUsage();
// 处理流式输出
if (nodeOutput instanceof StreamingOutput<?> streamingOutput) {
Message message = streamingOutput.message();
if (message == null) return;
if (message instanceof AssistantMessage assistantMessage) {
String reasoningContent = assistantMessage.getMetadata().get("reasoningContent").toString();
// ====================== 直接打印!======================
System.out.println("节点:" + node + " | 思考内容:" +reasoningContent);
}
}
} catch (Exception e) {
System.err.println("打印出错:" + e.getMessage());
}
}, error -> {
System.err.println("执行错误:" + error.getMessage());
});
打印结果:
text
节点:_AGENT_MODEL_ | 思考内容:好的,用户
节点:_AGENT_MODEL_ | 思考内容:问今天星期
节点:_AGENT_MODEL_ | 思考内容:几和几点
节点:_AGENT_MODEL_ | 思考内容:了。我需要调
节点:_AGENT_MODEL_ | 思考内容:用两个工具来获取
节点:_AGENT_MODEL_ | 思考内容:这些信息。
3. Graph
思考模式 是大模型节点的输出,在 Graph 工作流中的 LLM 节点和 AgentLlmNode 一样返回即可,使用方式也和 ReactAgent 一样,就不赘述了!!!