Spring AI 代码分析(四)--Client Chat
Spring AI Client Chat 分析
请关注微信公众号:阿呆-bot
1. 工程结构概览
spring-ai-client-chat 是 Spring AI 的高级 API 模块,提供了类似 WebClient 的流式 API,让 AI 对话编程变得更加简单和直观。
spring-ai-client-chat/
├── ChatClient.java # 核心接口,流式 API
├── DefaultChatClient.java # 默认实现
├── ChatClientRequest.java # 请求对象
├── ChatClientResponse.java # 响应对象
│
└── advisor/ # Advisor 机制
├── api/ # Advisor 接口定义
│ ├── Advisor.java
│ ├── CallAdvisor.java
│ ├── StreamAdvisor.java
│ └── BaseAdvisor.java
├── ChatModelCallAdvisor.java # 调用模型的 Advisor
├── ChatModelStreamAdvisor.java # 流式调用的 Advisor
├── ToolCallAdvisor.java # 工具调用 Advisor
└── SimpleLoggerAdvisor.java # 日志 Advisor
2. 技术体系与模块关系
ChatClient 建立在 ChatModel 之上,通过 Advisor 机制提供了强大的扩展能力:

3. 关键场景示例代码
3.1 基础使用
ChatClient 提供了非常友好的流式 API:
@Autowired
private ChatModel chatModel;
public void basicUsage() {
ChatClient chatClient = ChatClient.create(chatModel);
String response = chatClient.prompt()
.user("什么是 Spring AI?")
.call()
.content();
System.out.println(response);
}
3.2 流式调用
流式调用非常简单:
public void streamUsage() {
ChatClient chatClient = ChatClient.create(chatModel);
chatClient.prompt()
.user("讲一个故事")
.stream()
.content()
.doOnNext(chunk -> System.out.print(chunk))
.blockLast();
}
3.3 使用 Advisor
Advisor 是 ChatClient 的核心特性,可以增强请求和响应:
public void advisorUsage() {
// 创建 RAG Advisor
RetrievalAugmentationAdvisor ragAdvisor =
RetrievalAugmentationAdvisor.builder()
.documentRetriever(vectorStoreRetriever)
.build();
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(ragAdvisor)
.build();
String response = chatClient.prompt()
.user("查询文档中的信息")
.call()
.content();
}
3.4 结构化输出
ChatClient 支持直接将响应转换为 POJO:
public void structuredOutput() {
BeanOutputConverter<WeatherInfo> converter =
new BeanOutputConverter<>(WeatherInfo.class);
WeatherInfo weather = chatClient.prompt()
.user("查询北京天气,返回 JSON:" + converter.getFormat())
.call()
.entity(converter);
}
4. 核心时序图
4.1 同步调用流程

4.2 流式调用流程

5. 入口类与关键类关系

6. 关键实现逻辑分析
6.1 流式 API 设计
ChatClient 的流式 API 设计非常巧妙,使用了 Builder 模式和函数式接口:
public interface ChatClient {
ChatClientRequestSpec prompt();
interface ChatClientRequestSpec {
PromptUserSpec user(String text);
PromptSystemSpec system(String text);
AdvisorSpec advisors(Advisor... advisors);
CallResponseSpec call();
StreamResponseSpec stream();
}
interface CallResponseSpec {
String content();
<T> T entity(Class<T> type);
ChatResponse chatResponse();
}
}
这种设计让 API 既类型安全又易于使用。
6.2 Advisor 机制
Advisor 是 ChatClient 的核心扩展机制,类似于 Spring AOP 的切面:
public interface CallAdvisor extends Advisor {
ChatClientResponse adviseCall(
ChatClientRequest request,
CallAdvisorChain chain
);
}
Advisor 链的执行流程:
- Before 阶段:每个 Advisor 可以在调用前修改请求
- Call 阶段:调用下一个 Advisor 或最终调用模型
- After 阶段:每个 Advisor 可以在调用后修改响应
public class DefaultAroundAdvisorChain implements CallAdvisorChain {
public ChatClientResponse nextCall(ChatClientRequest request) {
if (currentIndex >= advisors.size()) {
// 链的末尾,调用模型
return chatModelCallAdvisor.adviseCall(request, this);
}
CallAdvisor currentAdvisor = advisors.get(currentIndex);
return currentAdvisor.adviseCall(request,
new DefaultAroundAdvisorChain(currentIndex + 1, ...));
}
}
6.3 工具调用处理
ToolCallAdvisor 负责处理工具调用,它会在检测到工具调用时自动执行:
public class ToolCallAdvisor implements CallAdvisor {
@Override
public ChatClientResponse adviseCall(...) {
boolean isToolCall = false;
do {
// 调用模型
chatClientResponse = callAdvisorChain.nextCall(request);
// 检查是否有工具调用
isToolCall = chatClientResponse.chatResponse().hasToolCalls();
if (isToolCall) {
// 执行工具调用
ToolExecutionResult result =
toolCallingManager.executeToolCalls(...);
// 将工具结果作为新的请求再次调用
request = new Prompt(result.getConversationHistory());
}
} while (isToolCall);
return chatClientResponse;
}
}
这种设计实现了自动工具调用循环,直到模型不再请求工具调用。
6.4 流式处理实现
流式处理通过 ChatModelStreamAdvisor 实现:
public class ChatModelStreamAdvisor implements StreamAdvisor {
@Override
public Flux<ChatClientResponse> adviseStream(...) {
Flux<ChatResponse> responseFlux =
chatModel.stream(request.prompt());
return responseFlux.map(chunk ->
ChatClientResponse.builder()
.chatResponse(chunk)
.context(request.context())
.build()
);
}
}
流式 Advisor 链的处理更复杂,因为需要在流式响应中插入处理逻辑。
7. 外部依赖
spring-ai-client-chat 的依赖:
- spring-ai-model:核心模型抽象
- Reactor Core:响应式流式处理
- Spring Framework:IoC 和核心功能
- Jackson:JSON 处理(用于结构化输出)
- MCP SDK:Model Context Protocol 支持
8. 工程总结
spring-ai-client-chat 模块的设计体现了几个重要的设计原则:
流式 API 设计。ChatClient 的 API 风格和 Spring WebClient 很像,用起来很顺手。开发者不需要学习新的 API,就能快速上手。
Advisor 机制。这是 ChatClient 的核心能力。通过 Advisor,我们可以给请求和响应"加料",比如做 RAG、记录对话历史、打日志、安全检查等,而且不需要改核心代码。
责任链模式。多个 Advisor 按顺序执行,每个 Advisor 都能修改请求和响应,就像过滤器链一样。
工具调用自动化。ToolCallAdvisor 会自动处理工具调用循环,模型说要调用工具,它就自动调用,然后把结果再传给模型,直到模型不再需要工具。整个过程对用户是透明的。
类型安全。通过泛型和函数式接口,API 既灵活又安全,编译期就能发现很多错误。
总的来说,spring-ai-client-chat 是一个设计得很好的高级 API。它让 AI 对话编程变得简单,同时通过 Advisor 机制提供了强大的扩展能力。简单场景用起来很顺手,复杂场景也能通过 Advisor 灵活扩展。

浙公网安备 33010602011771号