当前位置: 首页 > news >正文

AI 大模型统一集成|Spring AI + DeepSeek 实战接入指南

AI 大模型统一集成|Spring AI + DeepSeek 实战接入指南

🌟 在这系列文章中,我们将一起探索如何搭建一个支持大模型集成项目 ChatAI 的开发过程,从 架构设计 到 代码实战,逐步搭建一个支持 多种大模型(GPT-4、DeepSeek 等) 的 一站式大模型集成与管理平台,并集成 认证中心、微服务、流式对话 等核心功能。

本文将结合 Spring AI 与大语言模型,演示如何借助 Tool Calling 实现系统 API 的调用,并支持多轮对话中的上下文记忆处理,从而构建更智能、实用的企业级 AI 应用。并成功打通 DeepSeek 大模型,实现统一的 AI 接入方案。


✨ 为什么选择 Spring AI + DeepSeek?

在多模型百花齐放的时代,OpenAI、DeepSeek、Moonshot、Claude 各有千秋,我们如何实现统一接入、灵活切换、快速调用

Spring 团队开源的 Spring AI 正是为此而生,它提供了统一的编程模型,支持主流 AI 平台(OpenAI、Azure、HuggingFace、DeepSeek 等)。

而 DeepSeek 则是近年来在中文语义、代码能力方面表现优异的国产大模型,支持 OpenAI 接口风格,适配性强。


⚙️ Spring AI 工具调用

Spring AI 工具调用与不同 AI 模型一起使用的更多信息,请遵循工具调用文档。
在这里插入图片描述

工具元数据注入

在发起 Chat Request 时,将工具描述(name/description)、参数结构(input schema)等元数据封装至请求体,建立大模型的工具调用能力基线。每个工具定义都包含输入参数的名称、描述和方案。

模型决策响应

当模型决定调用工具时,它会发送一个响应,其中包含工具名称和输入参数,这些参数在定义的架构之后建模。
大模型根据上下文推理生成工具调用指令(tool_calls字段),返回包含选定工具名称及结构化参数的中间响应。

服务端路由执行

应用程序负责使用工具名称来识别并使用提供的输入参数执行工具。
Spring AI 模块解析工具调用指令,通过服务发现机制定位目标工具实例,注入参数并触发同步/异步执行。

执行结果标准化

工具调用的结果由应用程序处理。
工具返回原始执行结果后,系统进行数据类型校验、异常捕获和JSON序列化处理,生成模型可解析的标准化数据结构。

上下文增强推理

应用程序将工具调用结果发送回模型。
将标准化结果作为新增上下文(tool_outputs)回传大模型,触发基于增强上下文的二次推理流程。

终端响应生成

模型综合初始请求与工具执行结果,生成最终自然语言响应,完成工具增强的对话闭环。

🔧 环境准备

✅ 依赖版本

  • Spring Boot: 3.4.1
  • Spring AI: 1.0.0-M6
  • JDK: 21

✅ Maven 依赖配置

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>3.4.1</version><type>pom</type><scope>import</scope>
</dependency>
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-openai-spring-boot-starter</artifactId><version>1.0.0-M6</version>
</dependency>

虽然依赖名为 openai,但因为 DeepSeek 模拟了 OpenAI 接口协议,所以可以通用。


⚙️ DeepSeek 接口说明

DeepSeek 官方接口文档:https://api-docs.deepseek.com/zh-cn/

在这里插入图片描述

DeepSeek 官方提供的 API 接口地址:

https://api.deepseek.com

🛠️ Spring AI 配置 DeepSeek

application.yml 中添加如下配置:

spring:ai:openai:api-key: sk-xxx  # deepseek 密钥base-url: https://api.deepseek.comchat:options:model: deepseek-reasoner

📦 构建一个 Spring AI 工具调用

SpringAiAiInvoke

代码很简单,由于引入 spring ai 的 stater 之后按照模型配置接入即可。然后注入一个 ChatModel 。我们测试接口可以将实现类继承接口 CommandLineRunner 可在 SpringBoot 启动时自动执行方便查看效果。

import jakarta.annotation.Resource;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;/*** Spring AI 框架调用 AI 大模型(Deepseek)*/
@Component
public class SpringAiAiInvoke implements CommandLineRunner {@Resourceprivate ChatModel deepseekChatModel;@Overridepublic void run(String... args) throws Exception {AssistantMessage assistantMessage = deepseekChatModel.call(new Prompt("你好!")).getResult().getOutput();System.out.println("DeepSeek大模型调用结果:" + assistantMessage.getText());}
}

执行测试结果:

在这里插入图片描述


📦 Spring AI 上下文记忆

大型语言模型 (LLM) 是无状态的,这意味着它们不会保留有关以前交互的信息。当你希望在多个交互中维护上下文或状态时,这可能是一个限制。为了解决这个问题,Spring AI 提供了聊天内存功能,允许你在与 LLM 的多次交互中存储和检索信息。

可以基于 ChatMemory 抽象实现各种类型的内存以支持不同的使用案例。 消息的底层存储由ChatMemoryRepository,其唯一职责是存储和检索消息。这取决于ChatMemoryimplementation 来决定要保留哪些消息以及何时删除它们。策略示例可能包括保留最后 N 条消息、将消息保留一段时间或将消息保持在某个Tokens限制内。

其中 MessageChatMemoryAdvisor 实现聊天记忆,InMemoryChatMemory 为 SpringAI 自带的实现(基于内存)。可以使用 CHAT_MEMORY_CONVERSATION_ID_KEY 参数指定对话ID,不同的会话ID用于隔离记忆。

@Component
@Slf4j
public class AgentApp {private final ChatClient chatClient;private static final String SYSTEM_PROMPT = "你是一个专业的天气助手,必须用中文回答,回答需包含温度、湿度和风力。";/*** 初始化 ChatClient** @param deepseekChatModel*/public AgentApp(ChatModel deepseekChatModel) {// 初始化基于内存的对话记忆ChatMemory chatMemory = new InMemoryChatMemory();chatClient = ChatClient.builder(deepseekChatModel)
//                .defaultSystem(SYSTEM_PROMPT).defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory),// 自定义日志 Advisor,可按需开启new LoggerAdvisor()
//                        // 自定义推理增强 Advisor,可按需开启
//                       ,new ReReadingAdvisor()).build();}/*** AI 基础对话(支持多轮对话记忆)** @param message* @param chatId* @return*/public String doChat(String message, String chatId) {ChatResponse chatResponse = chatClient.prompt().user(message).advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId).param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10)).call().chatResponse();String content = chatResponse.getResult().getOutput().getText();log.info("content: {}", content);return content;}/*** AI 基础对话(支持多轮对话记忆)** DeepSeek Reasoner 严格要求 system 消息必须是第一条 显示声明** @param message* @param chatId* @return*/public String doChatDeepSeek(String message, String chatId) {ChatResponse chatResponse = chatClient.prompt()// .system(SYSTEM_PROMPT).user(message).advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId).param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10)).call().chatResponse();String content = chatResponse.getResult().getOutput().getText();log.info("content: {}", content);return content;}
}

LoggerAdvisor 可以打印大模型内容。这里补充一下 Advisor 的作用,可以理解为作为模型调用前或者调用后的拦截器。


import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.advisor.api.*;
import org.springframework.ai.chat.model.MessageAggregator;
import reactor.core.publisher.Flux;/*** 自定义日志 Advisor* 打印 INFO 级别日志、只输出单次用户提示词和 AI 回复的文本*/
@Slf4j
public class LoggerAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {@Overridepublic String getName() {return this.getClass().getSimpleName();}@Overridepublic int getOrder() {return 0;}private AdvisedRequest before(AdvisedRequest request) {log.info("AI Request: {}", request.userText());return request;}private void observeAfter(AdvisedResponse advisedResponse) {log.info("AI Response: {}", advisedResponse.response().getResult().getOutput().getText());}@Overridepublic AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {advisedRequest = before(advisedRequest);AdvisedResponse advisedResponse = chain.nextAroundCall(advisedRequest);observeAfter(advisedResponse);return advisedResponse;}@Overridepublic Flux<AdvisedResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain) {advisedRequest = before(advisedRequest);Flux<AdvisedResponse> advisedResponses = chain.nextAroundStream(advisedRequest);return new MessageAggregator().aggregateAdvisedResponse(advisedResponses, this::observeAfter);}}

接下来使用 Junit 测试看看效果。

@SpringBootTest
class AgentAppTest {@Resourceprivate AgentApp agentApp;@Testvoid doChat() {String chatId = UUID.randomUUID().toString();// 第一轮String message = "你好,我是小李。";String answer = agentApp.doChatDeepSeek(message, chatId);// 第二轮message = "今天天气如何?";answer = agentApp.doChatDeepSeek(message, chatId);Assertions.assertNotNull(answer);// 第三轮message = "你知道叫什么来着?刚跟你说过。";answer = agentApp.doChatDeepSeek(message, chatId);Assertions.assertNotNull(answer);}
}

自测效果:

在这里插入图片描述

通过连续对话3次,最后一次提问此前给过的信息,可以看到大模型的结果中正常回答,说明聊天记忆功能已生效。

💡 注意事项

DeepSeek 使用 OpenAI 接口兼容层

  • 实际上是伪装成 OpenAI,所以你必须手动设置 base-urlapi-key
  • 模型名称建议使用deepseek-chatdeepseek-coder(根据模型需求场景)。

🔄 后续如何扩展?

  • ✅ 替换为 Claude、Gemini、Moonshot 等其他模型,只需改配置即可;
  • ✅ 接入 RAG(支持 Embedding);
  • ✅ 搭建前端 Chat UI(如:Cursor、NextChat、ChatUI);
  • ✅ 封装为微服务,支持多用户、多模型切换。

📢 你对这个项目感兴趣吗?欢迎 Star & 关注! 📌 GitHub 项目地址 🌟 你的支持是我持续创作的动力,欢迎点赞、收藏、分享!

在这里插入图片描述

http://www.xdnf.cn/news/935641.html

相关文章:

  • 【教学类-53-02】20250607自助餐餐盘教学版(配餐+自助餐)
  • Windows下用CMake编译DCMTK及配置测试
  • DeepSeek R1 V2 深度探索:开源AI编码新利器,效能与创意并进
  • Argo CD 入门 - 安装与第一个应用的声明式同步
  • IDEA为何一直无法使用超过4g内存
  • 文献阅读:Exploring Autoencoder-based Error-bounded Compression for Scientific Data
  • LSTM-SVM多变量时序预测(Matlab完整源码和数据)
  • VB调用CryReport指南方案
  • JVM——对象模型:JVM对象的内部机制和存在方式是怎样的?
  • 【学习笔记】深入理解Java虚拟机学习笔记——第5章 调优案例分析与实战
  • 第12篇:数据库中间件日志设计与追踪系统落地实践
  • MySQL知识回顾总结----数据库基础
  • 计算机常用快捷键分类汇总,涵盖 Windows、macOS 以及通用软件场景
  • STM32[笔记]--1.前置准备
  • AI系统的构建
  • 基于React 的 AntD 库进行前端开发过程中的问题汇总
  • 空间转录组数据下游分析(二)
  • 玄机——某次行业攻防应急响应(带镜像)
  • Java求职者面试指南:计算机基础与源码原理深度解析
  • 智警杯备赛--机器学习算法实践
  • 深度学习登上Nature子刊!特征选择创新思路
  • C# 表达式和运算符(表达式和字面量)
  • 【JavaScript-Day 35】从 window 到 location,一文掌握浏览器对象模型 BOM
  • Web前端开发:JavaScript中的eval()函数
  • triton学习笔记7: GEMM相关
  • uniapp跳转到webview组件的时候,要注意:移除所有不可见字符(包括零宽空格)
  • Linux系统之grub-mkrescue详解
  • vue.js not detected解决方法
  • Oracle实用参考(13)——Oracle for Linux物理DG环境搭建(2)
  • 第四篇:服务商(工人端)-02服务商入驻审核