【SpringAI中Chat-Client用法】
Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~
🌱🌱个人主页:奋斗的明志
🌱🌱所属专栏:SpringAI
📚本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为展示我的学习过程及理解。文笔、排版拙劣,望见谅。
SprnigAI
- 了解
- 创建子工程
- 添加pom依赖(阿里云百炼平台)
- 添加配置
- 代码编写
- 多平台多模型动态配置大模型平台实战
- 配置类
- 接口
- 展示效果
- 定义3个ChatClient的bean
- 注意点
了解
ChatClient 基于ChatModel进行了封装提供了通用的 API,它适用所有的大模型, 使用ChatClient可以让你面向SpringAi通用的api 而无需面向为每一种不同的模型的api来进行编程,虽然您仍然可以使用 ChatModel 来实现某些模型更加个性化的操作(ChatModel更偏向于底层),但 ChatClient 提供了灵活、更全面的方法来构建您的客户端选项以与模型进行交互: 比如系统提示词、格式式化响应、聊天记忆 、tools 都更加易用和优雅,所以除非ChatClient无法实现,否则我们优先考虑用ChatClient。
所以我们后续基于ChatClient来进行学习应用。
基于ChatModel来学习源码,因为ChatClient底层依然还是ChatModel的封装。
创建子工程
添加pom依赖(阿里云百炼平台)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.mingzhi.springai</groupId><artifactId>spring-ai-parent</artifactId><version>0.0.1-mz</version></parent><artifactId>chat-client</artifactId><description>chat-client学习-聊天客户端</description><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--接入百炼平台--><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-dashscope</artifactId></dependency></dependencies></project>
添加配置
server:port: 8081 #端口号
spring:application:name: chat-client #服务应用名称dashscope:api-key: sk-e9bcb1abcaeb4da89114ef639067097edechat:options:model: qwen-vl-max-latest # 模型名称multi-model: true
代码编写
- 必须通过ChatClient.Builder 来进行构造
@SpringBootTest
public class ChatClientTest {@Autowiredprivate ChatClient.Builder builder;/*** 同步响应*/@Testpublic void test() {ChatClient chatClient = builder.build();String content = chatClient.prompt().user("hello")// 用户输入的提示词.call().content();System.out.println(content);}/*** 流式响应*/@Testpublic void test2() {ChatClient chatClient = builder.build();Flux<String> stringFlux = chatClient.prompt().user("hello")// 用户输入的提示词.stream().content();stringFlux.toIterable().forEach(System.out::println);}}
这种方式会在底层自动注入1个ChatModel
, 如果你配置了多个模型依赖, 会无法注入。引入多个大模型的依赖,在进行依赖注入的时候就会报错
<dependencies><!--接入百炼平台--><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-dashscope</artifactId></dependency><!--接入deepseek依赖--><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-deepseek</artifactId></dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-webflux</artifactId>-->
<!-- </dependency>--></dependencies>
Autowired会先根据类型进行匹配,类型匹配不上就会找对应的名称,名称再找不到,就会出现上述错误
如何进行避免呢?
可以通过这种方式动态选择ChatModel:
@Autowired
private DashScopeChatModel dashScopeChatModel;
@Test
public void test3() {ChatClient build = ChatClient.builder(dashScopeChatModel).build();String content = build.prompt().user("hello")// 用户输入的提示词.call().content();System.out.println(content);
}@Test
public void testChatStream() {ChatClient chatClient = ChatClient.builder(dashScopeChatModel).build();Flux<String> content = chatClient.prompt().user("Hello").stream().content();// 阻塞输出content.toIterable().forEach(System.out::println);}
多平台多模型动态配置大模型平台实战
配置类
MorPlatformAndModelOptions
package com.mingzhi.springai;public class MorPlatformAndModelOptions {/*** 平台*/private String platform;/*** 模型*/private String model;/*** 温度*/private Double temperature;public String getModel() {return model;}public void setModel(String model) {this.model = model;}public String getPlatform() {return platform;}public void setPlatform(String platform) {this.platform = platform;}public Double getTemperature() {return temperature;}public void setTemperature(Double temperature) {this.temperature = temperature;}
}
接口
MorPlatformAndModelController
package com.mingzhi.springai.controller;import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import com.mingzhi.springai.MorPlatformAndModelOptions;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.deepseek.DeepSeekChatModel;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;import java.util.HashMap;
import java.util.Map;@RestController
public class MorPlatformAndModelController {//声明一个map,用来初始化平台Map<String, ChatModel> platformMap = new HashMap<>();//通过构造函数进行自动注入public MorPlatformAndModelController(DashScopeChatModel dashScopeChatModel,DeepSeekChatModel deepSeekChatModel) {platformMap.put("dashscope", dashScopeChatModel);platformMap.put("deepseek", deepSeekChatModel);}/*** @param message 消息* @param options 选项* @return*/@RequestMapping(value = "/chat",produces = "text/stream;charset=UTF-8")public Flux<String> chat(String message,MorPlatformAndModelOptions options) {String platform = options.getPlatform();System.out.println("当前平台:" + platform);ChatModel chatModel = platformMap.get(platform);ChatOptions chatOptions = ChatOptions.builder().temperature(options.getTemperature()).model(options.getModel()).build();ChatClient chatClient = ChatClient.builder(chatModel).defaultOptions(chatOptions).build();Flux<String> content = chatClient.prompt().user(message).stream().content();return content;}
}
展示效果
定义3个ChatClient的bean
也可以根据请求动态创建, 看需求
@Configuration
public class AiConfig {@Beanpublic ChatClient deepseekR1(DeepSeekChatProperties chatProperties) {DeepSeekApi deepSeekApi = DeepSeekApi.builder().apiKey(System.getenv("DEEP_SEEK_KEY")).build();DeepSeekChatModel deepSeekChatModel = DeepSeekChatModel.builder().deepSeekApi(deepSeekApi).defaultOptions(DeepSeekChatOptions.builder().model(DeepSeekApi.ChatModel.DEEPSEEK_REASONER).build()).build();return ChatClient.builder(deepSeekChatModel).build();}@Beanpublic ChatClient deepseekV3() {DeepSeekApi deepSeekApi = DeepSeekApi.builder().apiKey(System.getenv("DEEP_SEEK_KEY")).build();DeepSeekChatModel deepSeekChatModel = DeepSeekChatModel.builder().deepSeekApi(deepSeekApi).defaultOptions(DeepSeekChatOptions.builder().model(DeepSeekApi.ChatModel.DEEPSEEK_CHAT).build()).build();return ChatClient.builder(deepSeekChatModel).build();}@Beanpublic ChatClient ollama(@Autowired OllamaApi ollamaApi, @Autowired OllamaChatProperties options) {OllamaChatModel ollamaChatModel = OllamaChatModel.builder().ollamaApi(ollamaApi).defaultOptions(OllamaOptions.builder().model(options.getModel()).build()).build();return ChatClient.builder(ollamaChatModel).build();}}
注意点
在单独引入阿里百炼平台时,有一个依赖可能会引入不进来