AI 原生应用开发中,与大语言模型(LLM)的高效交互是核心需求。Spring AI 提供的 ChatClient 组件,通过流畅的 API 设计、灵活的多模型支持、丰富的响应处理能力,极大简化了 LLM 集成流程。本文将从基础用法到高级特性,结合完整代码示例,全面解析 ChatClient 的使用场景与最佳实践。
一、ChatClient 核心概述
1.1 什么是 ChatClient?
ChatClient 是 Spring AI 框架中用于与 AI 大语言模型进行交互的核心组件。它作为应用程序与 LLM 之间的桥梁,封装了复杂的网络通信、请求构建、响应解析等底层细节,让开发者能够专注于业务逻辑的实现。
1.2 核心特性详解
ChatClient 是 Spring AI 中用于与 AI 模型通信的核心 API,具备以下关键特性:
-
Fluent API(流畅接口):采用方法链式调用的设计模式,简化 Prompt 构建与请求发送流程。这种设计模式源于构建器模式(Builder Pattern),通过链式调用提高代码的可读性和维护性。
-
同步与异步支持 :支持同步调用 与流式响应两种编程模型。同步调用适用于需要立即获取完整结果的场景,而流式响应则适合处理长文本生成,能够提供更即时的用户反馈。
-
多模型兼容性:兼容主流 LLM(DeepSeek、OpenAI、Anthropic、Google Gemini 等),支持多模型协同工作。这种设计体现了策略模式(Strategy Pattern)的思想,允许在运行时切换不同的 AI 模型。
-
高级开发能力:内置 Prompt 模板、参数替换、实体映射等高效开发能力。这些功能大大减少了样板代码,提高了开发效率。
-
企业级特性:支持对话记忆、检索增强生成(RAG)、日志监控等高级特性,满足企业级应用的需求。
-
可扩展架构:可通过 Advisors 机制扩展请求 / 响应处理逻辑,实现自定义的拦截器和处理器。
1.3 核心设计理念
核心设计理念:将复杂的 LLM 通信细节封装,让开发者专注于业务逻辑,而非底层网络交互与模型适配。这种设计理念体现了关注点分离(Separation of Concerns)的原则,通过抽象层将技术细节与业务逻辑解耦。
二、快速入门:创建第一个 ChatClient
2.1 依赖准备
首先需要在 Spring Boot 项目中引入 Spring AI 相关依赖(以 OpenAI 为例)【需要什么就替换你需要的模型】:
XML
<!-- Spring AI OpenAI 依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- Spring Web 用于HTTP接口暴露 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
其他模型依赖示例
除了 OpenAI,Spring AI 还支持多种主流模型事例、以下提供了1个例子
Anthropic Claude:
XML
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-anthropic-spring-boot-starter</artifactId>
</dependency>
2.2 配置模型密钥
在 application.properties 中配置 OpenAI API 密钥:
XML
# OpenAI API配置
spring.ai.openai.api-key=sk-your-openai-api-key
spring.ai.openai.chat.model=gpt-3.5-turbo
spring.ai.openai.chat.temperature=0.7
配置参数详解
-
api-key:你的 OpenAI API 密钥,用于身份验证。建议将密钥存储在环境变量或安全的密钥管理系统中,而不是直接写在配置文件中。
-
model:指定使用的具体模型版本。OpenAI 提供了多个模型选项:
-
gpt-3.5-turbo:成本效益最佳的模型,适合大多数应用场景 -
gpt-4:更强大的模型,适合复杂推理和创意任务 -
gpt-4-turbo:GPT-4 的优化版本,性能和成本更平衡
-
-
temperature:控制生成文本的随机性,范围 0-2:
-
0.0-0.3:更确定性、可预测的输出,适合事实性问答
-
0.7-1.0:平衡的创造性和一致性,适合一般对话
-
1.0-2.0:更具创造性但可能不够连贯,适合创意写作
-
安全配置最佳实践
XML
# 推荐做法:使用环境变量
spring.ai.openai.api-key=${OPENAI_API_KEY}
2.3 自动配置创建 ChatClient
Spring AI 提供自动配置功能,无需手动构建 ChatClient,直接注入 ChatClient.Builder 即可使用:
java
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
class AIController {
// 注入Spring自动配置的ChatClient.Builder
private final ChatClient chatClient;
// 构造函数注入Builder并构建ChatClient
public AIController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
// 暴露HTTP接口,接收用户输入并返回AI响应
@GetMapping("/ai/simple")
String generateResponse(@RequestParam(defaultValue = "介绍Spring AI") String userInput) {
// 流畅API构建请求:指定用户输入 → 发送请求 → 获取响应内容
return this.chatClient.prompt()
.user(userInput) // 设置用户消息
.call() // 同步调用AI模型
.content(); // 提取响应文本内容
}
}
自动配置原理
Spring Boot 的自动配置机制会在类路径下检测到相关依赖时,自动创建和配置必要的 Bean。对于 ChatClient,Spring AI 会自动:
-
创建
ChatModel实例(基于配置的模型类型) -
创建
ChatClient.Builder实例 -
应用默认的配置参数
-
注册到 Spring 应用上下文中
错误处理与重试机制
在实际应用中,建议添加适当的错误处理:
java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
class AIController {
private final ChatClient chatClient;
private static final Logger logger = LoggerFactory.getLogger(AIController.class);
public AIController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
@GetMapping("/ai/simple")
ResponseEntity<String> generateResponse(@RequestParam(defaultValue = "介绍Spring AI") String userInput) {
try {
String response = this.chatClient.prompt()
.user(userInput)
.call()
.content();
return ResponseEntity.ok(response);
} catch (Exception e) {
logger.error("AI服务调用失败", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("抱歉,AI服务暂时不可用,请稍后重试");
}
}
}
三、多模型支持:灵活切换与协同
3.1 多模型策略的背景与意义
在实际应用中,常需要使用多个 LLM(如不同模型适配不同任务)。ChatClient 提供了完善的多模型管理方案。
为什么需要多模型支持?
-
成本优化:不同模型的定价策略不同,可以根据任务复杂度选择合适的模型
-
性能平衡:某些模型在特定任务上表现更好,如 GPT-4 在推理任务上更强
-
风险分散:避免单点故障,提高系统可用性
-
合规要求:某些行业或地区可能需要使用特定的模型提供商
-
功能互补:不同模型有各自的优势领域,可以组合使用
3.2 核心配置前提
默认情况下,Spring AI 自动配置单个 ChatClient.Builder。如需使用多模型,需先禁用自动配置:
java
# 禁用默认ChatClient.Builder自动配置
spring.ai.chat.client.enabled=false
禁用自动配置的影响
禁用自动配置后,你需要:
-
手动创建所有需要的 ChatClient Bean
-
自行管理模型配置和依赖注入
-
负责错误处理和重试逻辑的实现
3.3 同类型模型多配置(如多个 OpenAI 模型)
适用于同一模型类型但不同参数配置的场景(如不同 temperature、不同模型版本)
java
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.chat.ChatClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
class MultiModelConfig {
// 配置第一个OpenAI客户端(侧重精准性)
@Bean
ChatClient preciseOpenAiClient(OpenAiChatModel openAiChatModel) {
return ChatClient.builder(openAiChatModel)
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-4")
.temperature(0.2) // 低随机性,结果更精准
.build())
.defaultSystemPrompt("你是一个精准的信息查询助手,回答简洁准确😊")
.build();
}
// 配置第二个OpenAI客户端(侧重创造性)
@Bean
ChatClient creativeOpenAiClient(OpenAiChatModel openAiChatModel) {
return ChatClient.builder(openAiChatModel)
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-3.5-turbo")
.temperature(0.9) // 高随机性,更具创造性
.build())
.defaultSystemPrompt("你是一个创意写作助手,语言生动有趣😊")
.build();
}
}
模型选择策略
在实际应用中,可以根据以下策略选择模型:
1、任务分类策略:
java
@Service
public class ModelRoutingService {
@Autowired
@Qualifier("preciseOpenAiClient")
private ChatClient preciseClient;
@Autowired
@Qualifier("creativeOpenAiClient")
private ChatClient creativeClient;
public String generateContent(String taskType, String prompt) {
ChatClient client = "creative".equals(taskType) ? creativeClient : preciseClient;
return client.prompt()
.user(prompt)
.call()
.content();
}
}
成本敏感策略
java
public class CostOptimizedService {
public String generateWithBudget(String prompt, double budget) {
ChatClient client = budget > 0.01 ? gpt4Client : gpt35Client;
return client.prompt()
.user(prompt)
.call()
.content();
}
}
3.4 不同类型模型集成(OpenAI + Anthropic)
适用于需要结合不同厂商模型优势的场景:
java
class CrossModelConfig {
// 配置OpenAI客户端
@Bean("openAiChatClient")
ChatClient openAiChatClient(OpenAiChatModel openAiChatModel) {
return ChatClient.create(openAiChatModel);
}
// 配置Anthropic客户端
@Bean("anthropicChatClient")
ChatClient anthropicChatClient(AnthropicChatModel anthropicChatModel) {
return ChatClient.create(anthropicChatModel);
}
// 示例:根据用户选择切换模型
@Bean
CommandLineRunner modelSwitchExample(
@Qualifier("openAiChatClient") ChatClient openAiClient,
@Qualifier("anthropicChatClient") ChatClient anthropicClient) {
return args -> {
// 模拟用户选择模型
String modelChoice = "openai"; // 可从前端或配置获取
ChatClient selectedClient = "openai".equals(modelChoice) ? openAiClient : anthropicClient;
// 发送请求
String response = selectedClient.prompt("解释量子计算的基本原理")
.call()
.content();
System.out.printf("使用%s模型的响应:%n%s", modelChoice, response);
};
}
}
多模型协同策略
1、投票机制:多个模型生成结果,选择最佳答案、【伪代码】
java
public class EnsembleService {
public String ensembleGenerate(String prompt) {
String openaiResult = openaiClient.prompt().user(prompt).call().content();
String anthropicResult = anthropicClient.prompt().user(prompt).call().content();
// 使用另一个模型评估哪个结果更好
return evaluationClient.prompt()
.user("请比较以下两个回答,选择更好的一个:\n1. " + openaiResult + "\n2. " + anthropicResult)
.call()
.content();
}
}
2、流水线模式:一个模型的输出作为另一个模型的输入
java
public class PipelineService {
public String pipelineGenerate(String topic) {
// 第一步:生成大纲
String outline = gpt4Client.prompt()
.user("为\"" + topic + "\"生成一个详细的大纲")
.call()
.content();
// 第二步:基于大纲生成详细内容
return claudeClient.prompt()
.user("基于以下大纲写一篇详细的文章:\n" + outline)
.call()
.content();
}
}
3.5 OpenAI 兼容 API 多端点(Groq + OpenAI)
许多平台提供 OpenAI 兼容 API(如 Groq、Ollama),可通过mutate()方法快速适配:
java
@Service
class MultiEndpointService {
private static final Logger logger = LoggerFactory.getLogger(MultiEndpointService.class);
@Autowired
private OpenAiChatModel baseOpenAiModel;
@Autowired
private OpenAiApi baseOpenAiApi;
public void multiEndpointDemo() {
try {
// 1. 配置Groq API(兼容OpenAI协议)
OpenAiApi groqApi = baseOpenAiApi.mutate()
.baseUrl("https://api.groq.com/openai")
.apiKey(System.getenv("GROQ_API_KEY")) // 从环境变量获取密钥
.build();
OpenAiChatModel groqModel = baseOpenAiModel.mutate()
.openAiApi(groqApi)
.defaultOptions(OpenAiChatOptions.builder()
.model("llama3-70b-8192")
.temperature(0.5)
.build())
.build();
// 2. 配置OpenAI GPT-4 API
OpenAiApi gpt4Api = baseOpenAiApi.mutate()
.baseUrl("https://api.openai.com/v1")
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
OpenAiChatModel gpt4Model = baseOpenAiModel.mutate()
.openAiApi(gpt4Api)
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-4")
.temperature(0.7)
.build())
.build();
// 3. 分别调用两个端点
String prompt = "法国的首都是哪里?";
String groqResponse = ChatClient.builder(groqModel).build()
.prompt(prompt)
.call()
.content();
String gpt4Response = ChatClient.builder(gpt4Model).build()
.prompt(prompt)
.call()
.content();
logger.info("Groq (Llama3) 响应:{}", groqResponse);
logger.info("OpenAI GPT-4 响应:{}", gpt4Response);
} catch (Exception e) {
logger.error("多端点调用失败", e);
}
}
}