一:系统提示词设计
搞系统提示词可以让豆包写。
然后可以到阿里云百炼的文本调试里面去做,内容调试

二:多轮对话实现
1:Chat Client API
功能比直接调用ChatModel功能更丰富。Chat Client需要用到Chet Model对象。
指定大模型+指定系统预设+指定配置参数,右边的聊天框就是一个chat client。

1:ChatClient两种创建方式
// 方式1:使用构造器注入
@Service
public class ChatService {
private final ChatClient chatClient;
public ChatService(ChatClient.Builder builder) {
this.chatClient = builder
.defaultSystem("你是恋爱顾问")
.build();
}
}
// 方式2:使用建造者模式
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultSystem("你是恋爱顾问")
.build();
推荐第二种。
2:Chat Client多种响应格式
返回整个文本,返回Java实体,返回List集合,流式返回
返回实体的这种形式被称为结构化输出。
// ChatClient支持多种响应格式
// 1. 返回 ChatResponse 对象(包含元数据如 token 使用量)
ChatResponse chatResponse = chatClient.prompt()
.user("Tell me a joke")
.call()
.chatResponse();
// 2. 返回实体对象(自动将 AI 输出映射为 Java 对象)
// 2.1 返回单个实体
record ActorFilms(String actor, List<String> movies) {}
ActorFilms actorFilms = chatClient.prompt()
.user("Generate the filmography for a random actor.")
.call()
.entity(ActorFilms.class);
// 2.2 返回泛型集合
List<ActorFilms> multipleActors = chatClient.prompt()
.user("Generate filmography for Tom Hanks and Bill Murray.")
.call()
.entity(new ParameterizedTypeReference<List<ActorFilms>>() {});
// 3. 流式返回(适用于打字机效果)
Flux<String> streamResponse = chatClient.prompt()
.user("Tell me a story")
.stream()
.content();
// 也可以流式返回ChatResponse
Flux<ChatResponse> streamWithMetadata = chatClient.prompt()
.user("Tell me a story")
.stream()
.chatResponse();
3:ChatClient设置默认参数
// 定义默认系统提示词
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultSystem("You are a friendly chat bot that answers question in the voice of a {voice}")
.build();
// 对话时动态更改系统提示词的变量
chatClient.prompt()
.system(sp -> sp.param("voice", voice))
.user(message)
.call()
.content());
支持指定的对话选项、默认拦截器、默认函数调用等等。
2:Advisors
Spring AI 使用 Advisors(顾问) 机制增强 AI 能力,可理解为可插拔的拦截器,在调用 AI 前后执行额外操作:
- 前置增强:调用 AI 前改写 Prompt 提示词、检查提示词安全性
- 后置增强:调用 AI 后记录日志、处理返回结果
后续教程中会将其称为拦截器。
典型用法示例
可直接为 ChatClient 指定默认拦截器,例如:MessageChatMemoryAdvisor(对话记忆拦截器),可实现多轮对话能力,无需手动维护对话列表。
var chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(
new MessageChatMemoryAdvisor(chatMemory), // 对话记忆 advisor
new QuestionAnswerAdvisor(vectorStore) // RAG 检索增强 advisor
)
.build();
String response = this.chatClient.prompt()
// 对话时动态设定拦截器参数,比如指定对话记忆的 id 和长度
.advisors(advisor -> advisor.param("chat_memory_conversation_id", "678")
// 最多拿100条记录获取上下文。
.param("chat_memory_response_size", 100))
.user(userText)
.call()
.content();

拦截器的作用:敏感词校验、添加上下文记忆、通过RAG进行检索增强。等等。拦截器是责任链的形式进行调用。
拦截器是有顺序的,顺序越小越先执行getOrder()。不是通过代码的编写顺序决定的。

Spring AI Advisors 模式核心内容提取
Advisors 分为 流式(Streaming) 和 非流式(Non-Streaming) 两种模式:
- 二者在用法上无明显区别 ,仅返回值不同。
- 若要自主实现 Advisors,为保证通用性,最好同时实现流式和非流式的环绕通知方法。

1:Spring内置的Advisors
Spring AI ChatMemoryAdvisor 内置实现方式提取
要实现对话记忆功能,可使用 Spring AI 的 ChatMemoryAdvisor,它主要有以下几种内置实现:
- MessageChatMemoryAdvisor :从记忆中检索历史对话,并将其作为消息集合添加到提示词中。
- PromptChatMemoryAdvisor :从记忆中检索历史对话,并将其添加到提示词的系统文本中。
- VectorStoreChatMemoryAdvisor :使用向量数据库来存储和检索历史对话。

2:MessageChatMemoryAdvisor 与 PromptChatMemoryAdvisor 核心区别提取
两者用法类似,但存在以下关键差异:
-
MessageChatMemoryAdvisor
-
将对话历史作为一系列独立消息添加到提示中
-
保留原始对话的完整结构,包含每条消息的角色标识(用户 / 助手 / 系统)
-
示例格式: json
[ {"role": "user", "content": "你好"}, {"role": "assistant", "content": "你好!有什么我能帮助你的吗?"}, {"role": "user", "content": "讲个笑话"} ]
-
-
PromptChatMemoryAdvisor
-
将对话历史添加到提示词的系统文本部分
-
可能会丢失原始的消息边界
-
示例格式:
以下是之前的对话历史: 用户:你好 助手:你好!有什么我能帮助你的吗? 用户:讲个笑话 现在请继续回答用户的问题。
-
一般情况下,更推荐使用 MessageChatMemoryAdvisor ,它更符合大多数现代 LLM 的对话模型设计,能更好地保持上下文连贯性。
**3:**MessageChatMemoryAdvisor
MessageChatMemoryAdvisor对象创建需要ChatMemory对象。
4:Chat Memory 核心内容提取
所有 ChatMemoryAdvisor 都依赖 Chat Memory 进行构造,它负责历史对话的存储,定义了保存消息、查询消息、清空消息历史的方法。
ChatMemory 接口定义
public interface ChatMemory {
// TODO: consider a non-blocking interface for streaming usages
default void add(String conversationId, Message message) {
this.add(conversationId, List.of(message));
}
void add(String conversationId, List<Message> messages);
List<Message> get(String conversationId, int lastN);
void clear(String conversationId);
}
Spring AI 内置 Chat Memory 实现
Spring AI 提供了多种可将对话保存到不同数据源的内置实现:
- InMemoryChatMemory:内存存储
- CassandraChatMemory:在 Cassandra 中带有过期时间的持久化存储
- Neo4jChatMemory:在 Neo4j 中没有过期时间限制的持久化存储
- JdbcChatMemory:在 JDBC 中没有过期时间限制的持久化存储
我们可以通过chatmemory来实现自己的持久化。(增删查)还是要我们自己保存下来。
所谓对话记忆的实现原理,就是每次对话把上下文发一遍,就有记忆了。