欢迎光临
我们一直在努力

关于spring AI调用大模型的几种方案实践

关于spring AI调用大模型的几种方案实践

背景介绍:

spring AI 是java的ai框架,旨在简化应用程序的开发过程,在不增加不必要的复杂性的前提下整合 AI(人工智能)功能。我这里提供我平时调用的大模型的方法,供初学者参考。

具体方案

1、使用自动注入的方式调用

我们可以通过引入对应依赖,配置application.yml文件实现多个大模型配置

(1)导入对应依赖

<!– 阿里的灵积 –>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
<version>1.0.0.2</version>
</dependency>
<!– openai –>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
<version>1.0.1</version>
</dependency>
<!– deepseek –>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-deepseek</artifactId>
<version>1.0.1</version>
</dependency>

<!– lombok方便日志输出 –>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.38</version
</dependency>

具体你要调哪个平台的你也可以直接去看spring AI、springAI alibaba 的官方文档,都有详细说明导入对应的SDK,有很多平台的模型都是兼容openai的,你只需要填写对应的base-url即可。这个版本我是自己看官方文档填的。

(2)配置application.yml文件

spring:
application:
name: xxx
ai:
dashscope:
base-url: https://dashscope.aliyuncs.com/compatiblemode/v1
api-key: yourkey
chat:
options:
model: qwenplus
deepseek:
base-url: https://api.deepseek.com/v1
api-key: yourkey
chat:
options:
model: deepseekchat
openai:
base-url: https://api.siliconflow.cn
api-key: yourkey
chat:
options:
model: deepseekai/DeepSeekV3.1
server:
port: 8080

上面分别配置了阿里灵积、deepseek、硅基流动的模型,除了deepseek,其他平台都是有免费额度的。

(3)controller调用

/**
* @author szq
**/

@RestController
@Slf4j
@RequestMapping("/modelTest")
public class modelTestController {

private final ChatClient dashCopeChatClient;
private final ChatClient deepSeekChatClient;
private final ChatClient openAiChatClient;

//建议采用构造的方法注入
public modelTestController(@Qualifier("dashscopeChatModel") ChatModel dashCopeChatModel,
@Qualifier("deepSeekChatModel") ChatModel deepSeekChatModel,
@Qualifier("openAiChatModel") ChatModel openAiChatModel
) {
this.dashCopeChatClient = ChatClient.builder(dashCopeChatModel).build();
this.deepSeekChatClient = ChatClient.builder(deepSeekChatModel).build();
this.openAiChatClient = ChatClient.builder(openAiChatModel).build();
}

@GetMapping("/test-dashScopeClient")
public String testDashScopeClient(@RequestParam(value = "userQuestion",defaultValue = "先告诉我你是谁,简短评价两眼一睁就是“瓦”") String userQuestion){
log.info("用户问题:{}",userQuestion);
String result = dashCopeChatClient.prompt().user(userQuestion).call().content();
log.info("模型结果:{}",result);
return result;
}

@GetMapping("/test-deepSeekClient")
public String testDeepSeekChatClient(@RequestParam(value = "userQuestion",defaultValue = "先告诉我你是谁,简短评价两眼一睁就是“瓦”") String userQuestion){
log.info("用户问题:{}",userQuestion);
String result = deepSeekChatClient.prompt().user(userQuestion).call().content();
log.info("模型结果:{}",result);
return result;
}

@GetMapping("/test-openAiClient")
public String testOpenAiChatClient(@RequestParam(value = "userQuestion",defaultValue = "先告诉我你是谁,简短评价两眼一睁就是“瓦”") String userQuestion){
log.info("用户问题:{}",userQuestion);
String result = openAiChatClient.prompt().user(userQuestion).call().content();
log.info("模型结果:{}",result);
return result;
}
}

结果演示: 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 都能正常调用,但话说,两眼一睁就是“瓦”,不应该是打瓦吗! 哈哈哈哈

tips: 这里说一下自己踩过的坑

通过导入对应的依赖,我们可以看到ChatModel有了对应的实现

在这里插入图片描述

由于是一个接口多个实现,我采用@Qualifier(“名称”)的方式注入,但"dashScopeChatModel"注入不进来,其他两个都可以,整得我一脸懵。

在这里插入图片描述

后面我决定看一下对应的bean到底叫什么名字,写了一个配置

/**
* 打印所有 ChatModel Bean 的名称
*/

@Configuration
public class BeanNamePrinter {

@Bean
public CommandLineRunner printBeans(ApplicationContext applicationContext) {
return args -> {
System.out.println("\\n========== 所有的 ChatModel Bean ==========");
String[] beanNames = applicationContext.getBeanNamesForType(ChatModel.class);
for (String beanName : beanNames) {
System.out.println("找到 Bean: " + beanName + " – 类型: " + applicationContext.getBean(beanName).getClass().getSimpleName());
}
System.out.println("总共找到 " + beanNames.length + " 个 ChatModel Bean");
System.out.println("==========================================\\n");
};
}
}

运行结果:

在这里插入图片描述

我也是服了,灵积这个没有采用驼峰命名全是小写(裂开)。

2、自己注册bean的方式

这个方式更加灵活,尤其是你在一个平台需要调用多个模型时,最好关闭自动配置(spring.ai.chat.client.enabled=false 来禁用 ChatClient.Builder bean 的自动配置)。

具体实现:

(1)写好对应的配置,我这里把ApiConfig和ClientConfig分开写的

@Configuration
public class MyApiConfiguration {

@Value("${spring.ai.dashscope.api-key}")
private String myDashScopeApiKey;

@Value("${spring.ai.dashscope.base-url}")
private String myDashScopeBaseUrl;

@Value("${spring.ai.deepseek.api-key}")
private String myDeepSeekApiKey;

@Value("${spring.ai.deepseek.base-url}")
private String myDeepSeekBaseUrl;

@Value("${spring.ai.openai.api-key}")
private String myOpenAiApiKey;

@Value("${spring.ai.openai.base-url}")
private String myOpenAiBaseUrl;

/**
*灵积
*/

@Bean("myDashScopeApi")
public DashScopeApi dashScopeApi() {
return DashScopeApi.builder()
.apiKey(myDashScopeApiKey)
.baseUrl(myDashScopeBaseUrl)
.build();
}

/**
*deepseek
*/

@Bean("myDeepSeekApi")
public DeepSeekApi deepSeekApi() {
return DeepSeekApi.builder()
.apiKey(myDeepSeekApiKey)
.baseUrl(myDeepSeekBaseUrl)
.build();
}

/**
*硅基流动
*/

@Bean("myOpenAiApi")
public OpenAiApi openAiApi() {
return OpenAiApi.builder()
.apiKey(myOpenAiApiKey)
.baseUrl(myOpenAiBaseUrl)
.build();
}

}

@Configuration
public class MyClientConfig {

@Value("${spring.ai.dashscope.chat.options.model}")
private String dashScopeModel;

@Value("${spring.ai.deepseek.chat.options.model}")
private String deepSeekModel;

@Value("${spring.ai.openai.chat.options.model}")
private String openAiModel;

/**
*灵积
*/

@Bean("myDashScopeChatModel")
public DashScopeChatModel dashScopeChatModel(@Qualifier("myDashScopeApi") DashScopeApi dashScopeApi) {
return DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.defaultOptions(DashScopeChatOptions.builder().withModel(dashScopeModel).build())
.build();
}

/**
*deepseek
*/

@Bean("myDeepSeekChatModel")
public DeepSeekChatModel deepseekChatModel(@Qualifier("myDeepSeekApi") DeepSeekApi deepSeekApi) {
return DeepSeekChatModel.builder()
.deepSeekApi(deepSeekApi)
.defaultOptions(DeepSeekChatOptions.builder().model(deepSeekModel).build())
.build();
}

/**
*硅基流动
*/

@Bean("myOpenAiChatModel")
public OpenAiChatModel openAiChatModel(@Qualifier("myOpenAiApi") OpenAiApi openAiApi) {
return OpenAiChatModel.builder()
.openAiApi(openAiApi)
.defaultOptions(OpenAiChatOptions.builder().model(openAiModel).build())
.build();
}
}

(2)controller里面使用

//建议采用构造的方法注入
public modelTestController(@Qualifier("myDashScopeChatModel") ChatModel dashCopeChatModel,
@Qualifier("myDeepSeekChatModel") ChatModel deepSeekChatModel,
@Qualifier("myOpenAiChatModel") ChatModel openAiChatModel
) {
this.dashCopeChatClient = ChatClient.builder(dashCopeChatModel).build();
this.deepSeekChatClient = ChatClient.builder(deepSeekChatModel).build();
this.openAiChatClient = ChatClient.builder(openAiChatModel).build();
}

tips:

1、我在使用中尝试过不禁用 ChatClient.Builder bean 的自动配置,发现只要你定义了同类名的bean,就会略过自动配置。下面明显可以看到只有自己注册的三个bean。

在这里插入图片描述 2、自己注册bean时像deepseek、dashscope我们引入的是官方依赖,它可以自动识别配置里面的base-url、model,所以可以通过下面的方式注册。

@Bean("myDashScopeApi")
public DashScopeApi dashScopeApi() {
return DashScopeApi.builder()
.apiKey(myDashScopeApiKey)
.build();
}

@Bean("myDeepSeekApi")
public DeepSeekApi deepSeekApi() {
return DeepSeekApi.builder()
.apiKey(myDeepSeekApiKey)
.build();
}
@Bean("myDashScopeChatModel")
public DashScopeChatModel dashScopeChatModel(@Qualifier("myDashScopeApi") DashScopeApi dashScopeApi) {
return DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
}

@Bean("myDeepSeekChatModel")
public DeepSeekChatModel deepseekChatModel(@Qualifier("myDeepSeekApi") DeepSeekApi deepSeekApi) {
return DeepSeekChatModel.builder()
.deepSeekApi(deepSeekApi)
.build();
}

注意: 硅基流动等使用非官方提供SDK,他无法自动读取配置里面的base-url、model 那么他会调用它默认地址。例如openai会调用:https://api.openai.com,模型名称也会不对,调用模型就会失败。所以你必须指定这些信息。

我之前就遇到了一直显示模型名称不存在。

400 {"code":20012,"message":"Model does not exist. Please check it carefully.","data":null}

总结

1、我这里列举了两种方式调用大模型,基本上是满足日常使用了,当初我刚接触AI时特别想找一个这样的文章+代码,可惜没看到。现在自己会了就分享出来,后续也会多写一些demo,感觉上传到网上,比自己写笔记好很多,毕竟知识共享嘛,希望可以帮助到需要的人。

2、这是这个demo的github地址,感兴趣的也可以直接下载(后续也会继续完善)。

赞(0)
未经允许不得转载:171主机测评 » 关于spring AI调用大模型的几种方案实践
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址