找回密码
 立即注册
首页 业界区 安全 Spring AI 代码分析(四)--Client Chat

Spring AI 代码分析(四)--Client Chat

鞍注塔 2025-11-20 21:55:03
Spring AI Client Chat 分析

请关注微信公众号:阿呆-bot
1. 工程结构概览

spring-ai-client-chat 是 Spring AI 的高级 API 模块,提供了类似 WebClient 的流式 API,让 AI 对话编程变得更加简单和直观。
  1. spring-ai-client-chat/
  2. ├── ChatClient.java              # 核心接口,流式 API
  3. ├── DefaultChatClient.java       # 默认实现
  4. ├── ChatClientRequest.java       # 请求对象
  5. ├── ChatClientResponse.java      # 响应对象
  6. └── advisor/                     # Advisor 机制
  7.     ├── api/                     # Advisor 接口定义
  8.     │   ├── Advisor.java
  9.     │   ├── CallAdvisor.java
  10.     │   ├── StreamAdvisor.java
  11.     │   └── BaseAdvisor.java
  12.     ├── ChatModelCallAdvisor.java    # 调用模型的 Advisor
  13.     ├── ChatModelStreamAdvisor.java  # 流式调用的 Advisor
  14.     ├── ToolCallAdvisor.java         # 工具调用 Advisor
  15.     └── SimpleLoggerAdvisor.java    # 日志 Advisor
复制代码
2. 技术体系与模块关系

ChatClient 建立在 ChatModel 之上,通过 Advisor 机制提供了强大的扩展能力:
1.png

3. 关键场景示例代码

3.1 基础使用

ChatClient 提供了非常友好的流式 API:
  1. @Autowired
  2. private ChatModel chatModel;
  3. public void basicUsage() {
  4.     ChatClient chatClient = ChatClient.create(chatModel);
  5.    
  6.     String response = chatClient.prompt()
  7.         .user("什么是 Spring AI?")
  8.         .call()
  9.         .content();
  10.    
  11.     System.out.println(response);
  12. }
复制代码
3.2 流式调用

流式调用非常简单:
  1. public void streamUsage() {
  2.     ChatClient chatClient = ChatClient.create(chatModel);
  3.    
  4.     chatClient.prompt()
  5.         .user("讲一个故事")
  6.         .stream()
  7.         .content()
  8.         .doOnNext(chunk -> System.out.print(chunk))
  9.         .blockLast();
  10. }
复制代码
3.3 使用 Advisor

Advisor 是 ChatClient 的核心特性,可以增强请求和响应:
  1. public void advisorUsage() {
  2.     // 创建 RAG Advisor
  3.     RetrievalAugmentationAdvisor ragAdvisor =
  4.         RetrievalAugmentationAdvisor.builder()
  5.             .documentRetriever(vectorStoreRetriever)
  6.             .build();
  7.    
  8.     ChatClient chatClient = ChatClient.builder(chatModel)
  9.         .defaultAdvisors(ragAdvisor)
  10.         .build();
  11.    
  12.     String response = chatClient.prompt()
  13.         .user("查询文档中的信息")
  14.         .call()
  15.         .content();
  16. }
复制代码
3.4 结构化输出

ChatClient 支持直接将响应转换为 POJO:
  1. public void structuredOutput() {
  2.     BeanOutputConverter<WeatherInfo> converter =
  3.         new BeanOutputConverter<>(WeatherInfo.class);
  4.    
  5.     WeatherInfo weather = chatClient.prompt()
  6.         .user("查询北京天气,返回 JSON:" + converter.getFormat())
  7.         .call()
  8.         .entity(converter);
  9. }
复制代码
4. 核心时序图

4.1 同步调用流程

2.png

4.2 流式调用流程

3.png

5. 入口类与关键类关系

4.png

6. 关键实现逻辑分析

6.1 流式 API 设计

ChatClient 的流式 API 设计非常巧妙,使用了 Builder 模式和函数式接口:
  1. public interface ChatClient {
  2.     ChatClientRequestSpec prompt();
  3.    
  4.     interface ChatClientRequestSpec {
  5.         PromptUserSpec user(String text);
  6.         PromptSystemSpec system(String text);
  7.         AdvisorSpec advisors(Advisor... advisors);
  8.         CallResponseSpec call();
  9.         StreamResponseSpec stream();
  10.     }
  11.    
  12.     interface CallResponseSpec {
  13.         String content();
  14.         <T> T entity(Class<T> type);
  15.         ChatResponse chatResponse();
  16.     }
  17. }
复制代码
这种设计让 API 既类型安全又易于使用。
6.2 Advisor 机制

Advisor 是 ChatClient 的核心扩展机制,类似于 Spring AOP 的切面:
  1. public interface CallAdvisor extends Advisor {
  2.     ChatClientResponse adviseCall(
  3.         ChatClientRequest request,
  4.         CallAdvisorChain chain
  5.     );
  6. }
复制代码
Advisor 链的执行流程

  • Before 阶段:每个 Advisor 可以在调用前修改请求
  • Call 阶段:调用下一个 Advisor 或最终调用模型
  • After 阶段:每个 Advisor 可以在调用后修改响应
  1. public class DefaultAroundAdvisorChain implements CallAdvisorChain {
  2.     public ChatClientResponse nextCall(ChatClientRequest request) {
  3.         if (currentIndex >= advisors.size()) {
  4.             // 链的末尾,调用模型
  5.             return chatModelCallAdvisor.adviseCall(request, this);
  6.         }
  7.         
  8.         CallAdvisor currentAdvisor = advisors.get(currentIndex);
  9.         return currentAdvisor.adviseCall(request,
  10.             new DefaultAroundAdvisorChain(currentIndex + 1, ...));
  11.     }
  12. }
复制代码
6.3 工具调用处理

ToolCallAdvisor 负责处理工具调用,它会在检测到工具调用时自动执行:
  1. public class ToolCallAdvisor implements CallAdvisor {
  2.     @Override
  3.     public ChatClientResponse adviseCall(...) {
  4.         boolean isToolCall = false;
  5.         do {
  6.             // 调用模型
  7.             chatClientResponse = callAdvisorChain.nextCall(request);
  8.             
  9.             // 检查是否有工具调用
  10.             isToolCall = chatClientResponse.chatResponse().hasToolCalls();
  11.             
  12.             if (isToolCall) {
  13.                 // 执行工具调用
  14.                 ToolExecutionResult result =
  15.                     toolCallingManager.executeToolCalls(...);
  16.                
  17.                 // 将工具结果作为新的请求再次调用
  18.                 request = new Prompt(result.getConversationHistory());
  19.             }
  20.         } while (isToolCall);
  21.         
  22.         return chatClientResponse;
  23.     }
  24. }
复制代码
这种设计实现了自动工具调用循环,直到模型不再请求工具调用。
6.4 流式处理实现

流式处理通过 ChatModelStreamAdvisor 实现:
  1. public class ChatModelStreamAdvisor implements StreamAdvisor {
  2.     @Override
  3.     public Flux<ChatClientResponse> adviseStream(...) {
  4.         Flux<ChatResponse> responseFlux =
  5.             chatModel.stream(request.prompt());
  6.         
  7.         return responseFlux.map(chunk ->
  8.             ChatClientResponse.builder()
  9.                 .chatResponse(chunk)
  10.                 .context(request.context())
  11.                 .build()
  12.         );
  13.     }
  14. }
复制代码
流式 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 灵活扩展。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册