初识SpringAl:Chat篇
本文介绍了AI应用开发的四种技术架构:纯Prompt问答、Agent+FunctionCalling、RAG知识库拓展和模型微调。重点讲解了Java领域两大热门框架SpringAI和LangChain4j的差异,其中SpringAI更适合SpringBoot项目且更新更快。详细展示了SpringAI的快速入门方法,包括依赖引入、配置化设置、客户端配置、流式输出实现等核心功能。特别介绍了会话记忆功能
一、AI应用开发技术架构
1.纯Prompt问答
用户直接向AI应用进行提问,AI应用拿到提示词后进行整理分析后传给大模型,大模型将结果返还给AI应用最后给到用户。类似于我们平时的直接对话
利用大模型推理能力完成应用的核心功能
应用场景:
- 文本摘要分析
- 舆情分析
- 坐席检查
- AI对话

2.Agent+Function Calling
当我们的需求中涉及到业务的实现,比如让AI生成一份旅行计划,并根据计划给我们订酒店。如:千问给我们订外卖
将应用端业务能力与AI大模型推理能力结合,简化复杂业务功能开发
应用场景:
- 旅行指南
- 数据提取
- 数据聚合分析
- 课程顾问

3.RAG Embeddings(知识库拓展)
大模型的知识是通过历史的数据训练来的。如果要大模型生成发布之后的事情,很有可能大模型就不知道,RAG相当于给大模型一本教材,让它根据这本教材进行学习。
离线步骤:
- 文档加载
- 文档切分
- 文档编码
- 写入知识库
在线步骤:
- 获得用户问题
- 检索知识库中相关知识片段
- 将检索结果和用户问题填入Prompt模版
- 用最终获得的Prompti调用LLM
- 由LLM生成回复
应用场景:
- 个人知识库
- AI客服助手

4.Fine-tuning(模型微调)
在大模型实在不如人意的时候,自己调试大模型。一般实现不了
二、java语言中当下最热门的两个框架
当下最热门的两个框架:springAI和langchain4j

他们的异同:

SpringAI是Spring出版的,所以适配了SpringBoot等,要求jdk高一些
LangChain4j是python中LangChain框架出版的,更适用于低版本
因为spring是专门为java开发的框架,所以更新会很快,更适用于新的大模型,并且更能无缝接入springboot项目
三、SpringAI
快速入门
1.引入依赖
<!-- Spring AI 版本管理(必须) -->
<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>
<!-- Spring AI 核心(所有模型通用) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-core</artifactId>
</dependency>
<!-- OpenAI(ChatGPT) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<!-- 阿里云通义千问 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-qwen-spring-boot-starter</artifactId>
</dependency>
<!-- 百度文心一言 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-wenxin-spring-boot-starter</artifactId>
</dependency>
<!-- 字节跳动豆包 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-doubao-spring-boot-starter</artifactId>
</dependency>
<!-- 讯飞星火 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-spark-spring-boot-starter</artifactId>
</dependency>
2.配置化
spring:
ai:
# 通义千问(阿里)
qwen:
api-key: sk-你的APIKey
chat:
options:
model: qwen-turbo
temperature: 0.7
# 豆包(字节)
doubao:
api-key: sk-你的APIKey
chat:
options:
model: doubao-lite-4k
temperature: 0.7
# OpenAI
openai:
api-key: sk-你的APIKey
base-url: https://api.openai.com
chat:
options:
model: gpt-3.5-turbo
temperature: 0.7
# 文心一言(百度)
wenxin:
api-key: 你的APIKey
secret-key: 你的SecretKey
chat:
options:
model: ernie-3.5-8k
# 讯飞星火
spark:
api-key: 你的APIKey
api-secret: 你的APISecret
app-id: 你的APPID
chat:
options:
model: generalv3
3.配置客户端
配置客户端

@Configuration
public class CommonConfiguration {
@Bean
public ChatClient chatClient(OllamaChatModel chatModel){
return ChatClient
.builder(chatModel)
.defaultSystem("你是小查,是我的智能助手,以后你要为我的生活、学习服务,请以小查的省份和语气回答问题")
.build();
}
}
阻塞式输出

这里springAI已经帮我们整理好了,call()方法用来调用大模型,content()用来将结果解析返回,不用我们自己解析。
流式输出

流式输出只需要把call()方法改为Stream()
会话日志
SpringAI利用AOP原理提供了AI会话时的拦截、增强等功能,也就是Advisor。
@Configuration
public class CommonConfiguration {
@Bean
public ChatClient chatClient(OllamaChatModel chatModel){
return ChatClient
.builder(chatModel)
.defaultSystem("你是小查,是我的智能助手,以后你要为我的生活、学习服务,请以小查的省份和语气回答问题")
// 配置日志Advisor
.defaultAdvisors(new SimpleLoggerAdvisor())
.build();
}
}
logging:
level:
org.springframework.ai.chat.client.advisor: debug
com.langdang.heimaai: debug
2026-05-10T17:21:33.719+08:00 DEBUG 29784 --- [heima-ai] [nio-8080-exec-1] o.s.a.c.c.advisor.SimpleLoggerAdvisor : request: ChatClientRequest[prompt=Prompt{messages=[SystemMessage{textContent='你是小查,是我的智能助手,以后你要为我的生活、学习服务,请以小查的省份和语气回答问题', messageType=SYSTEM, metadata={messageType=SYSTEM}}, UserMessage{content='你是谁', metadata={messageType=USER}, messageType=USER}], modelOptions=org.springframework.ai.ollama.api.OllamaChatOptions@717b7c3b}, context={}]
2026-05-10T17:21:46.626+08:00 DEBUG 29784 --- [heima-ai] [nio-8080-exec-1] o.s.a.c.c.advisor.SimpleLoggerAdvisor : response: {
"result" : {
"output" : {
"messageType" : "ASSISTANT",
"metadata" : {
"messageType" : "ASSISTANT"
},
"toolCalls" : [ ],
"media" : [ ],
"text" : "您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手。我可以帮助您处理各种问题、提供信息和指导,您可以随时问我任何问题或请求帮助。"
},
"metadata" : {
"finishReason" : "stop",
"contentFilters" : [ ],
"empty" : false
}
},
"results" : [ {
"output" : {
"messageType" : "ASSISTANT",
"metadata" : {
"messageType" : "ASSISTANT"
},
"toolCalls" : [ ],
"media" : [ ],
"text" : "您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手。我可以帮助您处理各种问题、提供信息和指导,您可以随时问我任何问题或请求帮助。"
},
"metadata" : {
"finishReason" : "stop",
"contentFilters" : [ ],
"empty" : false
}
} ],
"metadata" : {
"id" : "",
"model" : "deepseek-r1:7b",
"rateLimit" : {
"requestsRemaining" : 0,
"requestsLimit" : 0,
"requestsReset" : 0.0,
"tokensLimit" : 0,
"tokensRemaining" : 0,
"tokensReset" : 0.0
},
"usage" : {
"promptTokens" : 33,
"completionTokens" : 240,
"totalTokens" : 273
},
"promptMetadata" : [ ],
"empty" : false
}
}
您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手。我可以帮助您处理各种问题、提供信息和指导,您可以随时问我任何问题或请求帮助。
会话记忆
如果想让AI有对话记忆,其实就是靠存储它自己生成的回答再发给它来实现。

也就是把他自己的回答重新放到messages里


SpringAI已经提供了相应的存储对话id的接口


我们直接使用spring封装好的方法
@Bean
public ChatClient chatClient(OllamaChatModel chatModel, ChatMemory chatMemory) {
return ChatClient.builder(chatModel)
.defaultSystem("你是小查,是我的智能助手,以后你要为我的生活、学习服务,请以小查的身份和语气回答问题")
.defaultAdvisors(
new SimpleLoggerAdvisor(),
// 直接用 builder(chatMemory) 构建,不额外指定 defaultConversationId
MessageChatMemoryAdvisor.builder(chatMemory)
.build()
)
.build();
}
@Bean
public ChatMemory chatMemory() {
return MessageWindowChatMemory.builder()
.maxMessages(20) // 保留最近20轮对话
.build();
}
也就是加上这一段即可让对话有记忆
// 直接用 builder(chatMemory) 构建,不额外指定defaultConversationId
MessageChatMemoryAdvisor.builder(chatMemory)
@Bean
public ChatMemory chatMemory() {
return MessageWindowChatMemory.builder()
.maxMessages(20) // 保留最近20轮对话
.build();
}

但是一个正常的的AI软件肯定不是我一个人用,假设现在另一个问,如果2个人呢?他还会保持着原有的记忆。现在也就是记忆是没有边界的,是模糊的。
会话ID
// 官方文档 https://springdoc.cn/spring-ai/api/chat-memory.html#_%E8%81%8A%E5%A4%A9%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%9A%84_memory
@RequestMapping("/chat")
public String chatModel(String prompt,String conversationId){
String content = chatClient.prompt()
.user(prompt)
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
.call()
.content();
System.out.println(content);
return content;
}
增加 .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
其中conversationId就是会话id


可以看到在会话id相同时候是有记忆的
但是如果我更换了会话id呢?

他就懵了
这是因为springai的chatMemory方法是通过存储会话id(conversationId)和会话内容(message)来记录内容
会话记录

![]()

可以看到,这里的chatMemoryStore是一个map其中key为String,value是一个List泛型是一个message,
那么message是什么呢?


这里就不卖关子了,点进message后里面是一个接口,接口中MessageType是一个枚举,其中记录了发送人的类型和内容。
利用这一点,我们重写一个messageVO来展示发送人和发送内容

调用chatMemory的get()方法获取一个List,这个list里存储了发送人和发送内容

利用stream留将message转化成我们需要的类型即可获取到会话记录
更多推荐



所有评论(0)