Chat Client API
关于 ChatClient
ChatClient 提供了一个流畅的 API 用于与 AI 模型进行通信。它同时支持同步和流式编程模型。
关于 ChatClient 中命令式和响应式编程模型组合使用的相关说明,请参阅本文档底部的实现说明部分。
ChatClient API 提供了构建 Prompt 各个组成部分的方法,这些 Prompt 将作为输入传递给 AI 模型。从 API 的角度来看,Prompt 包含了一系列消息。AI 模型处理两种主要类型的消息:用户消息(来自用户的直接输入)和系统消息(由系统生成以指导对话)。这些消息通常包含占位符,这些占位符会在运行时根据用户输入进行替换,以定制 AI 模型对用户输入的响应。还可以指定 Prompt 选项,例如要使用的 AI 模型名称和 topK 或创造性的 temperature 设置。
创建 ChatClient
ChatClient 是使用 ChatClient.Builder 对象创建的。ChatBuilder 中需要传入一个 ChatModel,您可以集成相关的 Spring Boot Starter 或者使用编程方式自动创建一个 ChatModel 传入。
使用自动配置的 ChatClient.Builder
在最简单的用例中 ,Spring AI 提供了 Spring Boot Starter,为您创建一个原型ChatClient.Builder bean,您可以将其注入到您的类中。以下是一个简单的示例,展示如何获取对简单用户请求的 String 响应:
@RestController
class MyController {
private final ChatClient chatClient;
public MyController (ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
@GetMapping("/ai")
String generation (String userInput) {
return this.chatClient.prompt()
.user(userInput)
.call()
.content();
}
}
在这个简单的示例中,用户输入设置了用户消息的内容。call() 方法向 AI 模型发送请求,content() 方法返回 AI 模型的响应作为 String。
使用多个聊天模型
在单个应用程序中使用多个聊天模型有几种场景:
- 为不同类型的任务使用不同的模型(例如,使用强大的模型进行复杂推理,使用更快、更便宜的模型处理简单任务)
- 当一个模型服务不可用时实现回退机制
- 对不同的模型或配置进行 A/B 测试
- 根据用户偏好提供模型选择
- 组合专业模型(一个用于代码生成,另一个用于创意内容等)
默认情况下,Spring AI 自动配置单个 ChatClient.Builder bean。但是,您可能需要在应用程序中使用多个聊天模型。以下是处理这种情况的方法:
此时,您需要通过设置属性 spring.ai.chat.client.enabled=false 来禁用ChatClient.Builder 自动配置。这允许您手动创建多个 ChatClient 实例。
使用单个模型类型的多 个 ChatClient
本节介绍一个常见用例,您需要创建多个 ChatClient 实例,它们都使用相同的基础模型类型但具有不同的配置。
// 以编程方式创建 ChatClient 实例
ChatModel myChatModel = ... // 已由 Spring Boot 自动配置
ChatClient chatClient = ChatClient.create(myChatModel);
// 或使用构建器以获得更多控制
ChatClient.Builder builder = ChatClient.builder(myChatModel);
ChatClient customChatClient = builder
.defaultSystemPrompt("你是一个乐于助人的助手。")
.build();
不同模型类型的 ChatClient
当使用多个 AI 模型时,您可以为每个模型定义单独的 ChatClient bean:
@Configuration
public class ChatClientConfig {
@Bean
public ChatClient openAiChatClient (OpenAiChatModel chatModel) {
return ChatClient.create(chatModel);
}
@Bean
public ChatClient anthropicChatClient (AnthropicChatModel chatModel) {
return ChatClient.create(chatModel);
}
}
然后,您可以使用 @Qualifier 注解将这些 bean 注入到应用程序组件中:
@Configuration
public class ChatClientExample {
@Bean
CommandLineRunner cli (
@Qualifier("openAiChatClient") ChatClient openAiChatClient,
@Qualifier("anthropicChatClient") ChatClient anthropicChatClient) {
return args -> {
var scanner = new Scanner(System.in);
ChatClient chat;
// 模型选择
System.out.println("\n 选择您的 AI 模型:");
System.out.println("1. OpenAI");
System.out.println("2. Anthropic");
System.out.print("输入您的选择 (1 或 2):");
String choice = scanner.nextLine().trim();
if (choice.equals("1")) {
chat = openAiChatClient;
System.out.println("使用 OpenAI 模型");
} else {
chat = anthropicChatClient;
System.out.println("使用 Anthropic 模型");
}
// 使用选定的聊天客户端
System.out.print("\n 输入您的问题:");
String input = scanner.nextLine();
String response = chat.prompt(input).call().content();
System.out.println("助手:" + response);
scanner.close();
};
}
}
多个 OpenAI 兼容的 API 端点
OpenAiApi 和 OpenAiChatModel 类提供了 mutate() 方法,允许您创建具有不同属性的现有实例的变体。这在需要与多个 OpenAI 兼容的 API 一起工作时特别有用。
@Service
public class MultiModelService {
private static final Logger logger = LoggerFactory.getLogger(MultiModelService.class);
@Autowired
private OpenAiChatModel baseChatModel;
@Autowired
private OpenAiApi baseOpenAiApi;
public void multiClientFlow() {
try {
// 为 Groq (Llama3) 派生新的 OpenAiApi
OpenAiApi groqApi = baseOpenAiApi.mutate()
.baseUrl("https://api.groq.com/openai")
.apiKey(System.getenv("GROQ_API_KEY"))
.build();
// 为 OpenAI GPT-4 派生新的 OpenAiApi
OpenAiApi gpt4Api = baseOpenAiApi.mutate()
.baseUrl("https://api.openai.com")
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 为 Groq 派生新的 OpenAiChatModel
OpenAiChatModel groqModel = baseChatModel.mutate()
.openAiApi(groqApi)
.defaultOptions(OpenAiChatOptions.builder().model("llama3-70b-8192").temperature(0.5).build())
.build();
// 为 GPT-4 派生新的 OpenAiChatModel
OpenAiChatModel gpt4Model = baseChatModel.mutate()
.openAiApi(gpt4Api)
.defaultOptions(OpenAiChatOptions.builder().model("gpt-4").temperature(0.7).build())
.build();
// 两个模型的简单提示
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);
}
}
}
ChatClient Fluent API
ChatClient Fluent API 允许您使用重载的 prompt 方法以三种不同的方式创建提示:
prompt(): 这个无参数方法让您开始使用 Fluent API,允许您构建用户、系统和其他提示部分。prompt(Prompt prompt): 这个方法接受一个 Prompt 参数,让您传入使用 Prompt 的非 Fluent API 创建的 Prompt 实例。prompt(String content): 这是一个类似于前一个重载的便捷方法。它接受用户的文本内容。
ChatClient 响应
ChatClient API 提供了几种使用 Fluent API 格式化 AI 模型响应的方法。
返回 ChatResponse
AI 模型的响应是一个由ChatResponse类型定义的丰富结构。它包括有关如何生成响应的元数据,还可以包含多个响应,称为Generations,每个都有自己的元数据。元数据包括用于创建响应的令牌数量(每个令牌大约是一个单词的 3/4)。这些信息很重要,因为托管 AI 模型根据每个请求使用的令牌数量收费。
以下示例通过调用call()方法后的chatResponse()返回包含元数据的ChatResponse对象:
ChatResponse chatResponse = chatClient.prompt()
.user("给我讲个笑话")
.call()
.chatResponse();