Spring AI ChatClient 详细用法文档
概述
Spring AI ChatClient 是一个用于执行 AI 模型状态less请求的客户端 API,采用流式 API 设计。它提供了简洁而强大的方式来与各种 AI 模型进行交互,支持文本生成、结构化输出、工具调用等功能。
核心架构
1. 主要接口
ChatClient 接口
public interface ChatClient {
// 创建 ChatClient 实例
static ChatClient create(ChatModel chatModel)
static ChatClient create(ChatModel chatModel, ObservationRegistry observationRegistry)
// 构建器模式
static Builder builder(ChatModel chatModel)
// 提示词入口
ChatClientRequestSpec prompt()
ChatClientRequestSpec prompt(String content)
ChatClientRequestSpec prompt(Prompt prompt)
// 创建变异构建器
Builder mutate()
}
核心规范接口
- ChatClientRequestSpec - 请求规范
- PromptUserSpec - 用户提示词规范
- PromptSystemSpec - 系统提示词规范
- CallResponseSpec - 阻塞式调用响应规范
- StreamResponseSpec - 流式调用响应规范
- AdvisorSpec - 顾问规范
- Builder - 构建器规范
2. 实现类
- DefaultChatClient - ChatClient 的默认实现
- DefaultChatClientBuilder - ChatClient 构建器的默认实现
- DefaultChatClientRequestSpec - 请求规范的默认实现
创建 ChatClient
1. 基本创建方式
// 方式1:使用 create 方法
ChatClient chatClient = ChatClient.create(chatModel);
// 方式2:使用构建器
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultSystem("你是一个有帮助的助手")
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-4")
.temperature(0.7)
.build())
.build();
2. Spring Boot 自动配置
// 在 Spring Boot 环境中,ChatClient.Builder 会自动配置
@Service
public class ChatService {
private final ChatClient.Builder chatClientBuilder;
public ChatService(ChatClient.Builder chatClientBuilder) {
this.chatClientBuilder = chatClientBuilder;
}
public String chat(String message) {
ChatClient chatClient = chatClientBuilder
.defaultSystem("你是一个专业的助手")
.build();
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
基本用法
1. 简单文本生成
// 最简单的用法
String response = ChatClient.create(chatModel)
.prompt("你好,请介绍一下 Spring AI")
.call()
.content();
System.out.println(response);
2. 使用系统提示词和用户提示词
String response = ChatClient.builder(chatModel)
.build()
.prompt()
.system("你是一个专业的 Java 开发工程师")
.user("请解释什么是依赖注入")
.call()
.content();
3. 使用资源文件
// 从资源文件加载系统提示词
Resource systemResource = new ClassPathResource("prompts/system-message.st");
Resource userResource = new ClassPathResource("prompts/user-message.txt");
String response = ChatClient.create(chatModel)
.prompt()
.system(systemResource, StandardCharsets.UTF_8)
.user(userResource)
.call()
.content();
高级功能
1. 提示词模板和参数化
// 使用参数化提示词
String response = ChatClient.create(chatModel)
.prompt()
.system(s -> s.text("你是一个{name}专家,请用{voice}的语调回答问题")
.param("name", "Spring Boot")
.param("voice", "专业"))
.user(u -> u.text("请解释{topic}的概念")
.param("topic", "自动配置"))
.call()
.content();
2. 多模态输入(图片等)
// 添加媒体文件
String response = ChatClient.create(chatModel)
.prompt()
.user(u -> u.text("描述这张图片的内容")
.media(MimeTypeUtils.IMAGE_JPEG, new ClassPathResource("image.jpg"))
.media(MimeTypeUtils.IMAGE_PNG, imageUrl))
.call()
.content();
3. 结构化输出
// 输出为特定类型
record Actor(String name, List<String> movies) {}
List<Actor> actors = ChatClient.create(chatModel)
.prompt()
.user("生成5个著名演员及其代表作品")
.call()
.entity(new ParameterizedTypeReference<List<Actor>>() {});
// 输出为单个对象
WeatherInfo weather = ChatClient.create(chatModel)
.prompt()
.user("北京今天的天气情况")
.call()
.entity(WeatherInfo.class);
4. 流式输出
// 流式获取响应
Flux<String> streamResponse = ChatClient.create(chatModel)
.prompt()
.user("写一个短故事")
.stream()
.content();
streamResponse.subscribe(
content -> System.out.print(content),
error -> System.err.println("Error: " + error),
() -> System.out.println("\n完成!")
);
// 获取完整的流式响应
Flux<ChatResponse> fullStream = ChatClient.create(chatModel)
.prompt()
.user("解释机器学习")
.stream()
.chatResponse();
工具调用
1. 函数工具
// 定义工具函数
record WeatherRequest(String location) {}
record WeatherResponse(String location, double temperature, String condition) {}
@Function("获取指定地点的天气信息")
public WeatherResponse getWeather(WeatherRequest request) {
// 实现天气查询逻辑
return new WeatherResponse(request.location(), 25.0, "晴天");
}
// 使用工具
String response = ChatClient.builder(chatModel)
.defaultTools(new WeatherService()) // 或 .defaultToolCallbacks(getWeatherToolCallback())
.build()
.prompt()
.user("北京今天天气怎么样?")
.call()
.content();
2. 工具上下文
Map<String, Object> toolContext = Map.of(
"userId", "12345",
"sessionId", "abc-def"
);
String response = ChatClient.create(chatModel)
.prompt()
.user("执行用户操作")
.toolContext(toolContext)
.call()
.content();
顾问(Advisors)
1. 日志顾问
// 添加简单日志顾问
String response = ChatClient.create(chatModel)
.prompt()
.advisors(new SimpleLoggerAdvisor())
.user("解释 Spring AI 的架构")
.call()
.content();
2. 记忆顾问
// 使用聊天记忆
ChatMemoryAdvisor memoryAdvisor = new MessageChatMemoryAdvisor(
new InMemoryChatMemory(), 10, 2
);
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(memoryAdvisor)
.build();
// 第一次对话
String response1 = chatClient.prompt()
.user("我叫张三")
.call()
.content();
// 第二次对话,会记住之前的上下文
String response2 = chatClient.prompt()
.user("我刚才告诉你我叫什么名字?")
.call()
.content();
3. RAG 顾问
// 使用检索增强生成
QuestionAnswerAdvisor ragAdvisor = new QuestionAnswerAdvisor(vectorStore);
String response = ChatClient.builder(chatModel)
.defaultAdvisors(ragAdvisor)
.build()
.prompt()
.user("Spring Boot 的自动配置是如何工作的?")
.call()
.content();
4. 自定义顾问
// 创建自定义顾问
public class CustomAdvisor implements Advisor {
@Override
public AdvisedRequest adviseRequest(AdvisedRequest request, Map<String, Object> context) {
// 修改请求
return request;
}
@Override
public AdvisedResponse adviseResponse(AdvisedResponse response, Map<String, Object> context) {
// 修改响应
return response;
}
}
// 使用自定义顾问
String response = ChatClient.create(chatModel)
.prompt()
.advisors(new CustomAdvisor())
.user("你的问题")
.call()
.content();
配置选项
1. 模型选项
// 设置模型参数
ChatOptions options = OpenAiChatOptions.builder()
.model("gpt-4")
.temperature(0.7)
.maxTokens(1000)
.topP(0.9)
.presencePenalty(0.1)
.frequencyPenalty(0.1)
.build();
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultOptions(options)
.build();
2. 动态选项
// 为特定请求设置选项
String response = chatClient.prompt()
.user("生成一段创意文本")
.options(OpenAiChatOptions.builder()
.temperature(0.9)
.maxTokens(500)
.build())
.call()
.content();
响应处理
1. 获取完整响应
// 获取 ChatResponse 对象
ChatResponse response = ChatClient.create(chatModel)
.prompt("你好")
.call()
.chatResponse();
// 访问元数据
Map<String, Object> metadata = response.getMetadata();
String model = response.getMetadata().get("model");
List<Generation> generations = response.getResults();
2. 响应实体
// 获取响应实体
ResponseEntity<ChatResponse, MyEntity> entityResponse = ChatClient.create(chatModel)
.prompt("生成一个用户信息")
.call()
.responseEntity(MyEntity.class);
ChatResponse chatResponse = entityResponse.getResponse();
MyEntity entity = entityResponse.getEntity();
错误处理
1. 异常处理
try {
String response = ChatClient.create(chatModel)
.prompt("你的问题")
.call()
.content();
} catch (ChatModelException e) {
// 处理模型异常
logger.error("模型调用失败", e);
} catch (Exception e) {
// 处理其他异常
logger.error("未知错误", e);
}
2. 流式错误处理
Flux<String> streamResponse = ChatClient.create(chatModel)
.prompt("生成文本")
.stream()
.content();
streamResponse
.doOnError(error -> logger.error("流式响应错误", error))
.onErrorResume(error -> Flux.just("生成失败,请重试"))
.subscribe(System.out::print);
最佳实践
1. 构建 ChatClient 实例
@Configuration
public class ChatConfig {
@Bean
public ChatClient weatherChatClient(ChatModel chatModel) {
return ChatClient.builder(chatModel)
.defaultSystem("你是一个专业的天气预报助手")
.defaultOptions(OpenAiChatOptions.builder()
.temperature(0.3)
.maxTokens(500)
.build())
.defaultAdvisors(
new SimpleLoggerAdvisor(),
new MessageChatMemoryAdvisor(new InMemoryChatMemory(), 10, 2)
)
.build();
}
@Bean
public ChatClient codeChatClient(ChatModel chatModel) {
return ChatClient.builder(chatModel)
.defaultSystem("你是一个专业的编程助手")
.defaultOptions(OpenAiChatOptions.builder()
.temperature(0.1)
.maxTokens(2000)
.build())
.defaultTools(new CodeAnalysisService())
.build();
}
}
2. 使用模板渲染器
@Service
public class ChatService {
private final ChatClient chatClient;
private final TemplateRenderer templateRenderer;
public ChatService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder
.defaultTemplateRenderer(new StTemplateRenderer())
.build();
}
public String generateCode(String language, String requirement) {
return chatClient.prompt()
.system(s -> s.text("你是一个专业的{{language}}程序员")
.param("language", language))
.user(u -> u.text("请用{{language}}实现:{{requirement}}")
.param("requirement", requirement))
.call()
.content();
}
}
3. 批量处理
@Service
public class BatchProcessingService {
private final ChatClient chatClient;
public List<String> processBatch(List<String> prompts) {
return prompts.parallelStream()
.map(prompt -> chatClient.prompt()
.user(prompt)
.call()
.content())
.collect(Collectors.toList());
}
public Flux<String> processStreamingBatch(List<String> prompts) {
return Flux.fromIterable(prompts)
.flatMap(prompt -> chatClient.prompt()
.user(prompt)
.stream()
.content());
}
}
4. 缓存
@Service
public class CachedChatService {
private final ChatClient chatClient;
private final Cache<String, String> responseCache;
public CachedChatService(ChatModel chatModel) {
this.chatClient = ChatClient.builder(chatModel).build();
this.responseCache = Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(Duration.ofHours(1))
.build();
}
public String chat(String message) {
return responseCache.get(message, key ->
chatClient.prompt()
.user(key)
.call()
.content()
);
}
}
监控和观察
1. 启用观察
# application.yml
spring:
ai:
chatclient:
observations:
log-prompt: true # 启用提示词日志
log-completion: true # 启用响应日志
2. 自定义观察处理器
@Bean
public ChatClientObservationConvention customObservationConvention() {
return new DefaultChatClientObservationConvention() {
@Override
public String getName() {
return "spring.ai.chatclient.custom";
}
};
}
总结
Spring AI ChatClient 提供了一个强大而灵活的 API 来与 AI 模型交互。主要特点包括:
- 流式 API 设计 - 链式调用,代码简洁易读
- 多种调用模式 - 支持阻塞式和流式调用
- 结构化输出 - 支持直接映射到 Java 对象
- 工具集成 - 支持函数调用和工具集成
- 顾问模式 - 可扩展的请求/响应处理链
- Spring Boot 集成 - 自动配置和依赖注入支持
- 多模态支持 - 支持文本、图片等多种输入类型
- 模板系统 - 支持参数化提示词和模板渲染
通过合理使用这些功能,可以构建出功能强大、易于维护的 AI 应用程序。