1. SpringAI 架构与设计思想
1.1 核心定位
SpringAI 是 Spring 生态的 Java 大模型集成框架,专注于对接各类大模型,不参与模型训练。它核心作用是抹平各厂商大模型的接口、参数差异,实现一套代码适配所有主流大模型,避免切换模型时大幅改造业务代码。
1.2 核心设计思想
-
统一抽象:定义通用请求、响应、提示词标准,由厂商适配框架规范,开发者无需关注底层差异。
-
厂商解耦:业务代码仅依赖 SpringAI 通用 API,不绑定具体厂商,支持无缝切换大模型服务。
-
依赖倒置:厂商适配框架,而非业务适配厂商接口,避免第三方接口迭代导致业务代码失效。
1.3 四层架构分层
-
应用层:开发者业务入口,负责调用AI接口、配置RAG与拦截器。
-
核心抽象层:定义通用AI能力接口,无厂商专属逻辑,统一框架标准。
-
厂商适配层:转换各厂商接口、参数格式,屏蔽底层模型差异。
-
基础设施层:提供网络、序列化、日志、异常兜底等基础能力支撑。
1.4 自动配置原理
SpringAI 基于 SpringBoot 自动配置实现开箱即用,项目启动时根据依赖和配置,自动装配 ChatModel、向量库、Advisor 等核心 Bean。支持按需装配,开发者可自定义覆盖默认配置,实现业务个性化扩展。
本章小结
SpringAI 凭借标准化、解耦、可插拔的设计,结合自动配置能力,大幅简化Java项目大模型接入流程,适配企业级开发规范。
2. ChatModel 与 ChatClient 核心抽象
2.1 ChatModel(底层基础接口)
ChatModel 是 SpringAI 底层核心接口,所有大模型厂商必须实现该接口。仅提供同步、流式两种基础调用能力,只负责请求转发,无任何工程化增强,是AI能力的底层基础。
2.2 ChatClient(业务开发入口)
ChatModel 功能单一,无法满足业务开发需求。SpringAI 基于门面模式封装 ChatClient,整合提示词渲染、链路拦截、结果解析、异常处理等工程化能力,是业务开发的唯一首选入口。
简单区分:ChatModel 是底层原生基础工具,ChatClient 是上层工程化封装工具。
2.3 核心 API 实战代码
/**
* SpringAI 核心入口 API 演示
* ChatModel:底层原生接口,无增强
* ChatClient:工程化封装,业务首选
*/
@RestController
@RequestMapping("/ai")
public class AiBasicController {
/**
* 自动注入底层模型实例
* 根据配置文件自动适配:OpenAI/通义千问/Ollama 等
*/
@Resource
private ChatModel chatModel;
/**
* 自动注入工程化客户端(业务开发首选)
* 内置拦截器、模板渲染、异常处理、结构化解析
*/
@Resource
private ChatClient chatClient;
/**
* 原生 ChatModel 基础调用(底层裸调用)
* 适合简单测试,无任何工程化增强
*/
@GetMapping("/model/call")
public String modelCall() {
// 构建用户消息
Prompt prompt = new Prompt("简单介绍一下SpringAI");
// 原生模型调用,直接请求大模型
ChatResponse response = chatModel.call(prompt);
// 获取返回文本内容
return response.getResult().getOutput().getText();
}
/**
* ChatClient 链式调用(企业级标准写法)
* 代码简洁、可扩展、支持后续追加Advisor、参数配置
*/
@GetMapping("/client/call")
public String clientCall() {
return chatClient.prompt()
// 设置用户提问内容
.user("简单介绍一下SpringAI的核心优势")
// 统一执行调用
.call()
// 直接获取文本结果
.content();
}
}
2.4 ChatClient 生命周期
ChatClient 全局单例,项目启动时自动完成初始化、拦截器注册。单次请求复用全局实例,请求结束仅释放单次资源,无需开发者手动管理生命周期。
本章小结
双层抽象分工明确:ChatModel 统一底层模型标准,ChatClient 简化上层业务开发,兼顾解耦与开发效率。
3. 同步与流式调用机制
3.1 同步调用(阻塞式)
同步调用为阻塞式请求,需等待模型返回完整结果后,代码才会继续执行。用法简单、结果完整,但会占用服务线程,高并发、长文本场景易超时、耗尽线程资源。
适用场景:短文本问答、结构化数据生成、后台批量任务。
3.2 流式调用(非阻塞式)
流式调用基于 WebFlux+SSE 长连接实现,模型每生成一段 Token 就实时推送前端,形成打字机效果。非阻塞特性不占用服务线程,大幅提升并发能力。
适用场景:前端实时对话、长文本创作、交互式问答。
3.3 实战代码演示
/**
* 同步、流式调用双模式演示
* SSE 流式返回适配前端打字机效果
*/
@RestController
@RequestMapping("/ai/stream")
public class AiStreamController {
@Resource
private ChatClient chatClient;
/**
* 同步阻塞调用
*/
@GetMapping("/sync")
public String syncChat() {
return chatClient.prompt()
.user("SpringAI 和原生 OpenAI SDK 对比有什么优势?")
.call()
.content();
}
/**
* 流式非阻塞调用(SSE 长连接)
* produces = MediaType.TEXT_EVENT_STREAM_VALUE 固定SSE返回格式
*/
@GetMapping(value = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamChat() {
// stream() 方法开启流式调用,返回Flux流
return chatClient.prompt()
.user("详细讲解SpringAI RAG工作原理")
.stream()
// 分段输出每一段token文本
.map(ChatStreamResponse::content);
}
}
3.4 核心差异与通用规则
两种调用模式的底层参数、拦截链路完全一致,仅线程模型和数据推送方式不同,可按需灵活切换。
3.5 流式调用核心补充能力
背压机制:自动平衡前后端数据收发速率,避免前端数据堆积、页面卡顿。
断线重连机制:网络断开后,前端可携带对话ID重连,服务端接续推送内容,无需重新提问。
4. Prompt 提示词工程
4.1 三类核心对话消息
大模型输出完全依赖输入提示词,SpringAI 标准化三类对话消息,快速构建完整对话上下文:
-
系统消息:定义模型身份、回答规则和输出格式,优先级最高。
-
用户消息:用户实时提问内容,单次对话动态变更。
-
助手消息:模型历史回答,用于拼接多轮对话上下文,实现连续聊天。
4.2 硬编码提示词弊端
代码硬编码提示词会导致业务耦合严重、迭代繁琐,还容易出现拼接格式错误,不适合生产动态迭代。
4.3 PromptTemplate 原理与实战
PromptTemplate 采用模板与参数分离思想,固定提示词规则封装为模板,动态内容用占位符替代,运行时自动渲染生成完整提示词。支持配置化迭代,无需改代码,规避拼接错误,是企业级标准用法。
/**
* PromptTemplate 提示词模板实战
* 解决硬编码耦合问题,支持动态参数渲染
*/
@RestController
@RequestMapping("/ai/prompt")
public class PromptTemplateController {
@Resource
private ChatClient chatClient;
@GetMapping("/template")
public String promptTemplate() {
// 1. 定义模板,{subject} 为动态占位符
String templateStr = "你是一名资深Java架构师,请通俗易懂讲解:{subject},控制字数在200字以内";
PromptTemplate promptTemplate = new PromptTemplate(templateStr);
// 2. 绑定动态参数
Map<String, Object> params = new HashMap<>();
params.put("subject", "SpringAI Advisor责任链机制");
// 3. 自动渲染生成完整提示词
Prompt prompt = promptTemplate.create(params);
// 4. 调用模型
return chatClient.prompt(prompt).call().content();
}
}
5. AI 结构化输出与容错
5.1 原生输出痛点
大模型默认输出自由文本,格式杂乱,无法直接映射Java实体、入库或接口返回,手动解析冗余代码多、容错性差。
5.2 OutputParser 结构化解析原理
OutputParser 采用「前置格式约束+后置自动解析」机制:框架根据Java实体自动生成JSON格式约束提示词,强制模型输出规范结果,再自动解析为实体,统一处理格式异常。
5.3 结构化输出实战代码
/**
* 结构化输出 + 自动解析 + 异常兜底演示
*/
// 1. 定义接收结果的实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AiArticle {
// 文章标题
private String title;
// 核心摘要
private String summary;
// 关键知识点列表
private List<String> keyPoints;
}
@RestController
@RequestMapping("/ai/struct")
public class StructOutputController {
@Resource
private ChatClient chatClient;
@GetMapping("/parse")
public AiArticle structParse() {
// 直接通过entity方法强制结构化输出,框架自动补全格式约束Prompt
return chatClient.prompt()
.user("生成一篇SpringAI RAG原理的技术短文")
// 自动解析为实体,内置JSON格式约束
.entity(AiArticle.class)
.call();
}
}
5.4 降级兜底与场景适配
生产环境支持容错降级:解析异常时自动捕获错误、保留原始文本、返回默认实体,避免接口崩溃。
场景适配:业务入库、结构化数据用强约束实体解析;闲聊问答用弱约束格式,兼顾稳定与灵活。
6. Advisor 责任链机制
Advisor 是 SpringAI 核心扩展机制,结合AOP与责任链思想,无需修改核心代码,即可实现AI调用全链路增强,所有高阶能力均基于此实现。
6.1 环绕拦截链路
所有AI调用都会经过三段拦截链路,拦截器支持自定义优先级(数值越小,执行越早):
-
前置拦截:模型调用前执行,可做参数校验、权限控制、知识检索、提示词优化。
-
模型执行:前置拦截全部完成后,正式发起大模型调用。
-
后置拦截:模型返回结果后逆序执行,可做日志记录、数据脱敏、异常重试。
6.2 优先级与冲突规避
框架内置拦截器有固定优先级:权限校验 > RAG检索/日志 > 重试兜底。自定义Advisor优先级建议设置-50~50,避免覆盖核心逻辑导致功能异常。
6.3 异常传播与熔断规则
前置拦截报错会熔断整个调用链路,终止模型请求;后置拦截报错仅影响自身逻辑,不打断主流程,可自定义兜底逻辑避免接口崩溃。
6.4 同步与流式链路差异
同步调用:前后置拦截完整执行,所有增强逻辑生效;流式调用:前置拦截仅执行一次,后置拦截随每段Token触发,适合流式日志、实时脱敏,不适合缓存、批量处理。
7. 内置 Advisor 核心能力
-
记忆拦截器:自动维护多轮对话上下文,支持窗口裁剪,防止Token超限,实现连续对话。
-
函数调用拦截器:拦截模型工具调用指令,执行本地业务方法,让AI获取实时数据。
-
治理类拦截器:提供日志、重试、限流能力,保障服务稳定、保护模型配额。
所有内置拦截器均可插拔配置,支持按需开关、调整执行顺序。
7.1 记忆拦截器实战
/**
* 内置记忆拦截器实现多轮连续对话
* 自动维护上下文,无需手动拼接历史消息
*/
@RestController
@RequestMapping("/ai/chat")
public class MemoryChatController {
/**
* 注册带记忆能力的ChatClient
* 全局唯一,自动注入MemoryChatAdvisor
*/
@Bean
public ChatClient memoryChatClient(ChatClient.Builder builder) {
return builder
// 开启对话记忆,默认内存存储,支持滑动窗口
.defaultAdvisors(MessageChatMemoryAdvisor.chatMemoryAdvisor())
.build();
}
@Resource
private ChatClient memoryChatClient;
@GetMapping("/memory")
public String memoryChat(@RequestParam String msg) {
return memoryChatClient.prompt()
.user(msg)
.call()
.content();
}
}
8. 自定义 Advisor 开发
自定义Advisor可实现个性化链路增强(违规词校验、自定义日志、权限拦截等),核心开发规范如下:
-
实现ChatAdvisor接口,按需重写前后置拦截方法;
-
设置合理优先级,规避内置拦截器冲突;
-
注入Spring容器,框架自动纳入责任链;
-
保证拦截逻辑幂等,避免重复执行出错。
8.1 自定义拦截器完整示例
/**
* 自定义Advisor:全链路日志拦截器
* 优先级设置为10,早于默认兜底拦截器
*/
@Component
public class AiLogAdvisor implements ChatAdvisor, Ordered {
/**
* 前置拦截:请求模型之前执行
*/
@Override
public ChatRequest beforeChat(ChatRequest request) {
// 打印用户请求Prompt
System.out.println("【AI请求】" + request.getPrompt().getContents());
// 放行请求
return request;
}
/**
* 后置拦截:模型返回结果后执行
*/
@Override
public ChatResponse afterChat(ChatResponse response) {
// 打印模型返回内容
System.out.println("【AI响应】" + response.getResult().getOutput().getText());
return response;
}
/**
* 设置执行优先级,数值越小越先执行
*/
@Override
public int getOrder() {
return 10;
}
}
自定义Advisor无侵入接入全局链路,所有AI调用自动生效,扩展性极强。
9. 工业级 RAG 原理与实战
9.1 RAG 核心价值
普通大模型存在知识滞后、无法读取企业私有数据、容易幻觉瞎编的问题。RAG核心价值是先检索私有真实知识,再让模型基于真实内容作答,从根源解决上述问题。
9.2 RAG 五大核心组件
-
Document:私有数据统一载体,存储文档原文、来源、元数据。
-
DocumentReader:解析各类文档格式,统一转为标准Document对象。
-
TextSplitter:拆分长文档,避免上下文超限,提升检索精度。
-
EmbeddingModel:文本转向量,实现语义相似度计算。
-
VectorStore:持久化存储向量与原文,提供高效相似度检索。
9.3 三大文档切片策略
-
固定长度切片:按字符切割,速度快,适配通用文档;缺点是易切断语义。
-
重叠滑动切片:固定长度+片段重叠,保留上下文,解决语义断裂,是生产最优方案。
-
语义切片:按语义完整性切割,检索精度高,适配合同、规章等高精度文档;缺点是计算耗时稍长。
9.4 向量检索打分原理
向量检索通过计算问题与文档向量的相似度匹配内容,语义越相近、距离越近,匹配度越高:
-
余弦相似度:仅关注语义方向,不受文本长度影响,是RAG默认匹配规则。
-
欧式距离:关注向量整体距离,对文本长度敏感,适配规整的结构化文档。
9.5 工业级 RAG 四步闭环链路
基础RAG仅简单召回内容,精度低、噪声多,工业级RAG需完成四步闭环优化:
-
粗召回:向量检索快速筛选TopN相似文档片段。
-
排序:按相似度、文档权重、更新时间二次优化排序。
-
重排:通过Reranker模型精准比对语义,修正向量匹配误差。
-
降噪过滤:剔除相似度低、无关、过期的噪声内容。
9.6 混合检索机制
纯向量检索无法精准匹配专有名词、代码等内容。工业级采用「关键词+向量」混合检索,向量做语义模糊匹配,关键词做精准命中,兼顾智能性与准确性。
9.7 RAG 全流程实战代码
/**
* SpringAI RAG 完整流程代码
* 文档切片、向量化、入库、检索问答全流程
*/
@RestController
@RequestMapping("/ai/rag")
public class RagController {
// 注入向量存储
@Resource
private VectorStore vectorStore;
// 注入向量化模型
@Resource
private EmbeddingModel embeddingModel;
// 构建支持RAG的客户端
@Bean
public ChatClient ragChatClient(ChatClient.Builder builder) {
return builder
// 开启检索增强拦截器
.defaultAdvisors(RetrievalAugmentationAdvisor.retrievalAdvisor(vectorStore))
.build();
}
@Resource
private ChatClient ragChatClient;
/**
* 初始化知识库:写入文档、切片、向量化、入库
*/
@GetMapping("/init")
public String initKnowledge() {
// 1. 构建私有文档
String docContent = "SpringAI RAG可以实现私有知识库问答,解决大模型幻觉、知识滞后问题。" +
"通过文档切片、向量化、向量检索,让模型基于真实私有数据回答。";
Document document = new Document(docContent);
// 2. 重叠滑动切片(生产最优)
TokenTextSplitter splitter = new TokenTextSplitter(800, 150);
List<Document> splitDocs = splitter.split(List.of(document));
// 3. 向量入库
vectorStore.add(splitDocs);
return "知识库初始化完成,切片数量:" + splitDocs.size();
}
/**
* RAG智能问答
*/
@GetMapping("/query")
public String ragQuery(@RequestParam String msg) {
// 自动执行:问题向量化-检索-拼接prompt-模型生成
return ragChatClient.prompt()
.user(msg)
.call()
.content();
}
}
9.8 核心问题与生产优化方案
-
检索不准:优化切片策略、开启重排、使用混合检索;
-
上下文丢失">增大切片重叠区间、关联相邻片段;
-
噪声干扰:设置相似度阈值、配置文档黑白名单;
-
模型幻觉:补充兜底知识库、限制模型发散度。
9.9 Token 成本约束
大模型有Token上限,检索片段过多会导致超限报错、计费飙升。生产环境需限制TopK数量、动态截断、过滤无效片段,平衡检索精度与使用成本。
9.10 RAG 完整执行流程
离线构建:文档解析 → 智能切片 → 文本向量化 → 向量存储
在线问答:问题向量化 → 向量检索 → 拼接知识Prompt → 模型生成答案 → 格式化返回
9.11 与 Advisor 联动原理
SpringAI 内置RetrievalAdvisor检索拦截器,融入责任链。在模型调用前置阶段自动完成检索、Prompt拼接,无侵入实现RAG能力,支持按需自定义检索规则。
10. 模型超参调优
三大核心超参决定模型输出风格与效果,是生产调优核心控制点:
10.1 Temperature(温度值)
Temperature取值0~1,控制模型随机性与创造性。数值越低,回答越严谨稳定;数值越高,回答越灵活有创意。知识库问答取0.1~0.3,文案创作取0.7~0.9。
10.2 TopP(核采样)
TopP用于筛选模型候选词范围,配合温度参数平衡输出稳定性与多样性,生产环境一般固定0.9~1.0,无需随意修改。
10.3 MaxTokens(最大生成长度)
MaxTokens限制模型单次最大输出Token数,可防止无限生成、缩短接口耗时、控制计费成本,按需配置即可。
10.4 超参全局配置实战
/**
* 模型超参全局配置
*/
@Configuration
public class ModelParamConfig {
@Bean
public ChatClient chatClient(ChatClient.Builder builder) {
return builder
.defaultOptions(ChatOptions.builder()
// 知识库问答:低随机性,严谨输出
.temperature(0.2)
.topP(0.9)
// 限制最大生成长度
.maxTokens(2048)
.build())
.build();
}
}
11. AI 函数调用机制
11.1 核心作用
大模型无法获取实时业务数据、无法执行本地代码,函数调用可解决该问题,实现AI主动调用业务接口、操控业务逻辑。
完整执行流程:
-
函数注册:@Tool注解标记业务方法,框架自动注册给大模型;
-
模型判断:用户提问后,模型自主判断是否需要调用工具;
-
参数解析:模型生成合法的工具调用参数;
-
本地执行:拦截器捕获指令,执行本地Java业务方法;
-
二次推理:工具结果回传模型,生成最终自然语言答案。
11.3 函数调用实战代码
/**
* AI 函数调用(工具调用)实战
* 让AI主动调用本地Java方法获取实时数据
*/
@Service
public class AiToolService {
/**
* 注册为AI可调用工具
* description:告诉模型该方法的用途
*/
@Tool("根据城市名称查询当前天气")
public String getWeather(String city) {
// 模拟业务接口调用
return city + " 当前天气:晴天,25℃";
}
}
@RestController
@RequestMapping("/ai/tool")
public class AiToolController {
@Bean
public ChatClient toolChatClient(ChatClient.Builder builder, AiToolService aiToolService) {
return builder
// 注入工具类,自动注册所有@Tool方法
.defaultTools(aiToolService)
.build();
}
@Resource
private ChatClient toolChatClient;
@GetMapping("/chat")
public String toolChat(@RequestParam String msg) {
// AI自动判断是否调用本地天气工具
return toolChatClient.prompt()
.user(msg)
.call()
.content();
}
}
11.4 嵌套调用能力
支持单次问答多工具嵌套、循环调用,框架自动调度执行,直至满足用户提问需求。
12. 多轮对话上下文管理
12.1 核心痛点
多轮对话累积过多上下文,会引发Token超限、响应变慢、成本增高、回答精度下降,需通过窗口策略裁剪优化。
12.2 主流上下文优化策略
-
滑动窗口策略:保留最近N轮对话,丢弃最早记录,兼顾连贯与成本,生产首选;
-
截断策略:按Token长度截断超长内容,作为防超限兜底方案;
-
摘要压缩策略:自动浓缩超长历史对话,节省Token,适配长周期聊天。
12.3 滑动窗口配置实战
/**
* 多轮对话滑动窗口配置
* 限制最大对话轮数,防止Token累积超限
*/
@Configuration
public class ChatMemoryConfig {
@Bean
public ChatClient windowChatClient(ChatClient.Builder builder) {
// 滑动窗口:仅保留最近10轮对话
ChatMemory chatMemory = new InMemoryChatMemory(10);
return builder
.defaultAdvisors(MessageChatMemoryAdvisor.chatMemoryAdvisor(chatMemory))
.build();
}
}
13. 项目环境与依赖配置
项目适配SpringBoot3.2+、SpringAI1.0+,通过BOM统一管理依赖、规避版本冲突。仅需配置模型密钥、接口地址、超参即可开箱即用。
<!-- SpringAI 统一版本管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- SpringAI 核心依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
</dependencies>
14. 生产问题排查与性能调优
14.1 常见问题与解决方案
-
ChatClient注入失败:统一SpringBoot与SpringAI兼容版本;
-
模型调用超时:排查网络、开启重试、切换国内稳定模型;
-
结构化解析失败:优化提示词、简化实体、配置降级兜底;
-
RAG检索不准:优化切片、开启重排、启用混合检索;
-
Token超限:开启滑动窗口、限制检索片段、压缩上下文。
14.2 链路异常定位方式
开启框架DEBUG日志,可清晰查看Advisor执行顺序、接口出入参、检索链路,快速定位拦截冲突、执行异常、检索失效等问题。
14.3 生产核心调优策略
-
长文本业务优先用流式调用,减少阻塞超时;
-
多轮对话开启滑动窗口,控制上下文与Token成本;
-
固定提示词全部模板化,提升可维护性;
-
生产精简日志、保留核心监控,提升接口吞吐量;
-
结合RAG知识约束与超参调优,规避模型幻觉。
15. 核心知识点汇总
-
架构体系:四层架构+三大设计思想+自动配置,实现大模型接入标准化、解耦可插拔;
-
核心抽象:ChatModel统一底层标准,ChatClient封装工程化能力,适配业务开发;
-
调用模式:同步适配结构化业务,流式适配实时交互,自带背压、断线重连能力;
-
提示词工程:三类消息构建上下文,模板化渲染解决硬编码耦合问题;
-
结构化输出:双向约束+降级兜底,实现AI文本与Java实体无缝映射;
-
Advisor机制:基于责任链实现全链路增强,区分同步/流式差异、异常熔断与优先级;
-
函数调用:打通AI与本地业务,支持嵌套调用,实现智能业务操控;
-
上下文治理:多类窗口策略,解决多轮对话Token超限、成本过高问题;
-
模型调优:三大超参精准控制模型输出稳定性、随机性与生成长度;
-
工业级RAG:通过切片优化、混合检索、重排降噪,结合Advisor无侵入联动,解决模型幻觉、知识滞后、私有数据适配问题,是企业AI落地核心方案。