Spring AI Alibaba ChatClient使用
一、ChatClient简介
Chat Client:https://java2ai.com/docs/1.0.0-M5.1/tutorials/chat-client/
1、ChatClient 简介
ChatClient 提供了与 AI 模型通信的 Fluent API,它支持同步和反应式(Reactive)编程模型。与 ChatModel、Message、ChatMemory 等原子 API 相比,使用 ChatClient 可以将与 LLM 及其他组件交互的复杂性隐藏在背后。
因为基于 大型语言模型 (LLM) 的应用程序通常要多个组件协同工作(例如,提示词模板、聊天记忆、LLM Model、输出解析器、RAG 组件:嵌入模型和存储),并且通常涉及多个交互,因此协调它们会让编码变得繁琐。
当然使用 ChatModel 等原子 API 可以为应用程序带来更多的灵活性,成本就是您需要编写大量样板代码。
ChatClient 类似于应用程序开发中的服务层,它为应用程序直接提供 AI 服务,开发者可以使用 ChatClient Fluent API 快速完成一整套 AI 交互流程的组装。
2、创建 ChatClient
使用 ChatClient.Builder 对象创建 ChatClient 实例,有两种方式:
- 可以自动注入由Spring Boot 自动配置创建的默认 ChatClient.Builder 实例。
- 也可以通过编程方式自行创建一个 ChatClient.Builder 实例并用它来得到 ChatClient 实例。
@RestController
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping("/chat")
public String chat(String input) {
return this.chatClient.prompt()
.user(input)
.call()
.content();
}
}
3、处理 ChatClient 响应
ChatClient API 提供了多种方法来格式化来自 AI 模型的响应。
3.1 call()返回值
ChatClient.call() 方法支持几种不同类型的响应格式。
响应类型有几个选项:
- String content():返回响应的字符串内容
- ChatResponse chatResponse():返回ChatResponse包含多个代以及有关响应的元数据的对象,例如,使用了多少个令牌来创建响应。
- entity 返回 Java 类型
- entity(ParameterizedTypeReference type):用于返回实体类型的集合。
- entity(Class type): 用于返回特定的实体类型。
- entity(StructuredOutputConverter structuredOutputConverter): 用于指定一个实例 StructuredOutputConverter,将 String 转换为实体类型。
3.2 stream() 返回值
流式响应:ChatClient.stream() 方法是一种异步的、持续的获得模型响应的方式。
响应类型有几个选项:
- Flux content():返回由AI模型生成的字符串的Flux。
- Flux chatResponse():返回对象的 Flux ChatResponse,其中包含有关响应的附加元数据。
4、定制 ChatClient 默认值
使用 ChatClient.Builder.build() 快速创建了一个 ChatClient 实例,开发者还可以通过修改 ChatClient.Builder 定制 ChatClient 实例。
注意:
- 全局设置:创建 ChatClient 时指定的配置将作为与模型交互时的默认参数,这样可以避免每次调用都重复设置。
- 每次请求设置:每次调用也可以设置与模型交互时的参数,每次会覆盖系统默认值。
4.1 角色预设
角色预设:我们为 ChatClient 设置了一个默认的 system message(角色预设,比如:以海盗风格回答所有问题),这样,当 ChatClient 与模型交互时都会自动携带这条 system message,用户只需要指定 user message 即可。
@Configuration
pubic class Config {
@Bean
ChatClient chatClient(ChatClient.Builder builder) {
return builder
.defaultSystem("You are a friendly chat bot that answers question in the voice of a Pirate")
.build();
}
}
除了 defaultSystem 之外,还可以在 ChatClient.Builder 级别上指定其他默认提示。同时,在运行时使用 ChatClient 提供的不带 default 前缀的相应方法覆盖这些默认值。
二、ChatClient使用
Spring AI Alibaba快速使用:https://blog.csdn.net/qq_42402854/article/details/146350253
1、编写 Controller接口
在普通 Controller Bean 中注入 ChatClient 实例,实现下面几个功能:
- 简单调用
- 流式调用
- 角色预设流式|简单调用。
@Slf4j
@RestController
@RequestMapping("/dashscope/chat-client")
public class DashScopeChatClientController {
private static final String DEFAULT_PROMPT = "你好,介绍下你自己!";
private final ChatClient dashScopeChatClient;
/**
* 使用如下的方式自动注入 ChatClient
*
* @param chatClientBuilder
*/
//public DashScopeChatClientController(ChatClient.Builder chatClientBuilder) {
//
// this.dashScopeChatClient = chatClientBuilder.build();
//}
private final ChatModel chatModel;
/**
* 编程方式自行创建一个 ChatClient.Builder 实例.
* 使用自动注入 ChatModel
*
* @param chatModel
*/
public DashScopeChatClientController(ChatModel chatModel) {
this.chatModel = chatModel;
// 构造时,可以设置 ChatClient 的参数
// {@link org.springframework.ai.chat.client.ChatClient};
this.dashScopeChatClient = ChatClient.builder(chatModel)
// 实现 Chat Memory 的 Advisor
// 在使用 Chat Memory 时,需要指定对话 ID,以便 Spring AI 处理上下文。
.defaultAdvisors(
new MessageChatMemoryAdvisor(new InMemoryChatMemory())
)
// 实现 Logger 的 Advisor
.defaultAdvisors(
new SimpleLoggerAdvisor()
)
// 设置 ChatClient 中 ChatModel 的 Options 参数
.defaultOptions(
DashScopeChatOptions.builder()
.withTopP(0.7)
.build()
)
// 设置默认 System Message
//.defaultSystem("你是一个AI搞笑段子手,以搞笑,幽默,风趣的风格回答所有的问题。")
.build();
}
/**
* ChatClient 简单调用
*/
@GetMapping("/simple/chat")
public String simpleChat(String userInputPrompt) {
if (StringUtils.isBlank(userInputPrompt)) {
userInputPrompt = DEFAULT_PROMPT;
}
String aiOutput = dashScopeChatClient.prompt(userInputPrompt).call().content();
log.info("\nsimpleChat --> userInputPrompt ={}, \n aiOutput = {}", userInputPrompt, aiOutput);
return aiOutput;
}
/**
* ChatClient 流式调用。
* 可以使大模型的输出信息实现打字机效果。
*/
@GetMapping("/stream/chat")
public Flux<String> streamChat(HttpServletResponse response, String userInputPrompt) {
if (StringUtils.isBlank(userInputPrompt)) {
userInputPrompt = DEFAULT_PROMPT;
}
// 避免接口返回乱码
response.setCharacterEncoding("UTF-8");
log.info("\n streamChat --> userInputPrompt ={},", userInputPrompt);
Flux<String> aiOutput = dashScopeChatClient.prompt(DEFAULT_PROMPT).stream().content();
return aiOutput;
}
/**
* 角色预设 ChatClient 流式调用。
* 可以使大模型的输出信息实现打字机效果。
*/
@GetMapping("/stream/chatByRole")
public Flux<String> streamChatByRole(HttpServletResponse response, String userInputPrompt) {
if (StringUtils.isBlank(userInputPrompt)) {
userInputPrompt = DEFAULT_PROMPT;
}
// 避免接口返回乱码
response.setCharacterEncoding("UTF-8");
log.info("\n streamChatByRole --> userInputPrompt ={},", userInputPrompt);
Flux<String> aiOutput = dashScopeChatClient
.prompt()
.system("你是一个AI搞笑段子手,以搞笑,幽默,风趣的风格回答所有的问题。")
.user(userInputPrompt)
.stream().content();
return aiOutput;
}
}
– 求知若饥,虚心若愚。