摸索AI(六)Spring AI获取思考过程(推理)
Spring Aiadmin 发布于:2026-03-15 19:16:30
阅读:loading
之前也是花了巨多的时间从Github上下载了一些AI摸索的实践项目,涉及到的有文生图、文生视频、图生图、语音克隆、数字人等,它们的实践对电脑配置的依赖有一定的要求,而且实践的过程复杂程度较高,属于摸索着玩玩而已。本次摸索AI的范围则是面向对擅长领域的代码接入实践。如果你对Java代码交互的AI大模型有一些兴趣,又或者是跟我一样不知从哪里入手,或许看看我这里分享的前后实践过程与实践的案例范围,也是不错的选择。
1.基本介绍
所以,本系列教程相关的实践是在本地部署大模型,并且使用Java代码与本地的大模型进行交互。除了本地部署的大模型以为,也是可以付费接入网络上的一些付费大模型,比如Deepseek、千问等等,但是对我个人来讲,私有化的本地大模型更加有意义,毕竟可以免费的集成到企业级应用实践当中。
本次实践围绕使用Spring AI在花活应用中的科学实践,主要是在接口交互的过程中快速向用户反馈响应数据中的AI思考过程,AI的思考过程不是必须的,但若是呈现一个思考的过程则显得更加专业。所以,本期的实践则是使用Spring AI来获取大模型思考过程信息。前后也是花了许多的时间来摸索,尝试了Spring Open API中的多款框架均未摸索出来个结果,锲而不舍的一再尝试,最终在经历了spring-ai-openai、spring-ai-deepseek、spring-ai-ollama等等API后算是成功了。
前面的文章中使用Spring AI获取数据后,也有一些接口获取到了Reason的信息,但是未能成功的异步获取(再获取最终结果前优先获取到思考过程),所以在本篇特专门针对于获取思考过程的实现做个总结,(因为整个过程也是各种费劲,纯粹的闭门摸索,过程艰辛、程度复杂),非常有整理意义。特别值得说的一点是之前调用AI的本地大模型URL为“http://localhost:11434/v1/chat/completions”或“http://localhost:11434/v1/completions”,而本次实践的URL为“http://localhost:11434/api/chat”,这是最大的差异,并且相关API使用的是OllamaApi,其它的OpenAiApi、DeepSeekApi实践的未能成功。
2.单元测试示例
第一个示例演示是在单元测试中进行的,使用自带的API来消费接口的响应结果,参考代码和IDEA的控制台输出如下所示:
@RunWith(JUnit4.class)
public class AiHelloThinkTest {
@Test
public void testHelloThink() throws Exception {
final OllamaApi ollamaAiApi = OllamaApi.builder().baseUrl("http://localhost:11434").build();
List<OllamaApi.Message> messages = new ArrayList<>();
messages.add(OllamaApi.Message.builder(OllamaApi.Message.Role.SYSTEM).content("你是一个非常专业的问答专家,请使用中文回答问题。").build());
messages.add(OllamaApi.Message.builder(OllamaApi.Message.Role.USER).content("1 + 1 = ?").build());
OllamaApi.ChatRequest chatRequest = OllamaApi......build();
final Flux<OllamaApi.ChatResponse> chatResponseFlux = ollamaAiApi.streamingChat(chatRequest);
System.out.println(chatResponseFlux);
AtomicBoolean thinkStart = new AtomicBoolean(false);
AtomicBoolean thinkEnd = new AtomicBoolean(false);
chatResponseFlux.subscribe(chatResponse -> {
final OllamaApi.Message message = chatResponse.message();
final String thinking = message.thinking();
if (StringUtils.isNotEmpty(thinking)) {
if (! thinkStart.get()) {
System.out.println("\n<think>");
thinkStart.set(true);
}
System.out.print(thinking);
}
final String content = message.content();
if (StringUtils.isNotEmpty(content)) {
if (! thinkEnd.get()) {
System.out.println("\n</think>");
thinkEnd.set(true);
}
System.out.print(content);
}
});
chatResponseFlux.blockLast();
System.out.println("over1");
chatResponseFlux.onBackpressureLatest();
System.out.println("over2");
TimeUnit.MINUTES.sleep(5);
}
}
3.浏览器示例
第二个示例演示是在浏览器中进行的,用户通过URL传递自定义的问题,可以非常丝滑的看到AI大模型的思考过程,参考代码和IDEA的控制台输出如下所示:
@ApiVersion("1")
@RequestMapping(value = "/ai" , produces = MediaType.APPLICATION_JSON_VALUE)
@RestController
@Tag(name = "Ai")
public class AiController {
@GetMapping(consumes = MediaType.ALL_VALUE , produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@Operation(summary = "Ai" , description = "Ai简单问答")
@ApiOperationSupport(order = 10)
public Flux<OllamaApi.ChatResponse> getUsers(@RequestParam("content") String content) {
final OllamaApi ollamaAiApi = OllamaApi.builder().baseUrl("http://localhost:11434").build();
List<OllamaApi.Message> messages = new ArrayList<>();
messages.add(OllamaApi.Message.builder(OllamaApi.Message.Role.SYSTEM).content("你是一个非常专业的问答专家,请使用中文回答问题。").build());
messages.add(OllamaApi.Message.builder(OllamaApi.Message.Role.USER).content(content).build());
OllamaApi.ChatRequest chatRequest = OllamaApi......build()).messages(messages).build();
final Flux<OllamaApi.ChatResponse> chatResponseFlux = ollamaAiApi.streamingChat(chatRequest);
// 使用 Flux.create 创建流式响应
return chatResponseFlux;
}
}
(浏览器输出)

(F12查看网络请求)
4.其它说明
(1)本次实践的代码是使用Spring AI调用本地大模型并获取思考过程(推理)的实现;
(2)示例在执行过程中有一定的等待,有了思考过程的输出,实际上请求响应的结果并不是感觉很慢;
(3)示例中浏览器的输出结果包含了AI执行过程中的各个信息,JSON格式的对象值略有不同,参考JSON如下:
"data": {
"model": "qwen3:8b",
"created_at": "2026-03-15T12:17:13.814799200Z",
"message": {
"role": "assistant",
"content": "",
"thinking": "好的"
},
"done": false
},
"data": {
"model": "qwen3:8b",
"created_at": "2026-03-15T12:18:05.451375600Z",
"message": {
"role": "assistant",
"content": "学习"
},
"done": false
}
(4)给出两个案例实际执行的全过程预览效果图,上述的图片省流只摘选了一部分,完整的预览参考《
示例参考.zip》,包含完整的示例请求和响应结果;
(5)许多案例给出的是结合Spring Boot后的配置注入方式,这种把大模型的服务URL、模型名称等等参数细节配置在application配置文件中的形式,我感觉不够灵活,后续相关的示例均使用硬编码的形式给出,面向底层代码更加便于新手水平理解掌握;
点赞
欢迎来到陈冬冬的学习天地 | 学习与经验整理分享平台