* SpringAI多模型共存指南(如何配置多模型)

做过不少 AI 项目后你会发现,"只用一个模型"这件事越来越少见。DeepSeek 便宜、通义千问国内合规、Claude 代码能力强------不同场景用不同模型,或者主模型挂了自动切备用,这些都是真实需求。

这一节,我们来讲讲怎么在 Spring AI 里优雅地管理多模型,让业务代码完全不感知底层用的是哪个厂商。

一、前景回顾

早期我们在项目中配置了 Spring AI OpenAI Starter 的依赖如下:

1.1 依赖

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <!-- 继承 Spring Boot 父工程:统一管理 Spring Boot 相关依赖版本与插件配置 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.14</version>
        <relativePath/>
    </parent>
 
    <groupId>com.edu</groupId>
    <artifactId>edu-ai</artifactId>
    <version>1.0-SNAPSHOT</version>
 
    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>21</java.version>
        <spring-ai.version>1.1.5</spring-ai.version>
    </properties>
 
    <!-- Spring AI BOM:统一管理 spring-ai 所有子模块的版本 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>${spring-ai.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
    <dependencies>
        <!-- Spring Boot Web Starter:提供 Spring MVC、内嵌 Tomcat、RESTful 支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
 
        <!--
            Spring AI OpenAI Starter:支持 OpenAI 及所有兼容接口(DeepSeek、Moonshot 等)
            引入后自动配置 ChatModel、EmbeddingModel 等 Bean,版本由 spring-ai-bom 统一管理
        -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-openai</artifactId>
        </dependency>
 
        <!-- Spring Boot Test Starter:提供 JUnit 5、Mockito、SpringBootTest 等测试支持 -->
        <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>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
 
</project>

1.2 Yml配置

复制代码
spring:
  ai:
    openai:
      # 如果用 DeepSeek,改成 https://api.deepseek.com
      # 如果用 OpenAI,改成 https://api.openai.com(或者不填,默认就是这个)
      base-url: https://api.deepseek.com
      api-key: ${DEEPSEEK_API_KEY}   # 从环境变量读取,不要直接写在配置文件里
      chat:
        options:
          model: deepseek-chat        # DeepSeek-V3 的模型名
          temperature: 0.7

此时整个应用只有一个 ChatModel,Spring AI 的自动配置工作得毫无波澜。

二、引入Spring AI Alibaba

2.1 核心官方文档入口

资源类型 地址 说明
官方文档网站 https://java2ai.com/docs/1.0.0.2/get-started/chatbot 最权威的入门和参考文档,包含聊天、工作流、智能体等完整指南。
项目GitHub仓库 https://github.com/alibaba/spring-ai-alibaba 源代码、版本发布、issue追踪,是了解项目开发动态的最权威地方。
官方博客与公告 https://java2ai.com/blog 发布新版本、核心特性解读和社区动态。
代码示例仓库 https://github.com/springaialibaba/spring-ai-alibaba-examples 包含完整的项目示例,帮助你快速上手实践。
云原生文档 https://sca.aliyun.com/ai/ 关于AI网关、可观测性、Nacos配置管理等生产环境部署的内容。

2.2引入依赖

添加如下依赖

复制代码
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.alibaba.cloud.ai</groupId>
      <artifactId>spring-ai-alibaba-bom</artifactId>
      <version>1.1.2.2</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
    <version>1.1.2.2</version>
  </dependency>
</dependencies>

注意:spring-ai-alibaba-starter-dashscope需要指定对应的版本,因为spring-ai-alibaba-bom

中并没有管理它的版本

2.3 Yml配置

添加如下配置

复制代码
spring:
  ai:
    dashscope:
      api-key: xxx
      chat:
        options:
          model: qwen-plus

三、启动服务,出现问题

复制代码
***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 1 of method chatClientBuilder in org.springframework.ai.model.chat.client.autoconfigure.ChatClientAutoConfiguration required a single bean, but 2 were found:
	- dashScopeChatModel: defined by method 'dashScopeChatModel' in class path resource [com/alibaba/cloud/ai/autoconfigure/dashscope/DashScopeChatAutoConfiguration.class]
	- openAiChatModel: defined by method 'openAiChatModel' in class path resource [org/springframework/ai/model/openai/autoconfigure/OpenAiChatAutoConfiguration.class]

This may be due to missing parameter name information

Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

Ensure that your compiler is configured to use the '-parameters' flag.
You may need to update both your build tool settings as well as your IDE.
(See https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-6.1-Release-Notes#parameter-name-retention)

这是因为,在SpringAI启动时,会需要注入ChatModel对象,但是,现在由于引入了阿里云和OpenAI,会存在2个ChatModel对象实例,所以导致了报错。

3.1 分析问题

要想解决问题,首先我们需要找到启动时的自动配置类,在这里:

SpringAI就是由org.springframework.ai.autoconfigure.chat.client.ChatClientAutoConfiguration类完成自动配置的。

可以看到,在这个类中的chatClientBuilder方法,中注入了ChatModel对象,由于现在的Spring容器中存在2个实例,所以就报错了。

怎么解决这个问题呢?

3.2解决方法First

解决方法:SpringAIConfig中不通过ChatClient.Builder构建ChatClient对象,而是通过注入ChatModel的方式,来创建不同的ChatClient对象。

新构建ChatClient:(推荐)

复制代码
package com.edu.config;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringAIConfig {

    /**
     * 配置 ChatClient
     */
    @Bean
    public ChatClient chatClient(@Qualifier("openAiChatModel") ChatModel chatModel,
                                 Advisor loggerAdvisor) {  // 日志记录器
        return ChatClient.builder(chatModel)
                .defaultAdvisors(loggerAdvisor) //添加 Advisor 功能增强
                .build();
    }

    /**
     * 日志记录器
     * logging:
     *   level:
     *     org.springframework.ai.chat.client.advisor: DEBUG
     */
    @Bean
    public Advisor loggerAdvisor() {
        return new SimpleLoggerAdvisor();
    }
}

新写法通过 @Qualifier("openAiChatModel") 精确指定了用哪个模型来创建 ChatClient,彻底避开了歧义问题。


对比原来的写法(会报错):

复制代码
package com.edu.config;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringAIConfig {

    /**
     * 配置 ChatClient
     */
    @Bean
    public ChatClient chatClient(ChatClient.Builder chatClientBuilder,
                                 Advisor loggerAdvisor) {  // 日志记录器
        return chatClientBuilder
                .defaultAdvisors(loggerAdvisor) //添加 Advisor 功能增强
                .build();
    }

    /**
     * 日志记录器
     * logging:
     *   level:
     *     org.springframework.ai.chat.client.advisor: DEBUG
     */
    @Bean
    public Advisor loggerAdvisor() {
        return new SimpleLoggerAdvisor();
    }
}

3.3解决方法Second

排除用不到的自动配置,yml文件配置如下

复制代码
spring:
  autoconfigure:
    exclude:
      - org.springframework.ai.model.chat.client.autoconfigure.ChatClientAutoConfiguration
      - org.springframework.ai.model.openai.autoconfigure.OpenAiImageAutoConfiguration

为不同场景注册独立的 ChatClient:

复制代码
package com.jichi.springaialibaba.config;
 
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
 
@Configuration
public class MultiModelConfig {
 
    @Bean("primaryChatClient")
    @Primary
    public ChatClient primaryChatClient(OpenAiChatModel openAiChatModel) {
        return ChatClient.builder(openAiChatModel)
                .defaultSystem("你是一个专业的助手")
                .build();
    }
 
    @Bean("backupChatClient")
    public ChatClient backupChatClient(DashScopeChatModel dashScopeChatModel) {
        return ChatClient.builder(dashScopeChatModel)
                .defaultSystem("你是一个专业的助手")
                .build();
    }
}

四、同理出现多个EmbeddingModel

项目中虽然没有直接使用 EmbeddingModel ,但通过 VectorStore 的自动配置间接依赖

MilvusVectorStoreAutoConfiguration.vectorStore()

└── 需要注入一个 EmbeddingModel 参数

└── 但容器中有两个候选:

  • openAiEmbeddingModel (来自 OpenAI Starter)

  • dashscopeEmbeddingModel (来自 DashScope Starter)

4.1创建配置类

复制代码
package com.edu.config;

import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration
public class EmbeddingModelConfig {

    /**
     * 当存在多个 EmbeddingModel Bean (dashscopeEmbeddingModel, openAiEmbeddingModel) 时,
     * 将 openAiEmbeddingModel 标记为 @Primary,避免自动注入时因歧义报错。
     * 其他代码仍可通过 @Qualifier 指定使用非 Primary 的 Bean。
     */
    @Bean
    @Primary
    public EmbeddingModel primaryEmbeddingModel(@Qualifier("openAiEmbeddingModel") EmbeddingModel embeddingModel) {
        return embeddingModel;
    }
}

这个配置类的作用是解决 Bean 冲突 ,将 openAiEmbeddingModel 标记为 @Primary

4.2启动服务,进行测试

现在的配置已经正确地将 openAiEmbeddingModel 设为 @Primary,Spring 会优先使用它来创建 Milvus VectorStore。

启动成功!!!

五、小结

从单模型到多模型,Spring AI 引入多个厂商的 Starter 后,核心挑战就是 Bean 冲突。解决思路很清晰:

  1. ChatModel 冲突 :绕开自动 Builder,直接用 @Qualifier 注入具体模型构建 ChatClient。

  2. EmbeddingModel 冲突 :定义一个 @Primary Bean,明确告诉 Spring 默认用哪个。

  3. 想要多个 ChatClient:排除自动配置,手动注册 Bean。

搞定这些之后,你的应用就具备了"多模型共存"的能力,为后续的智能路由和降级打下了坚实的基础。而所有这些修改,几乎没有侵入业务代码,开发体验依旧丝滑。

相关推荐
zhangxingchao1 小时前
AI应用开发一: AI 编程、大模型调用和 Agent
前端·人工智能·后端
SomeOtherTime2 小时前
电场相关(AI回答)
人工智能
城事漫游Molly2 小时前
统计研究路线图:PPDAC问题解决循环
大数据·人工智能·论文笔记·科研统计
果汁华2 小时前
Claude 电脑与浏览器使用最佳实践
人工智能
拉拉拉拉拉拉拉马2 小时前
Windsurf 最新版进阶讲解:从 Cascade 到 Devin Local,重新理解 AI 编程工作流
人工智能·算法
BU摆烂会噶2 小时前
【LangGraph】节点内调用与状态隔离
android·人工智能·python·ui·langchain·人机交互
constCpp2 小时前
Cursor、Claude Code、Copilot——剥开壳子,是同一台机器
人工智能·copilot
水上冰石2 小时前
stable-diffusion-webui怎么生成视频
人工智能·stable diffusion
a flying bird2 小时前
【 LPIPS + 颜色保真 + 像素级相似度 + 生成逼真度的超分 / 图像增强】
人工智能·计算机视觉