Spring AI 多模型集成实战:OpenAI/DeepSeek/通义千问/智谱一套代码全搞定 Spring AI 多模型集成实战OpenAI/DeepSeek/通义千问/智谱一套代码全搞定演示地址http://ruoyioffice.com | 源码1·GitHubruoyi-office | 源码2·GitCoderuoyi-office | 源码3·Giteeruoyi-office | 微信17156169080备注「RuoYi Office」业务方今天要 DeepSeek、明天要通义千问、后天又说内网不能出公网得换成本地 Ollama。如果你的代码里到处是new OpenAiChatModel(...)每换一家模型就要改代码、发版、重测一遍。企业级 AI 集成真正的难点从来不是调通一个模型而是让十几家模型在同一套代码里随时热切换、各租户用各自的 Key、参数可配、调用方零感知。本文以 RuoYi Office 的 AI 模块为样本从两张配置表讲起拆解如何用 Spring AI 工厂模式把 OpenAI、DeepSeek、通义千问、智谱、文心、豆包、Ollama 等模型统一收口。▲ 多模型集成能力地图① 配置层ai_api_key 存密钥 ai_model 存模型参数→ ② 工厂层AiModelFactory 按平台 switch 构建 Spring AI ChatModel/EmbeddingModel/ImageModel 并缓存→ ③ 能力层对话/写作/知识库/绘图统一调用→ ④ 平台矩阵17 家大模型平台国内国外多媒体全覆盖引言企业接大模型到底难在哪每个想给系统加 AI 能力的团队几乎都会在接模型这步反复返工难点一模型 SDK 各不相同。OpenAI、通义 DashScope、智谱、文心 QianFan、豆包每家的 SDK 类名、鉴权方式、参数结构都不一样硬编码一家换家就重写。难点二Key 和参数写死在配置文件。application.yml里写死一个api-key多租户场景下没法让 A 公司用自己的 Key、B 公司用另一个 Key改个温度值还得重启。难点三换模型要发版。运营想把对话模型从 GPT 换成 DeepSeek 省成本结果是一次开发改代码 测试 上线的完整流程业务等不起。难点四本地与云端混用难。涉密场景要求模型部署在内网Ollama / 本地推理公开场景又想用云端大模型两套逻辑各写一遍。现状后果每家模型 SDK 硬编码换模型 改代码 发版Key/参数写死配置文件多租户无法各用各的 Key模型不可运营配置调温度、换模型都要重启云端/本地两套逻辑维护成本翻倍易出错RuoYi Office 的解法是把模型做成可运营配置的数据用ai_api_keyai_model两张表存配置用AiModelFactory工厂按平台动态构建 Spring AI 的标准ChatModel调用方只认modelId、完全不感知底层是哪家。下面从设计讲起。一、整体设计把模型变成一行可配置的数据Spring AI 是 Spring 官方推出的 AI 应用开发框架它把不同厂商的大模型抽象成统一接口ChatModel对话、EmbeddingModel向量化、ImageModel绘图、VectorStore向量库。只要拿到一个ChatModel实例上层调用就完全一致不用关心背后是 OpenAI 还是 DeepSeek。RuoYi Office 在 Spring AI 之上再封一层配置 工厂把模型集成拆成清晰的三层层职责关键类/表配置层存密钥、存模型参数可在管理后台增删改ai_api_key、ai_model工厂层按平台动态构建并缓存 Spring AI 模型实例AiModelFactory能力层对话/写作/知识库/绘图统一调用只认 modelIdAiModelService等一句话概括设计哲学「密钥和参数交给数据库、对象构建交给工厂、能力调用交给 Spring AI 标准接口」。三层解耦后新增一家模型只需在枚举里加一项、在工厂里加一个分支上层业务零改动。Spring AI 即 Spring 官方的 AI 集成框架用于在 Spring Boot 应用中以统一接口调用各家大模型例如把对话统一抽象成ChatModel.call(Prompt)屏蔽厂商差异。二、配置层两张表撑起多模型2.1 ai_api_key密钥与平台第一张表ai_api_key只管用哪个平台、哪把钥匙、连哪个地址。把密钥单独拆一张表是为了让多个模型复用同一把 Key比如通义的对话模型和向量模型共用一个 DashScope KeyTableName(ai_api_key)DatapublicclassAiApiKeyDOextendsBaseDO{TableIdprivateLongid;privateStringname;// 名称便于运营辨认privateStringapiKey;// 密钥privateStringplatform;// 平台对应 AiPlatformEnumprivateStringurl;// API 地址可空用默认自建/代理时填privateIntegerstatus;// 状态开启/关闭}2.2 ai_model模型与调用参数第二张表ai_model描述具体哪个模型 调用参数。一把 Key 下可以挂多个模型如deepseek-chat和deepseek-reasoner对话类参数温度、最大 token、上下文条数也存在这里运营随时可调TableName(ai_model)DatapublicclassAiModelDOextendsBaseDO{TableIdprivateLongid;privateLongkeyId;// 关联 ai_api_keyprivateStringname;// 模型名称privateStringmodel;// 模型标识如 deepseek-chat、qwen-maxprivateStringplatform;// 平台privateIntegertype;// 类型对话/向量/图片/语音…AiModelTypeEnumprivateIntegersort;privateIntegerstatus;// 对话参数调用时透传给大模型privateDoubletemperature;// 温度越高越发散privateIntegermaxTokens;// 单次回复最大 tokenprivateIntegermaxContexts;// 携带的历史消息条数}为什么拆成两张表而不是一张因为密钥和模型是一对多关系——一把 DashScope Key 下有qwen-max、qwen-plus、text-embedding-v3多个模型密钥轮换时只改一行所有挂在它下面的模型自动生效。这是典型的配置归一化。三、平台枚举一张表看懂支持哪些模型所有支持的平台集中在AiPlatformEnum一个枚举里新增厂商先在这里登记。RuoYi Office 当前覆盖国内主流、国外主流与多媒体三类共 17 个平台分类平台platform 值说明国内对话TongYi / YiYan / DeepSeek / ZhiPu / XingHuo / DouBao / HunYuan通义千问 / 文心 / DeepSeek / 智谱 / 星火 / 豆包 / 混元国内对话SiliconFlow / MiniMax / Moonshot / BaiChuan硅基流动 / MiniMax / 月之暗面 / 百川国外对话OpenAI / AzureOpenAI / Anthropic / Gemini / GrokGPT / Azure / Claude / Gemini / Grok本地Ollama内网私有化部署数据不出网多媒体StableDiffusion / Midjourney / Suno绘图 / 绘图 / 音乐模型类型用另一个枚举AiModelTypeEnum区分CHAT(1)对话、IMAGE(2)绘图、VOICE(3)语音、VIDEO(4)视频、EMBEDDING(5)向量、RERANK(6)重排。同一个平台可以同时提供对话和向量模型靠 type 区分用途。关键设计平台与类型用枚举集中管理意味着支持哪些模型是一份可枚举、可校验的清单而不是散落在各处的 if-else这对后续维护和排错极其友好。▲ AI 对话页面右上角可随时切换底层模型通义千问 / DeepSeek / 智谱等温度、上下文条数等参数随模型配置生效调用方完全无感。四、工厂层AiModelFactory 是整套设计的心脏这是整个多模型集成最关键的一环。AiModelFactory是一个工厂接口负责把平台 Key URL翻译成 Spring AI 的标准模型对象。它的接口定义就是一份能造什么的清单publicinterfaceAiModelFactory{// 按平台 密钥构建对话模型核心ChatModelgetOrCreateChatModel(AiPlatformEnumplatform,StringapiKey,Stringurl);// 向量模型用于知识库 EmbeddingEmbeddingModelgetOrCreateEmbeddingModel(AiPlatformEnumplatform,StringapiKey,Stringurl,Stringmodel);// 绘图模型ImageModelgetOrCreateImageModel(AiPlatformEnumplatform,StringapiKey,Stringurl);// 向量库知识库 RAG 用VectorStoregetOrCreateVectorStore(Class?extendsVectorStoretype,EmbeddingModelembeddingModel,MapString,Class?metadataFields);}4.1 按平台 switch构建对应 ChatModel实现类getOrCreateChatModel的核心就是一个switch拿到平台枚举分发到对应厂商的构建方法。每个 case 内部用对应的 Spring AI Starter 或自研包装类创建实例OverridepublicChatModelgetOrCreateChatModel(AiPlatformEnumplatform,StringapiKey,Stringurl){// 用「类型 平台 Key URL」拼出缓存 Key命中则复用避免重复创建StringcacheKeybuildClientCacheKey(ChatModel.class,platform,apiKey,url);returnSingleton.get(cacheKey,(Func0ChatModel)()-{switch(platform){caseDEEP_SEEK:returnbuildDeepSeekChatModel(apiKey,url);caseTONG_YI:returnbuildTongYiChatModel(apiKey);// 阿里 DashScopecaseZHI_PU:returnbuildZhiPuChatModel(apiKey,url);caseYI_YAN:returnbuildYiYanChatModel(apiKey);// 文心 QianFancaseDOU_BAO:returnbuildDouBaoChatModel(apiKey);caseOPENAI:returnbuildOpenAiChatModel(apiKey,url);caseANTHROPIC:returnbuildAnthropicChatModel(apiKey,url);caseOLLAMA:returnbuildOllamaChatModel(url);// 本地无需 Key// … 通义/星火/混元/硅基流动/MiniMax/月之暗面/百川/Gemini/Grok 等default:thrownewIllegalArgumentException(StrUtil.format(未知平台({}),platform));}});}两个值得学习的设计点客户端缓存Singleton.get同一组「平台 Key URL」只构建一次模型客户端后续命中缓存直接复用。大模型客户端内部往往持有连接池、HTTP 客户端频繁 new 既慢又浪费资源。统一返回 Spring AI 的ChatModel无论底层是官方 Starter、阿里 DashScope SDK还是自研的DouBaoChatModel、XingHuoChatModel包装类对外都收敛成同一个接口上层零差异。4.2 业务入口只认 modelId上层业务从不直接碰工厂而是通过AiModelService.getChatModel(Long id)——传一个模型 ID内部完成查模型 → 查密钥 → 调工厂的全过程OverridepublicChatModelgetChatModel(Longid){// 1. 校验模型存在 校验密钥可用AiModelDOmodelvalidateModel(id);AiApiKeyDOapiKeyapiKeyService.validateApiKey(model.getKeyId());// 2. 委托工厂构建命中缓存则复用returnmodelFactory.getOrCreateChatModel(AiPlatformEnum.validatePlatform(apiKey.getPlatform()),apiKey.getApiKey(),apiKey.getUrl());}这一步是调用方零感知的关键对话、写作、知识库问答等所有能力拿到的都是一个标准ChatModel它们根本不知道也不需要知道背后是 DeepSeek 还是通义。换模型改一下会话/角色绑定的modelId即可代码一行不动。五、能力层流式对话怎么调拿到ChatModel后发起一次对话就是 Spring AI 的标准用法。企业场景几乎都要打字机式流式输出用stream()返回Flux配合 SSE 推给前端// 1. 构建消息系统设定 用户输入ListMessagemessagesnewArrayList();messages.add(newSystemMessage(systemPrompt));// 角色设定messages.add(newUserMessage(userInput));// 用户问题// 2. 构建参数温度、最大 token 来自 ai_model 配置ChatOptionsoptionsAiUtils.buildChatOptions(platform,model.getModel(),model.getTemperature(),model.getMaxTokens());// 3. 流式调用逐块返回FluxChatResponsestreamstreamingChatModel.stream(newPrompt(messages,options));returnstream.map(chunk-{Stringtextchunk.getResult()!null?chunk.getResult().getOutput().getText():;returnsuccess(StrUtil.nullToDefault(text,));// 包成 CommonResult 推给前端});这段代码的价值在于它对所有平台都成立。无论streamingChatModel背后是 GPT 还是通义流式输出的写法完全一致——这正是 Spring AI 统一抽象带来的红利。六、RuoYi Office 多模型设计的创新点6.1 配置即模型换模型不发版模型平台、密钥、参数全部入库管理后台增删改即时生效。运营把对话模型从 GPT 换成 DeepSeek只是改一行数据不动代码、不发版。6.2 工厂 缓存新增厂商成本极低接入一家新模型只需枚举加一项、工厂加一个case分支。客户端按「平台KeyURL」缓存性能与资源都有保障。6.3 多租户各用各的 Keyai_api_key继承平台基础能力支持租户隔离A 公司用自己的通义 Key、B 公司用自己的 DeepSeek Key互不串号计费清晰。6.4 云端与本地一视同仁Ollama 作为本地平台与云端模型走同一套工厂逻辑。涉密数据走内网 Ollama、公开问答走云端大模型由模型配置决定代码无分叉。七、数据结构ai_api_key密钥表字段类型说明idbigint主键namevarchar密钥名称api_keyvarchar密钥敏感建议加密存储platformvarchar平台标识对应 AiPlatformEnumurlvarcharAPI 地址可空走默认statustinyint状态0 开启 / 1 关闭ai_model模型表字段类型说明idbigint主键key_idbigint关联 ai_api_keynamevarchar模型名称modelvarchar模型标识如 deepseek-chatplatformvarchar平台typetinyint类型1 对话 / 2 图片 / 5 向量…temperaturedouble温度max_tokensint单次最大 tokenmax_contextsint携带历史消息条数statustinyint状态设计要点密钥与模型 1:N一把 Key 挂多个模型密钥轮换改一行参数随模型存温度/上下文条数等可运营调不写死配置继承 BaseDO自带 creator/create_time/tenant_id天然多租户隔离。八、技术亮点总结设计要点实现方式价值配置入库ai_api_key ai_model 两表换模型不发版运营可自助统一抽象Spring AI ChatModel/EmbeddingModel上层调用零差异工厂构建AiModelFactory 按平台 switch新增厂商只加一个分支客户端缓存Singleton 按 平台KeyURL 缓存复用连接省资源流式输出ChatModel.stream → Flux SSE打字机式体验全平台一致多租户密钥按租户隔离各用各的 Key计费清晰本地/云端Ollama 与云端同走工厂涉密内网与公网统一逻辑九、快速体验在线演示http://ruoyioffice.com/web/账号 admin / admin123进入「AI 大模型 → 模型配置 / AI 对话」。推荐体验流程进入「AI 大模型 → API 密钥」新增一个平台密钥如 DeepSeek / 通义千问进入「模型管理」在该密钥下新增一个对话模型设置温度、最大 token打开「AI 对话」新建会话并选中刚配置的模型发起一次提问切换到另一个平台的模型发同样的问题对比效果与速度体会换模型只是切配置、代码零改动的设计价值。源码仓库仓库地址GitHubgithub.com/yuqing2026/ruoyi-officeGitCodegitcode.com/zhouzhongyan/ruoyi-officeGiteegitee.com/yqzy1688/ruoyi-office结语多模型集成的精髓不在于会调某一家模型的 API而在于把密钥、模型、能力三件事彻底解耦密钥与参数交给数据库、对象构建交给工厂、能力调用交给 Spring AI 标准接口。一旦解耦“接大模型就从绑死一家厂商的工程变成了配一条数据的运营动作”。这套「配置即模型 工厂动态构建」的思路同样适用于支付渠道、短信通道、对象存储等任何多厂商、需热切换的集成场景。你们的系统接 AI 时是怎么管理多模型的是写死一家还是也做了可配置切换欢迎在评论区聊聊。常见问题FAQRuoYi Office 支持哪些大模型可以体验吗支持。后端基于 Spring Boot 3.5 Spring AI已接入通义千问、文心一言、DeepSeek、智谱、星火、豆包、混元、硅基流动、MiniMax、月之暗面、百川以及 OpenAI、Azure、Anthropic、Gemini、Grok 与本地 Ollama 等共 17 个平台提供在线演示与本地部署体验完整能力与持续维护由商业版提供。怎么从 GPT 换成 DeepSeek要改代码吗不用改代码。在管理后台「API 密钥」里新增 DeepSeek 密钥、「模型管理」里新增对应模型然后把会话或角色绑定的模型改成 DeepSeek 即可底层由 AiModelFactory 自动构建上层无感。数据不能出公网怎么办用本地模型。把平台选为 Ollama填内网推理服务地址对话/向量化全部在内网完成数据不出网它与云端模型走同一套工厂逻辑业务代码不分叉。多个租户能各用各的模型密钥吗可以。密钥表按租户隔离每个租户配置自己的平台 Key 与模型互不影响计费与额度也各自独立。Spring AI 和直接调各家 SDK 有什么区别Spring AI 把各厂商模型抽象成统一的 ChatModel/EmbeddingModel/ImageModel 接口屏蔽了 SDK 差异。配合工厂模式新增一家厂商只需加一个枚举与一个构建分支上层对话/写作/知识库代码完全不用动。想要体验 RuoYi Office 的强大功能在线演示http://ruoyioffice.com/web/账号 admin / admin123源码仓库GitHub | GitCode | Gitee技术咨询添加微信17156169080备注「RuoYi Office」⭐如果觉得不错请给个 Star 支持一下