Spring AI实现一个项目使用多个相同OpenAI API协议(以ChatGPT和千问为例)

前言

 在做Spring AI项目的时候,如果想引入多个大模型,会发现:诶!好像不行!!

当然,这里指的是只导入Spring AI框架的东西,不引入各个大模型自家的SDK情况下,并且两个大模型的协议还是相同的。

原因很简单:同一个ChatModel的实现类仅能实现一个。比如我们都知道的,千问其实可以用Open AI的API协议,引入open-ai的maven,在配置文件配置千问的参数即可。

<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-openai</artifactId> </dependency>

但是!如果你还要再使用Chat GPT模型呢?那我怎么配置?很明显这时候就不行了。虽然这概率不是很大,但是这也确确实实是我团队的项目中遇到的一个障碍点。

ps:我们团队目前正在开发第二个AI Agent产品(面向大众娱乐型的),已经进入公测阶段。这里不介绍,感兴趣文章底部会放个链接可以去玩一下

问题原因

(这里不讲太深,不细扒底层源码,讲一下大致的流程和用到的类而已)

在Spring AI框架中,调用大模型API的流程其实就是你配置一个客户端ChatClient,ChatClient会配置ChatModel,真正发起大模型调用的是这个ChatModel,在ChatModel会按照自家的API协议封装请求体,比如OpenAI API协议用的是org.springframework.ai.openai.api.OpenAiApi。调用完成后,再封装成Spring AI框架的 ChatResponse 返回。

以上是最简单的流程。如果我同时要实现ChatGPT的调用和千问的调用,发现用的都是OpenAI协议,而使用这个协议的ChatModel目前只有 OpenAiChatModel 。你不能通过配置文件实现两个 OpenAiChatModel 。你要么配置ChatGPT的配置,要么配置Qwen的配置。最终Spring框架也只会自动给你注入一个Bean(这块在Spring AI框架中的OpenAIChatAutoConfiguration中)。

下面就来说说怎么解决。当然先放一张解决后的最终效果

解决后的效果

配置文件跟原生配置方式一样一点都不用变

配置客户端的时候直接用我们写好的QwenChatModel即可,跟使用OpenAIChatModel一样,自动装配的,无需操心。这样子你的项目里既可以有调用GPT的ChatClient也可以再有一个调用Qwen的ChatClient了。而且非常简单方便,完全都是原生相同的操作。

接下来我们看看实现方式吧

实现方式

核心是我们再实现一个同样适用OpenAIAPI接口的ChatModel实现类,且自动装配要按照我们自己的前缀(不能使用openai前缀不然就冲突了)

理解其实就很简单了,撸起袖子加油干!

配置类

首先看一下Spring原来的OpenAIChatModel是怎么自动装配的:

org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration

关键在他的装配条件

@ConditionalOnClass(OpenAiApi.class) @EnableConfigurationProperties({ OpenAiConnectionProperties.class, OpenAiChatProperties.class }) @ConditionalOnProperty(name = SpringAIModelProperties.CHAT_MODEL, havingValue = SpringAIModels.OPENAI, matchIfMissing = true)

意思是:当项目的classpath中存在OpenAiApi类,并且应用配置中明确指定(或未指定但默认)使用OpenAI作为聊天模型时,Spring容器才会自动启用并加载OpenAiConnectionProperties和OpenAiChatProperties这两个配置属性类

OpenAiConnectionProperties 和 OpenAiChatProperties 都继承了 OpenAiParentProperties。如下图:

那我们就仿造他的这三个配置属性类自己实现:

下面直接放代码

QwenParentProperties.java

QwenChatProperties.java

QwenConnectionProperties.java

可以看到我们使用配置前缀是spring.ai.qwen。当然你想改成什么都可以。

在Properties类中,有用到Options类,也就是具体的配置参数。这里虽然绝大部分和OpenAI协议一样,但我们还自己写一个,方便后面自己扩展。

QwenChatOptions.java

这里太长了,下面是代码部分。完整的直接参考:org.springframework.ai.openai.OpenAiChatOptions

只需要把OpenAiChatOptions改成QwenChatOptions即可

好,接下来我们就要自动装配我们的ChatModel了。可以先把自动装配类写了,ChatModel下一步再实现。

QwenChatAutoConfiguration.java

现在,QwenChatAutoConfiguration就可以帮我们实现根据配置文件的配置,装配一个我们想要的第二个ChatModel,这里我叫做qwenChatModel。

注意,上面这段里一句:

QwenAutoConfigurationUtil.ResolvedConnectionProperties resolved = resolveConnectionProperties(commonProperties, chatProperties, "chat");

这是哪来的?我们是仿造OpenAI的Configuration,使用先去看一下他的这段的作用:

他是解析参数的,我们直接仿造他写一个即可,这里细节一点就是提示信息可以变动一下,不然以后报错都不能一眼看出是哪的配置出问题了

QwenAutoConfigurationUtil.java

核心ChatModel的实现类

很好,现在我们就完成了自动装配的功能。下面着重实现ChatModel,也就是核心部分。核心思想其实也就是把类名换成自己的比如QwenChatModel,然后里面的Options使用上面我们自己实现的即可。

QwenChatModel.java

原代码太长了,我压缩了很多换行和空格。如果不是应急的话可以自己去实现一下。参考org.springframework.ai.openai.OpenAiChatModel

使用

到这里我们的项目已经可以根据Properties类中配置的前缀注入我们自定义的ChatModel的Bean了。那么我们怎么去使用?其实跟OpenAIChatModel使用一样。在配置类里配置一个ChatClient使用我们自己的ChatModel即可。调用的时候调用这个ChatClient。

最后

到这里我们就可以实现根据自己的配置前缀为我们自己的项目配置多个相同协议的ChatModel的实现了。这个场景来源于真实的项目里,这个任务并不是很急所以我并没有引入千问的sdk而是保持Spring AI框架这一套的导入,在里面添加完成这个需求。

在25年7月的时候,如果用spring-ai-starter-model-openai (当时还不是这个名字) 调用千问,如果大模型调用了工具@Tool而且时流式输出,会出现适配的问题,虽然不知道现在还有没有,但是上面这种实现方式可以很好地解决这个问题,如果以后项目中出现千问流式调用工具的适配问题,我直接修改我自己实现的类即可。

最后这里说一下我们小团队的项目,是一个很有意思的AI Agent小程序,面向大众娱乐化的。感兴趣可以看下面:

https://github.com/progingo/AI-Treasure-Trove-of-Life-Infohttps://github.com/progingo/AI-Treasure-Trove-of-Life-Info直接体验:

小程序:AI人生锦囊

Read more

Node.js 版本管理全指南:卸载 Node、安装 NVM、常用命令及问题解决

Node.js 版本管理全指南:卸载 Node、安装 NVM、常用命令及问题解决

一、卸载现有 Node.js(避免版本冲突) 在安装 Node Version Manager (NVM) 前,必须彻底卸载电脑中已有的 Node.js(若从未安装可跳过此步骤),否则可能导致 NVM 管理失效或版本冲突问题。 1. Windows 系统卸载流程 步骤 1:通过控制面板卸载 Node.js 1. 按下 Win + R 组合键打开运行窗口 2. 输入 control 并回车打开「控制面板」 3. 导航至「程序」→「程序和功能」 4. 在程序列表中找到所有 Node.js 相关条目(可能有多个版本) 5. 对每个 Node.js

By Ne0inhk
RabbitMQ如何成为分布式系统的“神经中枢“?——从安装部署到C++调用实战的完整流程,带你体验它的奥妙所在!​

RabbitMQ如何成为分布式系统的“神经中枢“?——从安装部署到C++调用实战的完整流程,带你体验它的奥妙所在!​

文章目录 * 本篇摘要 * ①·RabbitMq(轻量级消息队列中间件) 介绍 * RabbitMQ 是什么? * 核心功能与特点 * 1. **核心功能** * 2. **核心优势** * RabbitMQ 的核心概念 * 1. **生产者(Producer)** * 2. **消费者(Consumer)** * 3. **队列(Queue)** * 4. **交换机(Exchange)** * 5. **绑定(Binding)** * 工作流程(以 Direct 交换机为例) * 常见应用场景 * RabbitMQ 与相关技术对比 * 图像理解 * 总结一句话 * ②·RabbitMq 安装教程 * RabbitMq安装 * **1. 安装 RabbitMQ** * **2. 启动 & 检查状态** * **3. 创建管理员用户(

By Ne0inhk
【OpenClaw从入门到精通】第12篇:OpenClaw 2026子代理实战全攻略:用ACP架构搭建多智能体协作网络(附完整代码)

【OpenClaw从入门到精通】第12篇:OpenClaw 2026子代理实战全攻略:用ACP架构搭建多智能体协作网络(附完整代码)

摘要:本文聚焦OpenClaw 2026.3.2版本默认启用的ACP(Agent Communication Protocol)子代理机制,从核心概念、底层原理到企业级实操全流程拆解。先解析子代理的定义、ACP协议通信原理及主从代理分工逻辑,再提供环境准备的详细步骤(版本验证、配置调整、技能安装);随后通过三个递进式虚拟案例(客服分流、智能文档处理、企业级招聘全流程),提供可直接运行的完整代码、执行结果及技术要点解析;最后补充子代理管理运维、性能优化与避坑指南。全文注重实用价值,语言通俗,新手可按步骤快速搭建基础子代理,进阶读者可参考企业级案例扩展复杂协作网络,真正实现AI从“单打独斗”到“军团作战”的升级。 优质专栏欢迎订阅! 【DeepSeek深度应用】【Python高阶开发:AI自动化与数据工程实战】【YOLOv11工业级实战】 【机器视觉:C# + HALCON】【大模型微调实战:平民级微调技术全解】 【人工智能之深度学习】【AI 赋能:Python 人工智能应用实战】【数字孪生与仿真技术实战指南】

By Ne0inhk
Mysql之事务(下)

Mysql之事务(下)

🏝️专栏:Mysql_猫咪-9527的博客-ZEEKLOG博客 🌅主页:猫咪-9527-ZEEKLOG博客  “欲穷千里目,更上一层楼。会当凌绝顶,一览众山小。” 目录 5. 事务的隔离级别与并发控制 5.1事务的隔离级别 5.2查看与设置事务的隔离级别  查看全局隔离级别: 查看当前(会话)隔离级别 5.3读未提交(Read Uncommitted) 5.4读提交(Read Committed) 5.5可重复读(Repeatable Read) 5.6串行化(Serializable) 6.多版本并发控制(MVCC)   6.1数据库并发的三种场景及MVCC 6.2三个隐藏字段  6.3undo log 6.4READ VIEW 6.5事务简单流程

By Ne0inhk