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

 

本文详细介绍了如何利用 Spring AI 构建一个能够灵活切换不同生成式 AI 平台和模型的服务。通过 Spring Boot Web、Spring AI 的 DeepSeek、DashScope 和 Ollama 模块,文章展示了如何通过 `/chat` 端点实现按 Bean 名称直接调用预设模型,以及通过 `/chat2` 端点支持动态指定平台、模型、温度并实现流式输出。文中详细阐述了模块依赖、配置文件、核心代码设计,并提供了运行验证和常见问题解答,为企业在落地生成式 AI 时提供了实用的解决方案。

💡 **统一模型接口与配置**:通过 Spring AI 提供的 `ChatClient`,可以方便地将 DeepSeek、阿里云百炼 DashScope 和本地 Ollama 等多种模型服务进行统一封装。在 `AiConfig` 类中,为不同的模型(如 DeepSeek 的推理和聊天模型,以及 Ollama 模型)创建独立的 `ChatClient` Bean,并为其设置默认的 `ChatOptions`,实现了“即插即用”的接入方式,为后续的动态切换奠定了基础。

📞 **按名直切的 `/chat` 端点**:利用 Spring 的 `@Autowired Map` 机制,可以直接通过 Bean 的名称来选择并调用相应的 `ChatClient`。`/chat` 端点接收 `model` 参数,该参数对应于 `AiConfig` 中定义的 Bean 名称(如 `deepseekR1`、`ollama`),从而实现快速、直接的模型切换,适用于预设固定模型的场景。

🚀 **平台、模型、温度与流式输出的 `/chat2` 端点**:为了更灵活的控制,`/chat2` 端点允许用户动态指定 `platform`(如 'dashscope'、'ollama'、'deepseek')、`model`(平台支持的具体模型名)以及 `temperature`。通过将不同平台的 `ChatModel` 放入 `HashMap`,并构建新的 `ChatClient`,结合 `Flux` 实现流式文本的返回,为用户提供更佳的交互体验。

🛠️ **设计要点与最佳实践**:文章强调了将平台与模型解耦的重要性,建议在生产环境中采用更安全的密钥管理方式,并指出模型名称必须与所选平台兼容。同时,提供了关于如何新增平台、控制输出长度以及添加系统提示词的指导,并强调了容错处理和降级策略的重要性,以确保系统的稳定性和可用性。

背景与目标

本文基于模块 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 多模型切换 多平台 Ollama DeepSeek DashScope ChatClient 流式输出 Generative AI Multi-model Switching Multi-platform Streaming Output
相关文章