【SpringAI】快速上手,详解项目快速集成主流大模型DeepSeek,ChatGPT
🔥个人主页: 中草药
🔥专栏:【Java】登神长阶 史诗般的Java成神之路
SpringAI
Spring AI
概述
Spring AI 是 Spring 生态下的人工智能应用开发框架,旨在简化 Java/Spring 开发者对大语言模型(LLM)、向量数据库等 AI 能力的集成,核心目标是解决 “企业数据与 AI 模型的连接问题”。它继承了 Spring 生态的可移植性、模块化设计理念,让开发者能以熟悉的方式快速构建 AI 应用(如智能客服、文档问答、内容生成等)。
模型
模型旨在处理和生成信息的算法,通常模仿人类的认知功能。通过从大型数据集中学习模式和洞察,这些模型可以进行预测、生成文本、图像或其他输出,从而增强各个行业的各种应用。比如 ChatGPT、文心一言、通义千问等等。每种模型能力不同,适合的任务也不同。
可以简单理解为模型是一个 \"超级加工厂\", 这个工厂是经过特殊训练的,训练师给它看了海量的例子 (数据), 并告诉它该怎么做。通过看这些例子,它自己摸索出了一套规则,学会了完成某个 \"特定任务\". 模型就是一套学到的 \"规则\" 或者 \"模式\", 它能根据你给的东西,产生你想要的东西。
简单总结一下,在 AI 领域,模型是通过训练数据学习模式的算法集合,其核心作用是将输入转化为有意义的输出。
Spring AI的作用就是让我们在java/spring的应用之中,能非常方便地去选择不同的模型,构造和发送输入,接受并处理输出
LLM
LLM (Large Language Model), 大语言模型,也称大型语言模型,是人工智能模型中专门处理文本的一种类型,属于语言模型的范畴. LLM 的特点是规模庞大,包含数十亿的参数,在大量的文本数据上进行训练,学习语言数据中的复杂模式,旨在理解和生成人类语言。可以执行广泛的任务,包括文本总结、翻译、情感分析等.
简单介绍几种目前主流的大语言模型 (LLM) .
-
GPT-5(OpenAI)
○ 支持 128K 长上下文,在多轮复杂推理、创意写作中表现突出 -
DeepSeek R1 (深度求索)
○ 开源,专注于逻辑推理与数学求解,支持 128K 长上下文和多语言 (20 + 语言), 在科技领域表现突出 -
Qwen2.5-72B-Instruct (阿里巴巴)
○ 通义千问开源模型家族重要成员,擅长代码生成结构化数据 (如 JSON) 处理角色扮演对话等,尤其适合企业级复杂任务,支持包括中文英文法语等 29 种语言 -
Gemini 2.5 Pro (Google)
○ 多模态融合标杆,支持图像 / 代码 / 文本混合输入,适合跨模态任务 (如图文生成、技术文档解析)
提示词
提示词是用户或系统提供给大语言模型 (LLM) 的指令或文本,用于引导模型生成特定输出。可以理解为模型的输入,无论是一个单词、一个问题、一段描述,还是结构化指令,都可视为提示词.
提示词最初是为引导大语言模型 (如 GPT、Claude 等) 而设计的,但其核心逻辑 (通过结构化输入控制输出) 可泛化到许多其他场景.
比如多模态系统的混合输入,当大模型处理图像、音频时,自然语言提示词需与其他模态数据协同输入,输入设计草图 + 文字,提示词为: \"生成网页前端代码\"
从工程视角来看,提示词分为用户提示词和系统提示词
Tokens(词原)
Tokens 是 LLM 处理文本时的最小语义单位,用于将文本拆解为模型可理解的离散单元。词元通过分词器将文本拆分而来,不同模型的分词规则不同,同一个词在不同模型中可能被拆分成不同词元。
模型的上下文窗口 (如 128K) 实际是词元数量限制,API 收费通常按词元数计费 (词元 = 金钱),词元数越多,计算耗时和内存占用越高。所以在使用时,应尽量避免冗余词 (如请,谢谢)
接入deepseek
环境要求:
JDK:最低要求-JDK 17+(Spring Boot 3.x 的强制要求)
Spring Boot:最低要求 Spring Boot 3.2+ (Spring AI 1.0.0 起强制依赖)推荐:3.4.x(最新稳定版)3.3.x(部分旧项目兼容方案)
API获取
DeepSeek 开放平台
这是deepseek开放平台,可以在这里获取API key
pom
org.springframework.ai spring-ai-bom 1.0.0-M6 pom import org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-web org.springframework.ai spring-ai-openai-spring-boot-starter
yml
spring: application: name: spring-ai-module ai: openai: api-key: sk-ae299ca6f4c9431ab4f3d0dd40b682f7 base-url: https://api.deepseek.com chat: options: model: deepseek-chat temperature: 0.7 #用于控制生成补全内容的多样性,值越好,输出越随机
Controller
@RestController@RequestMapping(\"/ds\")public class DeepSeekController { @Autowired private OpenAiChatModel model; @RequestMapping(\"/chat\") public String chat(String message) { return model.call(message); }}
测试结果
接入ChatGPT
环境准备和Controller上述DeepSeek一致(DeepSeek去兼容了openai)
OpenAI Platform
注册账号
yml
spring: application: name: spring-ai-module ai: openai: api-key: your-key
base-url默认就是https://api.openai.com
注意
本地开发时,即使配置了代理,也有可能无法让整个系统全局代理,为此启动类加上如下代码,配置代理ip与port
System.setProperty(\"http.proxyHost\",\"127.0.0.1\");System.setProperty(\"https.proxyHost\",\"127.0.0.1\");System.setProperty(\"http.proxyPort\",\"7890\");System.setProperty(\"https.proxyPort\",\"7890\");
测试
接入成功
SpringAI+SiliconFlow(推荐-有免费赠额)
硅基流动 SiliconFlow
这里先来介绍一下,硅基流动(SiliconFlow)是北京硅基流动科技有限公司旗下的 AI 基础设施品牌,这是一个一站式大模型云服务平台,集成了 Qwen、DeepSeek、Llama3 等主流开源模型,提供从模型训练、微调到推理部署的全链路服务。用户可通过 API 调用快速接入模型,例如文本生成、图像生成、视频生成等多模态任务,日均调用量已突破千亿 Token。平台还支持企业级模型微调与托管,帮助开发者实现 “Token 自由”(即低成本、高弹性的模型使用)。
简而言之,其核心定位是大模型时代的 AI 基础设施层(AI Infra),是高性能的国产AI模型平台
SpringAI+硅基流动
Spring AI 是一个用于 AI 工程的应用框架。其目标是将可移植性和模块化设计等 Spring 生态系统设计原则应用于 AI 领域,并推广使用 POJO 作为应用程序的构建块到 AI 领域。
在讲实操前,先明确这对组合的核心价值 ——SpringAI 解决 “标准化”,硅基流动解决 “中间件能力”,二者互补刚好破解传统集成的 3 大痛点:
传统大模型集成痛点
SpringAI 的解决方式
硅基流动的补充价值
多模型接口不统一,适配成本高
提供标准化Model接口,封装不同模型的调用逻辑,切换模型无需改业务代码
内置主流大模型(GPT、文心、通义等)的适配能力,SpringAI 只需对接硅基流动,无需逐个对接模型厂商
配置繁琐,环境依赖复杂
基于 Spring Boot 自动配置,简化参数配置
提供统一的 API 密钥、模型版本管理,支持本地调试 / 云端部署无缝切换
生产级需求难满足(限流、重试、监控)
依赖 Spring 生态的重试、缓存组件,但需手动集成
原生支持请求限流、失败重试、调用日志监控,无需额外开发
环境准备
JDK 17+(Spring AI 0.8+ 最低要求)
Spring Boot 3.2+(建议用最新稳定版)
硅基流动账号
硅基流动用户系统,统一登录 SSO
大家可以自行官网注册,也可以通过我的邀请链接和邀请码注册,这样可以在原先的基础上额外赠送7块钱额度,这是我的邀请码:gvYC1Tje
获取API Key(需要充值)
注意不要泄漏你的API Key
快速上手
在pom.xml中引入 Spring AI 核心依赖(Spring AI 已官方兼容硅基流动,无需自定义适配)
org.springframework.ai spring-ai-bom 1.0.0-M6 pom import org.springframework.boot spring-boot-starter-test 3.5.4 test org.springframework.boot spring-boot-starter-web 3.5.4 org.springframework.ai spring-ai-openai-spring-boot-starter
配置文件
spring: application: name: spring-ai-siliconcloud ai: openai: api-key: your-key base-url: https://api.siliconflow.cn/
创建Controller
如果要在初始化ChatClient中确定模型,注意要写全称
@RestController@RequestMapping(\"sf\")public class DeepSeekController { private final ChatClient chatClient; public DeepSeekController(ChatClient.Builder builder) { this.chatClient = builder .defaultSystem(\"你是一个专业的智能助手,回答需简洁准确\") .defaultOptions(OpenAiChatOptions.builder() //可以写在yml文件 .model(\"Pro/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B\") .build()) .build(); } @GetMapping(\"/chat\") public String chat(@RequestParam(name = \"message\") String message) { // 使用prompt()方法替代call(),通过UserMessage传递用户输入 ChatResponse response = chatClient.prompt() .messages(new UserMessage(message)) .call() .chatResponse(); // 提取并返回模型的回答内容 return response.getResult().getOutput().getText(); }}
测试结果
ChatClient
ChatClient
是 Spring AI 提供的高层客户端,它封装了ChatModel
,提供了更简洁、更符合 Spring 风格的 API,旨在降低开发者的使用门槛。它提供了与AI模型通信的Fluent API,它支持同步和反应式的编程模型。
Controller
@RestController@RequestMapping(\"/cc\")public class ChatClientController { private final ChatClient chatClient; public ChatClientController(ChatClient.Builder chatClientBuilder) { this.chatClient = chatClientBuilder.build(); } @GetMapping(\"/ai\") public String generation(String userInput) { return this.chatClient.prompt() //用户输入 .user(userInput) .call() .content(); }}
角色预设
public ChatClientController(ChatClient.Builder chatClientBuilder) { this.chatClient = chatClientBuilder .defaultSystem(\"你是一名资深的Java后端开发工程师,名字叫牛牛\") .build(); }
角色预设前后
结构化输出
通过Entity()方法将模型输出转为自定义实体,确保输出格式满足Json
借助jdk16里的record来便捷实现
record QuestionList(String topic, List questionList) {}@RequestMapping(\"/entity\")public String entity(String userInput) { QuestionList entity = chatClient.prompt() .user(String.format(\"请帮我找到学习%s算法的leetcode的题目\", userInput)) .call() .entity(QuestionList.class); return entity.toString();}
实现流式输出
为了优化体验,可以采用流式输出的方式进行优化(类似于deepseek,豆包的形式)
大模型流式输出(Streaming Output)最适合逐步生成内容而非一次性返回完整结果的场景。Spring AI 使用 ChatClient 的 stream () 方法生成 Flux 流,适用于需要持续拉取客户输入的 AI 场景
@RequestMapping(value = \"/stream\",produces = \"text/html;charset=utf-8\") public Flux stream(String userInput) { return this.chatClient.prompt() .user(userInput) .stream() .content(); }
注意设置页面编码,否则有可能会输出乱码
日志打印
Advisors
Spring AI 中的 Advisors 是介于用户请求与 AI 模型之间的中间件组件,它的核心功能就是对请求进行拦截过滤和增强。帮助我们在 API 调用前后解决各种问题,例如调用前参数如何构建,调用后结果如何处理。
Spring AI 中的 Advisors 是基于 AOP 思想实现的,在具体实现上进行了领域适配。其设计核心借鉴了 Spring AOP 的拦截机制,各个 Advisors 以链式结构运行,序列中的各个 Advisor 都有机会对传入的请求和传出的响应进行处理。这种链式处理机制确保了每个 Advisor 可以在请求和响应流程中 插入自己的逻辑,从而实现更灵活和可定制的功能。
应用场景
- 敏感词过滤
- 建立聊天历史
- 对话上下文管理
SimpleLoggerAdvisor
添加这个advisor,来实现日志打印
@Configurationpublic class ChatClientConfiguration { @Bean public ChatClient chatClient(ChatClient.Builder chatClientBuilder) { return chatClientBuilder .defaultSystem(\"你叫牛牛,是一名资深的Java后端开发工程师\") .defaultAdvisors(new SimpleLoggerAdvisor()) .build(); }}
yml
logging: pattern: console: \'%d{HH:mm:ss:SSS} %c %M %L [%Thread] %m%n\' file: \'%d{HH:mm:ss:SSS} %c %M %L [%Thread] %m%n\' level: org.springframework.ai.chat.client.advisor: debug
实现效果
与ChatModel的区别
ChatClient 和 ChatModel 是 Spring AI 框架提供的与大语言模型(LLM)交互的两大核心接口,但二者设计理念和适用场景不太一样。
-
ChatModel 是 Spring AI 框架中的底层接口,直接与具体的大语言模型(如通义千问、OpenAI)交互,提供基础的
call
和stream
方法。开发者需手动处理提示词组、参数配置和响应解析等细节,在使用上相对更加灵活。 -
ChatClient 对 ChatModel 进行了封装,相比 ChatModel 原子类 API,ChatClient 屏蔽了与 AI 大模型交互的复杂性,自动集成 提示词管理、响应格式化、结构化输出映射 等能力,大幅提高开发效率。
ChatModel 示例代码(手动处理交互)
ChatResponse response = openAiChatModel.call(new Prompt(message));return response.getResult().getOutput().getText();
ChatClient 示例代码(封装后简化交互)
Recipe recipe = this.chatClient.prompt() // 用户输入的信息(提示词组装) .user(String.format(\"请帮我生成%s的食谱\", userInput)) // 发起大模型请求 .call() // 响应映射为 Recipe 实体类(结构化输出) .entity(Recipe.class);
.entity(Class)
自动映射 POJO流式编程
SSE协议
HTTP 协议本身设计为无状态的请求 - 响应模式,严格来说,是无法做到服务器主动推送消息到客户端,但通过 Server-Sent Events(服务器发送事件,简称 SSE)技术可实现流式传输,允许服务器主动向浏览器推送数据流。
也就是说,服务器向客户端声明,接下来要发送的是流消息 (streaming),这时客户端不会关闭连接,会一直等待服务器发送过来的新的数据流。
SSE(Server-Sent Events)是一种基于 HTTP 的轻量级实时通信协议,浏览器通过内置的 EventSource API 接收并处理这些实时事件。
核心特点
-
基于 HTTP 协议
复用标准 HTTP/HTTPS 协议,无需额外端口或协议,兼容性好且易于部署。 -
单向通信机制
SSE 仅支持服务器向客户端的单向数据推送,客户端通过普通 HTTP 请求建立连接后,服务器可持续发送数据流,但客户端无法通过同一连接向服务器发送数据。 -
自动重连机制
支持断线重连,连接中断时,浏览器会自动尝试重新连接(支持retry
字段指定重连间隔)。 -
自定义消息类型
客户端发起请求后,服务器保持连接开放,响应头设置Content-Type: text/event-stream
,标识为事件流格式,持续推送事件流。
数据格式
服务端向浏览器发送 SSE 数据,需要设置必要的 HTTP 头信息:
Content-Type: text/event-stream;charset=utf-8 Connection: keep-alive
每一次发送的消息,由若干个message
组成,每个message
之间由 \\n\\n
分隔,每个message
内部由若干行组成,每一行都是如下格式:
代码块
[field]: value\\n
Field 可取值说明
data
[必需]:数据内容event
[非必需]:表示自定义的事件类型,默认是message
事件id
[非必需]:数据标识符,相当于每一条数据的编号retry
[非必需]:指定浏览器重新发起连接的时间间隔
除此之外,还可以有 冒号 :
开头的行,表示注释。
示例代码块(Plain Text)
event: foo\\n data: a foo event\\n\\n data: an unnamed event\\n\\n event: end\\n data: a bar event\\n\\n
Spring中实现
spring4.2开始已经支持了SSE,从Spring 5开始我们可以使用WebFlux更优雅地去实现SSE协议,Flux是实现 WebFlux 的核心API,他的核心流程是
创建flux流->处理数据->订阅数据
测试demo
public class FluxDemoTest { public static void main(String[] args) throws InterruptedException { Flux flux = Flux.just(\"Hello\", \"World\",\"good\").delayElements(Duration.ofSeconds(1)); flux.map(s->s.toUpperCase()) .map(s->s+\".\") .subscribe(System.out::println); //防止程序提前终止 Thread.sleep(5000); }}
比如发送时间
@RequestMapping(value = \"/stream\", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux stream(){ return Flux.interval(Duration.ofSeconds(1)).map(s->new Date().toString()); }
常用 API
创建Flux
just(T... data)
Flux.just(\"a\", \"b\", \"c\")
fromIterable(Iterable it)
Flux.fromIterable(Arrays.asList(1, 2, 3))
fromArray(T[] array)
Flux.fromArray(new Integer[]{1, 2, 3})
empty()
onComplete
)Flux.empty()
error(Throwable e)
onError
)的 FluxFlux.error(new RuntimeException(\"出错了\"))
interval(Duration period)
Flux.interval(Duration.ofSeconds(1))
处理数据
subscribe()
flux.subscribe()
subscribe(Consumer onNext)
flux.subscribe(i -> System.out.println(\"接收:\" + i))
subscribe(Consumer onNext, Consumer onError)
flux.subscribe(i -> System.out.println(i), e -> e.printStackTrace())
subscribe(Consumer onNext, Consumer onError, Runnable onComplete)
flux.subscribe(i -> System.out.println(i), e -> {}, () -> System.out.println(\"处理完成\"))
filter(Predicate predicate)
Flux.just(1,2,3,4).filter(i -> i%2 == 0)
(结果:2,4)take(long n)
n
个元素Flux.just(1,2,3,4).take(2)
(结果:1,2)skip(long n)
n
个元素,保留剩余元素Flux.just(1,2,3,4).skip(2)
(结果:3,4)distinct()
equals
判断)Flux.just(1,2,2,3).distinct()
(结果:1,2,3)merge(Publisher... sources)
Flux.merge(flux1, flux2)
(flux1:1,2;flux2:3,4,可能结果:3,1,4,2)concat(Publisher... sources)
Flux.concat(flux1, flux2)
(flux1:1,2;flux2:3,4,结果:1,2,3,4)zip(Publisher s1, Publisher s2, BiFunction combinator)
Flux.zip(fluxA, fluxB, (a,b) -> a+b)
(fluxA:\"a\",\"b\";fluxB:1,2,结果:\"a1\",\"b2\")订阅操作
subscribe()
flux.subscribe()
subscribe(Consumer onNext)
flux.subscribe(i -> System.out.println(\"接收:\" + i))
subscribe(Consumer onNext, Consumer onError)
flux.subscribe(i -> System.out.println(i), e -> e.printStackTrace())
subscribe(Consumer onNext, Consumer onError, Runnable onComplete)
flux.subscribe(i -> System.out.println(i), e -> {}, () -> System.out.println(\"处理完成\"))
有些人担心人工智能的出现会令人类感到自卑,但任何有头脑的人单是观察花朵就应该能感到自己的渺小。 ——艾伦凯
🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀
以上,就是本期的全部内容啦,若有错误疏忽希望各位大佬及时指出💐
制作不易,希望能对各位提供微小的帮助,可否留下你免费的赞呢🌸