SpringAI集成DeepSeek实战
SpringAI集成DeepSeek实战教程
引言
Spring AI作为Spring生态系统中的新成员,为开发者提供了便捷的AI集成方案。本文将详细介绍如何在Spring项目中集成DeepSeek模型,实现智能对话等功能。
环境准备
在开始之前,请确保您的开发环境满足以下要求:
- JDK 17或更高版本
- Spring Boot 3.x
- Maven或Gradle构建工具
- DeepSeek API密钥
项目配置
首先,在pom.xml中添加Spring AI的依赖:
<dependencies><!-- Spring AI 核心依赖 --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-core</artifactId><version>0.8.0</version></dependency><!-- DeepSeek 集成依赖 --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-deepseek</artifactId><version>0.8.0</version></dependency>
</dependencies>
基础配置类
创建DeepSeek配置类:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ai.deepseek.DeepSeekAiClient;
import org.springframework.ai.deepseek.DeepSeekAiProperties;@Configuration
public class DeepSeekConfig {@Beanpublic DeepSeekAiProperties deepSeekAiProperties() {// 配置DeepSeek属性DeepSeekAiProperties properties = new DeepSeekAiProperties();properties.setApiKey("your-api-key-here");properties.setModel("deepseek-chat"); // 设置使用的模型return properties;}@Beanpublic DeepSeekAiClient deepSeekAiClient(DeepSeekAiProperties properties) {// 创建DeepSeek客户端实例return new DeepSeekAiClient(properties);}
}
服务层实现
创建一个服务类来处理与DeepSeek的交互:
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.stereotype.Service;@Service
public class ChatService {private final DeepSeekAiClient aiClient;public ChatService(DeepSeekAiClient aiClient) {this.aiClient = aiClient;}/*** 发送单轮对话请求* @param message 用户输入的消息* @return AI的响应内容*/public String sendMessage(String message) {// 创建用户消息UserMessage userMessage = new UserMessage(message);// 创建prompt对象Prompt prompt = new Prompt(userMessage);// 获取AI响应ChatResponse response = aiClient.generate(prompt);return response.getGeneration().getContent();}/*** 发送多轮对话请求* @param messages 对话历史记录* @return AI的响应内容*/public String sendConversation(List<String> messages) {List<Message> conversationHistory = new ArrayList<>();// 构建对话历史for (String message : messages) {conversationHistory.add(new UserMessage(message));}// 创建带有历史记录的promptPrompt prompt = new Prompt(conversationHistory);ChatResponse response = aiClient.generate(prompt);return response.getGeneration().getContent();}
}
控制器实现
创建REST API接口:
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/api/chat")
public class ChatController {private final ChatService chatService;public ChatController(ChatService chatService) {this.chatService = chatService;}/*** 处理单条消息请求* @param message 用户消息* @return AI响应*/@PostMapping("/message")public ResponseEntity<String> handleMessage(@RequestBody String message) {try {String response = chatService.sendMessage(message);return ResponseEntity.ok(response);} catch (Exception e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("处理消息时发生错误:" + e.getMessage());}}/*** 处理多轮对话请求* @param messages 对话历史* @return AI响应*/@PostMapping("/conversation")public ResponseEntity<String> handleConversation(@RequestBody List<String> messages) {try {String response = chatService.sendConversation(messages);return ResponseEntity.ok(response);} catch (Exception e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("处理对话时发生错误:" + e.getMessage());}}
}
异常处理
添加全局异常处理:
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;@ControllerAdvice
public class GlobalExceptionHandler {/*** 处理DeepSeek API相关异常*/@ExceptionHandler(DeepSeekApiException.class)public ResponseEntity<String> handleDeepSeekApiException(DeepSeekApiException e) {// 记录错误日志log.error("DeepSeek API错误", e);return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("AI服务暂时不可用,请稍后重试");}/*** 处理其他未预期的异常*/@ExceptionHandler(Exception.class)public ResponseEntity<String> handleGeneralException(Exception e) {log.error("系统错误", e);return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("系统发生错误,请联系管理员");}
}
使用示例
以下是一个简单的使用示例:
@SpringBootApplication
public class DeepSeekDemoApplication {@Autowiredprivate ChatService chatService;public void demonstrateChat() {// 发送单条消息String response1 = chatService.sendMessage("你好,请介绍一下自己");System.out.println("AI响应:" + response1);// 发送多轮对话List<String> conversation = Arrays.asList("你好,我想学习Java","请推荐一些好的学习资源","这些资源适合初学者吗?");String response2 = chatService.sendConversation(conversation);System.out.println("AI响应:" + response2);}public static void main(String[] args) {SpringApplication.run(DeepSeekDemoApplication.class, args);}
}
总结
通过本文的介绍,我们详细讲解了如何在Spring项目中集成DeepSeek AI服务。从基础配置到具体实现,再到异常处理,覆盖了实际开发中的主要场景。通过使用Spring AI提供的抽象层,我们可以更加便捷地集成和使用AI能力,而不需要直接处理底层的API调用细节。
需要注意的是,在实际开发中,还需要考虑以下几点:
- API密钥的安全存储
- 请求限流和错误重试
- 响应超时处理
- 模型参数优化
- 成本控制
相关文章:
SpringAI集成DeepSeek实战
SpringAI集成DeepSeek实战教程 引言 Spring AI作为Spring生态系统中的新成员,为开发者提供了便捷的AI集成方案。本文将详细介绍如何在Spring项目中集成DeepSeek模型,实现智能对话等功能。 环境准备 在开始之前,请确保您的开发环境满足以下要…...
解决 THC/THC.h: No such file or directory 报错
报错现象: cc1plus: warning: command line option ‘-Wstrict-prototypes’ is valid for C/ObjC but not for C In file included from /data/joyiot/liyong/codes/graspnet-baseline/knn/src/knn.h:5:0,from /data/joyiot/liyong/codes/graspnet-baseline/knn/s…...
S4D480 S4HANA 基于PDF的表单打印
2022年元旦的笔记草稿 SAP的表单打印从最早的SAPScripts 到后来的SMARTFORM,步入S4时代后由于Fiori的逐渐普及,更适应Web的Adobe Form成了SAP主流output文件格式。 目录 一、 基于PDF表单打印系统架构Interface 接口Form 表单ContextLayout 二、表单接…...
数组_移除元素
数组_移除元素 一、leetcode-27二、题解1.代码2.思考 一、leetcode-27 移除元素 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数…...
Vue2/Vue3分别如何使用Watch
在 Vue 2 和 Vue 3 中,watch 用于监听数据的变化并执行相应的逻辑。虽然两者的核心功能相同,但在语法和使用方式上有一些区别。以下是 Vue 2 和 Vue 3 中使用 watch 的详细说明: Vue 2 中的 watch 在 Vue 2 中,watch 是通过选项式…...
C++从入门到实战(四)C++引用与inline,nullptr
C从入门到实战(四)C引用与inline,nullptr 前言一、C 引用(一)什么是引用(二)引用的特点(三)引用作为函数参数(四)引用作为函数返回值(…...
Linux库制作与原理:【静态库】【动态库】【目标文件】【ELF文件】【ELF从形成到假造轮廓】【理解链接和加载】
目录 一.什么是库 二.静态库 2.1创建静态库 我们在之前的路径下新建lib使用我们自己的库 2.2 使用makefile生成静态库 三.动态库 3.1动态库生成 3.2动态库使用 3.3库运行搜索路径 四.目标文件 五.ELF文件 六.ELF从形成到加载轮廓 6.1ELF形成可执行 6.2 ELF可执行文…...
项目BUG
项目BUG 前言 我创作这篇博客的目的是记录学习技术过程中的笔记。希望通过分享自己的学习经历,能够帮助到那些对相关领域感兴趣或者正在学习的人们。 项目BUG 1.低频率信号(100k或 200K以下)可以直接用一根导线焊接出几根导线来分几路,高频率信号只能…...
wordpress部署nginx版的
一、通过nginx部署wordpress 1、用yum源安装nginx yum install -y nginx 2、安装php相关软件 前提安装webtatic rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm 通过yum源安装php相关软件 yum -y install php72w php72w-pdo php72w-mysqlnd php72w…...
【鸿蒙Next】优秀鸿蒙博客集锦
鸿蒙基础开发:多文件压缩上传及断点续传_鸿蒙 断点续传-CSDN博客...
【第2章:神经网络基础与实现——2.1 前馈神经网络的结构与工作原理】
老铁们好!今天我们要来一场长达两万字的超详细技术探险,我会像拆解乐高积木一样把前馈神经网络(Feedforward Neural Network)的每个零件摆在台面上,用最接地气的方式让你彻底搞懂这个深度学习基石的工作原理。准备好了吗?我们开始吧! 第一章:神经网络的 “乐高积木” 1…...
python-leetcode-阶乘后的零
172. 阶乘后的零 - 力扣(LeetCode) class Solution:def trailingZeroes(self, n: int) -> int:count 0while n > 5:n // 5count nreturn count...
Python:学生管理系统(继承性、多态性)。
输出样例如图: 题目内容: 利用继承、多态性等面向对象程序功能编写程序,实现学生管理系统,并包含以下内容: 第一,基类为学生类,并以此派生出本科生类、研究生类。 第二,本科生类包含…...
网络安全RSA加密
网络安全课相关知识: RSA预备知识 1.1 快速幂算法 顾名思义,快速幂就是快速算底数的$n$次幂。其时间复杂度为${\rm{O(log n)}}$,与朴素的$O\left( n \right)$相比,效率有了极大的提高。具体可以参考百度百科:快速幂。…...
Vue学习笔记4
Vue学习笔记 一、自定义创建项目 基于VueCli自定义创建项目架子 二、vuex基本认知 1、vuex概述 是什么:是vue的状态管理工具(插件),状态就是数据 大白话:vuex是一个插件,可以帮助我们管理vue通用的数…...
mariadb数据库的安装与部署
1、通过yum源安装mariadb数据库 yum -y install mariadb-server 2、启动mariadb数据库服务 systemctl start mariadb.service 3、配置mariadb数据库全局环境变量 systemctl enable mariadb.service 4、修改mariadb数据库默认密码,数据库默认密码为空 执行…...
单调队列与栈
一.题 1. 思路: 构建小压大的单调递减栈,对于每个栈的元素都进行处理并加到结果上 class Solution { public:int sumSubarrayMins(vector<int>& arr) {int stk[10000000],top 0;long long ans 0;for(int i 0;i<arr.size();i){while(top…...
Matlab 多项式曲线拟合(三维)
文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 对于高维空间曲线的拟合,参数化是一种非常好的方式,可以让我们很容易得到我们想要的目标曲线。 假设给定一组数据点 ( u i , x i ) 、 ( u i ...
机器翻译同样的文本,是从英语翻译成日语更准确还是中文翻译成日语更准确
在大多数情况下,从英语翻译成日语会比从中文翻译成日语更准确,原因如下: 1. 语言结构的相似性 英语和日语的句子结构更接近,特别是在语法、从句使用、定语位置等方面。例如,日语和英语都使用 SVO 结构(主…...
MAC 系统关屏幕后电量消耗极快 Wake Requests
日志为 Wake Requests [*processdasd requestSleepService…info"com.apple.alarm.user-invisible-com.apple.calaccessd… 本人有效方法为: sudo pmset -a hibernatemode 25 sudo pmset -a standby 0 sudo pmset -a autopoweroff 0 会导致hibernatemode 25是…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
