Spring AI系列之核心组件:ChatClient、Prompt 与 Advisor
一、ChatClient:流式 API 的优雅入口
ChatClient 是 Spring AI 提供的高阶客户端,采用**构建者模式(Builder Pattern)**设计,支持链式调用,极大地简化了 Prompt 构建和响应处理流程。
1.1 核心架构

*图:Spring AI ChatClient 整体架构图 *
ChatClient 位于应用层与 Chat Model 之间,封装了复杂的 HTTP 调用细节,提供了统一的 API 接口。
1.2 两种创建方式
方式一:配置类注入(推荐)
java
@Configuration
public class ChatClientConfig {
@Bean
ChatClient chatClient(ChatClient.Builder builder) {
return builder
.defaultSystem("你是专业的技术助手") // 设置全局系统消息
.build();
}
}
方式二:构造函数注入
java
@RestController
public class ChatController {
private final ChatClient chatClient;
// Spring 会自动注入 Builder
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
}
1.3 基础调用示例
java
@GetMapping("/ai/generate")
public String generate(@RequestParam String message) {
return chatClient.prompt() // 1. 创建 Prompt 构建器
.user(message) // 2. 设置用户消息
.call() // 3. 执行调用
.content(); // 4. 提取文本内容
}
1.4 设置系统消息(System Message)
系统消息用于定义 AI 的角色和行为准则:
java
String response = chatClient.prompt()
.system("你是一位资深Java工程师,回答需简洁准确") // 设定角色
.user("说说Springboot源码?")
.call()
.content();
二、Prompt:结构化消息的载体
Prompt 是 Spring AI 中消息的容器,支持多角色对话管理。
2.1 Prompt 的结构
┌─────────────────────────────────────┐
│ Prompt │
├─────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ │
│ │ System │ │ User │ │
│ │ Message │ │ Message │ │
│ │ (系统指令)│ │ (用户输入)│ │
│ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Assistant│ │ ... │ │
│ │ Message │ │ │ │
│ │ (AI回复) │ │ │ │
│ └──────────┘ └──────────┘ │
└─────────────────────────────────────┘
2.2 使用 PromptTemplate 实现动态模板
PromptTemplate 支持占位符替换,实现动态内容生成:
java
@GetMapping("/prompt/test1")
public String promptTest1() {
// 用户消息
String userText = "介绍一下海盗黄金时代的三位著名海盗";
Message userMessage = new UserMessage(userText);
// 系统消息模板(带变量)
SystemPromptTemplate systemTemplate = new SystemPromptTemplate("你是一个名叫{name}的助手,请以{voice}的风格回答。");
// 填充变量
Message systemMessage = systemTemplate.createMessage(Map.of(
"name", "Koki",
"voice", "幽默"
));
// 组装 Prompt
Prompt prompt = new Prompt(List.of(systemMessage, userMessage));
// 调用模型
return chatClient.prompt(prompt).call().content();
}
2.3 从文件加载模板(生产环境推荐)
将提示词模板外置,便于管理和热更新:
java
// 注入模板文件
@Value("classpath:/prompts/system-message.st")
private Resource systemResource;
@GetMapping("/prompt/test2")
public String promptTest2() {
// 用户消息
String userText = "你好呀,你是什么AI Agent";
Message userMessage = new UserMessage(userText);
// 系统消息模板(带变量)
SystemPromptTemplate systemTemplate = new SystemPromptTemplate(systemResource);
// 填充变量
Message systemMessage = systemTemplate.createMessage(Map.of(
"name", "小助手",
"voice", "友好"
));
// 组装 Prompt
Prompt prompt = new Prompt(List.of(systemMessage, userMessage));
// 调用模型
return chatClient.prompt(prompt).call().content();
}
模板文件示例 (src/main/resources/prompts/system-message.st):
你是{name},一个{voice}的 AI 助手。
请确保回答:
1. 准确可靠
2. 通俗易懂
3. 保持{voice}的风格
三、Advisor:拦截与增强机制
Advisor 是 Spring AI 的拦截器机制,允许在请求发送前后进行处理,实现横切关注点(Cross-cutting Concerns)。
3.1 Advisor 执行流程

*图:Advisor 拦截流程 - 请求和响应都会经过 Advisor 链处理 *
执行顺序说明:
- Before Advice:请求到达模型前执行(如添加历史记录)
- 调用 Chat Model:发送处理后的请求
- After Advice:收到响应后执行(如记录日志、过滤内容)
3.2 自定义日志 Advisor
实现 CallAroundAdvisor(同步)和 StreamAroundAdvisor(流式):
java
@Component
public class SimpleLoggerAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {
@Override
public String getName() {
return "simpleLoggerAdvisor";
}
@Override
public int getOrder() {
return 0; // 数字越小优先级越高
}
// 同步调用拦截
@Override
public AdvisedResponse aroundCall(
AdvisedRequest req,
CallAroundAdvisorChain chain) {
log.info("🚀 请求前: {}", req.userText());
AdvisedResponse res = chain.nextAroundCall(req); // 继续执行链
log.info("✅ 响应后: {}", res.response());
return res;
}
// 流式调用拦截
@Override
public Flux<AdvisedResponse> aroundStream(
AdvisedRequest req,
StreamAroundAdvisorChain chain) {
log.info("🌊 流式请求前: {}", req.userText());
return chain.nextAroundStream(req)
.doOnNext(res -> log.info("📝 流式响应: {}", res));
}
}
3.3 使用 Advisor
java
@Autowired
private SimpleLoggerAdvisor loggerAdvisor;
@GetMapping("/ai/chat")
public String chat(@RequestParam String message) {
return chatClient.prompt()
.advisors(loggerAdvisor) // 添加 Advisor
.user(message)
.call()
.content();
}
3.4 内置 Advisor 一览
| Advisor | 功能 | 适用场景 |
|---|---|---|
MessageChatMemoryAdvisor |
对话记忆管理 | 多轮对话保持上下文 |
QuestionAnswerAdvisor |
RAG 检索增强 | 基于知识库问答 |
SafeGuardAdvisor |
内容安全过滤 | 敏感词检测、合规检查 |
VectorStoreChatMemoryAdvisor |
向量存储记忆 | 长期记忆持久化 |
使用示例:
java
package com.example.ai.config;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ChatConfig {
@Bean
public ChatClient chatClient(ChatClient.Builder builder) {
return builder.defaultSystem("你是一个AI聊天助手")
.build();
}
/**
* 配置本地内存版的ChatMemory Bean
*/
@Bean
public ChatMemory chatMemory() {
// InMemoryChatMemory是ChatMemory的默认实现,基于本地内存存储对话上下文
return new InMemoryChatMemory();
}
}
java
@Autowired
private ChatMemory chatMemory;
@GetMapping("/ai/memory")
public String chatWithMemory(@RequestParam String message) {
return chatClient.prompt()
.advisors(new MessageChatMemoryAdvisor(chatMemory))
.user(message)
.call()
.content();
}
四、动态配置覆盖机制
Spring AI 支持全局默认配置 + 运行时动态覆盖的灵活配置策略。
4.1 配置层级
┌─────────────────────────────────────┐
│ 运行时动态配置 (最高优先级) │
│ .system(sp -> sp.param(...)) │
├─────────────────────────────────────┤
│ ChatClient 实例级配置 │
│ builder.defaultSystem(...) │
├─────────────────────────────────────┤
│ 应用全局配置 (application.yml) │
│ spring.ai.openai.chat.options... │
├─────────────────────────────────────┤
│ 模型默认配置 (最低优先级) │
│ OpenAI GPT-4 默认参数 │
└─────────────────────────────────────┘
4.2 实战示例
步骤 1:配置全局默认值
java
@Bean
ChatClient chatClient(ChatClient.Builder builder) {
return builder
.defaultSystem("你是{language}专家,精通{language}语法和表达")
.build();
}
步骤 2:运行时动态替换参数
java
@GetMapping("/ai/dynamic")
public String dynamicChat(
@RequestParam String language,
@RequestParam String topic) {
return chatClient.prompt()
.system(sp -> sp.param("language", language)) // 动态注入
.user("请讲解 " + topic)
.call()
.content();
}
// 调用示例:/ai/dynamic?language=英语&topic=过去完成时
五、完整实战:构建智能客服
java
@Service
public class CustomerService {
@Autowired
private ChatClient chatClient;
@Autowired
private VectorStore vectorStore;
public String handleQuery(String userQuery) {
return chatClient.prompt()
// 1. 系统角色设定
.system("你是专业客服助手,回答需礼貌、准确")
// 2. 添加 RAG Advisor(知识库检索)
.advisors(new QuestionAnswerAdvisor(vectorStore))
// 3. 添加记忆 Advisor(保持对话上下文)
.advisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory()))
// 4. 用户输入
.user(userQuery)
// 5. 执行调用
.call()
.content();
}
}
总结
| 组件 | 核心职责 | 关键特性 |
|---|---|---|
| ChatClient | 统一入口 | 链式 API、同步/流式双支持 |
| Prompt | 消息封装 | 多角色、模板化、文件加载 |
| Advisor | 横切增强 | 拦截链、内置丰富、可扩展 |
这三个组件构成了 Spring AI 的核心骨架,遵循单一职责原则,既保证了灵活性,又提供了强大的扩展能力。通过合理组合,可以快速构建企业级的 AI 应用。
参考资源: