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

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生态系统中的新成员&#xff0c;为开发者提供了便捷的AI集成方案。本文将详细介绍如何在Spring项目中集成DeepSeek模型&#xff0c;实现智能对话等功能。 环境准备 在开始之前&#xff0c;请确保您的开发环境满足以下要…...

解决 THC/THC.h: No such file or directory 报错

报错现象&#xff1a; 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&#xff0c;步入S4时代后由于Fiori的逐渐普及&#xff0c;更适应Web的Adobe Form成了SAP主流output文件格式。 目录 一、 基于PDF表单打印系统架构Interface 接口Form 表单ContextLayout 二、表单接…...

数组_移除元素

数组_移除元素 一、leetcode-27二、题解1.代码2.思考 一、leetcode-27 移除元素 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数…...

Vue2/Vue3分别如何使用Watch

在 Vue 2 和 Vue 3 中&#xff0c;watch 用于监听数据的变化并执行相应的逻辑。虽然两者的核心功能相同&#xff0c;但在语法和使用方式上有一些区别。以下是 Vue 2 和 Vue 3 中使用 watch 的详细说明&#xff1a; Vue 2 中的 watch 在 Vue 2 中&#xff0c;watch 是通过选项式…...

C++从入门到实战(四)C++引用与inline,nullptr

C从入门到实战&#xff08;四&#xff09;C引用与inline&#xff0c;nullptr 前言一、C 引用&#xff08;一&#xff09;什么是引用&#xff08;二&#xff09;引用的特点&#xff08;三&#xff09;引用作为函数参数&#xff08;四&#xff09;引用作为函数返回值&#xff08;…...

Linux库制作与原理:【静态库】【动态库】【目标文件】【ELF文件】【ELF从形成到假造轮廓】【理解链接和加载】

目录 一.什么是库 二.静态库 2.1创建静态库 我们在之前的路径下新建lib使用我们自己的库 2.2 使用makefile生成静态库 三.动态库 3.1动态库生成 3.2动态库使用 3.3库运行搜索路径 四.目标文件 五.ELF文件 六.ELF从形成到加载轮廓 6.1ELF形成可执行 6.2 ELF可执行文…...

项目BUG

项目BUG 前言 我创作这篇博客的目的是记录学习技术过程中的笔记。希望通过分享自己的学习经历&#xff0c;能够帮助到那些对相关领域感兴趣或者正在学习的人们。 项目BUG 1.低频率信号(100k或 200K以下)可以直接用一根导线焊接出几根导线来分几路&#xff0c;高频率信号只能…...

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】优秀鸿蒙博客集锦

鸿蒙基础开发&#xff1a;多文件压缩上传及断点续传_鸿蒙 断点续传-CSDN博客...

【第2章:神经网络基础与实现——2.1 前馈神经网络的结构与工作原理】

老铁们好!今天我们要来一场长达两万字的超详细技术探险,我会像拆解乐高积木一样把前馈神经网络(Feedforward Neural Network)的每个零件摆在台面上,用最接地气的方式让你彻底搞懂这个深度学习基石的工作原理。准备好了吗?我们开始吧! 第一章:神经网络的 “乐高积木” 1…...

python-leetcode-阶乘后的零

172. 阶乘后的零 - 力扣&#xff08;LeetCode&#xff09; class Solution:def trailingZeroes(self, n: int) -> int:count 0while n > 5:n // 5count nreturn count...

Python:学生管理系统(继承性、多态性)。

输出样例如图&#xff1a; 题目内容&#xff1a; 利用继承、多态性等面向对象程序功能编写程序&#xff0c;实现学生管理系统&#xff0c;并包含以下内容&#xff1a; 第一&#xff0c;基类为学生类&#xff0c;并以此派生出本科生类、研究生类。 第二&#xff0c;本科生类包含…...

网络安全RSA加密

网络安全课相关知识&#xff1a; RSA预备知识 1.1 快速幂算法 顾名思义&#xff0c;快速幂就是快速算底数的$n$次幂。其时间复杂度为${\rm{O(log n)}}$&#xff0c;与朴素的$O\left( n \right)$相比&#xff0c;效率有了极大的提高。具体可以参考百度百科&#xff1a;快速幂。…...

Vue学习笔记4

Vue学习笔记 一、自定义创建项目 基于VueCli自定义创建项目架子 二、vuex基本认知 1、vuex概述 是什么&#xff1a;是vue的状态管理工具&#xff08;插件&#xff09;&#xff0c;状态就是数据 大白话&#xff1a;vuex是一个插件&#xff0c;可以帮助我们管理vue通用的数…...

mariadb数据库的安装与部署

1、通过yum源安装mariadb数据库 yum -y install mariadb-server 2、启动mariadb数据库服务 systemctl start mariadb.service 3、配置mariadb数据库全局环境变量 systemctl enable mariadb.service 4、修改mariadb数据库默认密码&#xff0c;数据库默认密码为空 执行…...

单调队列与栈

一.题 1. 思路&#xff1a; 构建小压大的单调递减栈&#xff0c;对于每个栈的元素都进行处理并加到结果上 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 ​...

机器翻译同样的文本,是从英语翻译成日语更准确还是中文翻译成日语更准确

在大多数情况下&#xff0c;从英语翻译成日语会比从中文翻译成日语更准确&#xff0c;原因如下&#xff1a; 1. 语言结构的相似性 英语和日语的句子结构更接近&#xff0c;特别是在语法、从句使用、定语位置等方面。例如&#xff0c;日语和英语都使用 SVO 结构&#xff08;主…...

MAC 系统关屏幕后电量消耗极快 Wake Requests

日志为 Wake Requests [*processdasd requestSleepService…info"com.apple.alarm.user-invisible-com.apple.calaccessd… 本人有效方法为&#xff1a; sudo pmset -a hibernatemode 25 sudo pmset -a standby 0 sudo pmset -a autopoweroff 0 会导致hibernatemode 25是…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;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 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...