乐于分享
好东西不私藏

Spring AI 如何工作的?10 行代码给应用加上 AI 对话能力

Spring AI 如何工作的?10 行代码给应用加上 AI 对话能力

<<< 点赞👍🏻+关注❤️ 每天分享干货好文 >>>

🎁 福利时间

如果你正在备战大厂面试,我整理了一个 开发者的知识库 涵盖 Java 程序员需要掌握的核心知识。

知识库地址:https://farerboy.com/


在 Java 领域,Spring 生态系统一直占据着统治地位。随着大语言模型(LLM)的爆发,Spring 官方迅速响应,推出了 Spring AI 项目。它的目标很简单:让 Java 开发者能像使用 Spring Data 访问数据库一样,自然地访问 AI 模型

本文将带你从零开始,只需极少的代码,就能为你的 Spring Boot 应用赋予强大的 AI 对话能力,并深入剖析其背后的设计哲学。


一、 核心依赖与准备

Spring AI 目前对主流模型提供商(OpenAI, Azure OpenAI, Ollama, Mistral 等)都有很好的支持。为了方便演示,我们以 OpenAI(或者兼容 OpenAI 接口的模型,如 DeepSeek、Ollama)为例。

1. 环境要求

  • Java 17+
  • Spring Boot 3.2+
  • Spring AI 1.1.6 (目前比较新的版本)

2. 引入依赖

在 pom.xml 中添加 Spring AI BOM 和 Starter:

<dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>1.1.6</version><!-- 请使用最新稳定版本 --><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-openai-spring-boot-starter</artifactId></dependency><!-- Web 依赖用于测试 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>

3. 配置文件

在 application.yml 中配置你的 API Key 和 Base URL(如果使用 Ollama 或国内镜像,修改 base-url 即可):

spring:ai:openai:api-key:${OPENAI_API_KEY:your-api-key-here}base-url:https://api.openai.com# 如果是 Ollama 本地部署,通常是 http://localhost:11434chat:options:model:gpt-3.5-turbo# 或 gpt-4o, llama3 等temperature:0.7

二、 10 行代码实现对话

Spring AI 提供了两种主要的交互方式:底层的 ChatModel 接口和高层的 ChatClient 构建器。**推荐使用 ChatClient**,因为它提供了流式 API、Prompt 模板绑定等更强大的功能。

下面是一个完整的 Spring Boot Controller,实现了接收用户消息并返回 AI 回答的功能。

import org.springframework.ai.chat.client.ChatClient;import org.springframework.web.bind.annotation.*;@RestController@RequestMapping("/api")publicclassAiChatController{privatefinal ChatClient chatClient;// 1. 注入 ChatClient.BuilderpublicAiChatController(ChatClient.Builder builder){// 2. 构建 ChatClientthis.chatClient = builder.build();    }@GetMapping("/chat")public String chat(@RequestParam String message){// 3. 发起请求 (核心逻辑仅 3-4 行)return chatClient.prompt()                .user(message)           // 设置用户输入                .call()                  // 发起调用                .content();              // 获取文本内容    }}

启动应用,访问:http://localhost:8080/api/chat?message=给我讲个关于Java的笑话,你将立即收到 AI 的回复。


三、 Spring AI 是如何工作的?

为什么代码这么少?Spring AI 在背后做了大量的抽象工作。我们需要理解三个核心概念:ChatModelPrompt 和 ChatClient

1. 统一的模型抽象 ChatModel

Spring AI 的核心是一个名为 ChatModel 的接口。无论底层是 OpenAI、Claude 还是 Ollama,Spring AI 都将其统一为这个接口。

publicinterfaceChatModel{// 阻塞式调用ChatResponse call(Prompt prompt);// 流式调用Flux<ChatResponse> stream(Prompt prompt);}

开发者只需要面向 ChatModel 编程,无需关心底层是 HTTP 请求还是 gRPC,也无需关心 JSON 格式的差异。当你切换模型时,只需更改配置,业务代码零修改

2. Prompt 的工程化

在 AI 应用中,Prompt 不仅仅是字符串,它包含了 System Message、User Message、以及可选的 Function Calling 定义。

chatClient.prompt() 实际上是在构建一个 Prompt 对象。

  • .user(message):添加用户角色的消息。
  • .system("你是一个..."):添加系统提示词。
  • .functions("getWeather"):挂载工具调用。

3. ChatClient 的优雅之处

ChatClient 是基于 ChatModel 之上的高级封装。它采用了 Builder 模式,并引入了类似 Spring WebClient 的流畅接口设计。

底层源码逻辑示意:

当你调用 chatClient.prompt().user(msg).call().content() 时:

  1. prompt() 创建了一个 DefaultChatClientRequestSpec 实例。
  2. user(msg) 将消息加入到 Prompt 的 Messages 列表中。
  3. call() 触发了执行链。它内部会调用 ChatModel.call(prompt)
  4. content() 则是从返回的 ChatResponse 中提取 AssistantMessage 的文本内容。

四、 进阶用法:不仅仅是问答

虽然 10 行代码能跑通,但在实际生产中,我们需要更复杂的能力。

1. 使用 Prompt 模板 (PromptTemplate)

硬编码 Prompt 是不优雅的。Spring AI 支持类似 Thymeleaf 的模板引擎。

@GetMapping("/template")public String chatWithTemplate(@RequestParam String topic){// 定义模板    PromptTemplate template = new PromptTemplate("请作为一名专家,用通俗易懂的语言解释 {topic},并举一个例子。"    );// 渲染并发送    Prompt prompt = template.create(Map.of("topic", topic));return chatClient.prompt(prompt)            .call()            .content();}

2. 流式输出 (Streaming)

大模型生成速度较慢,流式输出能极大提升用户体验。ChatClient 天然支持 Reactor 的 Flux

@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<String> streamChat(@RequestParam String message){return chatClient.prompt()            .user(message)            .stream()          // 切换为流式模式            .content();        // 返回 Flux<String>,每个元素是一个 Token 或片段}

注:在 WebFlux 环境下配合 SSE (Server-Sent Events) 使用效果最佳。

3. Output Parsers (结构化输出)

LLM 通常返回文本,但我们需要 JSON 或 Java 对象。Spring AI 提供了 Bean Output Parser。

// 假设有一个类record JokeSetup(String setup, String punchline){}@GetMapping("/joke-obj")public JokeSetup getJokeObject(){    BeanOutputParser<JokeSetup> parser = new BeanOutputParser<>(JokeSetup.class);return chatClient.prompt()            .system("讲个笑话,并按 JSON 格式返回。格式要求: " + parser.getFormat())            .call()            .entity(JokeSetup.class)// 自动解析为对象}

五、 总结

Spring AI 的出现标志着 Java 生态在 AI 领域的成熟。它没有发明新的协议,而是将现有的 LLM API 进行了企业级封装

它的核心价值在于:

  1. 可移植性:代码不绑定特定厂商。
  2. 集成性:完美融入 Spring Boot 的自动配置和 Bean 管理。
  3. 工程化:提供了 Template、Parser、VectorStore 等 AI 应用开发必备的组件。

对于 Java 开发者来说,现在接入 AI 的门槛已经降到了历史最低。

架构设计之道在于在不同的场景采用合适的架构设计,架构设计没有完美,只有合适。

在代码的路上,我们一起砥砺前行。用代码改变世界!

感谢观看,如果觉得对您有用,还请动动您那发财的手指头,点赞、转发、在看、收藏

更多精彩合集请关注公众号🔽🔽🔽🔽🔽🔽🔽🔽

欢迎学习或从事编程开发、技术招聘 HR 进群,欢迎大家分享自己公司的内推信息,相互帮助,一起进步!

—— 斩获心仪Offer,破解面试密码 ——

广告人士勿入,切勿轻信私聊,防止被骗

工作 3 年还在写 CRUD?简历投递杳无音讯?面试屡屡受挫,迟迟拿不到 offer?

在竞争激烈的大环境下,只有不断提升核心竞争力才能立于不败之地。

公众号留言【我要晋级】,一对一指导,带你晋级。

往期精选>>>