大家好,我是野人。作为一名AI新手,当你第一次接触Spring AI时,可能会被各种概念弄晕:什么是ChatClient?什么是Advisor?怎么让AI记住我之前说的话?
别担心,本文将通过一个生动的 “恋爱助手” 案例,带你一步步梳理这些核心概念,并最终实现一个支持多轮对话的AI应用。
1. 核心工具:ChatClient
在Spring AI的世界里,ChatClient是你与大模型对话的主要入口。你可以把它想象成一个智能电话,你对着它说话,它帮你接通并转告给真正的大模型(如通义千问、ChatGPT)。
那么,如何获得这个“电话”呢?主要有两种方式:
方式一:构造函数注入(推荐)
这种方式代码清晰,便于测试和维护。就像你去营业厅,明确告诉工作人员你需要什么配置的电话。
方式二:字段注入 + 手动构造
这种方式比较直接,通过@Autowired拿到模型,然后手动用模型去创建电话
新手提示: 推荐使用第一种方式(构造器注入),因为它更符合Spring的规范,并且在你后续需要添加更多功能(比如拦截器)时会更加灵活。
2. 增强工具:Advisors(顾问)
光有电话还不够,我们有时想在打电话前先检查一下信号(检查提示词),或者在挂电话后记录一下通话内容(记录日志)。Spring AI 的 Advisors(顾问) 就是用来做这个的。
你可以把 Advisor 想象成一个个 “拦截器” ,它们像洋葱一样层层包裹住真正的大模型。你的话(Prompt)要先经过这些顾问才能传给模型,模型的回答也要经过它们才能返回来。
执行流程拆解:
- 请求发起:你的问题(Prompt)被包装成一个
AdvisedRequest。 - 前置增强:请求依次经过
AroundAdvisor链。每个顾问都可以查看或修改你的问题。 - 调用模型:经过所有顾问处理后,请求才真正发送给
ChatModel(大模型)。 - 后置增强:模型的返回结果被包装成
AdvisedResponse,再次逆序经过顾问链。顾问们可以查看或修改这个结果。 - 返回结果:最终的结果(ChatResponse)返回给你。
3. 赋予AI“记忆”:ChatMemoryAdvisor
默认情况下,大模型是没有记忆的。你问“你好”,它回答“你好”;你接着问“我刚才说了什么?”,它就忘了。为了让AI能记住上下文(实现多轮对话),我们就需要用到 ChatMemoryAdvisor。
Spring AI 提供了几种把“记忆”塞给AI的方式:
- MessageChatMemoryAdvisor(推荐) :把历史对话以原始消息格式(数组)塞给AI。就像把聊天记录截图发给AI看,它理解得最准确。
- PromptChatMemoryAdvisor:把历史对话转换成一段文字描述,放到系统提示词里。这会丢失一些格式信息。
- VectorStoreChatMemoryAdvisor:用向量数据库存储海量历史,适合超长对话。
记忆存储在哪里?ChatMemory
顾问本身不负责存数据,它只是负责“取”和“放”。真正存数据的是 ChatMemory。
Spring AI 提供了多种存储方案:
InMemoryChatMemory:存在内存里(程序重启就没了,适合测试)。JdbcChatMemory:存在数据库里(永久保存)。
4. 实战:打造一个会记住你的恋爱助手
现在,我们把上面的知识都串起来,写一个真正的 LoveApp。这个助手不仅能以恋爱专家的身份回答你,还能记住你上一轮说了什么(多轮对话)。
项目需求:
- AI角色:深耕恋爱心理领域的专家。
- 功能:支持多轮对话,能根据不同的
chatId区分不同用户的对话历史。
完整代码实现:
package com.swl.baoaiagent.app;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.stereotype.Component;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;
@Component
@Slf4j
public class LoveApp {
// 对话客户端
private ChatClient chatClient;
// 系统预设:告诉AI它该扮演什么角色
private static final String SYSTEM_PROMPT = "扮演深耕恋爱心理领域的专家。开场向用户表明身份,告知用户可倾诉恋爱难题。围绕单身、恋爱、已婚三种状态提问:单身状态询问社交圈拓展及追求心仪对象的困扰;恋爱状态询问沟通、习惯差异引发的矛盾;已婚状态询问家庭责任与亲属关系处理的问题。引导用户详述事情经过、对方反应及自身想法,以便给出专属解决方案。";
/**
* 构造函数:初始化AI助手
* @param dashscopeChatModel Spring注入的通义千问模型
*/
public LoveApp(ChatModel dashscopeChatModel) {
// 1. 创建记忆存储器(这里先用内存存储,方便测试)
ChatMemory chatMemory = new InMemoryChatMemory();
// 2. 构建ChatClient,并装配上“记忆顾问”
this.chatClient = ChatClient.builder(dashscopeChatModel)
.defaultSystem(SYSTEM_PROMPT) // 设置角色
.defaultAdvisors(
// 使用链式构造器创建记忆顾问
MessageChatMemoryAdvisor.builder(chatMemory).build()
)
.build();
}
/**
* AI 基础对话方法(支持多轮对话)
* @param message 用户输入的消息
* @param chatId 会话ID(用于区分不同用户的对话)
* @return AI 的回复内容
*/
public String doChat(String message, String chatId){
// 发起对话
ChatResponse chatResponse = chatClient.prompt()
.user(message) // 用户说:我最近和女朋友吵架了
.advisors(spec -> spec
// 告诉顾问:这是谁的对话(张三还是李四)
.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
// 告诉顾问:取最近几条历史记录?(这里取最近10条,后进先出)
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
.call() // 拨打电话
.chatResponse(); // 等待回复
// 解析回复
String content = chatResponse.getResult().getOutput().getText();
log.info("AI回复: {}", content);
return content;
}
}
代码讲解
-
构造函数:
- 我们通过构造器传入了
ChatModel(大模型)。 - 新建了一个
InMemoryChatMemory作为临时记忆仓库。 - 使用
ChatClient.builder(...)进行链式配置:设置系统提示词 (SYSTEM_PROMPT),并装配默认顾问 (MessageChatMemoryAdvisor)。
- 我们通过构造器传入了
-
doChat方法:-
关键点1:
chatId:这是一个非常重要的参数。它就像一个文件夹标签,告诉程序这个对话是属于“用户A”还是“用户B”。如果没有它,所有人的对话就会混在一起。 -
关键点2:
advisors配置:我们在调用prompt()时,通过advisors动态指定了两个参数:CHAT_MEMORY_CONVERSATION_ID_KEY:指定本次对话属于哪个会话ID。CHAT_MEMORY_RETRIEVE_SIZE_KEY:指定从记忆中取回多少条最近的对话。这里设置为10,意味着AI会看到最近10轮(用户和AI一来一回算一轮)的聊天记录。
-
5. 总结
通过这个简单的恋爱助手例子,你应该对Spring AI有了一个初步的认识:
ChatClient是你的AI应用的核心API。Advisors是强大的拦截器机制,用于横切关注点(如记忆、审核、日志)。ChatMemoryAdvisor+ChatMemory是实现多轮对话记忆的黄金搭档。Advisor负责处理逻辑,ChatMemory负责存储数据。
现在,你可以试着运行这个程序,连续问它几个关于恋爱的问题,比如“我喜欢一个女孩但不敢表白怎么办?”,然后接着问“你刚才建议我第一步做什么?”,你会发现,AI已经记住了你们的对话内容。