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

关于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/compatible-mode/v1 api-key: your-key chat:options:model: qwen-plus deepseek:base-url: https://api.deepseek.com/v1 api-key: your-key chat:options:model: deepseek-chat openai:base-url: https://api.siliconflow.cn api-key: your-key chat:options:model: deepseek-ai/DeepSeek-V3.1 server:port:8080

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

(3)controller调用

/** * @author szq **/@RestController@Slf4j@RequestMapping("/modelTest")publicclass modelTestController {privatefinalChatClient dashCopeChatClient;privatefinalChatClient deepSeekChatClient;privatefinalChatClient openAiChatClient;//建议采用构造的方法注入publicmodelTestController(@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")publicStringtestDashScopeClient(@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")publicStringtestDeepSeekChatClient(@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")publicStringtestOpenAiChatClient(@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 的名称 */@ConfigurationpublicclassBeanNamePrinter{@BeanpublicCommandLineRunnerprintBeans(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分开写的

@ConfigurationpublicclassMyApiConfiguration{@Value("${spring.ai.dashscope.api-key}")privateString myDashScopeApiKey;@Value("${spring.ai.dashscope.base-url}")privateString myDashScopeBaseUrl;@Value("${spring.ai.deepseek.api-key}")privateString myDeepSeekApiKey;@Value("${spring.ai.deepseek.base-url}")privateString myDeepSeekBaseUrl;@Value("${spring.ai.openai.api-key}")privateString myOpenAiApiKey;@Value("${spring.ai.openai.base-url}")privateString myOpenAiBaseUrl;/** *灵积 */@Bean("myDashScopeApi")publicDashScopeApidashScopeApi(){returnDashScopeApi.builder().apiKey(myDashScopeApiKey).baseUrl(myDashScopeBaseUrl).build();}/** *deepseek */@Bean("myDeepSeekApi")publicDeepSeekApideepSeekApi(){returnDeepSeekApi.builder().apiKey(myDeepSeekApiKey).baseUrl(myDeepSeekBaseUrl).build();}/** *硅基流动 */@Bean("myOpenAiApi")publicOpenAiApiopenAiApi(){returnOpenAiApi.builder().apiKey(myOpenAiApiKey).baseUrl(myOpenAiBaseUrl).build();}}
@ConfigurationpublicclassMyClientConfig{@Value("${spring.ai.dashscope.chat.options.model}")privateString dashScopeModel;@Value("${spring.ai.deepseek.chat.options.model}")privateString deepSeekModel;@Value("${spring.ai.openai.chat.options.model}")privateString openAiModel;/** *灵积 */@Bean("myDashScopeChatModel")publicDashScopeChatModeldashScopeChatModel(@Qualifier("myDashScopeApi")DashScopeApi dashScopeApi){returnDashScopeChatModel.builder().dashScopeApi(dashScopeApi).defaultOptions(DashScopeChatOptions.builder().withModel(dashScopeModel).build()).build();}/** *deepseek */@Bean("myDeepSeekChatModel")publicDeepSeekChatModeldeepseekChatModel(@Qualifier("myDeepSeekApi")DeepSeekApi deepSeekApi){returnDeepSeekChatModel.builder().deepSeekApi(deepSeekApi).defaultOptions(DeepSeekChatOptions.builder().model(deepSeekModel).build()).build();}/** *硅基流动 */@Bean("myOpenAiChatModel")publicOpenAiChatModelopenAiChatModel(@Qualifier("myOpenAiApi")OpenAiApi openAiApi){returnOpenAiChatModel.builder().openAiApi(openAiApi).defaultOptions(OpenAiChatOptions.builder().model(openAiModel).build()).build();}}

(2)controller里面使用

//建议采用构造的方法注入publicmodelTestController(@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")publicDashScopeApidashScopeApi(){returnDashScopeApi.builder().apiKey(myDashScopeApiKey).build();}@Bean("myDeepSeekApi")publicDeepSeekApideepSeekApi(){returnDeepSeekApi.builder().apiKey(myDeepSeekApiKey).build();}@Bean("myDashScopeChatModel")publicDashScopeChatModeldashScopeChatModel(@Qualifier("myDashScopeApi")DashScopeApi dashScopeApi){returnDashScopeChatModel.builder().dashScopeApi(dashScopeApi).build();}@Bean("myDeepSeekChatModel")publicDeepSeekChatModeldeepseekChatModel(@Qualifier("myDeepSeekApi")DeepSeekApi deepSeekApi){returnDeepSeekChatModel.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地址,感兴趣的也可以直接下载(后续也会继续完善)。

Read more

一文掌握 Git 分支:本地管理 + 远程协作 + 最佳实践

前言:为什么分支如此重要? 在现代软件开发中,分支(Branch) 是 Git 最强大的特性之一。想象一下: * 🚀 你可以在不影响主代码的情况下开发新功能 * 🐛 你可以独立修复紧急 Bug * 🧪 你可以安全地尝试实验性想法 * 👥 团队成员可以并行工作而不互相干扰 这一切都归功于 git branch 命令。本文将带你从零开始,全面掌握 Git 分支管理的核心技能。 一、分支的本质:理解 Git 分支模型 在深入命令之前,先理解分支的本质: ┌─────────────────────────────────────────────────┐ │ Git 分支 = 指向提交的轻量级指针 │ │ │ │ main ──→ ● ──→ ● ──→ ● (最新提交) │ │ ↘ │ │ feature ──→ ● ──→ ● (独立开发线) │ └─────────────────────────────────────────────────┘ 关键概念: * 分支只是一个指向特定提交的指针 * 创建分支几乎零成本(只创建指针,不复制文件)

By Ne0inhk
PandaWiki:更轻量的开源知识库,问答效果到底如何?(本地部署教程+效果实测)

PandaWiki:更轻量的开源知识库,问答效果到底如何?(本地部署教程+效果实测)

开源 RAG 项目我之前主要围绕 RAGFlow 写了不少落地案例。RAGFlow 定位是大而全的企业级 RAG 引擎,所以社区里也一直有人吐槽:资源吃得多、处理慢。但这事儿某种程度上就是端到端全包(解析、切分、向量化、检索、权限、工作流、评测)的代价,工程体量上去了,默认就不可能太轻。 如果你想找一款更轻量的开源方案,主要用来处理产品文档、技术文档、FAQ、博客等内容,那可以看看今天要介绍的 PandaWiki。一句话总结:PandaWiki 更像开源版的知识库产品,而不是一个给工程师从零拼装的 RAG 引擎。 这个项目实际我也是近期才注意到,GitHub 目前 8.6K Star,看趋势图下半年热度是一路走高。我花了几天集中测了下,确实有一些可圈可点的地方,这篇就抓大放小,来和各位说道说道。 这篇试图说清楚: PandaWiki 的手把手本地部署过程、

By Ne0inhk

3大开源修复模型横评:云端镜像快速部署,1天完成全面测试

3大开源修复模型横评:云端镜像快速部署,1天完成全面测试 你是不是也遇到过这样的情况:团队要选一个AI图像修复工具,大家各自在本地跑GFPGAN、CodeFormer、GPEN,结果有人用笔记本CPU跑,有人用高端显卡,测试速度、画质效果完全没法比?最后开会讨论时,谁的电脑配置高,谁的结果就“看起来更好”,根本没法做出公正决策。 这正是很多技术主管在搭建AI工具链时最头疼的问题——缺乏统一、可复现的测试环境。不同设备、不同依赖版本、不同参数设置,导致评估结果偏差巨大,选型变成“看运气”。 别急,今天我就来帮你解决这个痛点。我们不靠本地部署“拼电脑”,而是直接上云端标准化镜像环境,一键部署三大主流开源人脸修复模型:GFPGAN、CodeFormer 和 GPEN,在相同GPU资源下完成公平对比测试,1天内搞定从部署到出报告的全流程。 ZEEKLOG星图平台提供了预置好这三大模型的AI镜像,无需手动安装复杂依赖,不用折腾CUDA、PyTorch版本兼容问题,点击即用,还能对外暴露API服务,方便团队成员远程调用测试。整个过程就像租了一台“AI修复工作站”,谁都能用,结果可比对。

By Ne0inhk
手把手教你在GitHub上运行开源项目(新手必看版)

手把手教你在GitHub上运行开源项目(新手必看版)

📦 说在前面 GitHub这个程序员宝藏平台(我愿称之为代码界的金矿),每天都有成千上万的开源项目更新。但是很多新手朋友看到那些酷炫项目时,经常会遇到三大灵魂拷问:这项目怎么跑起来?需要装什么软件?报错了怎么办?今天咱们就用最接地气的方式,手把手教你从0到1运行GitHub项目! 🔧 准备工具包(装机三件套) 1. 代码编辑器(必装) 推荐直接上VS Code这个万金油,装好记得在扩展商店安装这两个插件: * GitLens(代码时光机,能看到每行代码的修改记录) * Code Runner(一键运行脚本的神器) (超级重要)👉 如果项目里有.vscode文件夹,一定要用VS Code打开,里面可能有预置的调试配置! 2. Git客户端(下载代码必备) Windows用户直接装Git for Windows,安装时记得勾选这个选项: Use Git and optional Unix tools from the Command Prompt (这样就能在CMD里用Linux命令了,真香!

By Ne0inhk