SpringBoot或SpringAI对接DeekSeek大模型
今日除夕夜,deepseek可是出尽了风头,但是我看网上还没有这方面的内容对接,官网也并没有,故而本次对接是为了完成这个空缺
我看很多的博客内容是流式请求虽然返回时正常的,但是他并不是实时返回,而是全部响应结束之后返回,是有问题的,我这里的这个方法弥补了这个缺陷
下一次我应该会开源一个Starter,让大家使用起来更加方便,下一次直接开源出来,供大家参考,应该就在这一两天,可以期待一下
这里需要仔细看一下了
因为我使用的是JDK21,不过你也可以使用JDK8去做这件事情,但是前提fastjson和okHttp的版本,因为有些方法可能不是很兼容,如果想要完成可能有一些方法需要替换一下,但是肯定是可以用的
文章目录
- 前言
-
目录
文章目录
一、DeepSeek是什么?
二、使用步骤
1.引入库
2.配置环境变量
3.配置
三、 请求
1.流式请求
2.非流失请求
1.定义类
2.非流式请求
四、返回结果
1.流式结果
2.非流式请求
总结
一、DeepSeek是什么?
我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-V3。
-
开发者:深度求索(DeepSeek),一家专注于实现AGI(通用人工智能)的中国科技公司。
-
技术架构:基于大规模语言模型(LLM),通过深度学习技术训练,具备自然语言理解、生成和推理能力。
-
数据来源:训练数据涵盖多领域公开文本(如书籍、网页、学术论文等),经过严格清洗和过滤,符合伦理与安全规范。
二、使用步骤
1.引入库
代码如下(示例):
<!--fastjson--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.66</version></dependency><!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp --><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.12.0</version></dependency>
2.配置环境变量
spring:ai:deepseek:api-key: 这里填写自己的APIKeyapi-host: https://api.deepseek.com/chat/completions
3.配置
package com.hhh.springai_test.config;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class ChatConfig {@Value("${spring.ai.deepseek.api-key}")private String DeepSeekConfigUrl;@Value("${spring.ai.deepseek.api-host}")private String DeepSeekConfigHost;public String getDeepSeekConfigUrl() {return DeepSeekConfigUrl;}public String getDeepSeekConfigHost() {return DeepSeekConfigHost;}}
三、 请求
1.流式请求
@Resource
private ChatConfig config;@GetMapping(value = "/ai/generateStreamAsString2", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<String> generateStreamAsString2(@RequestParam(value = "message") String message) throws Exception {// 初始化 OkHttpClientOkHttpClient client = new OkHttpClient().newBuilder().build();// 创建动态请求体,使用流式传输RequestBody body = new RequestBody() {@Overridepublic okhttp3.MediaType contentType() {return okhttp3.MediaType.parse("application/json");}@Overridepublic void writeTo(BufferedSink sink) throws IOException {// 构建请求体 JSON 数据String requestBodyJson = "{\n" +" \"messages\": [\n" +" {\n" +" \"content\": \"" + message + "\",\n" + // 动态插入用户消息" \"role\": \"user\"\n" +" }\n" +" ],\n" +" \"model\": \"deepseek-chat\",\n" +" \"frequency_penalty\": 0,\n" +" \"max_tokens\": 1024,\n" +" \"presence_penalty\": 0,\n" +" \"response_format\": {\n" +" \"type\": \"text\"\n" +" },\n" +" \"stop\": null,\n" +" \"stream\": true,\n" +" \"stream_options\": null,\n" +" \"temperature\": 1,\n" +" \"top_p\": 1,\n" +" \"tools\": null,\n" +" \"tool_choice\": \"none\",\n" +" \"logprobs\": false,\n" +" \"top_logprobs\": null\n" +"}";// 写入请求体数据sink.writeUtf8(requestBodyJson);}};// 创建 HeadersHeaders headers = new Headers.Builder().add("Content-Type", "application/json").add("Accept", "application/json").add("Authorization", "Bearer " + config.getDeepSeekConfigUrl()) // 使用您的 API 密钥.build();// 创建 HttpUrlHttpUrl url = HttpUrl.parse(config.getDeepSeekConfigHost()); // 使用您的 API URLif (url == null) {throw new IllegalArgumentException("您此时未携带URL参数");}// 构造 Requestokhttp3.Request request = new okhttp3.Request.Builder().url(url).post(body) // 使用流式请求体.headers(headers).build();// 执行请求并返回 Flux 流return Flux.create(sink -> {client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {// 异常发生时调用 sink.error()sink.error(e);}@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {ResponseBody responseBody = response.body();BufferedSource source = responseBody.source();while (true) {// 逐行读取响应数据String line = source.readUtf8Line();if (line == null) {break;} else if (line.startsWith("data:")) {String data = line.substring(5).trim();// 检查数据是否为结束信号"[DONE]"if (!"[DONE]".equals(data)) {// 解析接收到的数据为JSON对象JSONObject jsonResponse = new JSONObject(data);String finishReason = jsonResponse.getJSONArray("choices").getJSONObject(0).optString("finish_reason");if ("stop".equals(finishReason)) {// 结束时推送数据并完成sink.next(data);sink.complete();break;} else {// 否则继续推送数据sink.next(data);}// 打印调试信息System.out.println(jsonResponse.getJSONArray("choices"));}}}}});});}
2.非流失请求
1.定义类
package com.hhh.springai_test.model.dto.DeepSeekChat;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChatCompletionResponse {private String id;private String object;private long created;private String model;private List<Choice> choices;private Usage usage;private String system_fingerprint;@Data@AllArgsConstructor@NoArgsConstructorpublic static class Choice {private int index;private Message message;private Object logprobs;private String finish_reason;}@Data@AllArgsConstructor@NoArgsConstructorpublic static class Message {private String role;private String content;}@Data@AllArgsConstructor@NoArgsConstructorpublic static class Usage {private int prompt_tokens;private int completion_tokens;private int total_tokens;private PromptTokensDetails prompt_tokens_details;private int prompt_cache_hit_tokens;private int prompt_cache_miss_tokens;}@Data@AllArgsConstructor@NoArgsConstructorpublic static class PromptTokensDetails {private int cached_tokens;}
}
2.非流式请求
//引入这个bean
@Resource
private ChatConfig config;@GetMapping(value = "/ai/generateAsString3")public ChatCompletionResponse generateStreamAsString3(@RequestParam(value = "message") String message) {// 初始化 OkHttpClientOkHttpClient client = new OkHttpClient().newBuilder().build();okhttp3.MediaType mediaType = okhttp3.MediaType.parse("application/json");RequestBody requestBody = RequestBody.create(mediaType, "{\n" +" \"messages\": [\n" +" {\n" +" \"content\": \"" + "请介绍一下你自己" + "\",\n" + // 动态插入用户消息" \"role\": \"user\"\n" +" },\n" +" {\n" +" \"content\": \"" + message + "\",\n" + // 动态插入用户消息" \"role\": \"user\"\n" +" }\n" +" ],\n" +" \"model\": \"deepseek-chat\",\n" +" \"frequency_penalty\": 0,\n" +" \"max_tokens\": 1024,\n" +" \"presence_penalty\": 0,\n" +" \"response_format\": {\n" +" \"type\": \"text\"\n" +" },\n" +" \"stop\": null,\n" +" \"stream\": false,\n" +" \"stream_options\": null,\n" +" \"temperature\": 1,\n" +" \"top_p\": 1,\n" +" \"tools\": null,\n" +" \"tool_choice\": \"none\",\n" +" \"logprobs\": false,\n" +" \"top_logprobs\": null\n" +"}");Buffer buffer = new Buffer();try {requestBody.writeTo(buffer);System.out.println("Request Body Content: " + buffer.readUtf8());} catch (IOException e) {e.printStackTrace();}// 创建 HeadersHeaders headers = new Headers.Builder().add("Content-Type", "application/json").add("Accept", "application/json").add("Authorization", "Bearer " + config.getDeepSeekConfigUrl()) // 使用您的 API 密钥.build();// 创建 HttpUrlHttpUrl url = HttpUrl.parse(config.getDeepSeekConfigHost());if (url == null) {throw new IllegalArgumentException("您此时未携带URL参数");}// 构造 Requestokhttp3.Request request = new okhttp3.Request.Builder().url(url).post(requestBody).headers(headers).build();// 执行请求并打印响应try (Response response = client.newCall(request).execute()) {String responseBody = response.body().string();System.out.println(responseBody);ChatCompletionResponse responseVo = JSON.parseObject(responseBody, ChatCompletionResponse.class);return responseVo;} catch (IOException e) {throw new RuntimeException(e);}}
四、返回结果
1.流式结果

2.非流式请求

总结
因为我使用的是JDK21,不过你也可以使用JDK8去做这件事情,但是前提fastjson和okHttp的版本,因为有些方法可能不是很兼容,如果想要完成可能有一些方法需要替换一下,但是肯定是可以用的
相关文章:
SpringBoot或SpringAI对接DeekSeek大模型
今日除夕夜,deepseek可是出尽了风头,但是我看网上还没有这方面的内容对接,官网也并没有,故而本次对接是为了完成这个空缺 我看很多的博客内容是流式请求虽然返回时正常的,但是他并不是实时返回,而是全部响应…...
Funnel-Transformer:通过过滤序列冗余实现高效语言处理
摘要 随着语言预训练的成功,开发更具扩展性且能高效利用大量未标注数据的架构变得尤为重要。为了提高效率,我们研究了在维持完整token级别表示时的冗余问题,尤其是对于仅需要序列单向量表示的任务。基于这一直觉,我们提出了Funne…...
【搜索回溯算法】:BFS的魔力--如何使用广度优先搜索找到最短路径
✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨ 文章所属专栏:搜索回溯算法篇–CSDN博客 文章目录 一.广度优先搜索(BFS)解决最短路…...
【算法】经典博弈论问题——威佐夫博弈 python
目录 威佐夫博弈(Wythoff Game)【模板】 威佐夫博弈(Wythoff Game) 有两堆石子,数量任意,可以不同,游戏开始由两个人轮流取石子 游戏规定,每次有两种不同的取法 1)在任意的一堆中取走任意多的石子 2)可以在两堆中同时取走相同数量…...
CUDA学习-内存访问
一 访存合并 1.1 说明 本部分内容主要参考: 搞懂 CUDA Shared Memory 上的 bank conflicts 和向量化指令(LDS.128 / float4)的访存特点 - 知乎 1.2 share memory结构 图1.1 share memory结构 放在 shared memory 中的数据是以 4 bytes(即 32 bits)作为 1 个 word,依…...
力扣动态规划-13【算法学习day.107】
前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向(例如想要掌握基础用法,该刷哪些题?建议灵神的题单和代码随想录)和记录自己的学习过程,我的解析也不会做的非常详细,只会提供思路和一些关…...
《剪映5.9官方安装包》免费自动生成字幕
(避免失效建议存自己网盘后下载)剪映5.9官方Win.Mac 链接:https://pan.xunlei.com/s/VOHc-Fg2XRlD50MueEaOOeW1A1?pwdawtt# 官方唯一的免费版,Win和Mac都有,此版本官方已下架,觉得有用可转存收藏…...
ESP32-S3模组上跑通esp32-camera(32)
接前一篇文章:ESP32-S3模组上跑通esp32-camera(31) 一、OV5640初始化 2. 相机初始化及图像传感器配置 上一回开始解析camera_probe函数的第8段即最后一段代码,本回继续解析该段代码。为了便于理解和回顾,再次贴出camera_probe函数源码,在components/esp32-camera/drive…...
Brave132 编译指南 Windows 篇:安装 Visual Studio 2022(二)
1. 引言 在着手编译 Brave 浏览器的 132 版本之前,构建一个完备的开发环境至关重要。Visual Studio 2022 作为一款功能强大的集成开发环境(IDE),为 Brave 浏览器的编译提供了坚实的工具链和技术支持。它不仅提供了高效的代码编辑…...
DBO-高斯回归预测matlab
蜣螂优化算法(Dung Beetle Optimizer, DBO)是一种新型的群智能优化算法,在2022年底提出,主要是受蜣螂的的滚球、跳舞、觅食、偷窃和繁殖行为的启发。 本次研究使用的是 Excel 格式的股票预测数据。数据集按照 8:1:1 的比例&#x…...
2025美国大学生数学建模竞赛美赛E题成品参考论文(48页)(含模型,可运行代码,求解结果)
2025美国大学生数学建模竞赛E题成品参考论文 目录 一、问题重述 二、问题分析 三、模型假设 四、模型建立与求解 4.1问题1 4.1.1问题1思路分析 4.1.2问题1模型建立 4.1.3问题1代码(仅供参考) 4.1.4问题1求解结果(仅供参考&…...
VMware 中Ubuntu无网络连接/无网络标识解决方法【已解决】
参考文档 Ubuntu无网络连接/无网络标识解决方法_ubuntu没网-CSDN博客 再我们正常使用VMware时,就以Ubuntu举例可能有时候出现无网络连接,甚至出现无网络标识的情况,那么废话不多说直接上教程 环境:无网络 解决方案&#…...
Vuex中的getter和mutation有什么区别
在现代前端开发中,状态管理是一个不可忽视的话题,而Vuex作为Vue.js的官方状态管理库,在大型应用中扮演着至关重要的角色。当我们使用Vuex进行状态管理时,getter和mutation是两个重要的概念。虽然它们都是用来处理状态的࿰…...
笔试-二维数组2
应用 现有M(1<M<10)个端口组,每个端口组是长度为N(1<N<100),元素均为整数。如果这些端口组间存在2个及以上的元素相同,则认为端口组可以关联合并;若可以关联合并,请用二位数组表示输出结果。其中…...
基于RIP的MGRE VPN综合实验
实验拓扑 实验需求 1、R5为ISP,只能进行IP地址配置,其所有地址均配为公有IP地址; 2、R1和R5间使用PPP的PAP认证,R5为主认证方; R2与R5之间使用ppp的CHAP认证,R5为主认证方; R3与R5之间使用HDLC封…...
十三先天记
没有一刻,只有当下在我心里。我像星星之间的空间一样空虚。他们是我看到的第一件事,我知道的第一件事。 在接下来的时间里,我意识到我是谁,我是谁。我知道星星在我上方,星球的固体金属体在我脚下。这个支持我的世界是泰…...
Autosar-Os是怎么运行的?(Os基础模块)
写在前面: 入行一段时间了,基于个人理解整理一些东西,如有错误,欢迎各位大佬评论区指正!!! 书接上文 Autosar-Os是怎么运行的?(一)-CSDN博客 目录 1.Resourc…...
OPencv3.4.1安装及配置教程
来到GitHub上opencv的项目地址 https://github.com/opencv/opencv/releases/tag/3.4.1 以上资源包都是 OpenCV 3.4.1 版本相关资源,它们的区别如下: (1). opencv-3.4.1-android-sdk.zip:适用于 Android 平台的软件开发工具包(SDK…...
选择困难?直接生成pynput快捷键字符串
from pynput import keyboard# 文档:https://pynput.readthedocs.io/en/latest/keyboard.html#monitoring-the-keyboard # 博客(pynput相关源码):https://blog.csdn.net/qq_39124701/article/details/145230331 # 虚拟键码(十六进制):https:/…...
Vue.js组件开发-如何实现带有搜索功能的下拉框
创建 Vue 项目: 如果还没有创建一个 Vue 项目,可以使用 Vue CLI 来创建一个新的项目。 vue create my-project cd my-project安装依赖: 如果需要使用第三方组件库,比如 Element UI 或 Ant Design Vue,可以安装相应的…...
java 字符串日期字段格式化前端显示
在 Java 应用程序中,如果你有一个字符串类型的日期字段,并希望将其格式化后显示在前端,可以通过多种方式实现。这通常涉及到在后端将字符串转换为 Date 或 LocalDateTime 等对象,然后使用适当的注解或配置来确保它们以正确的格式序…...
LeetCode题练习与总结:安装栅栏--587
一、题目描述 给定一个数组 trees,其中 trees[i] [xi, yi] 表示树在花园中的位置。 你被要求用最短长度的绳子把整个花园围起来,因为绳子很贵。只有把 所有的树都围起来,花园才围得很好。 返回恰好位于围栏周边的树木的坐标。 示例 1: 输…...
< OS 有关 > 阿里云 几个小时前 使用密钥替换 SSH 密码认证后, 发现主机正在被“攻击” 分析与应对
信息来源: 文件:/var/log/auth.log 因为在 sshd_config 配置文件中,已经定义 LogLevel INFO 部分内容: 2025-01-27T18:18:55.68272708:00 jpn sshd[15891]: Received disconnect from 45.194.37.171 port 58954:11: Bye Bye […...
使用八爪鱼爬虫和Web Scraper抓取数据实战案例,附详细教程
最近有不少小伙伴咨询怎么抓取抖音视频或者评论的数据,他们多是自媒体或者商家,想要模仿爆火视频或者分析视频评论区的舆情信息,确实呀,现在抖音是流量高地,淘金的地方,真的是一个值得挖掘的宝藏。当然我一…...
海外问卷调查渠道查如何设置:最佳实践+示例
随着经济全球化和一体化进程的加速,企业间的竞争日益加剧,为了获得更大的市场份额,对企业和品牌而言,了解受众群体的的需求、偏好和痛点才是走向成功的关键。而海外问卷调查才是获得受众群体痛点的关键,制作海外问卷调…...
【C++数论】880. 索引处的解码字符串|2010
本文涉及知识点 数论:质数、最大公约数、菲蜀定理 LeetCode880. 索引处的解码字符串 给定一个编码字符串 s 。请你找出 解码字符串 并将其写入磁带。解码时,从编码字符串中 每次读取一个字符 ,并采取以下步骤: 如果所读的字符是…...
从ai产品推荐到利用cursor快速掌握一个开源项目再到langchain手搓一个Text2Sql agent
目录 0. 经验分享:产品推荐 1. 经验分享:提示词优化 2. 经验分享:使用cursor 阅读一篇文章 3. 经验分享:使用cursor 阅读一个完全陌生的开源项目 4. 经验分享:手搓一个text2sql agent (使用langchain l…...
freeswitch在centos上编译过程
操作系统:centos9-last usr/local/freeswitch/bin/freeswitch -version FreeSWITCH version: 1.10.13-devgit~20250125T131725Z~3f1e4bf90a~64bit (git 3f1e4bf 2025-01-25 13:17:25Z 64bit)vi /etc/ssh/sshd_config ip a nmtui reboot ip a curl -o /etc/pki/rpm-…...
项目测试之MockMvc
文章目录 基础基础概念Mockxxx一般实现文件位置 实战MockMvc与Test注解不兼容RequestParams参数RequestBody参数 基础 基础概念 定义:是Spring框架提供的一种用于测试Spring MVC控制器的工具,它允许开发者在不启动完整的web服务器的情况下,…...
Blazor-选择循环语句
今天我们来说说Blazor选择语句和循环语句。 下面我们以一个简单的例子来讲解相关的语法,我已经创建好了一个Student类,以此类来进行语法的运用 因为我们需要交互性所以我们将类创建在*.client目录下 if 我们做一个学生信息的显示,Gender为…...
