SpringBoot3集成多款主流大模型

集成:DeepSeek,豆包,混元,通义千问。

一、简介

2025年7月份,开始转型独立开发者。

第一款尝试的产品自然是AI方向,此前不具备专业的产品经验,所以只能更多的依赖大模型的能力。

年初DeepSeek成功证明模型即产品的理念,所以第一款产品尽量降低传统的产品设计思维,会把场景和流程交给大模型去处理,通过反复测试来调整干预的权重,找到一个相对平衡的比例。

有时候在反思,自己的脑回路会不会限制AI的发挥。

在产品的初期,先选择接入四款大模型,深度求索的DeepSeek,字节跳动的豆包,腾讯的混元,阿里的通义千问。

模型即产品,那产品是什么?

当然每家的大模型,都有自己的能力特点,这里只是从产品的整体功能考量,这几款模型可能更适合,后续可能也会在实践中做动态调整。

二、大模型自评

如何快速熟悉大模型的能力?多提问题,多和它来回拉扯。

首先给这几款大模型,抛出一个灵魂拷问:

作为一款很强的大模型,请你客观的分析DeepSeek,豆包,千问,混元,这四款大模型的差异,并从综合能力的角度给个排序。

看热闹不嫌事大,先让大模型自我分析一把,验证一下自己对它们的预期。

DeepSeek回答:

豆包回答:

通义千问回答:

混元回答:

各个大模型对于能力的排序,权当个热闹看一看。

不过有个结论可以得出来的:不同平台的业务和数据有很大差异,所以训练出来的模型能力也有差异。

此前文章中写过DeepSeek的代码测评,确实很惊艳;豆包的产品化能力,方便解决很多生活问题;混元经常用来分析行业热门事件;通义千问常用来提供业务设计的参考。

所以产品的不同功能,交给不同的大模型来处理,是比较合理的策略。

三、SpringBoot集成

从产品的业务需求出发,来设计后端框架的模型对接,既然需要集成多款大模型,自然是通用的组件更方便管理,通过测试对比个人倾向使用spring-ai-openai依赖包。

这几款模型的使用文档,都适配了OpenAI的接口规范,只是豆包有轻微的细节差异。

3.1 版本依赖

这里说一下简单的思路,是先敲定spring-ai-openai组件的版本,在这个组件中依赖spring-boot3.3.6版本,以此定了后端的框架和版本。

xml 复制代码
<spring-boot.version>3.3.6</spring-boot.version>
<spring-ai-openai.version>1.0.0-M5</spring-ai-openai.version>

<dependencies>
  <dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    <version>${spring-ai-openai.version}</version>
  </dependency>
</dependencies>

<!-- SpringBoot依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>${spring-boot.version}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

3.2 配置和测试

首先看基础的Yaml配置文件,比较常见的就是请求的地址和方法,然后指定大模型使用的版本名称,这里要注意豆包配置的差异,千问和混元也是一样的方式。

yaml 复制代码
spring:
  # 大模型配置
  ai:
    openai:
      base-url: https://api.deepseek.com
      api-key: sk-deep-seek
      chat:
        # 默认配置
        # 豆包大模型使用:/api/v3/chat/completions
        completions-path: /v1/chat/completions
        options:
          model: deepseek-chat

简单做个测试的用例,构建ChatClient类,传入自定义的提示词,请求DeepSeek大模型,没有使用流式输出,所以请求响应的时间比较长。

java 复制代码
@RestController
public class TestModelWeb {

    private final ChatClient chatClient ;

    public TestModelWeb(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    @GetMapping(value = "/client")
    public String chatClient() {
        String message = "讲个笑话,最好能把我听哭的那一种。";
        return  chatClient.prompt(new Prompt(message)).call().content();
    }
}

3.3 多模型封装

通过配置文件管理模型的集成虽然简单高效,但是产品的场景中有模型动态选择的功能,所以做个简单的封装,在容器中存ChatClient类,选中哪款调用哪款。

java 复制代码
/**
 * 大模型工厂
 * @author 七号楼
 * @since 2025-07-02 13:48
 */
@Component
public class ModelFactory {

    private static volatile Map<String, ChatClient> modelMap = new HashMap<>();

    /**
     * 获取模型
     * @since 2025-07-03 10:53
     */
    public static ChatClient getModel (String modelName){
        return modelMap.get(modelName);
    }

    /**
     * 移除模型
     * @since 2025-07-03 10:53
     */
    public static void removeModel (String modelName){
        if (CollUtil.contains(modelMap.keySet(),modelName)){
            modelMap.remove(modelName);
        }
    }
    /**
     * 添加模型
     * @since 2025-07-03 10:53
     */
    public static void putModel (OpenAiChatProperties properties,OpenAiChatOptions options){
        ChatClient buildClient = buildChatClient(properties,options);
        modelMap.put(options.getModel(),buildClient);
    }
    /**
     * 构建ChatClient对话客户端
     * @param properties 基础配置
     * @param options 选项配置
     * @return ChatClient
     */
    private static ChatClient buildChatClient(OpenAiChatProperties properties,OpenAiChatOptions options) {
        properties.setOptions(options);
        OpenAiApi openAiApi = new OpenAiApi(
                properties.getBaseUrl(),
                properties.getApiKey(),
                properties.getCompletionsPath(),
                "/v1/embeddings",
                RestClient.builder(),
                WebClient.builder(),
                RetryUtils.DEFAULT_RESPONSE_ERROR_HANDLER);
        OpenAiChatModel chatModel = new OpenAiChatModel(openAiApi,options);
        return ChatClient.builder(chatModel).build();
    }
}

多款大模型的配置信息,统一维护在表中即可,在服务启动时加载一次,初始化ModelFactory中的Map容器。

java 复制代码
@Service
public class ModelConfigServiceImpl extends ServiceImpl<ModelConfigMapper, ModelConfig> implements ModelConfigService {

    @PostConstruct
    public void init (){
        List<ModelConfig> modelList = this.list();
        if (CollUtil.isNotEmpty(modelList)){
            for (ModelConfig modelConfig:modelList) {
                // 基础配置
                OpenAiChatProperties properties = new OpenAiChatProperties();
                properties.setBaseUrl(modelConfig.getBaseUrl());
                properties.setCompletionsPath(modelConfig.getCompletionsPath());
                properties.setApiKey(modelConfig.getApiKey());
                // 选项配置
                OpenAiChatOptions options = OpenAiChatOptions.builder()
                        .model(modelConfig.getModelVersion())
                        .temperature(modelConfig.getTemperature())
                        .build();
                // 模型工厂
                ModelFactory.putModel(properties,options);
            }
        }
    }
}

简单的测试一下模型动态选择的封装。

java 复制代码
@RestController
public class TestModelWeb {
    @GetMapping(value = "/completion")
    public String completion() {
        String message = "你是哪个公司开发的?当前使用的是哪个版本的模型?";
        return  ModelFactory.getModel("qwen").prompt(new Prompt(message)).call().content()
                +"<br/><br/>"+
                ModelFactory.getModel("hunyuan").prompt(new Prompt(message)).call().content();
    }
}

四、最后总结

产品在完成大模型集成后,测试具体的业务场景时,可以先不考虑自定义的干预策略,就看一看大模型能发挥到什么程度。

如果效果不符合预期,再逐步的加入自定义的策略,直到产品和大模型这个"产品"形成默契的配合,建议测试过程放在模型官网的对话框进行。

毕竟独立开发者的收入,已经独立了。

plain 复制代码
文档仓库:
https://gitee.com/cicadasmile/butte-java-note

源码仓库:
https://gitee.com/cicadasmile/butte-mound
相关推荐
神奇小汤圆14 分钟前
浅析二叉树、B树、B+树和MySQL索引底层原理
后端
文艺理科生23 分钟前
Nginx 路径映射深度解析:从本地开发到生产交付的底层哲学
前端·后端·架构
千寻girling24 分钟前
主管:”人家 Node 框架都用 Nest.js 了 , 你怎么还在用 Express ?“
前端·后端·面试
南极企鹅26 分钟前
springBoot项目有几个端口
java·spring boot·后端
Luke君6079728 分钟前
Spring Flux方法总结
后端
define952731 分钟前
高版本 MySQL 驱动的 DNS 陷阱
后端
忧郁的Mr.Li1 小时前
SpringBoot中实现多数据源配置
java·spring boot·后端
暮色妖娆丶2 小时前
SpringBoot 启动流程源码分析 ~ 它其实不复杂
spring boot·后端·spring
Coder_Boy_2 小时前
Deeplearning4j+ Spring Boot 电商用户复购预测案例中相关概念
java·人工智能·spring boot·后端·spring
Java后端的Ai之路2 小时前
【Spring全家桶】-一文弄懂Spring Cloud Gateway
java·后端·spring cloud·gateway