摸索AI(二)Spring AI实现的Hello World
admin 发布于:2026-01-19 10:11:38
阅读:loading
之前也是花了巨多的时间从Github上下载了一些AI摸索的实践项目,涉及到的有文生图、文生视频、图生图、语音克隆、数字人等,它们的实践对电脑配置的依赖有一定的要求,而且实践的过程复杂程度较高,属于摸索着玩玩而已。本次摸索AI的范围则是面向对擅长领域的代码接入实践。如果你对Java代码交互的AI大模型有一些兴趣,又或者是跟我一样不知从哪里入手,或许看看我这里分享的前后实践过程与实践的案例范围,也是不错的选择。
所以,本系列教程相关的实践是在本地部署大模型,并且使用Java代码与本地的大模型进行交互。除了本地部署的大模型以为,也是可以付费接入网络上的一些付费大模型,比如Deepseek、千问等等,但是对我个人来讲,私有化的本地大模型更加有意义,毕竟可以免费的集成到企业级应用实践当中。
1.Spring AI介绍
Spring AI是一种基于Spring生态系统的人工智能平台,它的目标是将 Spring 生态系统的设计原则(例如可移植性和模块化设计)应用于人工智能领域,利用Spring框架(如Spring Boot)开发和部署AI应用。通过封装底层大模型的HTTP接口交互,简化了与各种人工智能模型的集成过程,提供了以Java语言实现的便捷连接和交互方式。这样,开发者可以在熟悉的Spring环境中,快速构建具有智能功能的应用,提升开发效率和系统的扩展性。
总结核心一段:Spring(Java)不生产AI,Spring AI只是AI大模型调用的搬运工。既然是HTTP接口的调用封装,只要你愿意,也可以不使用Spring AI,使用HttpClient、OkHttp、RestTemplate、OpenFeign都是可以的,使用Spring AI的优势则是在:
(1)可以做到以面向对象的形式游走在各个AI大模型之间,所有的接口交互均以对象的形式进行请求和响应;
(2)轻松集成各个AI大模型组件;
(3)Spring AI 的核心在于解决 AI 集成的根本挑战:将企业数据和API与AI 模型连接起来;
学习Spring AI就必须从官网“https://spring.io/projects/spring-ai”开始,看看一些一手的官方介绍,能理解多少就是多少,再有就是翻一翻官方提供的Github项目代码库“https://github.com/spring-projects/spring-ai”,主要就是看看官方提供的单元测试,查找一些AI调用的示例代码。
2.Spring AI HelloWorld 文本响应
(1)以Spring Boot项目为例,给我的感觉就的是它封装的AI框架叫OpenAI,随即在SpringBoot项目中想要集成官方AI的Maven Starter,Maven中央仓库“https://mvnrepository.com/”能找到的spring-ai-openai-spring-boot-starter最新的版本也只是“1.0.0-M6”,这个版本只是一个阶段性的里程碑版本,不要去使用,可以从“https://central.sonatype.com/”中下载到“1.3.0”的较新版本,不过我这里并不集成starter,所以引用简单的spring-ai-openai坐标,参考如下图所示:
<!-- 非最新的里程碑版本,不用这个 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.0.0-M6</version>
<scope>compile</scope>
</dependency>
<!-- sonatype比较新的版本,不用这个 -->
<dependency>
<groupId>io.github.pig-mesh.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<!-- 直接使用spring-ai-openai -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai</artifactId>
<version>1.1.2</version>
</dependency>(2)最简单的Hello World示例,直接使用单元测试的形式来运行,面向最底层的原始API交互调用,参考代码如下:
@RunWith(JUnit4.class)
public class AiHelloWorldTest {
@Test
public void helloWorld(){
var client = OpenAiChatModel.builder()
.openAiApi(OpenAiApi.builder().apiKey("Chendd").baseUrl("http://localhost:11434").build())
.defaultOptions(OpenAiChatOptions.builder().model("qwen3-vl:2b").streamUsage(false).build())
.build();
final ChatResponse response = client.call(new Prompt("1 + 1 = ?"));
System.out.println(JSON.toJSONString(response , true));
}
}运行结果

代码输出
{
"metadata":{
"empty":false,
"id":"chatcmpl-799",
"model":"qwen3-vl:2b",
"promptMetadata":[],
"rateLimit":{
},
"usage":{
"completionTokens":447,
"nativeUsage":{},
"promptTokens":16,
"totalTokens":463
}
},
"result":{
"metadata":{
"contentFilters":[],
"empty":true,
"finishReason":"STOP"
},
"output":{
"media":[],
"messageType":"ASSISTANT",
"metadata":{
"role":"ASSISTANT",
"messageType":"ASSISTANT",
"refusal":"",
"finishReason":"STOP",
"annotations":[
{}
],
"index":0,
"id":"chatcmpl-799"
},
"text":"The answer to **1 + 1 = ?** is **2**.\n\nThis is a fundamental arithmetic operation. In standard mathematics, adding 1 to 1 results in **2**. \n\n**Why?** \n- It follows the basic rule: **1 + 1 = 2**. \n- This applies universally in all standard mathematical systems (e.g., integers, real numbers). \n\nNo special context or trick is needed here. If this is a simple question for a child learning basic math, the answer is straightforward! \n\n**Answer: 2**",
"toolCalls":[]
}
},
"results":[
{"$ref":"$.result"}
]
}代码说明:
①:使用的本地大模型,apiKey没有要求任意填写即可;
②:baseUrl在源码中设置为本机的大模型地址,默认聊天模型的地址为/v1/chat/completions,可以不用设置;
③:model设置为本机的大模型地址,这个从上一篇文章中“ollama list”命令输出的大模型名称中选择而来;
④:streamUsage默认为false,也可以不用设置;
⑤:result.output.text是输出的纯文本结果;
3.Spring AI HelloWorld 流响应
参考代码
@RunWith(JUnit4.class)
public class AiHelloWorldTest {
@Test
public void helloStream() {
var client = OpenAiChatModel.builder()
.openAiApi(OpenAiApi.builder().apiKey("Chendd").baseUrl("http://localhost:11434")
.completionsPath("/v1/chat/completions").build())
.defaultOptions(OpenAiChatOptions.builder().model("qwen3-vl:2b").streamUsage(true).build())
.build();
final Flux<ChatResponse> stream = client.stream(new Prompt("1 + 1 等于 ?"));
stream.subscribe(chatResponse -> {
final Generation result = chatResponse.getResult();
if (result != null) {
final AssistantMessage output = result.getOutput();
if (output != null) {
final String text = output.getText();
System.out.println(text);
}
}
} , error -> {
System.out.println("发生错误:" + ExceptionUtils.getStackTrace(error));
} , () -> {
System.out.println("全部完成");
});
// 阻塞直到最后一个元素
stream.blockLast();
}
}运行结果

代码说明
①:使用流对象处理的返回值类型Flux<ChatResponse>的消费有一定的复杂度,需要自行处理;
②:如果使用Controller请求,可以直接将这个返回这种类型的返回值,由浏览器来流式输出;
4.其它说明
(1)本次实践的两个案例属于最简化的Spring AI的调用示例,尽可能的使用底层API发起的交互,比较基础;
(2)示例在执行过程中有一定的等待,受电脑性能影响实际的执行耗费了50秒;
(3)给出两个案例实际执行的全过程预览效果图,上述的图片省流只摘选了一部分,完整的预览参考《
示例预览.zip》;
(4)许多案例给出的是结合Spring Boot后的配置注入方式,这种把大模型的服务URL、模型名称等等参数细节配置在application配置文件中的形式,我感觉不够灵活,后续相关的示例均使用硬编码的形式给出,面向底层代码更加便于新手水平理解掌握;
点赞
欢迎来到陈冬冬的学习天地 | 学习与经验整理分享平台