摸索AI(二)Spring AI实现的Hello World


placeholder image
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));
    }

}

运行结果

HelloWorld-精简版-含水印.gif

代码输出

{
	"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();
    }

}

运行结果

HelloWorld-流精简版-含水印.gif

代码说明

①:使用流对象处理的返回值类型Flux<ChatResponse>的消费有一定的复杂度,需要自行处理;

②:如果使用Controller请求,可以直接将这个返回这种类型的返回值,由浏览器来流式输出;

4.其它说明

(1)本次实践的两个案例属于最简化的Spring AI的调用示例,尽可能的使用底层API发起的交互,比较基础;

(2)示例在执行过程中有一定的等待,受电脑性能影响实际的执行耗费了50秒;

(3)给出两个案例实际执行的全过程预览效果图,上述的图片省流只摘选了一部分,完整的预览参考《示例预览.zip》;

(4)许多案例给出的是结合Spring Boot后的配置注入方式,这种把大模型的服务URL、模型名称等等参数细节配置在application配置文件中的形式,我感觉不够灵活,后续相关的示例均使用硬编码的形式给出,面向底层代码更加便于新手水平理解掌握;


 点赞


 发表评论

当前回复:作者

 评论列表


留言区