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 灵活扩展。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |