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
相关推荐
lssjzmn15 分钟前
java中,synchronized 关键字与 ReentrantLock 重入锁的区别以及应用场景,注意事项
java·后端
南雨北斗23 分钟前
词性
后端
南雨北斗25 分钟前
动词的类型
后端
小厂永远得不到的男人28 分钟前
ioc 原理篇
java·后端
南雨北斗41 分钟前
英语音标
后端
ClouGence1 小时前
三步搞定!GaussDB 实时数据入仓
数据库·后端
whitepure1 小时前
万字详解Java枚举
java·后端
用户8356290780511 小时前
在 Java 中读取 Excel 文件
java·后端
canonical_entropy1 小时前
让演化可编程:XLang 与可逆计算的结构化范式
后端
whitepure1 小时前
万字详解Java泛型
后端