掘金 人工智能 10月08日 12:48
Spring AI 实现多平台模型灵活切换
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了如何利用 Spring AI 构建一个能够灵活切换不同生成式 AI 平台和模型的统一服务。通过暴露 `/chat` 和 `/chat2` 两个端点,实现了按 Bean 名称直接访问以及按平台、模型和温度参数进行动态切换和流式输出。文章详细阐述了模块依赖、配置文件、核心代码设计(如 `AiConfig` 和 `MultiModelsController`),并提供了实际的调用示例和常见问题解答,旨在帮助开发者在落地生成式 AI 项目时,能够更高效地平衡效果、成本和可用性。

💡 **统一服务与多模型接入**:通过 Spring AI,可以整合 DeepSeek、阿里云百炼(DashScope)和本地 Ollama 等多个生成式 AI 平台,并提供统一的服务接口。这使得开发者能够根据项目需求,灵活选择和切换不同的模型,以优化成本和效果。

🗣️ **两种交互模式**:文章介绍了两种主要的交互端点:`/chat` 支持通过预置的 Bean 名称直接调用不同的 `ChatClient`,适用于固定配置的场景;`/chat2` 则允许用户动态指定平台、模型以及 `temperature` 参数,并支持流式输出,为需要精细控制和实时反馈的应用场景提供了便利。

⚙️ **核心设计与配置**:实现的关键在于 `AiConfig` 类中为不同模型创建 `ChatClient` Bean,并利用 `Map` 自动注入机制实现按名称查找。`application.properties` 文件用于配置 API 密钥、默认模型和本地 Ollama 地址,确保了配置的集中管理和易用性。

🚀 **扩展性与最佳实践**:该方案具备良好的扩展性,可以方便地新增支持的平台。文章还强调了安全配置(如使用 KMS/Vault 管理密钥)、模型名与平台兼容性、以及必要的容错处理(如判空、合法性校验和降级策略),这些都是在生产环境中落地 AI 应用的重要考量。

背景与目标

本文基于模块 03-multi-model-switch 的完整实现展开说明,覆盖依赖、配置、核心代码、接口调用与常见问题。


模块与依赖

模块:03-multi-model-switch

关键依赖包括 Spring Boot Web、Spring AI DeepSeek、Alibaba DashScope、Ollama、测试、Lombok:

<dependencies>    <!--deepseek-->    <dependency>        <groupId>org.springframework.ai</groupId>        <artifactId>spring-ai-starter-model-deepseek</artifactId>    </dependency>    <!--百炼-->    <dependency>        <groupId>com.alibaba.cloud.ai</groupId>        <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>    </dependency>    <!--ollama-->    <dependency>        <groupId>org.springframework.ai</groupId>        <artifactId>spring-ai-starter-model-ollama</artifactId>    </dependency>    <!--web-->    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-web</artifactId>    </dependency>    <!--单元测试-->    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-test</artifactId>        <scope>test</scope>    </dependency>    <dependency>        <groupId>org.projectlombok</groupId>        <artifactId>lombok</artifactId>    </dependency></dependencies>

配置文件

src/main/resources/application.properties 中配置了 API Key、默认模型与本地 Ollama 地址等:

spring.application.name=chat-client# deepseekspring.ai.deepseek.api-key=${DEEPSEEK_API_KEY}spring.ai.deepseek.chat.options.model=deepseek-reasoner# dashscope (阿里云百炼)spring.ai.dashscope.api-key=${DASHSCOPE_API_KEY}spring.ai.dashscope.chat.options.model=qwen-plus# ollama (本地)spring.ai.ollama.base-url=http://127.0.0.1:11434spring.ai.ollama.chat.model=qwen3:0.6b

环境变量说明:


核心设计与代码解读

1) 统一模型装配与客户端暴露 AiConfig

提供多个 ChatClient Bean:deepseekR1(推理/Reasoner)、deepseekV3(聊天/Chat)、ollama(本地模型)。通过不同 ChatModel 与默认 options,形成“即插即用”的客户端:

@Configurationpublic class AiConfig {    @Bean    public ChatClient deepseekR1(DeepSeekChatProperties chatProperties) {        DeepSeekApi deepSeekApi = DeepSeekApi.builder()                .apiKey(System.getenv("DEEPSEEK_API_KEY"))                .build();        DeepSeekChatModel deepSeekChatModel = DeepSeekChatModel.builder()                .deepSeekApi(deepSeekApi)                .defaultOptions(DeepSeekChatOptions.builder()                        .model(DeepSeekApi.ChatModel.DEEPSEEK_REASONER)                        .build())                .build();        return ChatClient.builder(deepSeekChatModel).build();    }    @Bean    public ChatClient deepseekV3() {        DeepSeekApi deepSeekApi = DeepSeekApi.builder()                .apiKey(System.getenv("DEEPSEEK_API_KEY"))                .build();        DeepSeekChatModel deepSeekChatModel = DeepSeekChatModel.builder()                .deepSeekApi(deepSeekApi)                .defaultOptions(DeepSeekChatOptions.builder()                        .model(DeepSeekApi.ChatModel.DEEPSEEK_CHAT)                        .build())                .build();        return ChatClient.builder(deepSeekChatModel).build();    }    @Bean    public ChatClient ollama(@Autowired OllamaApi ollamaApi,                             @Autowired OllamaChatProperties options) {        OllamaChatModel ollamaChatModel = OllamaChatModel.builder()                .ollamaApi(ollamaApi)                .defaultOptions(OllamaOptions.builder()                        .model(options.getModel())                        .build())                .build();        return ChatClient.builder(ollamaChatModel).build();    }}

要点:

2) 简单模型切换端点 /chat(按 Bean 名直查)

通过自动注入 Map<String, ChatClient>,用 model 参数直接索引对应 ChatClient

@Slf4j@RestControllerpublic class MultiModelsController {    @Autowired    private Map<String, ChatClient> chatClientMap;    @PostConstruct    public void init(){        chatClientMap.forEach((key, value) ->                log.info("model: {} : {}", key, value.getClass().getName()));    }    @GetMapping("/chat")    String generation(@RequestParam String message,                      @RequestParam String model) {        ChatClient chatClient = chatClientMap.get(model);        String content = chatClient.prompt().user(message).call().content();        log.info("model: {} : {}", model, content);        return content;    }}

可用 model 值示例(取决于 Spring 注入命名):deepseekR1deepseekV3ollama

调用示例:

curl 'http://localhost:8080/chat?model=deepseekV3&message=用50字解释大语言模型'

3) 平台+模型+温度+流式端点 /chat2

支持 platformmodeltemperature 的动态指定,并以流式文本输出:

@RestControllerpublic class MultiPlatformAndModelController {    HashMap<String, ChatModel> platforms = new HashMap<>();    public MultiPlatformAndModelController(DashScopeChatModel dashScopeChatModel,                                           DeepSeekChatModel deepSeekChatModel,                                           OllamaChatModel ollamaChatModel) {        platforms.put("dashscope", dashScopeChatModel);        platforms.put("ollama", ollamaChatModel);        platforms.put("deepseek", deepSeekChatModel);    }    @RequestMapping(value = "/chat2", produces = "text/stream;charset=UTF-8")    public Flux<String> chat(String message, MultiPlatformAndModelOptions options) {        String platform = options.getPlatform();        ChatModel chatModel = platforms.get(platform);        ChatClient chatClient = ChatClient.builder(chatModel)                .defaultOptions(ChatOptions.builder()                        .temperature(options.getTemperature())                        .model(options.getModel())                        .build())                .build();        return chatClient.prompt().user(message).stream().content();    }}

options 参数对象:

@Datapublic class MultiPlatformAndModelOptions {    private String platform;    private String model;    private Double temperature;}

调用示例(浏览器/curl 均可):

curl -N 'http://localhost:8080/chat2?platform=ollama&model=qwen3:0.6b&temperature=0.3&message=用三点概括面向对象编程核心'

4) 启动类

@SpringBootApplicationpublic class MultiModelApplication {    public static void main(String[] args) {        SpringApplication.run(MultiModelApplication.class, args);    }}

运行与验证

    设置环境变量(macOS/zsh 举例):
export DEEPSEEK_API_KEY='你的deepseek_key'export DASHSCOPE_API_KEY='你的dashscope_key'
    确保本地 Ollama(可选)正常运行,并已拉取模型:
ollama run qwen3:0.6b
    启动应用:
cd /Volumes/artisan/code/2025/spring-ai-artisan/03-multi-model-switch./mvnw spring-boot:run
    验证直切端点:
curl 'http://localhost:8080/chat?model=deepseekR1&message=解释下RAG是什么'
    验证平台+模型+流式端点:
curl -N 'http://localhost:8080/chat2?platform=dashscope&model=qwen-plus&temperature=0.2&message=用两句话说明微服务的优缺点'

设计要点与最佳实践


常见问题(FAQ)


至此,基于 Spring AI 的多平台多模型动态切换方案已经打通:可在 DeepSeek、DashScope 与本地 Ollama 之间灵活切换,支持按名直切与平台+模型+温度的流式对话,便于在实际项目中快速对比与落地。

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Spring AI 生成式 AI 多模型切换 多平台 API 集成 Ollama DeepSeek DashScope 流式输出
相关文章