Spring AI Alibaba 模型全家桶:接入通义、百川、LLaMA 等第三方 LLM 上篇我们学会了用工作流编排多个 AI 任务但有一个问题遗留了下来所有 AI 节点都共用同一个模型。如果我想让逻辑推理用 DeepSeek中文润色用通义千问本地快速响应用 LLaMA怎么办今天这篇就是答案——用 Spring AI Alibaba 的多模型切换能力让你在一套代码里自由组合各大模型真正做到“一个项目全家桶模型随心配”。Spring AI 设计的核心原则之一就是“统一 API灵活适配”。你在前几篇中学到的ChatClient、Prompt、Stream等调用方式在与不同模型交互时完全一致。Spring AI Alibaba 不仅原生集成了通义千问还通过 Spring AI 的抽象层兼容了 OpenAI 格式的云端模型如百川、Moonshot和本地 Ollama 模型如 LLaMA。今天我们就来搭建一个“模型全家桶”项目让同一套业务代码可以根据需求动态选择底层大模型。一、痛点场景一家模型不够用的时候场景一多模型对比选型你们团队想评估通义千问、百川和本地 LLaMA 在客服场景下的表现。如果用三套不同的代码分别对接不仅开发量大而且业务逻辑一旦调整三套代码都得改。场景二按任务分派模型你的应用中有三种任务复杂推理交给 DeepSeek中文内容生成交给通义千问而一些简单的本地分类任务为了节约成本使用 LLaMA 3。你需要一个“调度中心”能根据任务类型自动路由到不同模型。场景三容灾与降级当某个云端模型服务出现故障或触发限流时你希望自动切换到备用模型保证服务可用性。这要求你的代码和模型之间是完全解耦的。这些需求都可以用 Spring AI 的多模型管理能力优雅解决。思路是为每个模型创建不同的ChatClientBean然后通过一个路由层根据策略选择调用哪一个。业务代码只需要和路由层交互完全不用关心底层是哪个模型。二、核心概念快览2.1 Spring AI 的统一模型抽象无论是 OpenAI、Azure OpenAI、Ollama 还是 DashScope只要它们实现了ChatModel接口Spring AI 就能将它们作为“可插拔”的组件集成。ChatClient是对ChatModel的再封装提供流式调用和 Advisor 支持。我们之前一直使用的就是ChatClient。2.2 Spring AI Alibaba 中的 DashScope 模型spring-ai-alibaba-starter-dashscope会自动创建DashScopeChatModel并注册为ChatModel和ChatClientBean。这就是通义千问的接入方式。2.3 兼容 OpenAI 接口的第三方模型百川、Moonshot、DeepSeek、零一万物等大量国产模型提供商都提供与 OpenAI 兼容的 HTTP API。在 Spring AI 中只要它们返回的 JSON 格式兼容 OpenAI Chat Completions 协议我们就可以使用spring-ai-starter-model-openai来接入只需更改base-url和api-key。2.4 本地 Ollama 模型之前第 7 篇我们详细讲过。它通过spring-ai-starter-model-ollama接入同样产生一个ChatModel实现。2.5 多模型路由策略最简单的路由是基于模型名称手动选择。你可以创建一个MapString, ChatClient根据前端传来的参数或任务类型从 Map 中取出对应的ChatClient调用。更高级的玩法是利用 Spring AI 的未来功能如ModelRouter但目前用 Map 已经足够实用。三、环境准备3.1 API Key 汇总由于要同时接入多个云端模型你需要准备至少两个 API Key通义千问百炼DASHSCOPE_API_KEY百川或其他兼容 OpenAI 的模型BAICHUAN_API_KEY百川、Moonshot 等平台的 API Key 获取方式类似在各自开放平台注册即可。本地 LLaMA 则需要安装 Ollama 并拉取模型参考第 7 篇。3.2 Maven 依赖我们需要在一个项目中同时引入 DashScope、OpenAI 和 Ollama 三个 starter而且还要管理好它们的版本。核心依赖propertiesspring-ai.version1.1.6/spring-ai.versionspring-ai-alibaba.version1.1.2.0/spring-ai-alibaba.version/propertiesdependencies!-- Spring Boot Web --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!-- DashScope Starter通义千问 --dependencygroupIdcom.alibaba.cloud.ai/groupIdartifactIdspring-ai-alibaba-starter-dashscope/artifactIdversion${spring-ai-alibaba.version}/version/dependency!-- OpenAI Starter用于百川等兼容 OpenAI 的模型 --dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-model-openai/artifactId/dependency!-- Ollama Starter本地 LLaMA 等 --dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-model-ollama/artifactId/dependency/dependenciesdependencyManagementdependenciesdependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-bom/artifactIdversion${spring-ai.version}/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagement注意这三个 starter 会分别注册各自的自动配置包括ChatModel和ChatClientBean。为了防止冲突我们不能直接通过Autowired ChatClient注入那样会因为有多个 Bean 而报错。我们需要使用Qualifier或者更简单的方式手动为每个模型创建独立的ChatClientBean并给予有意义的名字。3.3 多模型配置文件在application.yml中我们必须为不同的模型使用不同的配置前缀。由于 Spring AI 只允许一套spring.ai.openai和一套spring.ai.ollama而我们接入百川也要用 OpenAI 的 starter这就需要用不同的环境配置或手动创建 Bean 来区分。最简单的方法是不为百川使用自动配置而是手动构造一个OpenAiChatModel指定独立的 base-url 和 api-key。因此配置文件里只保留 DashScope 和 Ollama 的自动配置百川的配置我们通过硬编码从环境变量读取在 Bean 中创建。spring:ai:dashscope:api-key:${DASHSCOPE_API_KEY}chat:options:model:qwen-plustemperature:0.7ollama:base-url:http://localhost:11434chat:options:model:llama3:8btemperature:0.7四、代码实战4.1 创建多个 ChatClient Bean新建MultiModelConfig.javapackagecom.example.springaihelloworld.config;importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.openai.OpenAiChatModel;importorg.springframework.ai.openai.OpenAiChatOptions;importorg.springframework.ai.openai.api.OpenAiApi;importorg.springframework.ai.chat.model.ChatModel;importorg.springframework.beans.factory.annotation.Qualifier;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;ConfigurationpublicclassMultiModelConfig{// 自动配置的 ChatModel Bean 名称// DashScope ChatModel Bean 名称为 dashScopeChatModel// Ollama ChatModel Bean 名称为 ollamaChatModel/** * 通义千问 ChatClient使用 DashScope 自动配置的 ChatModel */BeanpublicChatClientqwenChatClient(Qualifier(dashScopeChatModel)ChatModelchatModel){returnChatClient.create(chatModel);}/** * 百川 ChatClient手动构建 OpenAiChatModel使用百川兼容 API */BeanpublicChatClientbaichuanChatClient(){StringapiKeySystem.getenv(BAICHUAN_API_KEY);if(apiKeynull){thrownewIllegalStateException(BAICHUAN_API_KEY 环境变量未设置);}OpenAiApibaichuanApinewOpenAiApi(https://api.baichuan-ai.com/v1,apiKey);ChatModelbaichuanModelOpenAiChatModel.builder().openAiApi(baichuanApi).defaultOptions(OpenAiChatOptions.builder().withModel(Baichuan4)// 百川模型名.withTemperature(0.7f).build()).build();returnChatClient.create(baichuanModel);}/** * 本地 LLaMA ChatClient使用 Ollama 自动配置的 ChatModel */BeanpublicChatClientllamaChatClient(Qualifier(ollamaChatModel)ChatModelchatModel){returnChatClient.create(chatModel);}}关键点解读通过Qualifier指定要注入哪一个ChatModelBean。自动配置的 Bean 名称通常在官方文档中会有说明或者你可以通过查看DashScopeAutoConfiguration和OllamaAutoConfiguration源码来确认。这里假设 DashScope 的 ChatModel Bean 名为dashScopeChatModelOllama 的为ollamaChatModel。如果名称不同请根据实际情况调整或者直接Autowired MapString, ChatModel查看所有 Bean 名称。百川的接入没有使用自动配置而是手动构建OpenAiApi和OpenAiChatModel这样就不会和默认的 OpenAI 配置冲突且可以自由指定 base-url 和 api-key。4.2 创建模型路由服务新建ModelRoutingService.java用 Map 存储所有模型对应的 ChatClientpackagecom.example.springaihelloworld.service;importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.stereotype.Service;importreactor.core.publisher.Flux;importjava.util.Map;ServicepublicclassModelRoutingService{privatefinalMapString,ChatClientmodelMap;/** * 构造器注入所有 ChatClient Bean通过名字区分 */publicModelRoutingService(ChatClientqwenChatClient,ChatClientbaichuanChatClient,ChatClientllamaChatClient){this.modelMapMap.of(qwen,qwenChatClient,baichuan,baichuanChatClient,llama,llamaChatClient);}/** * 同步对话 * param model 模型标识qwen / baichuan / llama */publicStringchat(Stringmodel,Stringmessage){ChatClientclientgetClient(model);returnclient.prompt().user(message).call().content();}/** * 流式对话 */publicFluxStringstreamChat(Stringmodel,Stringmessage){ChatClientclientgetClient(model);returnclient.prompt().user(message).stream().content();}privateChatClientgetClient(Stringmodel){ChatClientclientmodelMap.get(model);if(clientnull){thrownewIllegalArgumentException(不支持的模型: model可用模型: modelMap.keySet());}returnclient;}}4.3 创建路由 Controllerpackagecom.example.springaihelloworld.controller;importcom.example.springaihelloworld.service.ModelRoutingService;importorg.springframework.http.MediaType;importorg.springframework.web.bind.annotation.*;importreactor.core.publisher.Flux;RestControllerpublicclassModelRoutingController{privatefinalModelRoutingServiceroutingService;publicModelRoutingController(ModelRoutingServiceroutingService){this.routingServiceroutingService;}/** * 统一对话入口通过 model 参数切换底层模型 * GET /chat?modelqwenmsg你好 */GetMapping(/chat)publicStringchat(RequestParam(defaultValueqwen)Stringmodel,RequestParamStringmsg){returnroutingService.chat(model,msg);}/** * 流式对话入口 * GET /chat/stream?modelbaichuanmsg你好 */GetMapping(value/chat/stream,producesMediaType.TEXT_EVENT_STREAM_VALUE)publicFluxStringstreamChat(RequestParamStringmodel,RequestParamStringmsg){returnroutingService.streamChat(model,msg);}}现在调用者只需在请求中指定model参数就能在通义千问、百川、本地 LLaMA 之间自由切换。对业务代码来说切换模型就是一个参数的选择没有任何 if-else 的侵入。五、运行与演示5.1 启动项目确保DASHSCOPE_API_KEY、BAICHUAN_API_KEY已设置Ollama 本地服务已启动且已拉取llama3:8b模型。启动 Spring Boot。5.2 分别测试三个模型通义千问http://localhost:8080/chat?modelqwenmsg简单介绍你自己返回类似我是通义千问由阿里云自主研发的大语言模型...百川http://localhost:8080/chat?modelbaichuanmsg简单介绍你自己返回类似我是百川智能研发的大语言模型...本地 LLaMAhttp://localhost:8080/chat?modelllamamsg简单介绍你自己返回类似I am LLaMA, an AI assistant created by Meta...可以看到同一个接口/chat只是改变model参数底层调用的模型就完全不一样了。5.3 体验流式切换http://localhost:8080/chat/stream?modelbaichuanmsg讲一个简短的笑话使用 curl 观察打字机效果和之前的流式体验完全一致。六、常见问题与避坑提示问题一启动时提示多个 ChatClient Bean 冲突如果你之前在别的地方直接用Autowired ChatClient注入了 BeanSpring 会因为找到多个候选 Bean 而报错。解决方案是使用Qualifier指定名称或者在用到的地方注入我们手动创建的具名 Bean。本文的设计不会出现这个问题因为所有 ChatClient 都有明确的 Bean 名称。问题二自动配置的 ChatModel Bean 名称不确定DashScope 的自动配置类名为DashScopeAutoConfiguration它注册的 ChatModel Bean 名称通常为dashScopeChatModel。Ollama 的为ollamaChatModel。如果你不确定可以在Bean方法中使用Autowired MapString, ChatModel chatModels打印所有 Bean 名称来确定。问题三百川 API Key 环境变量未设置导致启动失败我们的baichuanChatClientBean 在创建时强制检查环境变量如果未设置则抛异常阻止启动。这在生产中是合理的但如果你暂时不想用百川可以移除该 Bean 或者改为 Optional 注入。问题四Ollama 模型未下载导致调用失败如果本地没有llama3:8b模型调用会报错。请先执行ollama pull llama3:8b。也可以更换为其他你已下载的模型只需在配置文件中修改model名称。问题五多模型计费与监控不同模型的计费标准不同在生产环境中建议在路由层加入调用次数和 Token 消耗的监控方便成本分析。Spring AI 的ChatResponse中包含getMetadata()可以获取 Token 使用信息。七、小结与下一步预告本篇回顾理解了多模型接入的场景价值对比选型、任务分派、容灾降级。掌握了在单个 Spring Boot 项目中同时管理多个模型的技巧手动为每个模型创建具名ChatClientBean。实现了基于参数的路由切换业务代码与具体模型完全解耦。分别演示了通义千问、百川、本地 LLaMA 三种模型的无缝切换。动手建议在你的项目中找出至少两个适用不同模型的任务如内容生成和代码审查用本文的路由模式接入对应的模型体验“一个项目多模协同”的开发效率。下一步预告多模型切换已经实现但每个模型的能力边界不同还有些原生高级功能如百炼的函数调用、参数调优我们还没深入挖掘。下一篇我们将进入Spring AI Alibaba 进阶聚焦 DashScope 的原生能力与生产环境最佳实践让你的百炼应用更稳定、更高效。下一篇《Spring AI Alibaba 进阶DashScope 原生能力与最佳实践》见。本系列博客基于 Spring AI 1.1.6 和 Spring AI Alibaba 1.1.2.0 版本编写。各第三方模型的 API 地址和模型名称可能随平台更新而调整请以官方文档为准。多模型共存时请注意依赖版本兼容建议通过 BOM 统一管理。